Neo-Tokyo Neon Noir design pour fiches items

- Nouvelle palette : #080c14 fond, accents néon par type (#00d4d4 item, #ff3d5a kungfu, #4a9eff spell, #cc44ff supernatural)
- Nouveaux composants LESS : .cde-neon-header (clip-path angulaire + accent line), .cde-avatar (clip-path), .cde-stat-grid/.cde-stat-cell (style terminal), .cde-badge (parallélogramme), .cde-neon-tabs (underline néon animé), .cde-check-cell
- Fix layout : .cde-sheet width: 100% + height: 100% + overflow: hidden, .cde-tab-body flex: 1 + min-height: 0, .cde-notes-editor flex stretch
- Fix positions : DEFAULT_OPTIONS height explicite pour tous les types (item 620x580, spell 660x680, kungfu 720x680, supernatural 560x520)
- 4 templates items reécrits avec nouvelles classes et structure épurée

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-03-26 00:18:04 +01:00
commit 068fca00e5
739 changed files with 7923 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
export default class CharacterDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })
const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial })
const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
const aspectField = (label, chinese) =>
new fields.SchemaField({
chinese: stringField(chinese),
label: stringField(label),
value: numberField(15, { min: 0 }),
})
const skillField = (label) =>
new fields.SchemaField({
label: stringField(label),
specialities: stringField(""),
value: numberField(0, { min: 0 }),
})
const resourceField = (label) =>
new fields.SchemaField({
label: stringField(label),
specialities: stringField(""),
value: numberField(0, { min: 0 }),
debt: boolField(false),
})
const componentField = () =>
new fields.SchemaField({
value: stringField(""),
})
const magicSpecialityField = () =>
new fields.SchemaField({
check: boolField(false),
})
const magicField = () =>
new fields.SchemaField({
visible: boolField(true),
value: numberField(0, { min: 0 }),
speciality: new fields.SchemaField({
essence: magicSpecialityField(),
mind: magicSpecialityField(),
purification: magicSpecialityField(),
manipulation: magicSpecialityField(),
aura: magicSpecialityField(),
acupuncture: magicSpecialityField(),
elixirs: magicSpecialityField(),
poisons: magicSpecialityField(),
arsenal: magicSpecialityField(),
potions: magicSpecialityField(),
curse: magicSpecialityField(),
transfiguration: magicSpecialityField(),
necromancy: magicSpecialityField(),
climatecontrol: magicSpecialityField(),
goldenmagic: magicSpecialityField(),
invocation: magicSpecialityField(),
tracking: magicSpecialityField(),
protection: magicSpecialityField(),
punishment: magicSpecialityField(),
domination: magicSpecialityField(),
neutralization: magicSpecialityField(),
divination: magicSpecialityField(),
earthlyprayer: magicSpecialityField(),
heavenlyprayer: magicSpecialityField(),
fungseoi: magicSpecialityField(),
}),
})
const treasureBranch = () =>
new fields.SchemaField({
value: numberField(0, { min: 0 }),
max: numberField(0, { min: 0 }),
min: numberField(0, { min: 0 }),
})
const treasureLevel = () =>
new fields.SchemaField({
san: treasureBranch(),
zing: treasureBranch(),
})
const schema = {
concept: stringField(""),
guardian: stringField("0"),
initiative: numberField(1, { min: 0 }),
anti_initiative: numberField(24, { min: 0 }),
description: htmlField(""),
prefs: new fields.SchemaField({
typeofthrow: new fields.SchemaField({
check: boolField(true),
choice: stringField("0"),
}),
}),
prompt: new fields.SchemaField({
typeofthrow: new fields.SchemaField({
check: boolField(true),
choice: stringField("0"),
}),
configure: new fields.SchemaField({
numberofdice: numberField(0),
aspect: numberField(0),
bonus: numberField(0),
bonusauspiciousdice: numberField(0),
typeofthrow: numberField(0),
aspectskill: numberField(0),
bonusmalusskill: numberField(0),
aspectspeciality: numberField(0),
rolldifficulty: numberField(0),
bonusmalusspeciality: numberField(0),
}),
}),
aspect: new fields.SchemaField({
fire: aspectField("CDE.Fire", "㊋"),
earth: aspectField("CDE.Earth", "㊏"),
metal: aspectField("CDE.Metal", "㊎"),
water: aspectField("CDE.Water", "㊌"),
wood: aspectField("CDE.Wood", "㊍"),
}),
skills: new fields.SchemaField({
art: skillField("CDE.Art"),
investigation: skillField("CDE.Investigation"),
erudition: skillField("CDE.Erudition"),
knavery: skillField("CDE.Knavery"),
wordliness: skillField("CDE.Wordliness"),
prowess: skillField("CDE.Prowess"),
sciences: skillField("CDE.Sciences"),
technologies: skillField("CDE.Technologies"),
kungfu: skillField("CDE.KungFu"),
rangedcombat: skillField("CDE.RangedCombat"),
}),
resources: new fields.SchemaField({
supply: resourceField("CDE.Supply"),
inquiry: resourceField("CDE.Inquiry"),
influence: resourceField("CDE.Influence"),
}),
component: new fields.SchemaField({
one: componentField(),
two: componentField(),
three: componentField(),
four: componentField(),
five: componentField(),
six: componentField(),
seven: componentField(),
eight: componentField(),
nine: componentField(),
zero: componentField(),
}),
magics: new fields.SchemaField({
internalcinnabar: magicField(),
alchemy: magicField(),
masteryoftheway: magicField(),
exorcism: magicField(),
geomancy: magicField(),
}),
threetreasures: new fields.SchemaField({
heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),
heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),
dicelevel: new fields.SchemaField({
level0d: treasureLevel(),
level1d: treasureLevel(),
level2d: treasureLevel(),
}),
}),
experience: new fields.SchemaField({
value: numberField(0, { min: 0 }),
max: numberField(0, { min: 0 }),
min: numberField(0, { min: 0 }),
}),
}
return schema
}
}

4
src/data/actors/index.js Normal file
View File

@@ -0,0 +1,4 @@
export { default as CharacterDataModel } from "./character.js"
export { default as NpcDataModel } from "./npc.js"
export { default as TinjiDataModel } from "./tinji.js"
export { default as LoksyuDataModel } from "./loksyu.js"

22
src/data/actors/loksyu.js Normal file
View File

@@ -0,0 +1,22 @@
export default class LoksyuDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
const polarity = () =>
new fields.SchemaField({
yin: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),
yang: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),
})
return {
fire: polarity(),
earth: polarity(),
metal: polarity(),
water: polarity(),
wood: polarity(),
description: htmlField(""),
}
}
}

46
src/data/actors/npc.js Normal file
View File

@@ -0,0 +1,46 @@
export default class NpcDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })
const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial })
const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
const aptitudeField = () =>
new fields.SchemaField({
value: numberField(0, { min: 0 }),
speciality: stringField(""),
})
const trackedField = () =>
new fields.SchemaField({
value: numberField(0, { min: 0 }),
calcul: numberField(0, { min: 0 }),
note: stringField(""),
})
return {
type: stringField(""),
levelofthreat: numberField(0, { min: 0 }),
powerofnuisance: numberField(0, { min: 0 }),
initiative: numberField(1, { min: 0 }),
anti_initiative: numberField(24, { min: 0 }),
aptitudes: new fields.SchemaField({
physical: aptitudeField(),
martial: aptitudeField(),
mental: aptitudeField(),
social: aptitudeField(),
spiritual: aptitudeField(),
}),
vitality: trackedField(),
hei: trackedField(),
description: htmlField(""),
prefs: new fields.SchemaField({
typeofthrow: new fields.SchemaField({
check: boolField(false),
choice: stringField("0"),
}),
}),
}
}
}

12
src/data/actors/tinji.js Normal file
View File

@@ -0,0 +1,12 @@
export default class TinjiDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
return {
value: numberField(0, { min: 0 }),
description: htmlField(""),
}
}
}

4
src/data/items/index.js Normal file
View File

@@ -0,0 +1,4 @@
export { default as EquipmentDataModel } from "./item.js"
export { default as KungfuDataModel } from "./kungfu.js"
export { default as SpellDataModel } from "./spell.js"
export { default as SupernaturalDataModel } from "./supernatural.js"

20
src/data/items/item.js Normal file
View File

@@ -0,0 +1,20 @@
export default class EquipmentDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })
const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
return {
subtype: stringField(""),
reference: stringField(""),
description: htmlField(""),
quantity: numberField(1, { min: 0 }),
weight: numberField(0, { min: 0 }),
protection: stringField(""),
damage: stringField(""),
range: stringField(""),
notes: htmlField(""),
}
}
}

32
src/data/items/kungfu.js Normal file
View File

@@ -0,0 +1,32 @@
export default class KungfuDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })
const techniqueField = () =>
new fields.SchemaField({
check: boolField(false),
name: stringField(""),
activation: stringField(""),
technique: htmlField(""),
})
return {
reference: stringField(""),
description: htmlField(""),
orientation: stringField(""),
aspect: stringField(""),
skill: stringField(""),
speciality: stringField(""),
style: stringField(""),
techniques: new fields.SchemaField({
technique1: techniqueField(),
technique2: techniqueField(),
technique3: techniqueField(),
}),
notes: htmlField(""),
}
}
}

22
src/data/items/spell.js Normal file
View File

@@ -0,0 +1,22 @@
export default class SpellDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
return {
reference: stringField(""),
description: htmlField(""),
specialityname: stringField(""),
associatedelement: stringField(""),
hei: stringField(""),
realizationtimeritual: stringField(""),
realizationtimeaccelerated: stringField(""),
flashback: stringField(""),
components: htmlField(""),
effects: htmlField(""),
examples: htmlField(""),
notes: htmlField(""),
}
}
}

View File

@@ -0,0 +1,13 @@
export default class SupernaturalDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const { fields } = foundry.data
const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial })
const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })
return {
reference: stringField(""),
description: htmlField(""),
notes: htmlField(""),
}
}
}