Add logic tree computation and item enchantment.
This commit is contained in:
parent
777443471c
commit
e9a892076d
|
|
@ -14,6 +14,7 @@ export type DamageType = typeof DAMAGE_TYPES[number];
|
||||||
export type WeaponType = typeof WEAPON_TYPES[number];
|
export type WeaponType = typeof WEAPON_TYPES[number];
|
||||||
|
|
||||||
export type FeatureID = string;
|
export type FeatureID = string;
|
||||||
|
export type FeatureEffectID = string;
|
||||||
export type i18nID = string;
|
export type i18nID = string;
|
||||||
|
|
||||||
export type RecursiveKeyOf<TObj extends object> = {
|
export type RecursiveKeyOf<TObj extends object> = {
|
||||||
|
|
@ -57,10 +58,6 @@ export type CharacterVariables = {
|
||||||
|
|
||||||
money: number;
|
money: number;
|
||||||
};
|
};
|
||||||
export enum TreeFlag {
|
|
||||||
AUTOMATIC = 1 << 0,
|
|
||||||
REPEATING = 1 << 1,
|
|
||||||
};
|
|
||||||
export type TreeLeaf = {
|
export type TreeLeaf = {
|
||||||
id: FeatureID;
|
id: FeatureID;
|
||||||
to?: FeatureID | Array<FeatureID> | Record<string, FeatureID>;
|
to?: FeatureID | Array<FeatureID> | Record<string, FeatureID>;
|
||||||
|
|
@ -68,14 +65,14 @@ export type TreeLeaf = {
|
||||||
};
|
};
|
||||||
export type TreeStructure = {
|
export type TreeStructure = {
|
||||||
name: string;
|
name: string;
|
||||||
starts: FeatureID;
|
start: FeatureID | Array<FeatureID> | Record<string, FeatureID>;
|
||||||
nodes: Record<FeatureID, TreeLeaf>;
|
nodes: Record<FeatureID, TreeLeaf>;
|
||||||
};
|
};
|
||||||
type CommonState = {
|
type CommonState = {
|
||||||
capacity?: number;
|
capacity?: number;
|
||||||
powercost?: number;
|
powercost?: number;
|
||||||
};
|
};
|
||||||
type ArmorState = { loss: number, health?: number, absorb?: { flat?: number, percent?: number } };
|
type ArmorState = { loss: number, health?: number, absorb: { flat?: number, percent?: number } };
|
||||||
type WeaponState = { attack?: number | string, hit?: number };
|
type WeaponState = { attack?: number | string, hit?: number };
|
||||||
type WondrousState = { };
|
type WondrousState = { };
|
||||||
type MundaneState = { };
|
type MundaneState = { };
|
||||||
|
|
@ -86,6 +83,7 @@ type ItemState = {
|
||||||
charges?: number;
|
charges?: number;
|
||||||
equipped?: boolean;
|
equipped?: boolean;
|
||||||
state?: (ArmorState | WeaponState | WondrousState | MundaneState) & CommonState;
|
state?: (ArmorState | WeaponState | WondrousState | MundaneState) & CommonState;
|
||||||
|
buffer?: Record<string, PropertySum>
|
||||||
};
|
};
|
||||||
export type CharacterConfig = {
|
export type CharacterConfig = {
|
||||||
peoples: Record<string, RaceConfig>;
|
peoples: Record<string, RaceConfig>;
|
||||||
|
|
@ -196,34 +194,35 @@ export type AspectConfig = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FeatureValue = {
|
export type FeatureValue = {
|
||||||
id: FeatureID;
|
id: FeatureEffectID;
|
||||||
category: "value";
|
category: "value";
|
||||||
operation: "add" | "set" | "min";
|
operation: "add" | "set" | "min";
|
||||||
property: RecursiveKeyOf<CompiledCharacter> | 'spec' | 'ability' | 'training';
|
property: RecursiveKeyOf<CompiledCharacter> | 'spec' | 'ability' | 'training';
|
||||||
value: number | `modifier/${MainStat}` | false;
|
value: number | `modifier/${MainStat}` | false;
|
||||||
}
|
}
|
||||||
export type FeatureEquipment = {
|
export type FeatureEquipment = {
|
||||||
id: FeatureID;
|
id: FeatureEffectID;
|
||||||
category: "value";
|
category: "value";
|
||||||
operation: "add" | "set" | "min";
|
operation: "add" | "set" | "min";
|
||||||
property: `item/${RecursiveKeyOf<ArmorState & WeaponState & WondrousState & MundaneState & CommonState>}`;
|
property: `item/${RecursiveKeyOf<ArmorState & WeaponState & WondrousState & MundaneState & CommonState>}`;
|
||||||
value: number | `modifier/${MainStat}` | false;
|
value: number | `modifier/${MainStat}` | false;
|
||||||
};
|
};
|
||||||
export type FeatureList = {
|
export type FeatureList = {
|
||||||
id: FeatureID;
|
id: FeatureEffectID;
|
||||||
category: "list";
|
category: "list";
|
||||||
list: "spells" | "sickness" | "action" | "reaction" | "freeaction" | "passive" | "mastery";
|
list: "spells" | "sickness" | "action" | "reaction" | "freeaction" | "passive" | "mastery";
|
||||||
action: "add" | "remove";
|
action: "add" | "remove";
|
||||||
item: string;
|
item: string;
|
||||||
};
|
};
|
||||||
export type FeatureTree = {
|
export type FeatureTree = {
|
||||||
id: FeatureID;
|
id: FeatureEffectID;
|
||||||
category: "tree";
|
category: "tree";
|
||||||
tree: string;
|
tree: string;
|
||||||
option?: string;
|
option?: string;
|
||||||
|
priority?: number;
|
||||||
};
|
};
|
||||||
export type FeatureChoice = {
|
export type FeatureChoice = {
|
||||||
id: FeatureID;
|
id: FeatureEffectID;
|
||||||
category: "choice";
|
category: "choice";
|
||||||
text: string; //TODO -> TextID
|
text: string; //TODO -> TextID
|
||||||
settings?: { //If undefined, amount is 1 by default
|
settings?: { //If undefined, amount is 1 by default
|
||||||
|
|
@ -294,7 +293,7 @@ export type CompiledCharacter = {
|
||||||
modifier: Record<MainStat, number>;
|
modifier: Record<MainStat, number>;
|
||||||
abilities: Partial<Record<Ability, number>>;
|
abilities: Partial<Record<Ability, number>>;
|
||||||
level: number;
|
level: number;
|
||||||
lists: { [K in FeatureList['list']]?: string[] }; //string => ListItem ID
|
lists: { [K in Exclude<FeatureList['list'], 'mastery'>]: string[] }; //string => ListItem ID
|
||||||
|
|
||||||
notes: { public: string, private: string };
|
notes: { public: string, private: string };
|
||||||
};
|
};
|
||||||
|
|
@ -156,8 +156,8 @@ export default defineNuxtConfig({
|
||||||
security: {
|
security: {
|
||||||
rateLimiter: {
|
rateLimiter: {
|
||||||
headers: true,
|
headers: true,
|
||||||
interval: 1000,
|
interval: 100,
|
||||||
tokensPerInterval: 5
|
tokensPerInterval: 3
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -183,6 +183,8 @@ export default defineNuxtConfig({
|
||||||
security: {
|
security: {
|
||||||
rateLimiter: {
|
rateLimiter: {
|
||||||
headers: true,
|
headers: true,
|
||||||
|
interval: 1000,
|
||||||
|
tokensPerInterval: 10
|
||||||
},
|
},
|
||||||
headers: {
|
headers: {
|
||||||
contentSecurityPolicy: {
|
contentSecurityPolicy: {
|
||||||
|
|
|
||||||
|
|
@ -5337,8 +5337,8 @@
|
||||||
{
|
{
|
||||||
"id": "d1xQebDQ~afaLpHgH_yz.VWc",
|
"id": "d1xQebDQ~afaLpHgH_yz.VWc",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "strength"
|
"priority": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5349,8 +5349,9 @@
|
||||||
{
|
{
|
||||||
"id": "ksIx8~LCJWCZMnS.MOz7IfrV",
|
"id": "ksIx8~LCJWCZMnS.MOz7IfrV",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "strength"
|
"option": "strength",
|
||||||
|
"priority": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "Jb-1RnRHwAPh2F0H_0aIfDPe",
|
"id": "Jb-1RnRHwAPh2F0H_0aIfDPe",
|
||||||
|
|
@ -5368,7 +5369,7 @@
|
||||||
{
|
{
|
||||||
"id": "HdMYachDsjo5HB3ThTctAHl.",
|
"id": "HdMYachDsjo5HB3ThTctAHl.",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armures"
|
"tree": "armor"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5379,8 +5380,9 @@
|
||||||
{
|
{
|
||||||
"id": "DY2K~wXSYfraOZ95dDNWM4WK",
|
"id": "DY2K~wXSYfraOZ95dDNWM4WK",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "strength"
|
"option": "strength",
|
||||||
|
"priority": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "value",
|
"category": "value",
|
||||||
|
|
@ -5411,7 +5413,8 @@
|
||||||
{
|
{
|
||||||
"id": "dFJoBM9hqmx-.W9d3skKzTey",
|
"id": "dFJoBM9hqmx-.W9d3skKzTey",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Bouclier"
|
"tree": "weapon",
|
||||||
|
"option": "shield"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "value",
|
"category": "value",
|
||||||
|
|
@ -5442,8 +5445,9 @@
|
||||||
{
|
{
|
||||||
"id": "zyfo6vWAwVlwKfHmaIU71yOE",
|
"id": "zyfo6vWAwVlwKfHmaIU71yOE",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "strength"
|
"option": "strength",
|
||||||
|
"priority": 4
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5454,7 +5458,7 @@
|
||||||
{
|
{
|
||||||
"id": "rGtX-s2~IEf-luCkammuc8pN",
|
"id": "rGtX-s2~IEf-luCkammuc8pN",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armures"
|
"tree": "armor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": ".jZrWD92hXVNdFac2HaDNgug",
|
"id": ".jZrWD92hXVNdFac2HaDNgug",
|
||||||
|
|
@ -5551,7 +5555,8 @@
|
||||||
{
|
{
|
||||||
"id": "l.o2_89Rr6vAJjtMnR1CblgF",
|
"id": "l.o2_89Rr6vAJjtMnR1CblgF",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Bouclier"
|
"tree": "weapon",
|
||||||
|
"option": "shield"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"category": "value",
|
"category": "value",
|
||||||
|
|
@ -5830,7 +5835,7 @@
|
||||||
{
|
{
|
||||||
"id": "0oZ9PR4Z9FEqT3XYpfhGcLku",
|
"id": "0oZ9PR4Z9FEqT3XYpfhGcLku",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Attaques multiples"
|
"tree": "multiattack"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5855,13 +5860,13 @@
|
||||||
{
|
{
|
||||||
"id": "5O0ivP35uUL_4867L~Oloxgd",
|
"id": "5O0ivP35uUL_4867L~Oloxgd",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Attaques multiples"
|
"tree": "multiattack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "d4ekXS0r2~v7ONux6oH2CaLP",
|
"id": "d4ekXS0r2~v7ONux6oH2CaLP",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "strength"
|
"priority": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5872,8 +5877,9 @@
|
||||||
{
|
{
|
||||||
"id": "rsw70mkMn5pVkN1VXXZCdxSQ",
|
"id": "rsw70mkMn5pVkN1VXXZCdxSQ",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "dexterity"
|
"option": "dexterity",
|
||||||
|
"priority": 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5884,7 +5890,7 @@
|
||||||
{
|
{
|
||||||
"id": "2_r_JSmTB76Nqkm3yed0IKHi",
|
"id": "2_r_JSmTB76Nqkm3yed0IKHi",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Attaques multiples"
|
"tree": "multiattack"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -5915,8 +5921,9 @@
|
||||||
{
|
{
|
||||||
"id": "BFvq2o_ujkwk5tteSE6aVJ9_",
|
"id": "BFvq2o_ujkwk5tteSE6aVJ9_",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armes",
|
"tree": "weapon",
|
||||||
"option": "dexterity"
|
"option": "dexterity",
|
||||||
|
"priority": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "A-MWtQHUJaxF8FDSY~93p~k5",
|
"id": "A-MWtQHUJaxF8FDSY~93p~k5",
|
||||||
|
|
@ -6093,7 +6100,7 @@
|
||||||
{
|
{
|
||||||
"id": "Hem_L_b9ALISR_BGSaPLz5Jo",
|
"id": "Hem_L_b9ALISR_BGSaPLz5Jo",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Attaques multiples"
|
"tree": "multiattack"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -6335,7 +6342,7 @@
|
||||||
{
|
{
|
||||||
"id": "qK8OzqEuvtC-dD0NcPbDQJaz",
|
"id": "qK8OzqEuvtC-dD0NcPbDQJaz",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Attaques multiples"
|
"tree": "multiattack"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -7194,7 +7201,7 @@
|
||||||
{
|
{
|
||||||
"id": "joKhNNXkaSGvq-w2r_s~QMZE",
|
"id": "joKhNNXkaSGvq-w2r_s~QMZE",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Rapidité)"
|
"tree": "magic_speed"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -7265,7 +7272,7 @@
|
||||||
{
|
{
|
||||||
"id": "szD-N-j274stZR~AitvELxTh",
|
"id": "szD-N-j274stZR~AitvELxTh",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Élements)"
|
"tree": "magic_elements"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "AcQYQ8DPvR7IJnQDvBtNA~jb",
|
"id": "AcQYQ8DPvR7IJnQDvBtNA~jb",
|
||||||
|
|
@ -7283,7 +7290,7 @@
|
||||||
{
|
{
|
||||||
"id": "e0.rWKd1gED~g4EnlVhOQHc6",
|
"id": "e0.rWKd1gED~g4EnlVhOQHc6",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Puissance)"
|
"tree": "magic_power"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "aAEVLEi0N0sQOh67e9cqK4ov",
|
"id": "aAEVLEi0N0sQOh67e9cqK4ov",
|
||||||
|
|
@ -7361,7 +7368,7 @@
|
||||||
{
|
{
|
||||||
"id": "fo5gX5BhxkJa8s09bP0MUhnp",
|
"id": "fo5gX5BhxkJa8s09bP0MUhnp",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Rapidité)"
|
"tree": "magic_speed"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -7392,7 +7399,7 @@
|
||||||
{
|
{
|
||||||
"id": "RbWEMZRq90g_OzGDz0EVrPO.",
|
"id": "RbWEMZRq90g_OzGDz0EVrPO.",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Puissance)"
|
"tree": "magic_power"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -7430,7 +7437,7 @@
|
||||||
{
|
{
|
||||||
"id": "rSLbAIefi-0gP5UDd7LPT6jK",
|
"id": "rSLbAIefi-0gP5UDd7LPT6jK",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Élements)"
|
"tree": "magic_elements"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "xvxTGbUzrMnHeWf6XOuXQTui",
|
"id": "xvxTGbUzrMnHeWf6XOuXQTui",
|
||||||
|
|
@ -7513,7 +7520,7 @@
|
||||||
{
|
{
|
||||||
"id": "nlAXO72~EJ_IBNf45Zw8W-MB",
|
"id": "nlAXO72~EJ_IBNf45Zw8W-MB",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Rapidité)"
|
"tree": "magic_speed"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -7608,7 +7615,7 @@
|
||||||
{
|
{
|
||||||
"id": "4_IIWDclB1mPDwPm2HH3.Fg7",
|
"id": "4_IIWDclB1mPDwPm2HH3.Fg7",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Élements)"
|
"tree": "magic_elements"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "XnUQYa_bHhFCzs-jig2Qb1PB",
|
"id": "XnUQYa_bHhFCzs-jig2Qb1PB",
|
||||||
|
|
@ -7626,7 +7633,7 @@
|
||||||
{
|
{
|
||||||
"id": "7H5c6ZmKWplUZLOvgg-z8-SB",
|
"id": "7H5c6ZmKWplUZLOvgg-z8-SB",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Magie (Puissance)"
|
"tree": "magic_power"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "EWi.ZCAfiKOHXW~xOnEz4E.I",
|
"id": "EWi.ZCAfiKOHXW~xOnEz4E.I",
|
||||||
|
|
@ -9934,7 +9941,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "oKABKwwIi5YK0CQ67~fu2VBB",
|
"id": "oKABKwwIi5YK0CQ67~fu2VBB",
|
||||||
"tree": "Magie (Rapidité)"
|
"tree": "magic_speed"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Rapidité)"
|
"text": "Magie (Rapidité)"
|
||||||
|
|
@ -9944,7 +9951,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "U-.yGz~-dQ_y4Ox~UcWLQeF7",
|
"id": "U-.yGz~-dQ_y4Ox~UcWLQeF7",
|
||||||
"tree": "Magie (Élements)"
|
"tree": "magic_elements"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Elements)"
|
"text": "Magie (Elements)"
|
||||||
|
|
@ -9954,7 +9961,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "6ZtTRHoNLzQS8ch0Wm9d9Nd2",
|
"id": "6ZtTRHoNLzQS8ch0Wm9d9Nd2",
|
||||||
"tree": "Magie (Puissance)"
|
"tree": "magic_power"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Puissance)"
|
"text": "Magie (Puissance)"
|
||||||
|
|
@ -9964,7 +9971,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": ".sO20lheuROha6h3Z-uiN9VK",
|
"id": ".sO20lheuROha6h3Z-uiN9VK",
|
||||||
"tree": "Magie (Instinct)"
|
"tree": "magic_instinct"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Instinct)"
|
"text": "Magie (Instinct)"
|
||||||
|
|
@ -10139,7 +10146,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "q.e.XKvHP~TPcJ.SmXbh1mFI",
|
"id": "q.e.XKvHP~TPcJ.SmXbh1mFI",
|
||||||
"tree": "Magie (Rapidité)"
|
"tree": "magic_speed"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Rapidité)"
|
"text": "Magie (Rapidité)"
|
||||||
|
|
@ -10149,7 +10156,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "YqykU8-_b646WG6FXCqhT~lo",
|
"id": "YqykU8-_b646WG6FXCqhT~lo",
|
||||||
"tree": "Magie (Élements)"
|
"tree": "magic_elements"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Elements)"
|
"text": "Magie (Elements)"
|
||||||
|
|
@ -10159,7 +10166,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "2aKy7p5C9gARXdpw.Q0yUigb",
|
"id": "2aKy7p5C9gARXdpw.Q0yUigb",
|
||||||
"tree": "Magie (Puissance)"
|
"tree": "magic_power"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Puissance)"
|
"text": "Magie (Puissance)"
|
||||||
|
|
@ -10169,7 +10176,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "z0WdFVj_p.~fXn9MX-vzOJlz",
|
"id": "z0WdFVj_p.~fXn9MX-vzOJlz",
|
||||||
"tree": "Magie (Instinct)"
|
"tree": "magic_instinct"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Instinct)"
|
"text": "Magie (Instinct)"
|
||||||
|
|
@ -10316,7 +10323,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "LpFHjh0.5aQCdiHJhbqQyHql",
|
"id": "LpFHjh0.5aQCdiHJhbqQyHql",
|
||||||
"tree": "Magie (Rapidité)"
|
"tree": "magic_speed"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Rapidité)"
|
"text": "Magie (Rapidité)"
|
||||||
|
|
@ -10326,7 +10333,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "dTr6toyWXfHaOmCQ-jVC5aR6",
|
"id": "dTr6toyWXfHaOmCQ-jVC5aR6",
|
||||||
"tree": "Magie (Élements)"
|
"tree": "magic_elements"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Elements)"
|
"text": "Magie (Elements)"
|
||||||
|
|
@ -10336,7 +10343,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "zoMsbEBlKi~-sE3FF_HJZG~h",
|
"id": "zoMsbEBlKi~-sE3FF_HJZG~h",
|
||||||
"tree": "Magie (Puissance)"
|
"tree": "magic_power"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Puissance)"
|
"text": "Magie (Puissance)"
|
||||||
|
|
@ -10346,7 +10353,7 @@
|
||||||
{
|
{
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"id": "utjjORBYquyxObvO0NusOU3I",
|
"id": "utjjORBYquyxObvO0NusOU3I",
|
||||||
"tree": "Magie (Instinct)"
|
"tree": "magic_instinct"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"text": "Magie (Instinct)"
|
"text": "Magie (Instinct)"
|
||||||
|
|
@ -11867,7 +11874,7 @@
|
||||||
{
|
{
|
||||||
"id": "PMe0K5J-08rVFV97xlt_9jc.",
|
"id": "PMe0K5J-08rVFV97xlt_9jc.",
|
||||||
"category": "tree",
|
"category": "tree",
|
||||||
"tree": "Armures"
|
"tree": "armor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "aXuZp3-NvumkAd5pkfxQA7ZJ",
|
"id": "aXuZp3-NvumkAd5pkfxQA7ZJ",
|
||||||
|
|
@ -11887,7 +11894,7 @@
|
||||||
"category": "value",
|
"category": "value",
|
||||||
"property": "capacity",
|
"property": "capacity",
|
||||||
"operation": "add",
|
"operation": "add",
|
||||||
"value": 5
|
"value": 7
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "jPeOIVxE~uL5pH14moZPKXDV",
|
"id": "jPeOIVxE~uL5pH14moZPKXDV",
|
||||||
|
|
@ -11907,7 +11914,7 @@
|
||||||
"category": "value",
|
"category": "value",
|
||||||
"property": "capacity",
|
"property": "capacity",
|
||||||
"operation": "add",
|
"operation": "add",
|
||||||
"value": 8
|
"value": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "jbZn~Zxqa_EMZ7-956OIZJ0N",
|
"id": "jbZn~Zxqa_EMZ7-956OIZJ0N",
|
||||||
|
|
@ -12090,6 +12097,13 @@
|
||||||
"action": "add",
|
"action": "add",
|
||||||
"list": "mastery",
|
"list": "mastery",
|
||||||
"item": "weapon/throw"
|
"item": "weapon/throw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "23oCnqr3NWxbf-bGMi2sWGqB",
|
||||||
|
"category": "value",
|
||||||
|
"property": "capacity",
|
||||||
|
"operation": "add",
|
||||||
|
"value": 4
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -12116,7 +12130,7 @@
|
||||||
"category": "value",
|
"category": "value",
|
||||||
"property": "capacity",
|
"property": "capacity",
|
||||||
"operation": "add",
|
"operation": "add",
|
||||||
"value": 4
|
"value": 5
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -12136,7 +12150,7 @@
|
||||||
"category": "value",
|
"category": "value",
|
||||||
"property": "capacity",
|
"property": "capacity",
|
||||||
"operation": "add",
|
"operation": "add",
|
||||||
"value": 4
|
"value": 6
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -12196,7 +12210,7 @@
|
||||||
"category": "value",
|
"category": "value",
|
||||||
"property": "capacity",
|
"property": "capacity",
|
||||||
"operation": "add",
|
"operation": "add",
|
||||||
"value": 5
|
"value": 6
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -13067,7 +13081,7 @@
|
||||||
"id": "ii6ibd_UBB4WNwROEKuZ2DsU",
|
"id": "ii6ibd_UBB4WNwROEKuZ2DsU",
|
||||||
"category": "value",
|
"category": "value",
|
||||||
"operation": "add",
|
"operation": "add",
|
||||||
"property": "attack",
|
"property": "item/attack",
|
||||||
"value": 2
|
"value": 2
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -13083,7 +13097,7 @@
|
||||||
"trees": {
|
"trees": {
|
||||||
"multiattack": {
|
"multiattack": {
|
||||||
"name": "Attaques multiples",
|
"name": "Attaques multiples",
|
||||||
"starts": "jkCWvHUXfcunAqObBMxG33LG",
|
"start": "jkCWvHUXfcunAqObBMxG33LG",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"jkCWvHUXfcunAqObBMxG33LG": {
|
"jkCWvHUXfcunAqObBMxG33LG": {
|
||||||
"id": "jkCWvHUXfcunAqObBMxG33LG",
|
"id": "jkCWvHUXfcunAqObBMxG33LG",
|
||||||
|
|
@ -13091,10 +13105,10 @@
|
||||||
},
|
},
|
||||||
".8XF~eY-V2Uw9.r-0FUqXI_v": {
|
".8XF~eY-V2Uw9.r-0FUqXI_v": {
|
||||||
"id": ".8XF~eY-V2Uw9.r-0FUqXI_v",
|
"id": ".8XF~eY-V2Uw9.r-0FUqXI_v",
|
||||||
"to": [
|
"to": {
|
||||||
"ge2eIqWU_QJG5eRBtcGmJkJF",
|
"weapon": "ge2eIqWU_QJG5eRBtcGmJkJF",
|
||||||
"8S59gbI3SlI_OnpX4xYCgOTR"
|
"natural": "8S59gbI3SlI_OnpX4xYCgOTR"
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"ge2eIqWU_QJG5eRBtcGmJkJF": {
|
"ge2eIqWU_QJG5eRBtcGmJkJF": {
|
||||||
"id": "ge2eIqWU_QJG5eRBtcGmJkJF",
|
"id": "ge2eIqWU_QJG5eRBtcGmJkJF",
|
||||||
|
|
@ -13106,10 +13120,10 @@
|
||||||
},
|
},
|
||||||
"8rJMdRfzlEZK~0Swy4lVBRCy": {
|
"8rJMdRfzlEZK~0Swy4lVBRCy": {
|
||||||
"id": "8rJMdRfzlEZK~0Swy4lVBRCy",
|
"id": "8rJMdRfzlEZK~0Swy4lVBRCy",
|
||||||
"to": [
|
"to": {
|
||||||
"9IjVXfs.Wn2hUO7MO-opqTv3",
|
"heavy": "9IjVXfs.Wn2hUO7MO-opqTv3",
|
||||||
".5jZ4i7PCjjMU~2cEJ_shA9A"
|
"standard": ".5jZ4i7PCjjMU~2cEJ_shA9A"
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"PSADBNT7X4X9iLp0yUebsKw7": {
|
"PSADBNT7X4X9iLp0yUebsKw7": {
|
||||||
"id": "PSADBNT7X4X9iLp0yUebsKw7"
|
"id": "PSADBNT7X4X9iLp0yUebsKw7"
|
||||||
|
|
@ -13124,7 +13138,7 @@
|
||||||
},
|
},
|
||||||
"armor": {
|
"armor": {
|
||||||
"name": "Armures",
|
"name": "Armures",
|
||||||
"starts": "EB6wYkE9UrY0cwDnC3dTkHgT",
|
"start": "EB6wYkE9UrY0cwDnC3dTkHgT",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"EB6wYkE9UrY0cwDnC3dTkHgT": {
|
"EB6wYkE9UrY0cwDnC3dTkHgT": {
|
||||||
"id": "EB6wYkE9UrY0cwDnC3dTkHgT",
|
"id": "EB6wYkE9UrY0cwDnC3dTkHgT",
|
||||||
|
|
@ -13139,26 +13153,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shield": {
|
|
||||||
"name": "Bouclier",
|
|
||||||
"starts": "896hiPc4jc8j95t8bcyyF7FL",
|
|
||||||
"nodes": {
|
|
||||||
"896hiPc4jc8j95t8bcyyF7FL": {
|
|
||||||
"id": "896hiPc4jc8j95t8bcyyF7FL"
|
|
||||||
},
|
|
||||||
"tlNKlSb296hvhubMzPh5k8NR": {
|
|
||||||
"id": "tlNKlSb296hvhubMzPh5k8NR",
|
|
||||||
"flags": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"weapon": {
|
"weapon": {
|
||||||
"name": "Armes",
|
"name": "Armes",
|
||||||
"starts": "Gfez7sWYRZ4VY4piDWW-RopA",
|
"start": "Gfez7sWYRZ4VY4piDWW-RopA",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"Gfez7sWYRZ4VY4piDWW-RopA": {
|
"Gfez7sWYRZ4VY4piDWW-RopA": {
|
||||||
"id": "Gfez7sWYRZ4VY4piDWW-RopA",
|
"id": "Gfez7sWYRZ4VY4piDWW-RopA",
|
||||||
"to": "1UGGF5Q-rupsYtMVF2VYzn5~"
|
"to": {
|
||||||
|
"": "1UGGF5Q-rupsYtMVF2VYzn5~",
|
||||||
|
"shield": "896hiPc4jc8j95t8bcyyF7FL"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"1UGGF5Q-rupsYtMVF2VYzn5~": {
|
"1UGGF5Q-rupsYtMVF2VYzn5~": {
|
||||||
"id": "1UGGF5Q-rupsYtMVF2VYzn5~",
|
"id": "1UGGF5Q-rupsYtMVF2VYzn5~",
|
||||||
|
|
@ -13183,19 +13187,28 @@
|
||||||
},
|
},
|
||||||
"jfiEWy9Vi7e_Id.iRrb9-AXa": {
|
"jfiEWy9Vi7e_Id.iRrb9-AXa": {
|
||||||
"id": "jfiEWy9Vi7e_Id.iRrb9-AXa",
|
"id": "jfiEWy9Vi7e_Id.iRrb9-AXa",
|
||||||
"flags": 1
|
"flags": 2
|
||||||
},
|
},
|
||||||
"R3e.waj.fT6Lcbpgg0IOw41W": {
|
"R3e.waj.fT6Lcbpgg0IOw41W": {
|
||||||
"id": "R3e.waj.fT6Lcbpgg0IOw41W"
|
"id": "R3e.waj.fT6Lcbpgg0IOw41W",
|
||||||
|
"to": "tlNKlSb296hvhubMzPh5k8NR"
|
||||||
},
|
},
|
||||||
"y7TB0Z2jcFgPbr8rW6QyaH7z": {
|
"y7TB0Z2jcFgPbr8rW6QyaH7z": {
|
||||||
"id": "y7TB0Z2jcFgPbr8rW6QyaH7z"
|
"id": "y7TB0Z2jcFgPbr8rW6QyaH7z",
|
||||||
|
"to": "tlNKlSb296hvhubMzPh5k8NR"
|
||||||
|
},
|
||||||
|
"896hiPc4jc8j95t8bcyyF7FL": {
|
||||||
|
"id": "896hiPc4jc8j95t8bcyyF7FL",
|
||||||
|
"flags": 4
|
||||||
|
},
|
||||||
|
"tlNKlSb296hvhubMzPh5k8NR": {
|
||||||
|
"id": "tlNKlSb296hvhubMzPh5k8NR"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"magic_instinct": {
|
"magic_instinct": {
|
||||||
"name": "Magie (Instinct)",
|
"name": "Magie (Instinct)",
|
||||||
"starts": "dOB1yNB3JKZ7uQWe88TezQAC",
|
"start": "dOB1yNB3JKZ7uQWe88TezQAC",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"dOB1yNB3JKZ7uQWe88TezQAC": {
|
"dOB1yNB3JKZ7uQWe88TezQAC": {
|
||||||
"id": "dOB1yNB3JKZ7uQWe88TezQAC",
|
"id": "dOB1yNB3JKZ7uQWe88TezQAC",
|
||||||
|
|
@ -13218,7 +13231,7 @@
|
||||||
},
|
},
|
||||||
"magic_speed": {
|
"magic_speed": {
|
||||||
"name": "Magie (Rapidité)",
|
"name": "Magie (Rapidité)",
|
||||||
"starts": "GNDBexNnuFuzLMoLbV-RuG5g",
|
"start": "GNDBexNnuFuzLMoLbV-RuG5g",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"GNDBexNnuFuzLMoLbV-RuG5g": {
|
"GNDBexNnuFuzLMoLbV-RuG5g": {
|
||||||
"id": "GNDBexNnuFuzLMoLbV-RuG5g",
|
"id": "GNDBexNnuFuzLMoLbV-RuG5g",
|
||||||
|
|
@ -13241,7 +13254,7 @@
|
||||||
},
|
},
|
||||||
"magic_power": {
|
"magic_power": {
|
||||||
"name": "Magie (Puissance)",
|
"name": "Magie (Puissance)",
|
||||||
"starts": "HDYn3D21~oauYy9haENxjjX5",
|
"start": "HDYn3D21~oauYy9haENxjjX5",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"HDYn3D21~oauYy9haENxjjX5": {
|
"HDYn3D21~oauYy9haENxjjX5": {
|
||||||
"id": "HDYn3D21~oauYy9haENxjjX5",
|
"id": "HDYn3D21~oauYy9haENxjjX5",
|
||||||
|
|
@ -13264,7 +13277,7 @@
|
||||||
},
|
},
|
||||||
"magic_elements": {
|
"magic_elements": {
|
||||||
"name": "Magie (Élements)",
|
"name": "Magie (Élements)",
|
||||||
"starts": "646baK3niCwFOKQy.hGiUcv-",
|
"start": "646baK3niCwFOKQy.hGiUcv-",
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"646baK3niCwFOKQy.hGiUcv-": {
|
"646baK3niCwFOKQy.hGiUcv-": {
|
||||||
"id": "646baK3niCwFOKQy.hGiUcv-",
|
"id": "646baK3niCwFOKQy.hGiUcv-",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Ability, Alignment, ArmorConfig, ArmorState, Character, CharacterConfig, CompiledCharacter, DamageType, EnchantementConfig, FeatureEquipment, FeatureID, FeatureItem, ItemConfig, ItemState, Level, MainStat, MundaneState, Resistance, SpellConfig, SpellElement, SpellType, TrainingLevel, WeaponConfig, WeaponState, WeaponType, WondrousState } from "~/types/character";
|
import type { Ability, Alignment, ArmorConfig, ArmorState, Character, CharacterConfig, CompiledCharacter, DamageType, EnchantementConfig, FeatureEquipment, FeatureID, FeatureItem, FeatureList, FeatureValue, ItemConfig, ItemState, Level, MainStat, MundaneState, Resistance, SpellConfig, SpellElement, SpellType, TrainingLevel, TreeStructure, WeaponConfig, WeaponState, WeaponType, WondrousState } from "~/types/character";
|
||||||
import { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
import characterConfig from '#shared/character-config.json';
|
import characterConfig from '#shared/character-config.json';
|
||||||
import proses, { preview } from "#shared/proses";
|
import proses, { preview } from "#shared/proses";
|
||||||
|
|
@ -127,6 +127,7 @@ const defaultCompiledCharacter = (character: Character) => ({
|
||||||
reaction: [],
|
reaction: [],
|
||||||
passive: [],
|
passive: [],
|
||||||
spells: [],
|
spells: [],
|
||||||
|
sickness: [],
|
||||||
},
|
},
|
||||||
aspect: {
|
aspect: {
|
||||||
id: character.aspect ?? "",
|
id: character.aspect ?? "",
|
||||||
|
|
@ -279,6 +280,7 @@ export const CharacterValidation = z.object({
|
||||||
|
|
||||||
type Property = { value: number | string | false, id: string, operation: "set" | "add" | "min" };
|
type Property = { value: number | string | false, id: string, operation: "set" | "add" | "min" };
|
||||||
export type PropertySum = { list: Array<Property>, min: number, value: number, _dirty: boolean };
|
export type PropertySum = { list: Array<Property>, min: number, value: number, _dirty: boolean };
|
||||||
|
type TreeState = { progression: Array<{ id: string, priority: number, path?: string }>, validated: string[], _dirty: boolean };
|
||||||
export class CharacterCompiler
|
export class CharacterCompiler
|
||||||
{
|
{
|
||||||
private _dirty: boolean = true;
|
private _dirty: boolean = true;
|
||||||
|
|
@ -294,6 +296,7 @@ export class CharacterCompiler
|
||||||
'modifier/charisma': { value: 0, _dirty: false, min: -Infinity, list: [] },
|
'modifier/charisma': { value: 0, _dirty: false, min: -Infinity, list: [] },
|
||||||
'modifier/psyche': { value: 0, _dirty: false, min: -Infinity, list: [] },
|
'modifier/psyche': { value: 0, _dirty: false, min: -Infinity, list: [] },
|
||||||
};
|
};
|
||||||
|
protected _trees: Record<string, TreeState> = {};
|
||||||
private _variableDebounce: NodeJS.Timeout = setTimeout(() => {});
|
private _variableDebounce: NodeJS.Timeout = setTimeout(() => {});
|
||||||
|
|
||||||
constructor(character: Character)
|
constructor(character: Character)
|
||||||
|
|
@ -325,7 +328,6 @@ export class CharacterCompiler
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(value.abilities).forEach(e => this._buffer[`abilities/${e[0]}`] = { value: 0, _dirty: true, min: -Infinity, list: [{ id: '', operation: 'add', value: e[1] }] })
|
Object.entries(value.abilities).forEach(e => this._buffer[`abilities/${e[0]}`] = { value: 0, _dirty: true, min: -Infinity, list: [{ id: '', operation: 'add', value: e[1] }] })
|
||||||
//Object.entries(value.abilities).forEach(e => this._result.abilities[e[0] as Ability] = e[1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get character(): Character
|
get character(): Character
|
||||||
|
|
@ -334,21 +336,49 @@ export class CharacterCompiler
|
||||||
}
|
}
|
||||||
get compiled(): CompiledCharacter
|
get compiled(): CompiledCharacter
|
||||||
{
|
{
|
||||||
Object.entries(this._character.abilities).forEach(e => this._result.abilities[e[0] as Ability] = e[1]);
|
if(this._dirty)
|
||||||
this._dirty && this.compile(Object.keys(this._buffer));
|
{
|
||||||
this._dirty = false;
|
Object.keys(this._trees).forEach(tree => {
|
||||||
|
if(!this._trees[tree]!._dirty || !config.trees[tree])
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._trees[tree]!.progression.sort((a, b) => a.priority - b.priority);
|
||||||
|
const validated = validateTree(config.trees[tree]!, this._trees[tree]!.progression);
|
||||||
|
|
||||||
|
this._trees[tree]!.validated.forEach(this.add, this);
|
||||||
|
validated.forEach(this.add, this);
|
||||||
|
|
||||||
|
this._trees[tree]!.validated = validated;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.compile(Object.keys(this._buffer));
|
||||||
|
this._dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
return this._result;
|
return this._result;
|
||||||
}
|
}
|
||||||
get values(): Record<string, number>
|
get values(): Record<string, number>
|
||||||
{
|
{
|
||||||
Object.entries(this._character.abilities).forEach(e => this._result.abilities[e[0] as Ability] = e[1]);
|
if(this._dirty)
|
||||||
|
{
|
||||||
|
Object.keys(this._trees).forEach(tree => {
|
||||||
|
if(!this._trees[tree]!._dirty || !config.trees[tree])
|
||||||
|
return;
|
||||||
|
|
||||||
const keys = Object.keys(this._buffer);
|
this._trees[tree]!.progression.sort((a, b) => a.priority - b.priority);
|
||||||
this._dirty && this.compile(keys);
|
const validated = validateTree(config.trees[tree]!, this._trees[tree]!.progression);
|
||||||
this._dirty = false;
|
|
||||||
|
|
||||||
return keys.reduce((p, v) => {
|
this._trees[tree]!.validated.forEach(this.add, this);
|
||||||
|
validated.forEach(this.add, this);
|
||||||
|
|
||||||
|
this._trees[tree]!.validated = validated;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.compile(Object.keys(this._buffer));
|
||||||
|
this._dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(this._buffer).reduce((p, v) => {
|
||||||
p[v] = this._buffer[v]!.value;
|
p[v] = this._buffer[v]!.value;
|
||||||
return p;
|
return p;
|
||||||
}, {} as Record<string, number>);
|
}, {} as Record<string, number>);
|
||||||
|
|
@ -367,6 +397,29 @@ export class CharacterCompiler
|
||||||
return this._character.variables.items.filter(e => config.items[e.id]?.equippable && e.equipped).reduce((p, v) => p + ((config.items[v.id]?.powercost ?? 0) + (v.enchantments?.reduce((_p, _v) => (config.enchantments[_v]?.power ?? 0) + _p, 0) ?? 0) * v.amount), 0);
|
return this._character.variables.items.filter(e => config.items[e.id]?.equippable && e.equipped).reduce((p, v) => p + ((config.items[v.id]?.powercost ?? 0) + (v.enchantments?.reduce((_p, _v) => (config.enchantments[_v]?.power ?? 0) + _p, 0) ?? 0) * v.amount), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enchant(item: ItemState)
|
||||||
|
{
|
||||||
|
if(item.equipped)
|
||||||
|
item.enchantments?.forEach(e => config.enchantments[e]?.effect.filter(e => e.category !== 'value' || !e.property.startsWith('item')).forEach(_e => this.apply(_e as FeatureValue | FeatureList)));
|
||||||
|
else
|
||||||
|
item.enchantments?.forEach(e => config.enchantments[e]?.effect.filter(e => e.category !== 'value' || !e.property.startsWith('item')).forEach(_e => this.undo(_e as FeatureValue | FeatureList)));
|
||||||
|
|
||||||
|
item.buffer ??= {} as Record<string, PropertySum>;
|
||||||
|
Object.keys(item.buffer).forEach(e => item.buffer![e]!.list = []);
|
||||||
|
item.enchantments?.forEach(e => (config.enchantments[e]?.effect.filter(e => e.category === 'value' && e.property.startsWith('item')) as FeatureEquipment[]).forEach(feature => {
|
||||||
|
const property = feature.property.substring(5);
|
||||||
|
item.buffer![property] ??= { list: [], value: 0, _dirty: true, min: -Infinity };
|
||||||
|
|
||||||
|
item.buffer![property]!.list.push({ operation: feature.operation, id: feature.id, value: feature.value });
|
||||||
|
|
||||||
|
item.buffer![property]!.min = -Infinity;
|
||||||
|
item.buffer![property]!._dirty = true;
|
||||||
|
}));
|
||||||
|
Object.keys(item.buffer).forEach(e => setProperty(item.state, e, 0, true));
|
||||||
|
this.compile(Object.keys(item.buffer), item.buffer, item.state);
|
||||||
|
|
||||||
|
this.saveVariables();
|
||||||
|
}
|
||||||
saveVariables()
|
saveVariables()
|
||||||
{
|
{
|
||||||
clearTimeout(this._variableDebounce);
|
clearTimeout(this._variableDebounce);
|
||||||
|
|
@ -411,10 +464,10 @@ export class CharacterCompiler
|
||||||
switch(feature.category)
|
switch(feature.category)
|
||||||
{
|
{
|
||||||
case "list":
|
case "list":
|
||||||
if(feature.action === 'add' && !this._result.lists[feature.list]!.includes(feature.item))
|
if(feature.action === 'add' && !(feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).includes(feature.item))
|
||||||
this._result.lists[feature.list]!.push(feature.item);
|
(feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).push(feature.item);
|
||||||
else if(feature.action === 'remove')
|
else if(feature.action === 'remove')
|
||||||
this._result.lists[feature.list]!.splice(this._result.lists[feature.list]!.findIndex((e: string) => e === feature.item), 1);
|
(feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).splice((feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).findIndex((e: string) => e === feature.item), 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case "value":
|
case "value":
|
||||||
|
|
@ -435,6 +488,15 @@ export class CharacterCompiler
|
||||||
if(choice)
|
if(choice)
|
||||||
choice.forEach(e => feature.options[e]!.effects.forEach((effect) => this.apply(effect)));
|
choice.forEach(e => feature.options[e]!.effects.forEach((effect) => this.apply(effect)));
|
||||||
|
|
||||||
|
return;
|
||||||
|
case "tree":
|
||||||
|
if(!config.trees[feature.tree])
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._trees[feature.tree] ??= { progression: [], validated: [], _dirty: true };
|
||||||
|
this._trees[feature.tree]!.progression.push({ id: feature.id, priority: feature.priority ?? 1, path: feature.option });
|
||||||
|
|
||||||
|
this._trees[feature.tree]!._dirty = true;
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
|
@ -449,17 +511,17 @@ export class CharacterCompiler
|
||||||
switch(feature.category)
|
switch(feature.category)
|
||||||
{
|
{
|
||||||
case "list":
|
case "list":
|
||||||
if(feature.action === 'remove' && !this._result.lists[feature.list]!.includes(feature.item))
|
if(feature.action === 'remove' && !(feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).includes(feature.item))
|
||||||
this._result.lists[feature.list]!.push(feature.item);
|
(feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).push(feature.item);
|
||||||
else if(feature.action === 'add')
|
else if(feature.action === 'add')
|
||||||
this._result.lists[feature.list]!.splice(this._result.lists[feature.list]!.findIndex((e: string) => e === feature.item), 1)
|
(feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).splice((feature.list === 'mastery' ? this._result.mastery : this._result.lists[feature.list]!).findIndex((e: string) => e === feature.item), 1)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case "value":
|
case "value":
|
||||||
this._buffer[feature.property] ??= { list: [], value: 0, _dirty: true, min: -Infinity };
|
this._buffer[feature.property] ??= { list: [], value: 0, _dirty: true, min: -Infinity };
|
||||||
|
|
||||||
const idx = this._buffer[feature.property]!.list.findIndex(e => e.id === feature.id);
|
const listIdx = this._buffer[feature.property]!.list.findIndex(e => e.id === feature.id);
|
||||||
idx !== -1 && this._buffer[feature.property]!.list.splice(idx, 1);
|
listIdx !== -1 && this._buffer[feature.property]!.list.splice(listIdx, 1);
|
||||||
|
|
||||||
this._buffer[feature.property]!.min = -Infinity;
|
this._buffer[feature.property]!.min = -Infinity;
|
||||||
this._buffer[feature.property]!._dirty = true;
|
this._buffer[feature.property]!._dirty = true;
|
||||||
|
|
@ -474,19 +536,27 @@ export class CharacterCompiler
|
||||||
if(choice)
|
if(choice)
|
||||||
choice.forEach(e => feature.options[e]!.effects.forEach((effect) => this.undo(effect)));
|
choice.forEach(e => feature.options[e]!.effects.forEach((effect) => this.undo(effect)));
|
||||||
|
|
||||||
|
return;
|
||||||
|
case "tree":
|
||||||
|
if(!config.trees[feature.tree] || !this._trees[feature.tree])
|
||||||
|
return;
|
||||||
|
|
||||||
|
const treeIdx = this._trees[feature.tree]!.progression.findIndex(e => e.id === feature.id);
|
||||||
|
treeIdx !== -1 && this._trees[feature.tree]!.progression.splice(treeIdx, 1);
|
||||||
|
this._trees[feature.tree]!._dirty = true;
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected compile(queue: string[])
|
protected compile(queue: string[], _buffer: Record<string, PropertySum> = this._buffer, _result: Record<string, any> = this._result)
|
||||||
{
|
{
|
||||||
for(let i = 0; i < queue.length; i++)
|
for(let i = 0; i < queue.length; i++)
|
||||||
{
|
{
|
||||||
if(queue[i] === undefined || queue[i] === "") continue;
|
if(queue[i] === undefined || queue[i] === "") continue;
|
||||||
|
|
||||||
const property = queue[i]!;
|
const property = queue[i]!;
|
||||||
const buffer = this._buffer[property];
|
const buffer = _buffer[property];
|
||||||
|
|
||||||
if(buffer && buffer._dirty === true)
|
if(buffer && buffer._dirty === true)
|
||||||
{
|
{
|
||||||
|
|
@ -499,7 +569,7 @@ export class CharacterCompiler
|
||||||
|
|
||||||
if(typeof item.value === 'string') // Add or set a modifier
|
if(typeof item.value === 'string') // Add or set a modifier
|
||||||
{
|
{
|
||||||
const modifier = this._buffer[item.value as string]!;
|
const modifier = _buffer[item.value as string]!;
|
||||||
if(modifier._dirty)
|
if(modifier._dirty)
|
||||||
{
|
{
|
||||||
//Put it back in queue since its dependencies haven't been resolved yet
|
//Put it back in queue since its dependencies haven't been resolved yet
|
||||||
|
|
@ -533,20 +603,100 @@ export class CharacterCompiler
|
||||||
if(stop === true)
|
if(stop === true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
setProperty(this._result, property, Math.max(sum, this._buffer[property]!.min));
|
setProperty(_result, property, Math.max(sum, _buffer[property]!.min));
|
||||||
|
|
||||||
this._buffer[property]!.value = Math.max(sum, this._buffer[property]!.min);
|
_buffer[property]!.value = Math.max(sum, _buffer[property]!.min);
|
||||||
this._buffer[property]!._dirty = false;
|
_buffer[property]!._dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function setProperty<T>(root: any, path: string, value: T | ((old: T) => T))
|
export enum TreeFlag {
|
||||||
|
REPEATING = 1 << 0,
|
||||||
|
MULTIPLE = 1 << 1,
|
||||||
|
HIDDEN = 1 << 2,
|
||||||
|
};
|
||||||
|
function validateTree(structure: TreeStructure, progression: Array<{ path?: string }>): string[]
|
||||||
|
{
|
||||||
|
const validated = [] as string[];
|
||||||
|
const paths = new Map<string | undefined, string>(), multiples: Record<string, string[]> = {};
|
||||||
|
|
||||||
|
const hasFlag = (node: string, flag: number) => structure.nodes[node] && structure.nodes[node].flags && (structure.nodes[node].flags & flag) === flag;
|
||||||
|
const addRequirement = (target: string, requirement: string) => { multiples[target] ??= []; multiples[target].push(requirement) };
|
||||||
|
|
||||||
|
//Precompute the requirements for the nodes with multiples inputs
|
||||||
|
Object.values(structure.nodes).forEach(node => {
|
||||||
|
if(Array.isArray(node.to))
|
||||||
|
node.to.forEach(to => { if(hasFlag(to, TreeFlag.MULTIPLE)) addRequirement(to, node.id) });
|
||||||
|
else if(typeof node.to === 'object')
|
||||||
|
Object.values(node.to).forEach(to => { if(hasFlag(to, TreeFlag.MULTIPLE)) addRequirement(to, node.id) });
|
||||||
|
else if(node.to)
|
||||||
|
if(hasFlag(node.to, TreeFlag.MULTIPLE)) addRequirement(node.to, node.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
const nextPath = (path: string | undefined, node: string): boolean => {
|
||||||
|
if(!structure.nodes[node])
|
||||||
|
return false;
|
||||||
|
else if(hasFlag(node, TreeFlag.MULTIPLE))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paths.set(path, node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(Array.isArray(structure.start))
|
||||||
|
structure.start.some(e => nextPath(undefined, e));
|
||||||
|
else if(typeof structure.start === 'object')
|
||||||
|
Object.keys(structure.start).forEach(e => nextPath(e === "" ? undefined: e, (structure.start as Record<string, string>)[e]!));
|
||||||
|
else if(structure.start)
|
||||||
|
nextPath(undefined, structure.start);
|
||||||
|
|
||||||
|
for(let i = 0; progression[i] && i < progression.length; i++)
|
||||||
|
{
|
||||||
|
const progress = progression[i];
|
||||||
|
let path: string | undefined, valid = false;
|
||||||
|
if(paths.has(progress?.path))
|
||||||
|
path = progress?.path;
|
||||||
|
else
|
||||||
|
path = undefined;
|
||||||
|
|
||||||
|
const next = paths.get(path);
|
||||||
|
if(!next || !structure.nodes[next])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const node = structure.nodes[next];
|
||||||
|
Object.keys(multiples).forEach(e => {
|
||||||
|
multiples[e] = multiples[e]!.filter(node => node !== next);
|
||||||
|
if(multiples[e].length === 0)
|
||||||
|
{
|
||||||
|
validated.push(e);
|
||||||
|
delete multiples[e];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
validated.push(next);
|
||||||
|
paths.delete(path);
|
||||||
|
|
||||||
|
if(hasFlag(next, TreeFlag.REPEATING))
|
||||||
|
paths.set(path, next);
|
||||||
|
else if(Array.isArray(node.to))
|
||||||
|
node.to.some(e => nextPath(path, e));
|
||||||
|
else if(typeof node.to === 'object')
|
||||||
|
Object.keys(node.to).forEach(e => nextPath(e === "" ? undefined: e, (node.to as Record<string, string>)[e]!));
|
||||||
|
else if(node.to)
|
||||||
|
nextPath(path, node.to);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validated;
|
||||||
|
}
|
||||||
|
function setProperty<T>(root: any, path: string, value: T | ((old: T) => T), force: boolean = false)
|
||||||
{
|
{
|
||||||
const arr = path.split("/"); //Get the property path as an array
|
const arr = path.split("/"); //Get the property path as an array
|
||||||
const object = arr.length === 1 ? root : arr.slice(0, -1).reduce((p, v) => { p[v] ??= {}; return p[v]; }, root); //Get into the second to last property using the property path
|
const object = arr.length === 1 ? root : arr.slice(0, -1).reduce((p, v) => { p[v] ??= {}; return p[v]; }, root); //Get into the second to last property using the property path
|
||||||
|
|
||||||
if(object.hasOwnProperty(arr.slice(-1)[0]!))
|
if(force || object.hasOwnProperty(arr.slice(-1)[0]!))
|
||||||
object[arr.slice(-1)[0]!] = typeof value === 'function' ? (value as (old: T) => T)(object[arr.slice(-1)[0]!]) : value;
|
object[arr.slice(-1)[0]!] = typeof value === 'function' ? (value as (old: T) => T)(object[arr.slice(-1)[0]!]) : value;
|
||||||
}
|
}
|
||||||
export class CharacterBuilder extends CharacterCompiler
|
export class CharacterBuilder extends CharacterCompiler
|
||||||
|
|
@ -1469,9 +1619,9 @@ export class CharacterSheet
|
||||||
|
|
||||||
{ id: 'inventory', title: [ text('Inventaire') ], content: this.itemsTab(character) },
|
{ id: 'inventory', title: [ text('Inventaire') ], content: this.itemsTab(character) },
|
||||||
|
|
||||||
{ id: 'aspect', title: [ text('Aspect') ], content: () => [
|
{ id: 'aspect', title: [ text('Aspect') ], content: () => this.aspectTab(character) },
|
||||||
text('TODO'),
|
|
||||||
] },
|
{ id: 'effects', title: [ text('Afflictions') ], content: () => this.effectsTab(character) },
|
||||||
|
|
||||||
{ id: 'notes', title: [ text('Notes') ], content: () => [
|
{ id: 'notes', title: [ text('Notes') ], content: () => [
|
||||||
div('flex flex-col gap-2', [
|
div('flex flex-col gap-2', [
|
||||||
|
|
@ -1479,154 +1629,8 @@ export class CharacterSheet
|
||||||
div('flex flex-col gap-2', [ span('text-lg font-bold', 'Notes privés'), div('border border-light-35 dark:border-dark-35 bg-light20 dark:bg-dark-20 p-1 h-64', [ privateNotes.dom ]) ]),
|
div('flex flex-col gap-2', [ span('text-lg font-bold', 'Notes privés'), div('border border-light-35 dark:border-dark-35 bg-light20 dark:bg-dark-20 p-1 h-64', [ privateNotes.dom ]) ]),
|
||||||
])
|
])
|
||||||
] },
|
] },
|
||||||
|
], { focused: this.tab, class: { container: 'flex-1 gap-4 px-4 max-w-[960px] h-full', content: 'overflow-auto' }, switch: v => { this.tab = v; } });
|
||||||
|
|
||||||
{ id: 'details', title: [ text('Détails') ], content: () => [
|
|
||||||
div('grid grid-cols-3 gap-2', [
|
|
||||||
() => character.health ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Vie'), span('font-semibold', text(() => character.health ?? "")) ]) : undefined,
|
|
||||||
() => character.mana ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Mana'), span('font-semibold', text(() => character.mana ?? "")) ]) : undefined,
|
|
||||||
() => character.spellslots ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Sorts maitrisés'), span('font-semibold', text(() => character.spellslots ?? "")) ]) : undefined,
|
|
||||||
() => character.artslots ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Oeuvres maitrisées'), span('font-semibold', text(() => character.artslots ?? "")) ]) : undefined,
|
|
||||||
() => character.speed ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Vitesse de course'), span('font-semibold', text(() => character.speed === false ? 'Aucun' : character.speed ?? "")) ]) : undefined,
|
|
||||||
() => character.capacity ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Poids supporté'), span('font-semibold', text(() => character.capacity === false ? 'Aucun' : character.capacity ?? "")) ]) : undefined,
|
|
||||||
() => character.initiative ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Initiative'), span('font-semibold', text(() => character.initiative ?? "")) ]) : undefined,
|
|
||||||
() => character.exhaust ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Fatigue max bonus'), span('font-semibold', text(() => character.exhaust ?? "")) ]) : undefined,
|
|
||||||
() => character.itempower ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Puissance magique max'), span('font-semibold', text(() => character.itempower ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.amount ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Nombre de transformation'), span('font-semibold', text(() => character.aspect.amount ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.duration ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Durée de transformation'), span('font-semibold', text(() => character.aspect.duration ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.shift_bonus ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de transformation'), span('font-semibold', text(() => character.aspect.shift_bonus ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.strength ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de force'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.strength ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.dexterity ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de dextérité'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.dexterity ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.constitution ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de constitution'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.constitution ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.intelligence ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance d\'intelligence'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.intelligence ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.curiosity ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de curiosité'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.curiosity ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.charisma ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de charisme'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.charisma ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.defense?.psyche ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de psyché'), span('font-semibold', text(() => character.aspect?.bonus?.defense?.psyche ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.athletics ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Athlétisme'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.athletics ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.acrobatics ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Acrobatisme'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.acrobatics ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.intimidation ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Intimidation'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.intimidation ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.sleightofhand ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Doigté'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.sleightofhand ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.stealth ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Discrétion'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.stealth ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.survival ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Survie'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.survival ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.investigation ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Enquête'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.investigation ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.history ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Histoire'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.history ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.religion ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Religion'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.religion ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.arcana ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Arcanes'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.arcana ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.understanding ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Compréhension'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.understanding ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.perception ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Perception'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.perception ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.performance ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Représentation'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.performance ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.medecine ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Médicine'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.medecine ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.persuasion ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Persuasion'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.persuasion ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.animalhandling ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Dressage'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.animalhandling ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.abilities?.deception ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Mensonge'), span('font-semibold', text(() => character.aspect?.bonus?.abilities?.deception ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.type.instinct ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts d\'instinct'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.type.instinct ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.type.precision ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de précision'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.type.precision ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.type.knowledge ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de savoir'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.type.knowledge ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.type.arts ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux oeuvres'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.type.arts ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.rank[1] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de rang 1'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.rank[1] ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.rank[2] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de rang 2'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.rank[2] ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.rank[3] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de rang 3'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.rank[3] ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.rank[4] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts spéciaux'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.rank[4] ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.fire ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de feu'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.fire ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.ice ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de glace'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.ice ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.thunder ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de foudre'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.thunder ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.earth ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de terre'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.earth ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.arcana ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts d\'arcane'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.arcana ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.air ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts d\'air'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.air ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.nature ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de nature'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.nature ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.light ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de lumière'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.light ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.spells?.elements.psyche ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de psy'), span('font-semibold', text(() => character.aspect?.bonus?.spells?.elements.psyche ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.light ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes légères'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.light ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.shield ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux boucliers'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.shield ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.heavy ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes lourdes'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.heavy ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.classic ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes standard'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.classic ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.throw ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes de jet'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.throw ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.natural ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes naturelles'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.natural ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.twohanded ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes à deux mains'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.twohanded ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.finesse ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes maniables'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.finesse ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.reach ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes longues'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.reach ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.projectile ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes à projectiles'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.projectile ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.weapon?.improvised ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes improvisées'), span('font-semibold', text(() => character.aspect?.bonus?.weapon?.improvised ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.stun ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des hébètements'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.stun ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.bleed ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des saignements'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.bleed ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.poison ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des poisons'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.poison ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.fear ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté de la peur'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.fear ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.influence ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des influences'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.influence ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.charm ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des charmes'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.charm ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.possesion ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des possessions'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.possesion ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.precision ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des sorts de précision'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.precision ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.knowledge ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des sorts de savoir'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.knowledge ?? "")) ]) : undefined,
|
|
||||||
() => character.aspect.bonus?.resistance?.instinct ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des sorts d\'instinct'), span('font-semibold', text(() => character.aspect?.bonus?.resistance?.instinct ?? "")) ]) : undefined,
|
|
||||||
() => character.defense.activeparry ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de parade active'), span('font-semibold', text(() => character.defense.activeparry ?? "")) ]) : undefined,
|
|
||||||
() => character.defense.activedodge ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus d\'esquive active'), span('font-semibold', text(() => character.defense.activedodge ?? "")) ]) : undefined,
|
|
||||||
() => character.defense.passiveparry ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de parade passive'), span('font-semibold', text(() => character.defense.passiveparry ?? "")) ]) : undefined,
|
|
||||||
() => character.defense.passivedodge ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus d\'esquive parade passive'), span('font-semibold', text(() => character.defense.passivedodge ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.strength ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de force'), span('font-semibold', text(() => character.bonus.defense?.strength ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.dexterity ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de dextérité'), span('font-semibold', text(() => character.bonus.defense?.dexterity ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.constitution ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de constitution'), span('font-semibold', text(() => character.bonus.defense?.constitution ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.intelligence ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance d\'intelligence'), span('font-semibold', text(() => character.bonus.defense?.intelligence ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.curiosity ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de curiosité'), span('font-semibold', text(() => character.bonus.defense?.curiosity ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.charisma ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de charisme'), span('font-semibold', text(() => character.bonus.defense?.charisma ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.defense.psyche ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de jet de résistance de psyché'), span('font-semibold', text(() => character.bonus.defense?.psyche ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.athletics ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Athlétisme'), span('font-semibold', text(() => character.bonus.abilities?.athletics ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.acrobatics ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Acrobatisme'), span('font-semibold', text(() => character.bonus.abilities?.acrobatics ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.intimidation ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Intimidation'), span('font-semibold', text(() => character.bonus.abilities?.intimidation ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.sleightofhand ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Doigté'), span('font-semibold', text(() => character.bonus.abilities?.sleightofhand ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.stealth ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Discrétion'), span('font-semibold', text(() => character.bonus.abilities?.stealth ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.survival ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Survie'), span('font-semibold', text(() => character.bonus.abilities?.survival ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.investigation ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Enquête'), span('font-semibold', text(() => character.bonus.abilities?.investigation ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.history ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Histoire'), span('font-semibold', text(() => character.bonus.abilities?.history ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.religion ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Religion'), span('font-semibold', text(() => character.bonus.abilities?.religion ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.arcana ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Arcanes'), span('font-semibold', text(() => character.bonus.abilities?.arcana ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.understanding ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Compréhension'), span('font-semibold', text(() => character.bonus.abilities?.understanding ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.perception ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Perception'), span('font-semibold', text(() => character.bonus.abilities?.perception ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.performance ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Représentation'), span('font-semibold', text(() => character.bonus.abilities?.performance ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.medecine ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Médicine'), span('font-semibold', text(() => character.bonus.abilities?.medecine ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.persuasion ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Persuasion'), span('font-semibold', text(() => character.bonus.abilities?.persuasion ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.animalhandling ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Dressage'), span('font-semibold', text(() => character.bonus.abilities?.animalhandling ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.abilities.deception ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus en Mensonge'), span('font-semibold', text(() => character.bonus.abilities?.deception ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.type.instinct ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts d\'instinct'), span('font-semibold', text(() => character.bonus.spells?.type.instinct ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.type.precision ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de précision'), span('font-semibold', text(() => character.bonus.spells?.type.precision ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.type.knowledge ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de savoir'), span('font-semibold', text(() => character.bonus.spells?.type.knowledge ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.type.arts ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux oeuvres'), span('font-semibold', text(() => character.bonus.spells?.type.arts ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.rank[1] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de rang 1'), span('font-semibold', text(() => character.bonus.spells?.rank[1] ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.rank[2] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de rang 2'), span('font-semibold', text(() => character.bonus.spells?.rank[2] ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.rank[3] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de rang 3'), span('font-semibold', text(() => character.bonus.spells?.rank[3] ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.rank[4] ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts spéciaux'), span('font-semibold', text(() => character.bonus.spells?.rank[4] ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.fire ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de feu'), span('font-semibold', text(() => character.bonus.spells?.elements.fire ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.ice ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de glace'), span('font-semibold', text(() => character.bonus.spells?.elements.ice ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.thunder ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de foudre'), span('font-semibold', text(() => character.bonus.spells?.elements.thunder ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.earth ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de terre'), span('font-semibold', text(() => character.bonus.spells?.elements.earth ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.arcana ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts d\'arcane'), span('font-semibold', text(() => character.bonus.spells?.elements.arcana ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.air ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts d\'air'), span('font-semibold', text(() => character.bonus.spells?.elements.air ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.nature ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de nature'), span('font-semibold', text(() => character.bonus.spells?.elements.nature ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.light ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de lumière'), span('font-semibold', text(() => character.bonus.spells?.elements.light ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.spells.elements.psyche ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux sorts de psy'), span('font-semibold', text(() => character.bonus.spells?.elements.psyche ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.light ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes légères'), span('font-semibold', text(() => character.bonus.weapon?.light ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.shield ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux boucliers'), span('font-semibold', text(() => character.bonus.weapon?.shield ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.heavy ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes lourdes'), span('font-semibold', text(() => character.bonus.weapon?.heavy ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.classic ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes standard'), span('font-semibold', text(() => character.bonus.weapon?.classic ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.throw ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes de jet'), span('font-semibold', text(() => character.bonus.weapon?.throw ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.natural ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes naturelles'), span('font-semibold', text(() => character.bonus.weapon?.natural ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.twohanded ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes à deux mains'), span('font-semibold', text(() => character.bonus.weapon?.twohanded ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.finesse ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes maniables'), span('font-semibold', text(() => character.bonus.weapon?.finesse ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.reach ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes longues'), span('font-semibold', text(() => character.bonus.weapon?.reach ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.projectile ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes à projectiles'), span('font-semibold', text(() => character.bonus.weapon?.projectile ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.weapon.improvised ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus aux armes improvisées'), span('font-semibold', text(() => character.bonus.weapon?.improvised ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.stun ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des hébètements'), span('font-semibold', text(() => character.bonus.resistance?.stun ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.bleed ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des saignements'), span('font-semibold', text(() => character.bonus.resistance?.bleed ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.poison ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des poisons'), span('font-semibold', text(() => character.bonus.resistance?.poison ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.fear ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté de la peur'), span('font-semibold', text(() => character.bonus.resistance?.fear ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.influence ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des influences'), span('font-semibold', text(() => character.bonus.resistance?.influence ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.charm ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des charmes'), span('font-semibold', text(() => character.bonus.resistance?.charm ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.possesion ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des possessions'), span('font-semibold', text(() => character.bonus.resistance?.possesion ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.precision ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des sorts de précision'), span('font-semibold', text(() => character.bonus.resistance?.precision ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.knowledge ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des sorts de savoir'), span('font-semibold', text(() => character.bonus.resistance?.knowledge ?? "")) ]) : undefined,
|
|
||||||
() => character.bonus.resistance.instinct ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de difficulté des sorts d\'instinct'), span('font-semibold', text(() => character.bonus.resistance?.instinct ?? "")) ]) : undefined,
|
|
||||||
() => character.craft.level ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Tier de fabrication'), span('font-semibold', text(() => character.craft.level ?? "")) ]) : undefined,
|
|
||||||
() => character.craft.bonus ? div('flex flex-row gap-1 items-center justify-between', [ span('italic text-light-70 dark:text-dark-70', 'Bonus de fabrication'), span('font-semibold', text(() => character.craft.bonus ?? "")) ]) : undefined,
|
|
||||||
])
|
|
||||||
] },
|
|
||||||
], { focused: this.tab, class: { container: 'flex-1 gap-4 px-4 w-[960px] h-full', content: 'overflow-auto' }, switch: v => { this.tab = v; } });
|
|
||||||
this.container.replaceChildren(div('flex flex-col justify-start gap-1 h-full', [
|
this.container.replaceChildren(div('flex flex-col justify-start gap-1 h-full', [
|
||||||
div("flex flex-row gap-4 justify-between", [
|
div("flex flex-row gap-4 justify-between", [
|
||||||
div(),
|
div(),
|
||||||
|
|
@ -1711,7 +1715,7 @@ export class CharacterSheet
|
||||||
dom("span", { class: "text-sm 2xl:text-base", text: "Initiative" })
|
dom("span", { class: "text-sm 2xl:text-base", text: "Initiative" })
|
||||||
]),
|
]),
|
||||||
div("flex flex-col px-2 items-center", [
|
div("flex flex-col px-2 items-center", [
|
||||||
dom("span", { class: "2xl:text-2xl text-xl font-bold" }, [ text(() => character.speed === false ? "Aucun déplacement" : `${character.speed} cases`) ]),
|
dom("span", { class: "2xl:text-2xl text-xl font-bold" }, [ text(() => character.speed === false ? "N/A" : `${character.speed}`) ]),
|
||||||
dom("span", { class: "text-sm 2xl:text-base", text: "Course" })
|
dom("span", { class: "text-sm 2xl:text-base", text: "Course" })
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
@ -1757,7 +1761,7 @@ export class CharacterSheet
|
||||||
div("flex flex-1 border-t border-dashed border-light-50 dark:border-dark-50")
|
div("flex flex-1 border-t border-dashed border-light-50 dark:border-dark-50")
|
||||||
]),
|
]),
|
||||||
|
|
||||||
div("grid grid-cols-2 gap-x-3 gap-y-1 text-sm", { list: character.mastery, render: (e, _c) => proses('a', preview, [ text('Arme légère') ], { href: 'regles/annexes/equipement#Les armes légères', label: 'Arme légère', class: 'text-sm text-light-70 dark:text-dark-70 cursor-help decoration-dotted underline', }) }),
|
div("grid grid-cols-2 gap-x-3 gap-y-1 text-sm", { list: character.mastery, render: (e, _c) => proses('a', preview, [ text(masteryTexts[e].text) ], { href: masteryTexts[e].href, label: masteryTexts[e].text, class: 'text-sm text-light-70 dark:text-dark-70 cursor-help decoration-dotted underline', }) }),
|
||||||
div("grid grid-cols-2 gap-x-3 gap-y-1 text-sm", [
|
div("grid grid-cols-2 gap-x-3 gap-y-1 text-sm", [
|
||||||
() => character.spellranks.precision > 0 ? div('flex flex-row items-center gap-2', [ proses('a', preview, [ text('Précision') ], { href: 'regles/la-magie/magie#Les sorts de précision', label: 'Précision', class: 'text-sm text-light-70 dark:text-dark-70 cursor-help decoration-dotted underline' }), span('font-bold', text(() => character.spellranks.precision)) ]) : undefined,
|
() => character.spellranks.precision > 0 ? div('flex flex-row items-center gap-2', [ proses('a', preview, [ text('Précision') ], { href: 'regles/la-magie/magie#Les sorts de précision', label: 'Précision', class: 'text-sm text-light-70 dark:text-dark-70 cursor-help decoration-dotted underline' }), span('font-bold', text(() => character.spellranks.precision)) ]) : undefined,
|
||||||
() => character.spellranks.knowledge > 0 ? div('flex flex-row items-center gap-2', [ proses('a', preview, [ text('Savoir') ], { href: 'regles/la-magie/magie#Les sorts de savoir', label: 'Savoir', class: 'text-sm text-light-70 dark:text-dark-70 cursor-help decoration-dotted underline' }), span('font-bold', text(() => character.spellranks.knowledge)) ]) : undefined,
|
() => character.spellranks.knowledge > 0 ? div('flex flex-row items-center gap-2', [ proses('a', preview, [ text('Savoir') ], { href: 'regles/la-magie/magie#Les sorts de savoir', label: 'Savoir', class: 'text-sm text-light-70 dark:text-dark-70 cursor-help decoration-dotted underline' }), span('font-bold', text(() => character.spellranks.knowledge)) ]) : undefined,
|
||||||
|
|
@ -2032,7 +2036,7 @@ export class CharacterSheet
|
||||||
this.character?.character.campaign ? button(text('Partager'), () => {
|
this.character?.character.campaign ? button(text('Partager'), () => {
|
||||||
|
|
||||||
}, 'px-2 text-sm h-5 box-content') : undefined,
|
}, 'px-2 text-sm h-5 box-content') : undefined,
|
||||||
button(icon('radix-icons:minus', { width: 12, height: 12 }), () => {
|
button(icon(() => e.amount === 1 ? 'radix-icons:trash' : 'radix-icons:minus', { width: 12, height: 12 }), () => {
|
||||||
const idx = items.findIndex(_e => _e === e);
|
const idx = items.findIndex(_e => _e === e);
|
||||||
if(idx === -1) return;
|
if(idx === -1) return;
|
||||||
|
|
||||||
|
|
@ -2056,10 +2060,10 @@ export class CharacterSheet
|
||||||
}, 'px-2 text-sm h-5 box-content'),
|
}, 'px-2 text-sm h-5 box-content'),
|
||||||
])
|
])
|
||||||
], [ div('flex flex-row justify-between', [
|
], [ div('flex flex-row justify-between', [
|
||||||
div('flex flex-row items-center gap-4', [
|
div('flex flex-row items-center gap-y-1 gap-x-4 flex-wrap', [
|
||||||
item.equippable ? checkbox({ defaultValue: e.equipped, change: v => {
|
item.equippable ? checkbox({ defaultValue: e.equipped, change: v => {
|
||||||
e.equipped = v;
|
e.equipped = v;
|
||||||
|
this.character?.enchant(e);
|
||||||
}, class: { container: '!w-5 !h-5' } }) : undefined,
|
}, class: { container: '!w-5 !h-5' } }) : undefined,
|
||||||
div('flex flex-row items-center gap-4', [ span([colorByRarity[item.rarity], 'text-lg'], item.name), div('flex flex-row gap-2 text-light-60 dark:text-dark-60 text-sm italic', subnameFactory(item).map(e => span('', e))) ]),
|
div('flex flex-row items-center gap-4', [ span([colorByRarity[item.rarity], 'text-lg'], item.name), div('flex flex-row gap-2 text-light-60 dark:text-dark-60 text-sm italic', subnameFactory(item).map(e => span('', e))) ]),
|
||||||
item.category === 'armor' ? div('flex flex-row gap-2 items-center text-sm', [ icon('game-icons:shoulder-armor', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('italic', () => `${item.health + ((e.state as ArmorState)?.health ?? 0) - ((e.state as ArmorState)?.loss ?? 0)}/${item.health + ((e.state as ArmorState)?.health ?? 0)} (${[item.absorb.static + ((e.state as ArmorState).absorb?.flat ?? 0) > 0 ? '-' + (item.absorb.static + ((e.state as ArmorState).absorb?.flat ?? 0)) : undefined, item.absorb.percent + ((e.state as ArmorState).absorb?.percent ?? 0) > 0 ? '-' + (item.absorb.percent + ((e.state as ArmorState).absorb?.percent ?? 0)) + '%' : undefined].filter(e => !!e).join('/')})`) ]) :
|
item.category === 'armor' ? div('flex flex-row gap-2 items-center text-sm', [ icon('game-icons:shoulder-armor', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('italic', () => `${item.health + ((e.state as ArmorState)?.health ?? 0) - ((e.state as ArmorState)?.loss ?? 0)}/${item.health + ((e.state as ArmorState)?.health ?? 0)} (${[item.absorb.static + ((e.state as ArmorState).absorb?.flat ?? 0) > 0 ? '-' + (item.absorb.static + ((e.state as ArmorState).absorb?.flat ?? 0)) : undefined, item.absorb.percent + ((e.state as ArmorState).absorb?.percent ?? 0) > 0 ? '-' + (item.absorb.percent + ((e.state as ArmorState).absorb?.percent ?? 0)) + '%' : undefined].filter(e => !!e).join('/')})`) ]) :
|
||||||
|
|
@ -2073,7 +2077,7 @@ export class CharacterSheet
|
||||||
e.amount > 1 && !!item.weight ? tooltip(weight, `Poids unitaire: ${item.weight}`, 'bottom') : weight,
|
e.amount > 1 && !!item.weight ? tooltip(weight, `Poids unitaire: ${item.weight}`, 'bottom') : weight,
|
||||||
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('game-icons:battery-pack', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', () => item.charge ? `${item.charge}` : '-') ]),
|
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('game-icons:battery-pack', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', () => item.charge ? `${item.charge}` : '-') ]),
|
||||||
]),
|
]),
|
||||||
])], { open: false, class: { icon: 'px-2', container: 'p-1 gap-2', content: 'px-4 pb-1 flex flex-col' } })
|
])], { open: false, class: { icon: 'px-2', container: 'p-1 gap-2', content: 'px-4 pb-1 flex flex-col gap-1' } })
|
||||||
}})
|
}})
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
|
|
@ -2191,9 +2195,7 @@ export class CharacterSheet
|
||||||
else
|
else
|
||||||
current.item!.enchantments?.splice(idx, 1);
|
current.item!.enchantments?.splice(idx, 1);
|
||||||
|
|
||||||
current.item!.state ??= {};
|
this.character?.enchant(current.item!);
|
||||||
|
|
||||||
this.character?.saveVariables();
|
|
||||||
}, 'p-1 !border-solid !border-r'),
|
}, 'p-1 !border-solid !border-r'),
|
||||||
]),
|
]),
|
||||||
])], { open: false, class: { icon: 'px-2', container: 'border border-light-35 dark:border-dark-35 p-1 gap-2', content: 'px-2 pb-1' } })
|
])], { open: false, class: { icon: 'px-2', container: 'border border-light-35 dark:border-dark-35 p-1 gap-2', content: 'px-2 pb-1' } })
|
||||||
|
|
@ -2210,4 +2212,16 @@ export class CharacterSheet
|
||||||
container.setAttribute('data-state', 'inactive');
|
container.setAttribute('data-state', 'inactive');
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
aspectTab(character: CompiledCharacter)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
effectsTab(character: CompiledCharacter)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,16 +237,19 @@ export class HomebrewBuilder
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spellTypeTexts[spell.type]) ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spellTypeTexts[spell.type]) ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(`${spell.cost} mana`) ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(`${spell.cost} mana`) ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spell.speed === 'action' ? 'Action' : spell.speed === 'reaction' ? 'Réaction' : `${spell.speed} minutes`) ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spell.speed === 'action' ? 'Action' : spell.speed === 'reaction' ? 'Réaction' : `${spell.speed} minutes`) ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(`${elementTexts[spell.elements[0]!].text}${spell.elements.length > 1 ? `+${spell.elements.length - 1}` : ''}`) ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(`${elementTexts[spell.elements[0]!].text}${spell.elements.length > 1 ? ` (+${spell.elements.length - 1})` : ''}`) ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spell.range === 'personnal' ? 'Personnel' : spell.range === 0 ? 'Toucher' : `${spell.range} cases`) ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spell.range === 'personnal' ? 'Personnel' : spell.range === 0 ? 'Toucher' : `${spell.range} cases`) ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(`${spell.tags && spell.tags.length > 0 ? spellTagTexts[spell.tags[0]!] : ''}${spell.tags && spell.tags.length > 1 ? `+${spell.tags.length - 1}` : ''}`) ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(`${spell.tags && spell.tags.length > 0 ? spellTagTexts[spell.tags[0]!] : ''}${spell.tags && spell.tags.length > 1 ? ` (+${spell.tags.length - 1})` : ''}`) ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spell.concentration ? 'Concentration' : '') ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text(spell.concentration ? 'Concentration' : '') ]),
|
||||||
]),
|
]),
|
||||||
div('flex flex-row justify-center gap-2', [ button(icon('radix-icons:pencil-1'), () => editing.id = spell.id, 'p-1'), button(icon('radix-icons:trash'), () => remove(spell), 'p-1') ])
|
div('flex flex-row justify-center gap-2', [ button(icon('radix-icons:pencil-1'), () => editing.id = spell.id, 'p-1'), button(icon('radix-icons:trash'), () => remove(spell), 'p-1') ])
|
||||||
])
|
])
|
||||||
], { class: { container: 'border-light-35 dark:border-dark-35 py-1', content: 'gap-2 px-4 py-1 flex items-center *:flex-1' }, open: false });
|
], { class: { container: 'border-light-35 dark:border-dark-35 py-1', content: 'gap-2 px-4 py-1 flex items-center *:flex-1' }, open: false });
|
||||||
};
|
};
|
||||||
const edit = (spell: SpellConfig) => {
|
const edit = (id: string) => {
|
||||||
|
const spell = config.spells[id] ? { ...config.spells[id] } : undefined;
|
||||||
|
if(!spell) return;
|
||||||
|
|
||||||
MarkdownEditor.singleton.onChange = v => {};
|
MarkdownEditor.singleton.onChange = v => {};
|
||||||
MarkdownEditor.singleton.content = spell.description;
|
MarkdownEditor.singleton.content = spell.description;
|
||||||
return foldable([
|
return foldable([
|
||||||
|
|
@ -264,8 +267,14 @@ export class HomebrewBuilder
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text('Tags'), multiselect([{ text: 'Dégâts', value: 'damage' }, { text: 'Buff', value: 'buff' }, { text: 'Debuff', value: 'debuff' }, { text: 'Support', value: 'support' }, { text: 'Tank', value: 'tank' }, { text: 'Mouvement', value: 'movement' }, { text: 'Utilitaire', value: 'utilitary' }], { change: (value) => spell.tags = value, defaultValue: spell.tags, class: { container: '!m-0 !h-9 w-full' } }), ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text('Tags'), multiselect([{ text: 'Dégâts', value: 'damage' }, { text: 'Buff', value: 'buff' }, { text: 'Debuff', value: 'debuff' }, { text: 'Support', value: 'support' }, { text: 'Tank', value: 'tank' }, { text: 'Mouvement', value: 'movement' }, { text: 'Utilitaire', value: 'utilitary' }], { change: (value) => spell.tags = value, defaultValue: spell.tags, class: { container: '!m-0 !h-9 w-full' } }), ]),
|
||||||
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text('Concentration'), toggle({ change: (value) => spell.concentration = value, defaultValue: spell.concentration, class: { container: '!m-0 !flex-none' } }), ]),
|
dom('label', { class: 'flex flex-col items-center justify-start gap-2 flex-1 *:text-center' }, [ text('Concentration'), toggle({ change: (value) => spell.concentration = value, defaultValue: spell.concentration, class: { container: '!m-0 !flex-none' } }), ]),
|
||||||
]),
|
]),
|
||||||
div('flex flex-row gap-2', [ ])
|
div('flex flex-row gap-2', [ tooltip(button(icon('radix-icons:check'), () => {
|
||||||
])
|
spell.description = MarkdownEditor.singleton.content;
|
||||||
|
Object.assign(config.spells[spell.id]!, spell);
|
||||||
|
editing.id = '';
|
||||||
|
}, 'p-1'), "Valider", 'left'), tooltip(button(icon('radix-icons:cross-1'), () => {
|
||||||
|
editing.id = '';
|
||||||
|
}, 'p-1'), "Annuler", 'left') ]),
|
||||||
|
])
|
||||||
], { class: { container: 'border-light-35 dark:border-dark-35 py-1', content: 'gap-2 px-4 py-1 flex items-center *:flex-1' }, open: false });
|
], { class: { container: 'border-light-35 dark:border-dark-35 py-1', content: 'gap-2 px-4 py-1 flex items-center *:flex-1' }, open: false });
|
||||||
};
|
};
|
||||||
const add = () => {
|
const add = () => {
|
||||||
|
|
@ -292,7 +301,7 @@ export class HomebrewBuilder
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return [ div('flex px-8 py-4 flex-col gap-4', [ div('flex flex-row-reverse', [ button(icon('radix-icons:plus'), add, 'p-1') ]), div('flex flex-col divide-y', { list: () => Object.values(config.spells), render: (e, _c) => editing.id === e.id ? edit(e) : _c ?? render(e)}) ] ) ];
|
return [ div('flex px-8 py-4 flex-col gap-4', [ div('flex flex-row-reverse', [ button(icon('radix-icons:plus'), add, 'p-1') ]), div('flex flex-col divide-y', { list: () => Object.values(config.spells), render: (e, _c) => editing.id === e.id ? edit(e.id) : render(e)}) ] ) ];
|
||||||
}
|
}
|
||||||
actions()
|
actions()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue