Initial skeleton

This commit is contained in:
2026-03-05 21:51:31 +01:00
commit 12458925a1
53 changed files with 6646 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
export { default as AwECharacter } from "./character.mjs"
export { default as AwECreature } from "./creature.mjs"
export { default as AwEAbility } from "./ability.mjs"
export { default as AwEField } from "./field.mjs"
export { default as AwEArchetype } from "./archetype.mjs"
export { default as AwEBackground } from "./background.mjs"
export { default as AwEKit } from "./kit.mjs"
export { default as AwEWeapon } from "./weapon.mjs"
export { default as AwEEquipment } from "./equipment.mjs"
+28
View File
@@ -0,0 +1,28 @@
import { SYSTEM } from "../config/system.mjs"
export default class AwEAbility extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.abilityType = new fields.StringField({
required: true,
nullable: false,
initial: "field",
choices: Object.keys(SYSTEM.ABILITY_TYPE)
})
schema.cost = new fields.StringField({
required: true,
nullable: false,
initial: "one",
choices: Object.keys(SYSTEM.ABILITY_COST)
})
schema.frequency = new fields.StringField({ initial: "", required: false, nullable: true })
schema.requirements = new fields.StringField({ initial: "", required: false, nullable: true })
schema.trigger = new fields.StringField({ initial: "", required: false, nullable: true })
schema.traits = new fields.ArrayField(new fields.StringField())
return schema
}
}
+13
View File
@@ -0,0 +1,13 @@
export default class AwEArchetype extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.prerequisiteLevel = new fields.NumberField({
required: true, nullable: false, integer: true, initial: 2, min: 1
})
return schema
}
}
+11
View File
@@ -0,0 +1,11 @@
export default class AwEBackground extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.bonus = new fields.StringField({ initial: "", required: false, nullable: true })
return schema
}
}
+74
View File
@@ -0,0 +1,74 @@
import { SYSTEM } from "../config/system.mjs"
export default class AwECharacter extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.notes = new fields.HTMLField({ required: true, textSearch: true })
// Identity
schema.pronouns = new fields.StringField({ initial: "", required: false, nullable: true })
schema.fieldName = new fields.StringField({ initial: "", required: false, nullable: true })
schema.specialization = new fields.StringField({ initial: "", required: false, nullable: true })
schema.archetypeName = new fields.StringField({ initial: "", required: false, nullable: true })
schema.backgroundName = new fields.StringField({ initial: "", required: false, nullable: true })
// Core stats
schema.level = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1, max: 10 })
schema.stride = new fields.NumberField({ ...requiredInteger, initial: 5, min: 0 })
// Hit Points
schema.hp = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }),
temp: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
})
// Flow Points
schema.flowPoints = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
temp: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
})
// Attributes: agility, fitness, awareness, influence
// boostLevel: how many boosts applied (0-4)
// mod = level + boostLevel (computed in prepareDerivedData)
// dc = 10 + mod (computed)
// bonus: manual +/- bonus
const attributeField = () => new fields.SchemaField({
boostLevel: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 4 }),
bonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 })
})
schema.attributes = new fields.SchemaField(
Object.values(SYSTEM.ATTRIBUTES).reduce((obj, attr) => {
obj[attr.id] = attributeField()
return obj
}, {})
)
return schema
}
/** @override */
prepareDerivedData() {
super.prepareDerivedData()
const level = this.level
for (const attrId of Object.keys(SYSTEM.ATTRIBUTES)) {
const attr = this.attributes[attrId]
attr.mod = level + attr.boostLevel + attr.bonus
attr.dc = 10 + attr.mod
}
// Compute max HP if not overridden
// Base HP = 10 + (level * 2) + fitness modifier
const fitnessMod = this.attributes.fitness.mod ?? 0
if (this.hp.max === 10) {
this.hp.max = 10 + (level * 2) + fitnessMod
}
}
}
+46
View File
@@ -0,0 +1,46 @@
export default class AwECreature extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.level = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 })
schema.stride = new fields.NumberField({ ...requiredInteger, initial: 5, min: 0 })
schema.hp = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 })
})
// Raw attribute values (mod = value directly, no boosts)
schema.attributes = new fields.SchemaField({
agility: new fields.SchemaField({
mod: new fields.NumberField({ ...requiredInteger, initial: 2 }),
dc: new fields.NumberField({ ...requiredInteger, initial: 12 })
}),
fitness: new fields.SchemaField({
mod: new fields.NumberField({ ...requiredInteger, initial: 2 }),
dc: new fields.NumberField({ ...requiredInteger, initial: 12 })
}),
awareness: new fields.SchemaField({
mod: new fields.NumberField({ ...requiredInteger, initial: 2 }),
dc: new fields.NumberField({ ...requiredInteger, initial: 12 })
}),
influence: new fields.SchemaField({
mod: new fields.NumberField({ ...requiredInteger, initial: 2 }),
dc: new fields.NumberField({ ...requiredInteger, initial: 12 })
})
})
// Eureka Rubric
schema.eurekaClaims = new fields.StringField({ initial: "", required: false, nullable: true })
schema.eurekaEvidence = new fields.StringField({ initial: "", required: false, nullable: true })
schema.eurekaThreshold1 = new fields.StringField({ initial: "", required: false, nullable: true })
schema.eurekaThreshold2 = new fields.StringField({ initial: "", required: false, nullable: true })
schema.eurekaHints = new fields.StringField({ initial: "", required: false, nullable: true })
return schema
}
}
+13
View File
@@ -0,0 +1,13 @@
export default class AwEEquipment extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
schema.weight = new fields.NumberField({ required: true, nullable: false, initial: 0, min: 0 })
return schema
}
}
+26
View File
@@ -0,0 +1,26 @@
import { SYSTEM } from "../config/system.mjs"
export default class AwEField extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.keyAttribute = new fields.StringField({
required: true,
nullable: false,
initial: "agility",
choices: Object.keys(SYSTEM.ATTRIBUTES)
})
schema.keyAttribute2 = new fields.StringField({
required: false,
nullable: true,
initial: null,
choices: [...Object.keys(SYSTEM.ATTRIBUTES), null]
})
schema.specializations = new fields.ArrayField(new fields.StringField())
schema.knowledgeBonus = new fields.StringField({ initial: "", required: false, nullable: true })
return schema
}
}
+16
View File
@@ -0,0 +1,16 @@
export default class AwEKit extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.fieldName = new fields.StringField({ initial: "", required: false, nullable: true })
schema.charges = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
})
return schema
}
}
+23
View File
@@ -0,0 +1,23 @@
import { SYSTEM } from "../config/system.mjs"
export default class AwEWeapon extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.range = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
schema.damageFormula = new fields.StringField({ initial: "1d6", required: true, nullable: false })
schema.damageType = new fields.StringField({ initial: "physical", required: true, nullable: false })
schema.attackAttribute = new fields.StringField({
required: true,
nullable: false,
initial: "agility",
choices: Object.keys(SYSTEM.ATTRIBUTES)
})
schema.traits = new fields.ArrayField(new fields.StringField())
return schema
}
}