First round of changes
This commit is contained in:
BIN
modif/L5RxChiaroscuro _ Dev Foundry VTT.docx
Normal file
BIN
modif/L5RxChiaroscuro _ Dev Foundry VTT.docx
Normal file
Binary file not shown.
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "l5r5e",
|
||||
"name": "l5rx-chiaroscuro",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "l5r5e",
|
||||
"name": "l5rx-chiaroscuro",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "l5r5e",
|
||||
"name": "l5rx-chiaroscuro",
|
||||
"version": "1.0.0",
|
||||
"description": "This is a game system for Legend of the Five Rings (5th edition) by Edge Studio",
|
||||
"main": "index.js",
|
||||
|
||||
@@ -76,7 +76,10 @@
|
||||
"signature_scroll": "Signature Scroll",
|
||||
"item_pattern": "Item Pattern",
|
||||
"army_fortification": "Fortification",
|
||||
"army_cohort": "Cohort"
|
||||
"army_cohort": "Cohort",
|
||||
"arcane": "Arcane",
|
||||
"etat": "State",
|
||||
"mystere": "Mystery"
|
||||
},
|
||||
"Journal": {
|
||||
"journal": "Journal"
|
||||
@@ -318,7 +321,8 @@
|
||||
"school_ability": "School Ability",
|
||||
"mastery_ability": "Mastery Ability",
|
||||
"title_ability": "Title Ability",
|
||||
"specificity": "Specificity"
|
||||
"specificity": "Specificity",
|
||||
"mot_invocation": "Invocation Word"
|
||||
},
|
||||
"peculiarities": {
|
||||
"types": {
|
||||
@@ -869,5 +873,142 @@
|
||||
"range_band": "Range Band {band}",
|
||||
"range_abbreviation": "RB {range}"
|
||||
}
|
||||
},
|
||||
"chiaroscuro": {
|
||||
"skill_ranks": {
|
||||
"0": "—",
|
||||
"initie": "Initiate",
|
||||
"expert": "Expert",
|
||||
"maitre": "Master",
|
||||
"parangon1": "Paragon I",
|
||||
"parangon2": "Paragon II",
|
||||
"parangon3": "Paragon III"
|
||||
},
|
||||
"difficulties": {
|
||||
"simple": "Simple (7)",
|
||||
"moyenne": "Average (10)",
|
||||
"assez_difficile": "Somewhat Difficult (13)",
|
||||
"difficile": "Difficult (16)",
|
||||
"tres_difficile": "Very Difficult (22)",
|
||||
"heroique": "Heroic (28)",
|
||||
"improbable": "Improbable (32)"
|
||||
},
|
||||
"aspects": {
|
||||
"solar": "Solar Aspect",
|
||||
"lunar": "Lunar Aspect",
|
||||
"gauge": "Aspect Gauge",
|
||||
"desequilibre_solaire": "Solar Imbalance",
|
||||
"desequilibre_lunaire": "Lunar Imbalance"
|
||||
},
|
||||
"danger": {
|
||||
"simple": "Simple",
|
||||
"moyenne": "Average",
|
||||
"assez_difficile": "Somewhat Difficult",
|
||||
"difficile": "Difficult"
|
||||
},
|
||||
"arcane": {
|
||||
"title": "Arcanes",
|
||||
"label": "Arcane",
|
||||
"arcane_type": "Type",
|
||||
"application": "Skills",
|
||||
"bonus": "Bonus",
|
||||
"progression": "Progression",
|
||||
"xp_cost": "XP Cost"
|
||||
},
|
||||
"etat": {
|
||||
"title": "States",
|
||||
"label": "State",
|
||||
"application": "Application",
|
||||
"mod": "Modifier",
|
||||
"effect": "Effect",
|
||||
"elimination": "Elimination Condition"
|
||||
},
|
||||
"mystere": {
|
||||
"title": "Mysteries",
|
||||
"label": "Mystery",
|
||||
"mystere_type": "Type",
|
||||
"mineur": "Minor",
|
||||
"majeur": "Major",
|
||||
"prerequisite_skill": "Prerequisite Skill",
|
||||
"prerequisite_condition": "Prerequisite Condition"
|
||||
},
|
||||
"character": {
|
||||
"is_samurai": "Samurai",
|
||||
"quick_info": "Quick Info",
|
||||
"default_ring": "Default Ring",
|
||||
"region": "Region",
|
||||
"education": "Education",
|
||||
"past_problems": "Problematic Past",
|
||||
"koku": "Koku",
|
||||
"bu": "Bu",
|
||||
"zeni": "Zeni"
|
||||
},
|
||||
"weapon": {
|
||||
"bonus": "Bonus",
|
||||
"categories": {
|
||||
"arbalete": "Crossbow",
|
||||
"arc": "Bow",
|
||||
"contondante": "Bludgeoning Weapon",
|
||||
"poing": "Hand Weapon",
|
||||
"hast": "Polearm",
|
||||
"improvisee": "Improvised Weapon",
|
||||
"shinobi": "Shinobi Weapon",
|
||||
"specialisee": "Specialized Weapon",
|
||||
"bouclier": "Shield",
|
||||
"hache": "Axe",
|
||||
"naturel": "Natural",
|
||||
"sabre": "Sword",
|
||||
"nemuranai": "Nemuranai"
|
||||
}
|
||||
},
|
||||
"armor": {
|
||||
"categories": {
|
||||
"vetement": "Clothing",
|
||||
"leger": "Light",
|
||||
"moyen": "Medium",
|
||||
"lourd": "Heavy",
|
||||
"nemuranai": "Nemuranai"
|
||||
}
|
||||
},
|
||||
"item": {
|
||||
"types": {
|
||||
"ordinaire": "Ordinary",
|
||||
"shinobi": "Shinobi",
|
||||
"interdit": "Forbidden",
|
||||
"gaijin": "Gaijin",
|
||||
"nemuranai": "Nemuranai"
|
||||
}
|
||||
},
|
||||
"technique": {
|
||||
"mot_invocation": "Invocation Word",
|
||||
"invocation_type": "Invocation Type",
|
||||
"invocation_types": {
|
||||
"general": "General",
|
||||
"neutre": "Neutral",
|
||||
"precis": "Precise"
|
||||
},
|
||||
"mode_invocation": "Invocation Mode"
|
||||
},
|
||||
"tabs": {
|
||||
"invocations": "Invocations",
|
||||
"identity": "Identity",
|
||||
"identity_text1": "Appearance",
|
||||
"identity_text2": "Biography"
|
||||
},
|
||||
"dice": {
|
||||
"title": "Chiaroscuro Roll",
|
||||
"difficulty_label": "Difficulty",
|
||||
"modifier_label": "Modifier",
|
||||
"options": "Options",
|
||||
"aspect_point": "Aspect Point",
|
||||
"assistance": "Assistance",
|
||||
"total_dice": "Dice to roll",
|
||||
"bonus": "Rank bonus",
|
||||
"roll": "Roll",
|
||||
"dice_result": "Dice total",
|
||||
"adjusted": "Adjusted (Parangon)",
|
||||
"success": "Success",
|
||||
"failure": "Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,10 @@
|
||||
"signature_scroll": "Rouleau de marque",
|
||||
"item_pattern": "Procédé de fabrication",
|
||||
"army_fortification": "Fortification",
|
||||
"army_cohort": "Régiment"
|
||||
"army_cohort": "Régiment",
|
||||
"arcane": "Arcane",
|
||||
"etat": "État",
|
||||
"mystere": "Mystère"
|
||||
},
|
||||
"Journal": {
|
||||
"journal": "Journal"
|
||||
@@ -318,7 +321,8 @@
|
||||
"school_ability": "Capacité d'école",
|
||||
"mastery_ability": "Capacité de maîtrise",
|
||||
"title_ability": "Capacité de Titre",
|
||||
"specificity": "Particularité"
|
||||
"specificity": "Particularité",
|
||||
"mot_invocation": "Mot d'Invocation"
|
||||
},
|
||||
"peculiarities": {
|
||||
"types": {
|
||||
@@ -869,5 +873,142 @@
|
||||
"range_band": "Portée {band}",
|
||||
"range_abbreviation": "NP {range}"
|
||||
}
|
||||
},
|
||||
"chiaroscuro": {
|
||||
"skill_ranks": {
|
||||
"0": "—",
|
||||
"initie": "Initié",
|
||||
"expert": "Expert",
|
||||
"maitre": "Maître",
|
||||
"parangon1": "Parangon I",
|
||||
"parangon2": "Parangon II",
|
||||
"parangon3": "Parangon III"
|
||||
},
|
||||
"difficulties": {
|
||||
"simple": "Simple (7)",
|
||||
"moyenne": "Moyenne (10)",
|
||||
"assez_difficile": "Assez difficile (13)",
|
||||
"difficile": "Difficile (16)",
|
||||
"tres_difficile": "Très difficile (22)",
|
||||
"heroique": "Héroïque (28)",
|
||||
"improbable": "Improbable (32)"
|
||||
},
|
||||
"aspects": {
|
||||
"solar": "Aspect Solaire",
|
||||
"lunar": "Aspect Lunaire",
|
||||
"gauge": "Jauge d'Aspect",
|
||||
"desequilibre_solaire": "Déséquilibre Solaire",
|
||||
"desequilibre_lunaire": "Déséquilibre Lunaire"
|
||||
},
|
||||
"danger": {
|
||||
"simple": "Simple",
|
||||
"moyenne": "Moyenne",
|
||||
"assez_difficile": "Assez Difficile",
|
||||
"difficile": "Difficile"
|
||||
},
|
||||
"arcane": {
|
||||
"title": "Arcanes",
|
||||
"label": "Arcane",
|
||||
"arcane_type": "Type",
|
||||
"application": "Compétences",
|
||||
"bonus": "Bonus",
|
||||
"progression": "Progression",
|
||||
"xp_cost": "Coût XP"
|
||||
},
|
||||
"etat": {
|
||||
"title": "États",
|
||||
"label": "État",
|
||||
"application": "Application",
|
||||
"mod": "Modificateur",
|
||||
"effect": "Effet",
|
||||
"elimination": "Condition d'élimination"
|
||||
},
|
||||
"mystere": {
|
||||
"title": "Mystères",
|
||||
"label": "Mystère",
|
||||
"mystere_type": "Type",
|
||||
"mineur": "Mineur",
|
||||
"majeur": "Majeur",
|
||||
"prerequisite_skill": "Compétence prérequis",
|
||||
"prerequisite_condition": "Condition prérequis"
|
||||
},
|
||||
"character": {
|
||||
"is_samurai": "Samouraï",
|
||||
"quick_info": "Info rapide",
|
||||
"default_ring": "Anneau par défaut",
|
||||
"region": "Région",
|
||||
"education": "Éducation",
|
||||
"past_problems": "Passé problématique",
|
||||
"koku": "Koku",
|
||||
"bu": "Bu",
|
||||
"zeni": "Zeni"
|
||||
},
|
||||
"weapon": {
|
||||
"bonus": "Bonus",
|
||||
"categories": {
|
||||
"arbalete": "Arbalète",
|
||||
"arc": "Arc",
|
||||
"contondante": "Arme Contondante",
|
||||
"poing": "Arme de Poing",
|
||||
"hast": "Arme Hast",
|
||||
"improvisee": "Arme Improvisée",
|
||||
"shinobi": "Arme Shinobi",
|
||||
"specialisee": "Arme Spécialisée",
|
||||
"bouclier": "Bouclier",
|
||||
"hache": "Hache",
|
||||
"naturel": "Naturel",
|
||||
"sabre": "Sabre",
|
||||
"nemuranai": "Nemuranai"
|
||||
}
|
||||
},
|
||||
"armor": {
|
||||
"categories": {
|
||||
"vetement": "Vêtement",
|
||||
"leger": "Léger",
|
||||
"moyen": "Moyen",
|
||||
"lourd": "Lourd",
|
||||
"nemuranai": "Nemuranai"
|
||||
}
|
||||
},
|
||||
"item": {
|
||||
"types": {
|
||||
"ordinaire": "Ordinaire",
|
||||
"shinobi": "Shinobi",
|
||||
"interdit": "Interdit",
|
||||
"gaijin": "Gaijin",
|
||||
"nemuranai": "Nemuranai"
|
||||
}
|
||||
},
|
||||
"technique": {
|
||||
"mot_invocation": "Mot d'Invocation",
|
||||
"invocation_type": "Type d'invocation",
|
||||
"invocation_types": {
|
||||
"general": "Général",
|
||||
"neutre": "Neutre",
|
||||
"precis": "Précis"
|
||||
},
|
||||
"mode_invocation": "Mode d'Invocation"
|
||||
},
|
||||
"tabs": {
|
||||
"invocations": "Invocations",
|
||||
"identity": "Identité",
|
||||
"identity_text1": "Apparence",
|
||||
"identity_text2": "Biographie"
|
||||
},
|
||||
"dice": {
|
||||
"title": "Jet Chiaroscuro",
|
||||
"difficulty_label": "Difficulté",
|
||||
"modifier_label": "Modificateur",
|
||||
"options": "Options",
|
||||
"aspect_point": "Point d'Aspect",
|
||||
"assistance": "Assistance",
|
||||
"total_dice": "Dés à lancer",
|
||||
"bonus": "Bonus rang",
|
||||
"roll": "Lancer les dés",
|
||||
"dice_result": "Somme des dés",
|
||||
"adjusted": "Ajusté (Parangon)",
|
||||
"success": "Réussite",
|
||||
"failure": "Échec"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,52 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
parseInt(sheetData.data.system.xp_total) - parseInt(sheetData.data.system.xp_spent)
|
||||
);
|
||||
|
||||
// Chiaroscuro: Skill ranks list for <select>
|
||||
sheetData.data.skillRanksList = Object.keys(CONFIG.l5r5e.skillRanks).map((id) => ({
|
||||
id,
|
||||
label: game.i18n.localize(`chiaroscuro.skill_ranks.${id}`),
|
||||
}));
|
||||
|
||||
// Chiaroscuro: Normalize skill values 0 (number) → "0" (string) for selectOptions matching
|
||||
for (const category of Object.values(sheetData.data.system.skills)) {
|
||||
for (const [key, value] of Object.entries(category)) {
|
||||
if (value === 0) category[key] = "0";
|
||||
}
|
||||
}
|
||||
|
||||
// Chiaroscuro: Aspects gauge data
|
||||
const aspectsData = sheetData.data.system.aspects?.aspects ?? {};
|
||||
const gauge = aspectsData.gauge ?? 0;
|
||||
sheetData.data.aspectsData = {
|
||||
solar: aspectsData.solar ?? 0,
|
||||
lunar: aspectsData.lunar ?? 0,
|
||||
gauge,
|
||||
gaugePercent: ((gauge + 10) / 20) * 100,
|
||||
gaugeColor: gauge > 0 ? "#d4a855" : gauge < 0 ? "#5588aa" : "#888888",
|
||||
};
|
||||
|
||||
// Chiaroscuro: État items active on the character
|
||||
sheetData.data.etatItems = sheetData.items.filter((i) => i.type === "etat");
|
||||
|
||||
// Chiaroscuro: Invocations split by type (from splitTechniquesList)
|
||||
const invocations = sheetData.data.splitTechniquesList["mot_invocation"] ?? [];
|
||||
sheetData.data.splitInvocationsList = {
|
||||
general: invocations.filter((t) => !t.system.invocation_type || t.system.invocation_type === "general"),
|
||||
neutre: invocations.filter((t) => t.system.invocation_type === "neutre"),
|
||||
precis: invocations.filter((t) => t.system.invocation_type === "precis"),
|
||||
};
|
||||
|
||||
// Chiaroscuro: Arcane items
|
||||
sheetData.data.arcaneItems = sheetData.items.filter((i) => i.type === "arcane");
|
||||
|
||||
// Chiaroscuro: Identity tabs enriched HTML
|
||||
sheetData.data.enrichedHtml.identity_text1 = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
this.actor.system.identity_text1 ?? "", { async: true }
|
||||
);
|
||||
sheetData.data.enrichedHtml.identity_text2 = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
this.actor.system.identity_text2 ?? "", { async: true }
|
||||
);
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
|
||||
@@ -120,6 +166,14 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
// XP +/-
|
||||
html.find(".xp-control").on("click", this._modifyXP.bind(this));
|
||||
|
||||
// Chiaroscuro: set default ring on ring-name click
|
||||
html.find(".ring-set-default").on("click", (event) => {
|
||||
event.preventDefault();
|
||||
const ring = $(event.currentTarget).data("ring");
|
||||
this.actor.update({ "system.default_ring": ring });
|
||||
});
|
||||
|
||||
|
||||
// Advancements Tab to current rank onload
|
||||
// TODO class "Active" Bug on load, dunno why :/
|
||||
this._tabs
|
||||
@@ -127,6 +181,18 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
.activate("advancement_rank_" + (this.actor.system.identity.school_rank || 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Override base dice picker to open Chiaroscuro d6 dialog.
|
||||
* @param {Event} event
|
||||
*/
|
||||
_openDicePickerForSkill(event) {
|
||||
event.preventDefault();
|
||||
const el = $(event.currentTarget);
|
||||
const skillId = el.data("skill");
|
||||
const ringId = el.data("ring") || this.actor.system?.default_ring || "void";
|
||||
new game.l5r5e.ChiaroscuroDiceDialog({ actor: this.actor, ringId, skillId }).render(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the school advancement, calculate the total xp spent and the current total xp spent by rank
|
||||
*/
|
||||
@@ -218,6 +284,13 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
delete formData["system.money.zeni"];
|
||||
}
|
||||
|
||||
// Chiaroscuro: convert skill rank "0" (string from <select>) back to 0 (number)
|
||||
for (const [key, value] of Object.entries(formData)) {
|
||||
if (key.startsWith("system.skills.") && value === "0") {
|
||||
formData[key] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Save computed values
|
||||
const currentData = this.object.system;
|
||||
formData["system.focus"] = currentData.focus;
|
||||
|
||||
@@ -50,6 +50,21 @@ export class NpcSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
label: game.i18n.localize("l5r5e.character_types." + e),
|
||||
}));
|
||||
|
||||
// Danger levels for martial/social danger selects
|
||||
const dangerLevels = ["simple", "moyenne", "assez_difficile", "difficile"];
|
||||
sheetData.data.dangerList = dangerLevels.map((id) => ({
|
||||
id,
|
||||
label: game.i18n.localize(`chiaroscuro.danger.${id}`),
|
||||
}));
|
||||
|
||||
// Invocations list (mot_invocation techniques, split by type like character sheet)
|
||||
const invocations = sheetData.data.splitTechniquesList?.["mot_invocation"] ?? [];
|
||||
sheetData.data.splitInvocationsList = {
|
||||
general: invocations.filter((t) => !t.system.invocation_type || t.system.invocation_type === "general"),
|
||||
neutre: invocations.filter((t) => t.system.invocation_type === "neutre"),
|
||||
precis: invocations.filter((t) => t.system.invocation_type === "precis"),
|
||||
};
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
|
||||
@@ -101,4 +116,16 @@ export class NpcSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
|
||||
return super._updateObject(event, formData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override base dice picker to open Chiaroscuro d6 dialog.
|
||||
* @param {Event} event
|
||||
*/
|
||||
_openDicePickerForSkill(event) {
|
||||
event.preventDefault();
|
||||
const el = $(event.currentTarget);
|
||||
const skillId = el.data("skill");
|
||||
const ringId = el.data("ring") || this.actor.system?.default_ring || "void";
|
||||
new game.l5r5e.ChiaroscuroDiceDialog({ actor: this.actor, ringId, skillId }).render(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,50 @@ export const L5R5E = {
|
||||
skillCostMultiplier: 2,
|
||||
techniqueCost: 3,
|
||||
},
|
||||
|
||||
// --- Chiaroscuro additions ---
|
||||
|
||||
/** Skill rank enum values and associated flat bonus */
|
||||
skillRanks: {
|
||||
0: { bonus: 0 },
|
||||
initie: { bonus: 1 },
|
||||
expert: { bonus: 2 },
|
||||
maitre: { bonus: 3 },
|
||||
parangon1: { bonus: 3, passive: 1 }, // dice results of 1 count as 2
|
||||
parangon2: { bonus: 3, passive: 2 }, // dice results of 1-2 count as 3
|
||||
parangon3: { bonus: 3, passive: 3 }, // dice results of 1-3 count as 4
|
||||
},
|
||||
|
||||
/** Difficulty thresholds (Chiaroscuro scale) */
|
||||
difficulties: {
|
||||
simple: 7,
|
||||
moyenne: 10,
|
||||
assez_difficile: 13,
|
||||
difficile: 16,
|
||||
tres_difficile: 22,
|
||||
heroique: 28,
|
||||
improbable: 32,
|
||||
},
|
||||
|
||||
/** Ring colors for Chiaroscuro visual style */
|
||||
ringColors: {
|
||||
air: "rgb(145, 120, 150)",
|
||||
water: "rgb(95, 145, 155)",
|
||||
fire: "rgb(155, 115, 80)",
|
||||
earth: "rgb(105, 150, 120)",
|
||||
void: "rgb(75, 70, 65)",
|
||||
},
|
||||
|
||||
/** Aspect gauge configuration */
|
||||
aspects: {
|
||||
solarConditionId: "desequilibre_lunaire",
|
||||
lunarConditionId: "desequilibre_solaire",
|
||||
imbalanceThreshold: 5,
|
||||
resetThreshold: 10,
|
||||
},
|
||||
|
||||
// --- End Chiaroscuro additions ---
|
||||
|
||||
// For rings wound to be aligned, add them first
|
||||
conditions: [{
|
||||
id: "lightly_wounded_fire",
|
||||
@@ -180,6 +224,16 @@ export const L5R5E = {
|
||||
name: "l5r5e.conditions.unconscious",
|
||||
img: "systems/l5r5e/assets/icons/conditions/unconscious.webp",
|
||||
system: { id: "L5RCoreCon000015" }
|
||||
},{
|
||||
id: "desequilibre_solaire",
|
||||
name: "chiaroscuro.aspects.desequilibre_solaire",
|
||||
img: "systems/l5r5e/assets/icons/conditions/desequilibre_solaire.webp",
|
||||
system: { id: "ChiaCon000001" }
|
||||
},{
|
||||
id: "desequilibre_lunaire",
|
||||
name: "chiaroscuro.aspects.desequilibre_lunaire",
|
||||
img: "systems/l5r5e/assets/icons/conditions/desequilibre_lunaire.webp",
|
||||
system: { id: "ChiaCon000002" }
|
||||
}],
|
||||
regex: {
|
||||
techniqueDifficulty: /^@([TS]):([^|]+?)(?:\|(min|max)(?:\(([^)]+?)\))?)?$/,
|
||||
@@ -344,6 +398,8 @@ L5R5E.techniques.set("mastery_ability", { type: "school", displayInTypes: false
|
||||
L5R5E.techniques.set("title_ability", { type: "title", displayInTypes: false });
|
||||
// Custom
|
||||
L5R5E.techniques.set("specificity", { type: "custom", displayInTypes: false });
|
||||
// Chiaroscuro
|
||||
L5R5E.techniques.set("mot_invocation", { type: "chiaroscuro", displayInTypes: true });
|
||||
|
||||
// *** SkillId - CategoryId ***
|
||||
L5R5E.skills = new Map();
|
||||
|
||||
327
system/scripts/dice/chiaroscuro-dice-dialog.js
Normal file
327
system/scripts/dice/chiaroscuro-dice-dialog.js
Normal file
@@ -0,0 +1,327 @@
|
||||
/**
|
||||
* Chiaroscuro Dice Dialog
|
||||
*
|
||||
* d6 pool system: ring value × multiplier d6, sum vs difficulty.
|
||||
* Multiplier: ×1 base, ×2 if aspect or assistance, ×3 if both.
|
||||
* Parangon passives adjust individual die results before summing.
|
||||
*/
|
||||
export class ChiaroscuroDiceDialog extends FormApplication {
|
||||
/**
|
||||
* Current Actor
|
||||
* @type {ActorL5r5e}
|
||||
* @private
|
||||
*/
|
||||
_actor = null;
|
||||
|
||||
/**
|
||||
* Payload Object
|
||||
*/
|
||||
object = {
|
||||
ring: { id: "void", value: 1 },
|
||||
skill: { id: "", name: "", bonus: 0, rank: "0" },
|
||||
difficulty: { id: "moyenne", value: 10 },
|
||||
modifier: 0,
|
||||
useAspectPoint: false,
|
||||
aspectType: "solar",
|
||||
useAssistance: false,
|
||||
};
|
||||
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
id: "l5r5e-chiaroscuro-dice-dialog",
|
||||
classes: ["l5r5e", "chiaroscuro-dice-dialog"],
|
||||
template: CONFIG.l5r5e.paths.templates + "dice/chiaroscuro-dice-dialog.html",
|
||||
title: game.i18n.localize("chiaroscuro.dice.title"),
|
||||
width: 440,
|
||||
height: "auto",
|
||||
});
|
||||
}
|
||||
|
||||
get id() {
|
||||
return `l5r5e-chiaroscuro-dice-dialog-${this._actor?.id ?? "no-actor"}`;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return game.i18n.localize("chiaroscuro.dice.title") + (this._actor ? " — " + this._actor.name : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Total dice to roll (ring value × multiplier)
|
||||
* @return {number}
|
||||
*/
|
||||
get totalDice() {
|
||||
const base = this.object.ring.value;
|
||||
const both = this.object.useAspectPoint && this.object.useAssistance;
|
||||
const either = this.object.useAspectPoint || this.object.useAssistance;
|
||||
return base * (both ? 3 : either ? 2 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param options actor, actorId, ringId, skillId
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
super({}, options);
|
||||
|
||||
// Resolve actor
|
||||
[
|
||||
options?.actor,
|
||||
game.actors.get(options?.actorId),
|
||||
canvas.tokens.controlled[0]?.actor,
|
||||
game.user.character,
|
||||
].forEach((actor) => {
|
||||
if (!this._actor && actor instanceof Actor && actor.isOwner) {
|
||||
this._actor = actor;
|
||||
}
|
||||
});
|
||||
|
||||
// Default ring: options > actor default_ring > void
|
||||
const ringId = options.ringId ?? this._actor?.system?.default_ring ?? "void";
|
||||
this.ringId = ringId;
|
||||
|
||||
// Skill
|
||||
if (options.skillId) {
|
||||
this.skillId = options.skillId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ring (id + value from actor)
|
||||
* @param {string} ringId
|
||||
*/
|
||||
set ringId(ringId) {
|
||||
this.object.ring.id = CONFIG.l5r5e.stances.includes(ringId) ? ringId : "void";
|
||||
this.object.ring.value = this._actor?.system?.rings?.[this.object.ring.id] || 1;
|
||||
// Auto-derive aspect type from ring (fire/earth → solar, air/water → lunar; void = manual)
|
||||
if (this.object.ring.id !== "void") {
|
||||
this.object.aspectType = ["fire", "earth"].includes(this.object.ring.id) ? "solar" : "lunar";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set skill (id, name, rank, bonus)
|
||||
* @param {string} skillId
|
||||
*/
|
||||
set skillId(skillId) {
|
||||
if (!skillId) return;
|
||||
const catId = CONFIG.l5r5e.skills.get(skillId.toLowerCase().trim());
|
||||
const rank = this._actor?.system?.skills?.[catId]?.[skillId] ?? "0";
|
||||
this.object.skill = {
|
||||
...this.object.skill,
|
||||
id: skillId,
|
||||
name: catId ? game.i18n.localize(`l5r5e.skills.${catId}.${skillId}`) : skillId,
|
||||
rank,
|
||||
bonus: CONFIG.l5r5e.skillRanks?.[rank]?.bonus ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
async getData(options = null) {
|
||||
const difficultiesList = Object.entries(CONFIG.l5r5e.difficulties).map(([id, value]) => ({
|
||||
id,
|
||||
label: game.i18n.localize(`chiaroscuro.difficulties.${id}`),
|
||||
value,
|
||||
}));
|
||||
|
||||
const aspectsList = [
|
||||
{ id: "solar", label: game.i18n.localize("chiaroscuro.aspects.solar") },
|
||||
{ id: "lunar", label: game.i18n.localize("chiaroscuro.aspects.lunar") },
|
||||
];
|
||||
|
||||
return {
|
||||
...(await super.getData(options)),
|
||||
actor: this._actor,
|
||||
data: this.object,
|
||||
totalDice: this.totalDice,
|
||||
ringsList: game.l5r5e.HelpersL5r5e.getRingsList(this._actor),
|
||||
difficultiesList,
|
||||
aspectsList,
|
||||
isVoidRing: this.object.ring.id === "void",
|
||||
quickInfo: this._actor?.system?.quick_info ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Ring selector
|
||||
html.find(".ring-selection-chi").on("click", async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.ringId = event.currentTarget.dataset.ringid;
|
||||
this.render(false);
|
||||
});
|
||||
|
||||
// Difficulty select
|
||||
html.find("select[name='difficulty.id']").on("change", (event) => {
|
||||
this.object.difficulty.id = event.target.value;
|
||||
this.object.difficulty.value = CONFIG.l5r5e.difficulties[this.object.difficulty.id];
|
||||
this.render(false);
|
||||
});
|
||||
|
||||
// Flat modifier
|
||||
html.find("input[name='modifier']").on("change", (event) => {
|
||||
this.object.modifier = parseInt(event.target.value) || 0;
|
||||
});
|
||||
|
||||
// Aspect point checkbox
|
||||
html.find("#use_aspect_point").on("change", (event) => {
|
||||
this.object.useAspectPoint = event.target.checked;
|
||||
this.render(false);
|
||||
});
|
||||
|
||||
// Aspect type select (solar / lunar)
|
||||
html.find("select[name='aspectType']").on("change", (event) => {
|
||||
this.object.aspectType = event.target.value;
|
||||
});
|
||||
|
||||
// Assistance checkbox
|
||||
html.find("#use_assistance").on("change", (event) => {
|
||||
this.object.useAssistance = event.target.checked;
|
||||
this.render(false);
|
||||
});
|
||||
}
|
||||
|
||||
async _updateObject(event, formData) {
|
||||
const nbDice = this.totalDice;
|
||||
const skillRank = this.object.skill.rank;
|
||||
const skillBonus = this.object.skill.bonus;
|
||||
const flatModifier = this.object.modifier;
|
||||
const difficulty = this.object.difficulty.value;
|
||||
|
||||
// Roll the dice using FoundryVTT Roll API
|
||||
const roll = await new Roll(`${nbDice}d6`).evaluate();
|
||||
const rawResults = roll.dice[0].results.map((r) => r.result);
|
||||
|
||||
// Apply parangon passive adjustments
|
||||
const adjustedResults = rawResults.map((r) => this._applyParangon(r, skillRank));
|
||||
const diceAdjustedFlags = rawResults.map((r, i) => adjustedResults[i] !== r);
|
||||
const wasAdjusted = diceAdjustedFlags.some(Boolean);
|
||||
|
||||
// Compute total
|
||||
const rawSum = adjustedResults.reduce((a, b) => a + b, 0);
|
||||
const total = rawSum + skillBonus + flatModifier;
|
||||
const success = total >= difficulty;
|
||||
const bonus = success ? total - difficulty : 0;
|
||||
|
||||
// Update aspect gauge after roll
|
||||
if (this._actor && this.object.useAspectPoint) {
|
||||
await this._updateAspectGauge();
|
||||
}
|
||||
|
||||
// Post chat message
|
||||
await this._sendChatMessage({
|
||||
nbDice,
|
||||
rawResults,
|
||||
adjustedResults,
|
||||
diceAdjustedFlags,
|
||||
wasAdjusted,
|
||||
rawSum,
|
||||
total,
|
||||
skillBonus,
|
||||
flatModifier,
|
||||
difficulty,
|
||||
success,
|
||||
bonus,
|
||||
});
|
||||
|
||||
return this.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply parangon rank passive: replace low die results with higher value.
|
||||
* parangon1: 1 → 2
|
||||
* parangon2: 1–2 → 3
|
||||
* parangon3: 1–3 → 4
|
||||
* @param {number} result
|
||||
* @param {string} rank
|
||||
* @return {number}
|
||||
*/
|
||||
_applyParangon(result, rank) {
|
||||
if (rank === "parangon3" && result <= 3) return 4;
|
||||
if (rank === "parangon2" && result <= 2) return 3;
|
||||
if (rank === "parangon1" && result <= 1) return 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the aspect gauge on the actor after an aspect point roll.
|
||||
* Gauge positive = solar side, negative = lunar side.
|
||||
* ±5 → apply Déséquilibre. ±10 → full reset.
|
||||
*/
|
||||
async _updateAspectGauge() {
|
||||
// Support both single-nested (system.aspects) and double-nested (system.aspects.aspects)
|
||||
const aspectsPath = this._actor.system.aspects?.aspects !== undefined
|
||||
? "system.aspects.aspects"
|
||||
: "system.aspects";
|
||||
const aspects = foundry.utils.getProperty(this._actor, aspectsPath) ?? {};
|
||||
|
||||
const gaugeDirection = this.object.aspectType === "solar" ? 1 : -1;
|
||||
const newGauge = (aspects.gauge ?? 0) + gaugeDirection;
|
||||
|
||||
if (Math.abs(newGauge) >= 10) {
|
||||
// Full reset
|
||||
await this._actor.update({
|
||||
[`${aspectsPath}.gauge`]: 0,
|
||||
[`${aspectsPath}.solar`]: 0,
|
||||
[`${aspectsPath}.lunar`]: 0,
|
||||
});
|
||||
// Remove all desequilibre conditions
|
||||
const toRemove = this._actor.items
|
||||
.filter((i) => i.type === "etat" && ["desequilibre_solaire", "desequilibre_lunaire"].includes(i.system?.condition_type))
|
||||
.map((i) => i.id);
|
||||
if (toRemove.length) {
|
||||
await this._actor.deleteEmbeddedDocuments("Item", toRemove);
|
||||
}
|
||||
} else {
|
||||
await this._actor.update({ [`${aspectsPath}.gauge`]: newGauge });
|
||||
|
||||
if (Math.abs(newGauge) >= 5) {
|
||||
// Apply opposing desequilibre
|
||||
const condType = this.object.aspectType === "solar" ? "desequilibre_lunaire" : "desequilibre_solaire";
|
||||
const existing = this._actor.items.find(
|
||||
(i) => i.type === "etat" && i.system?.condition_type === condType
|
||||
);
|
||||
if (!existing) {
|
||||
await this._actor.createEmbeddedDocuments("Item", [
|
||||
{
|
||||
type: "etat",
|
||||
name: game.i18n.localize(`chiaroscuro.aspects.${condType}`),
|
||||
system: { condition_type: condType },
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and send the chat message.
|
||||
*/
|
||||
async _sendChatMessage(rollData) {
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
CONFIG.l5r5e.paths.templates + "dice/chiaroscuro-chat-roll.html",
|
||||
{
|
||||
actor: this._actor,
|
||||
profileImg: this._actor?.img ?? "icons/svg/mystery-man.svg",
|
||||
ring: this.object.ring,
|
||||
skill: this.object.skill,
|
||||
difficulty: this.object.difficulty,
|
||||
useAspectPoint: this.object.useAspectPoint,
|
||||
aspectType: this.object.aspectType,
|
||||
useAssistance: this.object.useAssistance,
|
||||
modifier: this.object.modifier,
|
||||
quickInfo: this._actor?.system?.quick_info ?? "",
|
||||
...rollData,
|
||||
}
|
||||
);
|
||||
|
||||
return ChatMessage.implementation.create({
|
||||
user: game.user.id,
|
||||
speaker: {
|
||||
actor: this._actor?.id ?? null,
|
||||
alias: this._actor?.name ?? null,
|
||||
},
|
||||
content,
|
||||
sound: CONFIG.sounds.dice,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,11 @@ export const RegisterHandlebars = function () {
|
||||
return objects.join("");
|
||||
});
|
||||
|
||||
// Chiaroscuro: return the flat bonus for a given skill rank id
|
||||
Handlebars.registerHelper("skillRankBonus", (rankId) => {
|
||||
return CONFIG.l5r5e.skillRanks?.[rankId]?.bonus ?? 0;
|
||||
});
|
||||
|
||||
// Add a setter
|
||||
Handlebars.registerHelper("setVar", function (varName, varValue, options) {
|
||||
options.data.root[varName] = varValue;
|
||||
|
||||
44
system/scripts/items/arcane-sheet.js
Normal file
44
system/scripts/items/arcane-sheet.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { BaseItemSheetL5r5e } from "./base-item-sheet.js";
|
||||
|
||||
/**
|
||||
* Sheet for Arcane items (Chiaroscuro).
|
||||
* @extends {BaseItemSheetL5r5e}
|
||||
*/
|
||||
export class ArcaneSheetL5r5e extends BaseItemSheetL5r5e {
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["l5r5e", "sheet", "arcane"],
|
||||
template: CONFIG.l5r5e.paths.templates + "items/arcane/arcane-sheet.html",
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "attributes" }],
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async getData(options = {}) {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
// Convert application array to comma-separated string for display
|
||||
const app = sheetData.data.system.application;
|
||||
sheetData.data.system.applicationDisplay = Array.isArray(app) ? app.join(", ") : (app ?? "");
|
||||
|
||||
sheetData.data.enrichedHtml = {
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
sheetData.data.system.description ?? "",
|
||||
{ async: true }
|
||||
),
|
||||
};
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _updateObject(event, formData) {
|
||||
// Convert comma-separated application string back to array
|
||||
const raw = formData["system.applicationDisplay"] ?? "";
|
||||
formData["system.application"] = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
||||
delete formData["system.applicationDisplay"];
|
||||
|
||||
return super._updateObject(event, formData);
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,16 @@ export class ArmorSheetL5r5e extends ItemSheetL5r5e {
|
||||
template: CONFIG.l5r5e.paths.templates + "items/armor/armor-sheet.html",
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async getData(options = {}) {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
const catObj = game.l5r5e.HelpersL5r5e.getLocalizedRawObject("chiaroscuro.armor.categories") ?? {};
|
||||
sheetData.data.armorCategories = Object.entries(catObj)
|
||||
.filter(([k]) => k !== "label")
|
||||
.map(([id, label]) => ({ id, label }));
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
}
|
||||
|
||||
30
system/scripts/items/etat-sheet.js
Normal file
30
system/scripts/items/etat-sheet.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { BaseItemSheetL5r5e } from "./base-item-sheet.js";
|
||||
|
||||
/**
|
||||
* Sheet for État items (Chiaroscuro).
|
||||
* @extends {BaseItemSheetL5r5e}
|
||||
*/
|
||||
export class EtatSheetL5r5e extends BaseItemSheetL5r5e {
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["l5r5e", "sheet", "etat"],
|
||||
template: CONFIG.l5r5e.paths.templates + "items/etat/etat-sheet.html",
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "attributes" }],
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async getData(options = {}) {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
sheetData.data.enrichedHtml = {
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
sheetData.data.system.description ?? "",
|
||||
{ async: true }
|
||||
),
|
||||
};
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
}
|
||||
35
system/scripts/items/mystere-sheet.js
Normal file
35
system/scripts/items/mystere-sheet.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { BaseItemSheetL5r5e } from "./base-item-sheet.js";
|
||||
|
||||
/**
|
||||
* Sheet for Mystère items (Chiaroscuro).
|
||||
* @extends {BaseItemSheetL5r5e}
|
||||
*/
|
||||
export class MystereSheetL5r5e extends BaseItemSheetL5r5e {
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["l5r5e", "sheet", "mystere"],
|
||||
template: CONFIG.l5r5e.paths.templates + "items/mystere/mystere-sheet.html",
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "attributes" }],
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async getData(options = {}) {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
sheetData.data.mystereTypes = [
|
||||
{ id: "mineur", label: game.i18n.localize("chiaroscuro.mystere.mineur") },
|
||||
{ id: "majeur", label: game.i18n.localize("chiaroscuro.mystere.majeur") },
|
||||
];
|
||||
|
||||
sheetData.data.enrichedHtml = {
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
sheetData.data.system.description ?? "",
|
||||
{ async: true }
|
||||
),
|
||||
};
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,27 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
// List all available techniques type
|
||||
const types = ["core", "school", "title"];
|
||||
const types = ["core", "school", "title", "chiaroscuro"];
|
||||
if (game.settings.get(CONFIG.l5r5e.namespace, "techniques-customs")) {
|
||||
types.push("custom");
|
||||
}
|
||||
sheetData.data.techniquesList = game.l5r5e.HelpersL5r5e.getTechniquesList({ types });
|
||||
|
||||
// Invocation sub-type fields (visible only for mot_invocation)
|
||||
sheetData.data.isMotInvocation = sheetData.data.system.technique_type === "mot_invocation";
|
||||
sheetData.data.invocationTypes = [
|
||||
{ id: "general", label: game.i18n.localize("chiaroscuro.technique.invocation_types.general") },
|
||||
{ id: "neutre", label: game.i18n.localize("chiaroscuro.technique.invocation_types.neutre") },
|
||||
{ id: "precis", label: game.i18n.localize("chiaroscuro.technique.invocation_types.precis") },
|
||||
];
|
||||
sheetData.data.modeInvocationValues = [
|
||||
{ id: "-3", label: "-3" },
|
||||
{ id: "0", label: "0" },
|
||||
{ id: "3", label: "+3" },
|
||||
];
|
||||
// Convert mode_invocation to string for selectOptions matching
|
||||
sheetData.data.system.mode_invocation_str = String(sheetData.data.system.mode_invocation ?? 0);
|
||||
|
||||
// Sanitize Difficulty and Skill list
|
||||
sheetData.data.system.difficulty = TechniqueSheetL5r5e.formatDifficulty(sheetData.data.system.difficulty);
|
||||
sheetData.data.system.skill = TechniqueSheetL5r5e.translateSkillsList(
|
||||
@@ -55,6 +70,12 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
TechniqueSheetL5r5e.translateSkillsList(formData["system.skill"].split(","), true)
|
||||
).join(",");
|
||||
|
||||
// Convert mode_invocation_str back to number
|
||||
if ("system.mode_invocation_str" in formData) {
|
||||
formData["system.mode_invocation"] = parseInt(formData["system.mode_invocation_str"] ?? "0", 10);
|
||||
delete formData["system.mode_invocation_str"];
|
||||
}
|
||||
|
||||
return super._updateObject(event, formData);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ export class WeaponSheetL5r5e extends ItemSheetL5r5e {
|
||||
label: "l5r5e.skills." + cat.toLowerCase() + "." + id.toLowerCase(),
|
||||
}));
|
||||
|
||||
// Weapon categories (Chiaroscuro)
|
||||
const catObj = game.l5r5e.HelpersL5r5e.getLocalizedRawObject("chiaroscuro.weapon.categories") ?? {};
|
||||
sheetData.data.weaponCategories = [{ id: "", label: "—" }].concat(
|
||||
Object.entries(catObj).map(([id, label]) => ({ id, label }))
|
||||
);
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { RingDie } from "./dice/dietype/ring-die.js";
|
||||
import { RollL5r5e } from "./dice/roll.js";
|
||||
import { DicePickerDialog } from "./dice/dice-picker-dialog.js";
|
||||
import { RollnKeepDialog } from "./dice/roll-n-keep-dialog.js";
|
||||
import { ChiaroscuroDiceDialog } from "./dice/chiaroscuro-dice-dialog.js";
|
||||
import { CombatL5r5e } from "./combat.js";
|
||||
// Items
|
||||
import { ItemL5r5e } from "./item.js";
|
||||
@@ -33,6 +34,9 @@ import { TitleSheetL5r5e } from "./items/title-sheet.js";
|
||||
import { BondSheetL5r5e } from "./items/bond-sheet.js";
|
||||
import { SignatureScrollSheetL5r5e } from "./items/signature-scroll-sheet.js";
|
||||
import { ItemPatternSheetL5r5e } from "./items/item-pattern-sheet.js";
|
||||
import { ArcaneSheetL5r5e } from "./items/arcane-sheet.js";
|
||||
import { EtatSheetL5r5e } from "./items/etat-sheet.js";
|
||||
import { MystereSheetL5r5e } from "./items/mystere-sheet.js";
|
||||
import { ArmyCohortSheetL5r5e } from "./items/army-cohort-sheet.js";
|
||||
import { ArmyFortificationSheetL5r5e } from "./items/army-fortification-sheet.js";
|
||||
// JournalEntry
|
||||
@@ -118,6 +122,7 @@ Hooks.once("init", async () => {
|
||||
ActorL5r5e,
|
||||
DicePickerDialog,
|
||||
RollnKeepDialog,
|
||||
ChiaroscuroDiceDialog,
|
||||
GmToolbox,
|
||||
GmMonitor,
|
||||
storage: new Storage(),
|
||||
@@ -223,6 +228,21 @@ Hooks.once("init", async () => {
|
||||
label: "TYPES.Item.army_fortification",
|
||||
makeDefault: true,
|
||||
});
|
||||
fdc.Items.registerSheet(L5R5E.namespace, ArcaneSheetL5r5e, {
|
||||
types: ["arcane"],
|
||||
label: "TYPES.Item.arcane",
|
||||
makeDefault: true,
|
||||
});
|
||||
fdc.Items.registerSheet(L5R5E.namespace, EtatSheetL5r5e, {
|
||||
types: ["etat"],
|
||||
label: "TYPES.Item.etat",
|
||||
makeDefault: true,
|
||||
});
|
||||
fdc.Items.registerSheet(L5R5E.namespace, MystereSheetL5r5e, {
|
||||
types: ["mystere"],
|
||||
label: "TYPES.Item.mystere",
|
||||
makeDefault: true,
|
||||
});
|
||||
|
||||
// Journal
|
||||
fdc.Journal.unregisterSheet("core", fav1s.JournalSheet);
|
||||
|
||||
@@ -309,6 +309,29 @@ export class MigrationL5r5e {
|
||||
}
|
||||
// ***** End of 1.3.0 *****
|
||||
|
||||
// ***** Start of 2.0.0 (Chiaroscuro) *****
|
||||
if (options?.force || MigrationL5r5e.needUpdate("2.0.0")) {
|
||||
// Migrate character skill ranks from numeric (1-5) to Chiaroscuro string enum.
|
||||
// Rank 0 (unranked) stays as the number 0 — this is intentional: the template
|
||||
// defaults to 0 (number) and JS coerces it correctly when keying into skillRanks.
|
||||
if (actor.type === "character" && system.skills) {
|
||||
const rankMap = { 1: "initie", 2: "expert", 3: "maitre", 4: "parangon1", 5: "parangon2" };
|
||||
const groups = ["artisan", "martial", "scholar", "social", "trade"];
|
||||
for (const group of groups) {
|
||||
const groupSkills = system.skills[group];
|
||||
if (!groupSkills) continue;
|
||||
for (const [skillName, rank] of Object.entries(groupSkills)) {
|
||||
const numRank = Number(rank);
|
||||
// Only migrate non-zero numeric ranks; 0 is already valid as-is
|
||||
if (numRank > 0 && rankMap[numRank]) {
|
||||
updateData[`system.skills.${group}.${skillName}`] = rankMap[numRank];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ***** End of 2.0.0 (Chiaroscuro) *****
|
||||
|
||||
return updateData;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,15 @@ export const PreloadTemplates = async function () {
|
||||
// *** Actors : PC ***
|
||||
`${tpl}actors/character/advancement-school.html`,
|
||||
`${tpl}actors/character/advancement-others.html`,
|
||||
`${tpl}actors/character/aspects.html`,
|
||||
`${tpl}actors/character/attributes.html`,
|
||||
`${tpl}actors/character/category.html`,
|
||||
`${tpl}actors/character/conflict.html`,
|
||||
`${tpl}actors/character/experience.html`,
|
||||
`${tpl}actors/character/identity.html`,
|
||||
`${tpl}actors/character/identity-text.html`,
|
||||
`${tpl}actors/character/inventory.html`,
|
||||
`${tpl}actors/character/invocations.html`,
|
||||
`${tpl}actors/character/narrative.html`,
|
||||
`${tpl}actors/character/rings.html`,
|
||||
`${tpl}actors/character/effects.html`,
|
||||
@@ -74,5 +77,6 @@ export const PreloadTemplates = async function () {
|
||||
`${tpl}items/weapon/weapon-sheet.html`,
|
||||
`${tpl}items/army-cohort/army-cohort-entry.html`,
|
||||
`${tpl}items/army-fortification/army-fortification-entry.html`,
|
||||
`${tpl}dice/chiaroscuro-chat-roll.html`,
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -21,5 +21,6 @@
|
||||
@import "../scss/items";
|
||||
@import "../scss/twenty-questions";
|
||||
@import "../scss/tactical-grid";
|
||||
@import "../scss/chiaroscuro";
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
376
system/styles/scss/chiaroscuro.scss
Normal file
376
system/styles/scss/chiaroscuro.scss
Normal file
@@ -0,0 +1,376 @@
|
||||
// ── Chiaroscuro UI Styles ──────────────────────────────────────────────────
|
||||
|
||||
// ── Aspects (header block on character sheet) ─────────────────────────────
|
||||
.aspects-section {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.25rem 0.5rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border: 1px solid rgba($chi-title, 0.3);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
|
||||
.aspect-fields {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
flex: 1;
|
||||
|
||||
.attribute-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
&:nth-child(1) { color: $chi-solar; } // solar
|
||||
&:nth-child(2) { color: $chi-lunar; } // lunar
|
||||
input[type="number"] {
|
||||
width: 3rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.gauge-bar-wrapper {
|
||||
flex: 0 0 100%;
|
||||
height: 0.4rem;
|
||||
background: linear-gradient(to right, $chi-lunar, rgba(128,128,128,0.3) 50%, $chi-solar);
|
||||
border-radius: 0.25rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.gauge-bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
border-radius: 0.25rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── État badges (character sheet header) ─────────────────────────────────
|
||||
.etat-summary {
|
||||
flex: 0 0 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
padding: 0.1rem 0;
|
||||
font-size: 0.8rem;
|
||||
.etat-summary-label {
|
||||
color: $l5r5e-label;
|
||||
font-style: italic;
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
.etat-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
padding: 0.1rem 0.35rem;
|
||||
border-radius: 0.2rem;
|
||||
background: rgba($chi-title, 0.18);
|
||||
border: 1px solid rgba($chi-title, 0.4);
|
||||
color: $chi-title;
|
||||
cursor: default;
|
||||
&:hover { background: rgba($chi-title, 0.32); }
|
||||
}
|
||||
}
|
||||
|
||||
// ── NPC Danger levels (identity.html) ────────────────────────────────────
|
||||
.danger-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
.danger-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
.danger-select {
|
||||
font-size: 0.85rem;
|
||||
background: $l5r5e-white;
|
||||
border: 0 none;
|
||||
color: $l5r5e-bold;
|
||||
font-family: $font-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.danger-icons {
|
||||
display: flex;
|
||||
gap: 0.15rem;
|
||||
.danger-icon {
|
||||
font-size: 0.9rem;
|
||||
&.fa-skull { color: $l5r5e-red; }
|
||||
&.fa-star { color: $l5r5e-shuji; }
|
||||
}
|
||||
}
|
||||
|
||||
// ── Chiaroscuro Dice Dialog ───────────────────────────────────────────────
|
||||
&.chiaroscuro-dice-dialog {
|
||||
// Header: portrait + actor name
|
||||
.chi-dice-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
border-bottom: 1px solid rgba($chi-title, 0.3);
|
||||
.profile-img {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
border: 2px solid rgba($chi-title, 0.5);
|
||||
}
|
||||
.chi-dice-actor-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
strong { font-family: $font-secondary; font-size: 1.1rem; color: $chi-title; }
|
||||
.chi-dice-quick-info { font-size: 0.8rem; color: $l5r5e-label; font-style: italic; }
|
||||
}
|
||||
}
|
||||
|
||||
// Section fieldsets
|
||||
.chi-dice-section {
|
||||
flex: 0 0 100%;
|
||||
border: 1px solid rgba($chi-subtitle, 0.35);
|
||||
border-radius: 0.25rem;
|
||||
margin: 0.35rem 0.5rem 0;
|
||||
padding: 0.25rem 0.5rem 0.4rem;
|
||||
legend {
|
||||
font-family: $font-tertiary;
|
||||
font-size: 0.8rem;
|
||||
color: $chi-subtitle;
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Ring selector
|
||||
.chi-rings {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.2rem;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
li { flex: 1; }
|
||||
.ring-selection-chi {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0.2rem;
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid rgba($l5r5e-title, 0.2);
|
||||
cursor: pointer;
|
||||
font-size: 0.75rem;
|
||||
&:hover { border-color: rgba($chi-title, 0.6); background: rgba($chi-title, 0.08); }
|
||||
&.ring-selected {
|
||||
border-color: $chi-title;
|
||||
background: rgba($chi-title, 0.15);
|
||||
strong { text-decoration: underline; }
|
||||
}
|
||||
i { font-size: 1.5rem; }
|
||||
.ring-value { font-weight: bold; font-size: 0.9rem; }
|
||||
}
|
||||
.earth.ring-selection-chi { color: $l5r5e-earth; }
|
||||
.air.ring-selection-chi { color: $l5r5e-air; }
|
||||
.water.ring-selection-chi { color: $l5r5e-water; }
|
||||
.fire.ring-selection-chi { color: $l5r5e-fire; }
|
||||
.void.ring-selection-chi { color: $l5r5e-void-light; }
|
||||
}
|
||||
|
||||
// Skill info row
|
||||
.chi-skill-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.4rem;
|
||||
.chi-skill-name { font-weight: bold; flex: 1; }
|
||||
.chi-skill-rank { font-size: 0.8rem; color: $l5r5e-label; }
|
||||
.chi-skill-bonus { font-size: 0.85rem; color: $chi-solar; font-weight: bold; }
|
||||
}
|
||||
|
||||
// Difficulty + modifier row
|
||||
.chi-difficulty-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
select { flex: 1; }
|
||||
.chi-modifier-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// Options checkboxes
|
||||
.chi-options-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.15rem 0;
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.chi-auto-aspect { font-size: 0.8rem; color: $l5r5e-label; }
|
||||
}
|
||||
|
||||
// Dice total summary
|
||||
.chi-dice-total-summary {
|
||||
flex: 0 0 100%;
|
||||
text-align: center;
|
||||
padding: 0.4rem;
|
||||
font-size: 0.9rem;
|
||||
.chi-total-dice { font-size: 1.3rem; color: $chi-title; margin: 0 0.2rem; }
|
||||
}
|
||||
|
||||
// Submit button
|
||||
.chi-dice-submit {
|
||||
flex: 0 0 100%;
|
||||
padding: 0.4rem 0.5rem;
|
||||
button[type="submit"] {
|
||||
width: 100%;
|
||||
background: rgba($chi-title, 0.85);
|
||||
border: 1px solid $chi-title;
|
||||
color: $white;
|
||||
font-family: $font-tertiary;
|
||||
font-size: 1rem;
|
||||
padding: 0.4rem;
|
||||
cursor: pointer;
|
||||
border-radius: 0.2rem;
|
||||
&:hover { background: $chi-title; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Chiaroscuro Chat Roll ─────────────────────────────────────────────────
|
||||
.chiaroscuro-chat-roll {
|
||||
padding: 0.35rem;
|
||||
font-size: 0.9rem;
|
||||
|
||||
// Header: portrait + actor + badges
|
||||
.chi-chat-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
margin-bottom: 0.3rem;
|
||||
.profile-img {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
border: 2px solid rgba($chi-title, 0.5);
|
||||
}
|
||||
.chi-chat-actor {
|
||||
flex: 1;
|
||||
strong { font-family: $font-secondary; color: $chi-title; }
|
||||
.chi-chat-quick-info { font-size: 0.75rem; color: $l5r5e-label; font-style: italic; }
|
||||
}
|
||||
.chi-chat-badges {
|
||||
display: flex;
|
||||
gap: 0.2rem;
|
||||
align-items: center;
|
||||
.chi-aspect-badge {
|
||||
font-size: 1rem;
|
||||
&.solar { color: $chi-solar; }
|
||||
&.lunar { color: $chi-lunar; }
|
||||
}
|
||||
.chi-assistance-badge { color: $l5r5e-label; font-size: 1rem; }
|
||||
}
|
||||
}
|
||||
|
||||
// Description line
|
||||
.chi-chat-desc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
margin-bottom: 0.3rem;
|
||||
font-size: 0.85rem;
|
||||
.chi-chat-skill { font-weight: bold; color: $chi-title; }
|
||||
.chi-chat-vs { color: $l5r5e-label; }
|
||||
.chi-chat-diff { color: $chi-subtitle; font-style: italic; }
|
||||
}
|
||||
|
||||
// Dice pool
|
||||
.chi-chat-dice-pool {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
margin-bottom: 0.35rem;
|
||||
.chi-die {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
border-radius: 0.25rem;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
background: rgba($l5r5e-black, 0.35);
|
||||
border: 1px solid rgba($l5r5e-title, 0.4);
|
||||
position: relative;
|
||||
&.die-low { color: $l5r5e-red; border-color: rgba($l5r5e-red, 0.5); }
|
||||
&.die-high { color: $chi-solar; border-color: rgba($chi-solar, 0.5); }
|
||||
.die-adj-icon {
|
||||
position: absolute;
|
||||
top: -0.3rem;
|
||||
right: -0.2rem;
|
||||
font-size: 0.6rem;
|
||||
color: $chi-solar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Breakdown
|
||||
.chi-chat-breakdown {
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 0.25rem;
|
||||
color: $l5r5e-label;
|
||||
strong { color: $white; }
|
||||
}
|
||||
|
||||
// Result banner
|
||||
.chi-chat-result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
font-family: $font-tertiary;
|
||||
font-size: 1rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.2rem;
|
||||
&.chi-success {
|
||||
background: rgba($chi-subtitle, 0.25);
|
||||
border: 1px solid rgba($chi-subtitle, 0.5);
|
||||
color: $chi-subtitle;
|
||||
}
|
||||
&.chi-failure {
|
||||
background: rgba($l5r5e-red, 0.12);
|
||||
border: 1px solid rgba($l5r5e-red, 0.35);
|
||||
color: $l5r5e-red;
|
||||
}
|
||||
.chi-bonus-successes {
|
||||
font-size: 0.85rem;
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Skill rank: bonus display ──────────────────────────────────────────────
|
||||
.skill-bonus {
|
||||
color: $chi-solar;
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
|
||||
// ── Default ring indicator ────────────────────────────────────────────────
|
||||
.rings .default-ring {
|
||||
text-decoration: underline 2px $chi-title;
|
||||
text-underline-offset: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -56,7 +56,20 @@ $l5r5e-chat-color-whisper: rgba(225, 200, 225, 0.75);
|
||||
// Misc
|
||||
$l5r5e-selection-circle-color: #8a1a00;
|
||||
|
||||
// -- Rings
|
||||
// -- Chiaroscuro Colors
|
||||
|
||||
// Title (was: rgba(186, 187, 177, 0.5) → spec: rgb(158, 65, 76))
|
||||
$chi-title: rgb(158, 65, 76);
|
||||
// Subtitle (spec: rgb(103, 128, 119))
|
||||
$chi-subtitle: rgb(103, 128, 119);
|
||||
// Solar aspect (spec: rgb(150, 119, 116))
|
||||
$chi-solar: rgb(150, 119, 116);
|
||||
// Lunar aspect (spec: rgb(100, 147, 137))
|
||||
$chi-lunar: rgb(100, 147, 137);
|
||||
// Active tab accent
|
||||
$chi-tab-active: rgb(158, 65, 76);
|
||||
// Tab hover accent
|
||||
$chi-tab-hover: rgb(103, 128, 119);
|
||||
|
||||
// Earth
|
||||
$l5r5e-earth: rgb(105, 150, 120);
|
||||
|
||||
@@ -28,7 +28,7 @@ nav {
|
||||
.item {
|
||||
flex: 1;
|
||||
&:hover {
|
||||
background-color: $l5r5e-label;
|
||||
background-color: $chi-tab-hover;
|
||||
color: $white-light;
|
||||
text-shadow: none;
|
||||
clip-path: polygon(
|
||||
@@ -44,7 +44,7 @@ nav {
|
||||
}
|
||||
}
|
||||
.item.active {
|
||||
background-color: rgba(73, 12, 11, 0.85);
|
||||
background-color: $chi-tab-active;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
clip-path: polygon(
|
||||
0% var(--notchSize),
|
||||
@@ -58,7 +58,7 @@ nav {
|
||||
);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(73, 12, 11, 0.85);
|
||||
background-color: $chi-tab-active;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"id": "l5r5e",
|
||||
"id": "l5rx-chiaroscuro",
|
||||
"title": "Legend of the Five Rings (5th Edition)",
|
||||
"description": "This is an authorised multilingual game system En|Fr|Es, for Legend of the Five Rings (5th Edition) by <a href='https://edge-studio.net/'>Edge Studio</a> <p> - Join the official Discord server: <a href='https://discord.gg/foundryvtt'> Official Discord</a></p><p> - Rejoignez la communauté Francophone: <a href='https://discord.gg/pPSDNJk'>Francophone Discord</a></p>",
|
||||
"url": "https://gitlab.com/teaml5r/l5r5e",
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
"age": "",
|
||||
"clan": "",
|
||||
"family": "",
|
||||
"region": "",
|
||||
"education": "",
|
||||
"female": null,
|
||||
"marital_status": "",
|
||||
"roles": "",
|
||||
@@ -36,6 +38,7 @@
|
||||
"status": 0,
|
||||
"ninjo": "",
|
||||
"giri": "",
|
||||
"past_problems": "",
|
||||
"bushido_tenets": {
|
||||
"paramount": "",
|
||||
"less_significant": ""
|
||||
@@ -118,18 +121,34 @@
|
||||
"mantra": false,
|
||||
"specificity": true
|
||||
}
|
||||
},
|
||||
"aspects": {
|
||||
"aspects": {
|
||||
"solar": 0,
|
||||
"lunar": 0,
|
||||
"gauge": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"character": {
|
||||
"templates": ["softlock", "identity", "rings", "social", "skills", "techniques", "conflict", "advancement"],
|
||||
"templates": ["softlock", "identity", "rings", "social", "skills", "techniques", "conflict", "advancement", "aspects"],
|
||||
"template": "core",
|
||||
"twenty_questions": {},
|
||||
"zeni": 0
|
||||
"is_samurai": true,
|
||||
"quick_info": "",
|
||||
"default_ring": "void",
|
||||
"koku": 0,
|
||||
"bu": 0,
|
||||
"zeni": 0,
|
||||
"identity_text1": "",
|
||||
"identity_text2": "",
|
||||
"twenty_questions": {}
|
||||
},
|
||||
"npc": {
|
||||
"templates": ["softlock", "identity", "rings", "social", "techniques", "conflict"],
|
||||
"type": "adversary",
|
||||
"attitude": "",
|
||||
"martial_danger": "simple",
|
||||
"social_danger": "simple",
|
||||
"conflict_rank": {
|
||||
"martial": 0,
|
||||
"social": 0
|
||||
@@ -194,7 +213,10 @@
|
||||
"signature_scroll",
|
||||
"item_pattern",
|
||||
"army_cohort",
|
||||
"army_fortification"
|
||||
"army_fortification",
|
||||
"arcane",
|
||||
"etat",
|
||||
"mystere"
|
||||
],
|
||||
"templates": {
|
||||
"basics": {
|
||||
@@ -224,10 +246,12 @@
|
||||
}
|
||||
},
|
||||
"item": {
|
||||
"templates": ["basics", "item"]
|
||||
"templates": ["basics", "item"],
|
||||
"item_type": ""
|
||||
},
|
||||
"armor": {
|
||||
"templates": ["basics", "item"],
|
||||
"armor_category": "",
|
||||
"armor": {
|
||||
"physical": 0,
|
||||
"supernatural": 0
|
||||
@@ -236,6 +260,7 @@
|
||||
"weapon": {
|
||||
"templates": ["basics", "item"],
|
||||
"category": "",
|
||||
"bonus": 0,
|
||||
"skill": "melee",
|
||||
"readied": false,
|
||||
"range": "0",
|
||||
@@ -248,7 +273,9 @@
|
||||
"templates": ["basics", "advancement"],
|
||||
"skill": "",
|
||||
"difficulty": "",
|
||||
"technique_type": "kata"
|
||||
"technique_type": "kata",
|
||||
"invocation_type": "",
|
||||
"mode_invocation": 0
|
||||
},
|
||||
"property": {
|
||||
"templates": ["basics"],
|
||||
@@ -303,6 +330,27 @@
|
||||
"difficulty": 0,
|
||||
"attrition_reduction": 0,
|
||||
"notes": ""
|
||||
},
|
||||
"arcane": {
|
||||
"templates": ["basics"],
|
||||
"arcane_type": "",
|
||||
"application": [],
|
||||
"bonus": 2,
|
||||
"progression": "",
|
||||
"xp_cost": 1
|
||||
},
|
||||
"etat": {
|
||||
"templates": ["basics"],
|
||||
"application": "",
|
||||
"mod": 0,
|
||||
"effect": "",
|
||||
"elimination": ""
|
||||
},
|
||||
"mystere": {
|
||||
"templates": ["basics"],
|
||||
"mystere_type": "mineur",
|
||||
"prerequisite_skill": "",
|
||||
"prerequisite_condition": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
{{> 'systems/l5r5e/templates/actors/character/attributes.html'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-fields chiaroscuro-aspects-wrapper">
|
||||
{{> 'systems/l5r5e/templates/actors/character/aspects.html'}}
|
||||
</div>
|
||||
</header>
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
@@ -38,9 +41,11 @@
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="skills">{{localize 'l5r5e.skills.title'}}</a>
|
||||
<a class="item" data-tab="narrative">{{localize 'l5r5e.sheets.narrative'}}</a>
|
||||
<a class="item" data-tab="invocations">{{localize 'chiaroscuro.tabs.invocations'}}</a>
|
||||
<a class="item" data-tab="conflict">{{localize 'l5r5e.conflict.title'}}</a>
|
||||
<a class="item" data-tab="inventory">{{localize 'l5r5e.sheets.inventory'}}</a>
|
||||
<a class="item" data-tab="experience">{{localize 'l5r5e.sheets.experience'}}</a>
|
||||
<a class="item" data-tab="identity">{{localize 'chiaroscuro.tabs.identity'}}</a>
|
||||
</nav>
|
||||
|
||||
{{!-- Skills Tab --}}
|
||||
@@ -72,5 +77,15 @@
|
||||
<article class="tab experience" data-group="primary" data-tab="experience">
|
||||
{{> 'systems/l5r5e/templates/actors/character/experience.html'}}
|
||||
</article>
|
||||
|
||||
{{!-- Invocations Tab --}}
|
||||
<article class="tab invocations" data-group="primary" data-tab="invocations">
|
||||
{{> 'systems/l5r5e/templates/actors/character/invocations.html'}}
|
||||
</article>
|
||||
|
||||
{{!-- Identity Tab --}}
|
||||
<article class="tab identity" data-group="primary" data-tab="identity">
|
||||
{{> 'systems/l5r5e/templates/actors/character/identity-text.html'}}
|
||||
</article>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
30
system/templates/actors/character/aspects.html
Normal file
30
system/templates/actors/character/aspects.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<div class="aspects-section">
|
||||
<div class="aspect-fields">
|
||||
<label class="attribute-label">
|
||||
{{localize 'chiaroscuro.aspects.solar'}}
|
||||
<input type="number" name="system.aspects.aspects.solar" value="{{data.system.aspects.aspects.solar}}" class="select-on-focus" data-dtype="Number" min="0" max="100" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
<label class="attribute-label">
|
||||
{{localize 'chiaroscuro.aspects.lunar'}}
|
||||
<input type="number" name="system.aspects.aspects.lunar" value="{{data.system.aspects.aspects.lunar}}" class="select-on-focus" data-dtype="Number" min="0" max="100" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
<label class="attribute-label">
|
||||
{{localize 'chiaroscuro.aspects.gauge'}}
|
||||
<input type="number" name="system.aspects.aspects.gauge" value="{{data.system.aspects.aspects.gauge}}" class="select-on-focus" data-dtype="Number" min="-10" max="10" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
<div class="gauge-bar-wrapper">
|
||||
<div class="gauge-bar" style="width: {{data.aspectsData.gaugePercent}}%; background-color: {{data.aspectsData.gaugeColor}};"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if data.etatItems.length}}
|
||||
<div class="etat-summary">
|
||||
<span class="etat-summary-label">{{localize 'chiaroscuro.etat.title'}}</span>
|
||||
{{#each data.etatItems as |etat|}}
|
||||
<span class="etat-badge l5r5e-tooltip" title="{{etat.system.effect}}">
|
||||
<img src="{{etat.img}}" width="16" height="16" />
|
||||
{{etat.name}}
|
||||
</span>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
10
system/templates/actors/character/identity-text.html
Normal file
10
system/templates/actors/character/identity-text.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="identity-text-wrapper flexrow">
|
||||
<fieldset class="identity-text-block">
|
||||
<legend class="text-block-header">{{localize 'chiaroscuro.tabs.identity_text1'}}</legend>
|
||||
{{editor data.enrichedHtml.identity_text1 target="system.identity_text1" button=true editable=options.editable engine="prosemirror" collaborate=false}}
|
||||
</fieldset>
|
||||
<fieldset class="identity-text-block">
|
||||
<legend class="text-block-header">{{localize 'chiaroscuro.tabs.identity_text2'}}</legend>
|
||||
{{editor data.enrichedHtml.identity_text2 target="system.identity_text2" button=true editable=options.editable engine="prosemirror" collaborate=false}}
|
||||
</fieldset>
|
||||
</div>
|
||||
@@ -1,21 +1,27 @@
|
||||
<ul class="identity-content">
|
||||
<li>
|
||||
<label class="attribute-label is-samurai-label">
|
||||
{{localize 'chiaroscuro.character.is_samurai'}}
|
||||
<input type="checkbox" name="system.is_samurai" {{checked data.system.is_samurai}} {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="attribute-label">
|
||||
{{#ifCond data.system.template '==' 'pow'}}
|
||||
{{localize 'l5r5e.sheets.region'}}
|
||||
{{else}}
|
||||
{{#if data.system.is_samurai}}
|
||||
{{localize 'l5r5e.clans.label'}}
|
||||
{{/ifCond}}
|
||||
{{else}}
|
||||
{{localize 'chiaroscuro.character.region'}}
|
||||
{{/if}}
|
||||
<input type="text" name="system.identity.clan" value="{{data.system.identity.clan}}" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="attribute-label">
|
||||
{{#ifCond data.system.template '==' 'pow'}}
|
||||
{{localize 'l5r5e.sheets.upbringing'}}
|
||||
{{else}}
|
||||
{{#if data.system.is_samurai}}
|
||||
{{localize 'l5r5e.sheets.family'}}
|
||||
{{/ifCond}}
|
||||
{{else}}
|
||||
{{localize 'chiaroscuro.character.education'}}
|
||||
{{/if}}
|
||||
<input type="text" name="system.identity.family" value="{{data.system.identity.family}}" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
@@ -37,4 +43,10 @@
|
||||
<input type="text" name="system.identity.roles" value="{{data.system.identity.roles}}" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="attribute-label quick-info-label">
|
||||
{{localize 'chiaroscuro.character.quick_info'}}
|
||||
<input type="text" name="system.quick_info" value="{{data.system.quick_info}}" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
17
system/templates/actors/character/invocations.html
Normal file
17
system/templates/actors/character/invocations.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<div class="invocations-wrapper">
|
||||
{{#each data.splitInvocationsList as |list type|}}
|
||||
<fieldset class="section-header flexrow">
|
||||
<legend class="technique-controls">
|
||||
<span>{{localize (concat 'chiaroscuro.technique.invocation_types.' type)}}</span>
|
||||
{{#if ../data.editable_not_soft_locked}}
|
||||
<a data-item-type="technique" class="technique-control item-add" data-tech-type="mot_invocation" title="{{localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
{{#each list as |item|}}
|
||||
{{> 'systems/l5r5e/templates/items/technique/technique-entry.html' technique=item editable=../../data.editable_not_soft_locked}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</div>
|
||||
@@ -7,12 +7,16 @@
|
||||
<textarea type="text" name="system.social.ninjo" {{^if data.editable_not_soft_locked}}disabled{{/if}}>{{data.system.social.ninjo}}</textarea>
|
||||
</label>
|
||||
<label class="attribute-label">
|
||||
{{#ifCond data.system.template '==' 'pow'}}
|
||||
{{localize 'l5r5e.social.past'}}
|
||||
{{else}}
|
||||
{{#if data.system.is_samurai}}
|
||||
{{localize 'l5r5e.social.giri'}}
|
||||
{{/ifCond}}
|
||||
<textarea type="text" name="system.social.giri" {{^if data.editable_not_soft_locked}}disabled{{/if}}>{{data.system.social.giri}}</textarea>
|
||||
{{else}}
|
||||
{{localize 'chiaroscuro.character.past_problems'}}
|
||||
{{/if}}
|
||||
{{#if data.system.is_samurai}}
|
||||
<textarea type="text" name="system.social.giri" {{^if data.editable_not_soft_locked}}disabled{{/if}}>{{data.system.social.giri}}</textarea>
|
||||
{{else}}
|
||||
<textarea type="text" name="system.social.past_problems" {{^if data.editable_not_soft_locked}}disabled{{/if}}>{{data.system.social.past_problems}}</textarea>
|
||||
{{/if}}
|
||||
</label>
|
||||
</fieldset>
|
||||
{{!-- Bushido Tenets --}}
|
||||
|
||||
@@ -2,35 +2,35 @@
|
||||
<li id="earth">
|
||||
<label class="earth {{#ifCond 'earth' '==' data.system.stance}}stance-active{{/ifCond}}">
|
||||
<i class="i_earth dice-picker rollable" data-ring="earth"></i>
|
||||
<strong>{{localizeRing 'earth'}}</strong>
|
||||
<strong class="ring-set-default {{#ifCond 'earth' '==' data.system.default_ring}}default-ring{{/ifCond}}" data-ring="earth" title="{{localize 'chiaroscuro.character.default_ring'}}">{{localizeRing 'earth'}}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.rings.earth" value="{{data.system.rings.earth}}" data-dtype="Number" min="1" max="9" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="air">
|
||||
<label class="air {{#ifCond 'air' '==' data.system.stance}}stance-active{{/ifCond}}">
|
||||
<i class="i_air dice-picker rollable" data-ring="air"></i>
|
||||
<strong>{{localizeRing 'air'}}</strong>
|
||||
<strong class="ring-set-default {{#ifCond 'air' '==' data.system.default_ring}}default-ring{{/ifCond}}" data-ring="air" title="{{localize 'chiaroscuro.character.default_ring'}}">{{localizeRing 'air'}}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.rings.air" value="{{data.system.rings.air}}" data-dtype="Number" min="1" max="9" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="water">
|
||||
<label class="water {{#ifCond 'water' '==' data.system.stance}}stance-active{{/ifCond}}">
|
||||
<i class="i_water dice-picker rollable" data-ring="water"></i>
|
||||
<strong>{{localizeRing 'water'}}</strong>
|
||||
<strong class="ring-set-default {{#ifCond 'water' '==' data.system.default_ring}}default-ring{{/ifCond}}" data-ring="water" title="{{localize 'chiaroscuro.character.default_ring'}}">{{localizeRing 'water'}}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.rings.water" value="{{data.system.rings.water}}" data-dtype="Number" min="1" max="9" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="fire">
|
||||
<label class="fire {{#ifCond 'fire' '==' data.system.stance}}stance-active{{/ifCond}}">
|
||||
<i class="i_fire dice-picker rollable" data-ring="fire"></i>
|
||||
<strong>{{localizeRing 'fire'}}</strong>
|
||||
<strong class="ring-set-default {{#ifCond 'fire' '==' data.system.default_ring}}default-ring{{/ifCond}}" data-ring="fire" title="{{localize 'chiaroscuro.character.default_ring'}}">{{localizeRing 'fire'}}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.rings.fire" value="{{data.system.rings.fire}}" data-dtype="Number" min="1" max="9" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="void">
|
||||
<label class="void {{#ifCond 'void' '==' data.system.stance}}stance-active{{/ifCond}}">
|
||||
<i class="i_void dice-picker rollable" data-ring="void"></i>
|
||||
<strong>{{localizeRing 'void'}}</strong>
|
||||
<strong class="ring-set-default {{#ifCond 'void' '==' data.system.default_ring}}default-ring{{/ifCond}}" data-ring="void" title="{{localize 'chiaroscuro.character.default_ring'}}">{{localizeRing 'void'}}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.rings.void" value="{{data.system.rings.void}}" data-dtype="Number" min="1" max="9" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
</label>
|
||||
</li>
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
<li class="skill skill-wrapper">
|
||||
<label class="skill-content">
|
||||
<span class="dice-picker attribute-label rollable" data-skill="{{skillId}}">{{localizeSkill categoryId skillId}}</span>
|
||||
<input
|
||||
class="centered-input select-on-focus"
|
||||
type="number"
|
||||
name="system.skills.{{categoryId}}.{{skillId}}"
|
||||
value="{{skill}}"
|
||||
data-dtype="Number"
|
||||
min="0"
|
||||
max="9"
|
||||
placeholder="0"
|
||||
{{^if data.editable_not_soft_locked}}disabled{{/if}}
|
||||
/>
|
||||
<select name="system.skills.{{categoryId}}.{{skillId}}" {{^if data.editable_not_soft_locked}}disabled{{/if}}>
|
||||
{{selectOptions data.skillRanksList selected=skill valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
{{#ifCond skill '!=' '0'}}<span class="skill-bonus">+{{skillRankBonus skill}}</span>{{/ifCond}}
|
||||
</label>
|
||||
</li>
|
||||
|
||||
@@ -45,4 +45,27 @@
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{{!-- Arcane items list --}}
|
||||
<fieldset class="section-header flexrow">
|
||||
<legend class="text-block-header">
|
||||
{{localize 'chiaroscuro.arcane.title'}}
|
||||
{{#if data.editable_not_soft_locked}}
|
||||
<a data-item-type="arcane" class="arcane-control item-add" title="{{localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
{{#each data.arcaneItems as |item|}}
|
||||
<li class="item technique flexcol" data-item-id="{{item._id}}">
|
||||
<ul class="item-header technique-controls">
|
||||
<li class="item-img"><img src="{{item.img}}" title="{{item.name}}" width="32px" height="32px"/></li>
|
||||
<li class="item-name l5r5e-tooltip" data-item-id="{{item._id}}">{{item.name}}</li>
|
||||
{{#if ../data.editable_not_soft_locked}}
|
||||
<li data-item-id="{{item._id}}" class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
</div>
|
||||
@@ -41,6 +41,7 @@
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="skills">{{localize 'l5r5e.skills.title'}}</a>
|
||||
<a class="item" data-tab="narrative">{{localize 'l5r5e.sheets.narrative'}}</a>
|
||||
<a class="item" data-tab="invocations">{{localize 'chiaroscuro.tabs.invocations'}}</a>
|
||||
<a class="item" data-tab="conflict">{{localize 'l5r5e.conflict.title'}}</a>
|
||||
<a class="item" data-tab="inventory">{{localize 'l5r5e.sheets.inventory'}}</a>
|
||||
</nav>
|
||||
@@ -55,6 +56,11 @@
|
||||
{{> 'systems/l5r5e/templates/actors/npc/narrative.html'}}
|
||||
</article>
|
||||
|
||||
{{!-- Invocations Tab --}}
|
||||
<article class="tab invocations" data-group="primary" data-tab="invocations">
|
||||
{{> 'systems/l5r5e/templates/actors/character/invocations.html'}}
|
||||
</article>
|
||||
|
||||
{{!-- Conflict Tab --}}
|
||||
<article class="tab conflict" data-group="primary" data-tab="conflict">
|
||||
{{> 'systems/l5r5e/templates/actors/npc/conflict.html'}} {{>
|
||||
|
||||
@@ -5,14 +5,34 @@
|
||||
{{selectOptions data.types selected=data.system.type valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
</li>
|
||||
{{!-- Martial --}}
|
||||
<li>
|
||||
{{!-- Martial Danger --}}
|
||||
<li class="danger-row">
|
||||
<i class="i_bushi" title="{{localize 'l5r5e.social.npc.combat'}}"></i>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.conflict_rank.martial" value="{{data.system.conflict_rank.martial}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<div class="danger-wrapper">
|
||||
<select name="system.martial_danger" {{^if data.editable_not_soft_locked}}disabled{{/if}}>
|
||||
{{selectOptions data.dangerList selected=data.system.martial_danger valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
<div class="danger-icons">
|
||||
<i class="fas fa-skull danger-icon"></i>
|
||||
{{#ifCond '["moyenne","assez_difficile","difficile"]' 'includes' data.system.martial_danger}}<i class="fas fa-skull danger-icon"></i>{{/ifCond}}
|
||||
{{#ifCond '["assez_difficile","difficile"]' 'includes' data.system.martial_danger}}<i class="fas fa-skull danger-icon"></i>{{/ifCond}}
|
||||
{{#ifCond data.system.martial_danger '==' 'difficile'}}<i class="fas fa-skull danger-icon"></i>{{/ifCond}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{!-- Social --}}
|
||||
<li>
|
||||
{{!-- Social Danger --}}
|
||||
<li class="danger-row">
|
||||
<i class="i_courtier" title="{{localize 'l5r5e.social.npc.intrigue'}}"></i>
|
||||
<input class="centered-input select-on-focus" type="number" name="system.conflict_rank.social" value="{{data.system.conflict_rank.social}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<div class="danger-wrapper">
|
||||
<select name="system.social_danger" {{^if data.editable_not_soft_locked}}disabled{{/if}}>
|
||||
{{selectOptions data.dangerList selected=data.system.social_danger valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
<div class="danger-icons">
|
||||
<i class="fas fa-star danger-icon"></i>
|
||||
{{#ifCond '["moyenne","assez_difficile","difficile"]' 'includes' data.system.social_danger}}<i class="fas fa-star danger-icon"></i>{{/ifCond}}
|
||||
{{#ifCond '["assez_difficile","difficile"]' 'includes' data.system.social_danger}}<i class="fas fa-star danger-icon"></i>{{/ifCond}}
|
||||
{{#ifCond data.system.social_danger '==' 'difficile'}}<i class="fas fa-star danger-icon"></i>{{/ifCond}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
52
system/templates/dice/chiaroscuro-chat-roll.html
Normal file
52
system/templates/dice/chiaroscuro-chat-roll.html
Normal file
@@ -0,0 +1,52 @@
|
||||
<div class="l5r5e chat-roll chiaroscuro-chat-roll">
|
||||
{{!-- Header --}}
|
||||
<div class="chi-chat-header">
|
||||
<img class="profile-img" src="{{profileImg}}" alt="{{actor.name}}" />
|
||||
<div class="chi-chat-actor">
|
||||
<strong>{{actor.name}}</strong>
|
||||
{{#if quickInfo}}<div class="chi-chat-quick-info">{{quickInfo}}</div>{{/if}}
|
||||
</div>
|
||||
<div class="chi-chat-badges">
|
||||
<span class="ring-icon {{ring.id}}" title="{{ring.label}}"><i class="i_{{ring.id}}"></i></span>
|
||||
{{#if useAspectPoint}}<span class="chi-aspect-badge {{aspectType}}" title="{{localize 'chiaroscuro.dice.aspect_point'}}">
|
||||
{{#ifCond aspectType '==' 'solar'}}☀{{else}}☽{{/ifCond}}
|
||||
</span>{{/if}}
|
||||
{{#if useAssistance}}<span class="chi-assistance-badge" title="{{localize 'chiaroscuro.dice.assistance'}}">⚑</span>{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Roll description line --}}
|
||||
<div class="chi-chat-desc">
|
||||
{{#if skill.name}}<span class="chi-chat-skill">{{skill.name}}</span>{{/if}}
|
||||
<span class="chi-chat-vs">→</span>
|
||||
<span class="chi-chat-diff">{{localize (concat 'chiaroscuro.difficulties.' difficulty.id)}} ({{difficulty.value}})</span>
|
||||
</div>
|
||||
|
||||
{{!-- Dice results --}}
|
||||
<div class="chi-chat-dice-pool">
|
||||
{{#each adjustedResults}}
|
||||
<span class="chi-die {{#ifCond this '<' 3}}die-low{{else}}{{#ifCond this '>' 4}}die-high{{/ifCond}}{{/ifCond}}">
|
||||
{{this}}
|
||||
{{#if (lookup ../diceAdjustedFlags @index)}}<i class="fas fa-caret-up die-adj-icon" title="{{localize 'chiaroscuro.dice.adjusted'}}"></i>{{/if}}
|
||||
</span>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
{{!-- Breakdown --}}
|
||||
<div class="chi-chat-breakdown">
|
||||
<span>{{localize 'chiaroscuro.dice.dice_result'}} : {{rawSum}}</span>
|
||||
{{#if skill.bonus}}<span> + {{skill.bonus}} ({{localize 'chiaroscuro.dice.bonus'}})</span>{{/if}}
|
||||
{{#if modifier}}<span> {{#ifCond modifier '>' 0}}+{{/ifCond}}{{modifier}} ({{localize 'chiaroscuro.dice.modifier_label'}})</span>{{/if}}
|
||||
<strong> = {{total}}</strong>
|
||||
</div>
|
||||
|
||||
{{!-- Result --}}
|
||||
<div class="chi-chat-result {{#if success}}chi-success{{else}}chi-failure{{/if}}">
|
||||
{{#if success}}
|
||||
<i class="fas fa-check"></i> {{localize 'chiaroscuro.dice.success'}}
|
||||
{{#if bonus}}<span class="chi-bonus-successes">(+{{bonus}})</span>{{/if}}
|
||||
{{else}}
|
||||
<i class="fas fa-times"></i> {{localize 'chiaroscuro.dice.failure'}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
97
system/templates/dice/chiaroscuro-dice-dialog.html
Normal file
97
system/templates/dice/chiaroscuro-dice-dialog.html
Normal file
@@ -0,0 +1,97 @@
|
||||
<form class="l5r5e chiaroscuro-dice-dialog" autocomplete="off">
|
||||
{{!-- Header: portrait + quick info --}}
|
||||
<div class="chi-dice-header">
|
||||
<img class="profile-img" src="{{#if actor.img}}{{actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}" alt="{{actor.name}}" />
|
||||
<div class="chi-dice-actor-info">
|
||||
<strong>{{actor.name}}</strong>
|
||||
{{#if quickInfo}}<div class="chi-dice-quick-info">{{quickInfo}}</div>{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Ring selector --}}
|
||||
<fieldset class="chi-dice-section">
|
||||
<legend>{{localize 'l5r5e.rings.title'}}</legend>
|
||||
<ul class="rings chi-rings">
|
||||
{{#each ringsList}}
|
||||
<li>
|
||||
<label class="attribute-label {{this.id}} centered-input ring-selection-chi pointer-choice {{#ifCond ../data.ring.id '==' this.id}}ring-selected{{/ifCond}}" data-ringid="{{this.id}}">
|
||||
<i class="i_{{this.id}}"></i>
|
||||
<strong>{{this.label}}</strong>
|
||||
<span class="ring-value">{{this.value}}</span>
|
||||
</label>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
{{!-- Skill info --}}
|
||||
{{#if data.skill.name}}
|
||||
<fieldset class="chi-dice-section">
|
||||
<legend>{{localize 'l5r5e.skills.title'}}</legend>
|
||||
<div class="chi-skill-row">
|
||||
<span class="chi-skill-name">{{data.skill.name}}</span>
|
||||
<span class="chi-skill-rank">{{localize (concat 'chiaroscuro.skill_ranks.' data.skill.rank)}}</span>
|
||||
{{#ifCond data.skill.bonus '>' 0}}<span class="chi-skill-bonus skill-bonus">+{{data.skill.bonus}}</span>{{/ifCond}}
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/if}}
|
||||
|
||||
{{!-- Difficulty + Modifier --}}
|
||||
<fieldset class="chi-dice-section">
|
||||
<legend>{{localize 'chiaroscuro.dice.difficulty_label'}}</legend>
|
||||
<div class="chi-difficulty-row">
|
||||
<select name="difficulty.id">
|
||||
{{selectOptions difficultiesList selected=data.difficulty.id valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
<label class="chi-modifier-label">
|
||||
{{localize 'chiaroscuro.dice.modifier_label'}}
|
||||
<input type="number" name="modifier" value="{{data.modifier}}" class="centered-input select-on-focus" style="width: 3em;" />
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{!-- Aspect Point + Assistance --}}
|
||||
<fieldset class="chi-dice-section">
|
||||
<legend>{{localize 'chiaroscuro.dice.options'}}</legend>
|
||||
<div class="chi-options-row">
|
||||
<label>
|
||||
<input type="checkbox" id="use_aspect_point" {{checked data.useAspectPoint}} />
|
||||
{{localize 'chiaroscuro.dice.aspect_point'}}
|
||||
{{#if isVoidRing}}
|
||||
<select name="aspectType">
|
||||
{{selectOptions aspectsList selected=data.aspectType valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
{{else}}
|
||||
<em class="chi-auto-aspect">
|
||||
{{#ifCond '["fire","earth"]' 'includes' data.ring.id}}
|
||||
({{localize 'chiaroscuro.aspects.solar'}})
|
||||
{{else}}
|
||||
({{localize 'chiaroscuro.aspects.lunar'}})
|
||||
{{/ifCond}}
|
||||
</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="chi-options-row">
|
||||
<label>
|
||||
<input type="checkbox" id="use_assistance" {{checked data.useAssistance}} />
|
||||
{{localize 'chiaroscuro.dice.assistance'}}
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{!-- Total dice summary --}}
|
||||
<div class="chi-dice-total-summary">
|
||||
<span>{{localize 'chiaroscuro.dice.total_dice'}} :</span>
|
||||
<strong class="chi-total-dice">{{totalDice}}d6</strong>
|
||||
{{#if data.skill.bonus}}<span> + {{data.skill.bonus}} ({{localize 'chiaroscuro.dice.bonus'}})</span>{{/if}}
|
||||
{{#if data.modifier}}<span> {{#ifCond data.modifier '>' 0}}+{{/ifCond}}{{data.modifier}} ({{localize 'chiaroscuro.dice.modifier_label'}})</span>{{/if}}
|
||||
</div>
|
||||
|
||||
{{!-- Submit --}}
|
||||
<div class="chi-dice-submit">
|
||||
<button name="roll" type="submit">
|
||||
{{localize 'chiaroscuro.dice.roll'}} <i class="fas fa-dice"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
35
system/templates/items/arcane/arcane-sheet.html
Normal file
35
system/templates/items/arcane/arcane-sheet.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
|
||||
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
|
||||
</header>
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item active" data-group="primary" data-tab="attributes">{{localize 'l5r5e.sheets.attributes'}}</a>
|
||||
<a class="item" data-group="primary" data-tab="description">{{localize 'l5r5e.sheets.infos'}}</a>
|
||||
</nav>
|
||||
<section class="sheet-body">
|
||||
<article class="attributes" data-group="primary" data-tab="attributes">
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.arcane.arcane_type'}}
|
||||
<input type="text" name="system.arcane_type" value="{{data.system.arcane_type}}" />
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.arcane.application'}}
|
||||
<input type="text" name="system.applicationDisplay" value="{{data.system.applicationDisplay}}" placeholder="compétence1, compétence2" />
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.arcane.bonus'}}
|
||||
<input class="select-on-focus" type="number" name="system.bonus" value="{{data.system.bonus}}" data-dtype="Number" min="0" placeholder="2"/>
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.arcane.progression'}}
|
||||
<input type="text" name="system.progression" value="{{data.system.progression}}" />
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.arcane.xp_cost'}}
|
||||
<input class="select-on-focus" type="number" name="system.xp_cost" value="{{data.system.xp_cost}}" data-dtype="Number" min="0" placeholder="1"/>
|
||||
</label>
|
||||
</article>
|
||||
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}
|
||||
</section>
|
||||
</form>
|
||||
@@ -11,6 +11,13 @@
|
||||
<input type="checkbox" name="system.equipped" {{checked data.system.equipped}} />
|
||||
{{ localize 'l5r5e.armors.equipped' }}
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'l5r5e.armors.type'}}
|
||||
<select name="system.armor_category">
|
||||
<option value="">—</option>
|
||||
{{selectOptions data.armorCategories selected=data.system.armor_category valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
</label>
|
||||
{{> 'systems/l5r5e/templates/items/item/item-value.html' }}
|
||||
<fieldset class="attribute type">
|
||||
<legend class="text-header">{{localize 'l5r5e.armors.type'}}</legend>
|
||||
|
||||
31
system/templates/items/etat/etat-sheet.html
Normal file
31
system/templates/items/etat/etat-sheet.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
|
||||
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
|
||||
</header>
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item active" data-group="primary" data-tab="attributes">{{localize 'l5r5e.sheets.attributes'}}</a>
|
||||
<a class="item" data-group="primary" data-tab="description">{{localize 'l5r5e.sheets.infos'}}</a>
|
||||
</nav>
|
||||
<section class="sheet-body">
|
||||
<article class="attributes" data-group="primary" data-tab="attributes">
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.etat.application'}}
|
||||
<input type="text" name="system.application" value="{{data.system.application}}" />
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.etat.mod'}}
|
||||
<input class="select-on-focus" type="number" name="system.mod" value="{{data.system.mod}}" data-dtype="Number" placeholder="0"/>
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.etat.effect'}}
|
||||
<input type="text" name="system.effect" value="{{data.system.effect}}" />
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.etat.elimination'}}
|
||||
<input type="text" name="system.elimination" value="{{data.system.elimination}}" />
|
||||
</label>
|
||||
</article>
|
||||
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}
|
||||
</section>
|
||||
</form>
|
||||
29
system/templates/items/mystere/mystere-sheet.html
Normal file
29
system/templates/items/mystere/mystere-sheet.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
|
||||
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
|
||||
</header>
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item active" data-group="primary" data-tab="attributes">{{localize 'l5r5e.sheets.attributes'}}</a>
|
||||
<a class="item" data-group="primary" data-tab="description">{{localize 'l5r5e.sheets.infos'}}</a>
|
||||
</nav>
|
||||
<section class="sheet-body">
|
||||
<article class="attributes" data-group="primary" data-tab="attributes">
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.mystere.mystere_type'}}
|
||||
<select name="system.mystere_type">
|
||||
{{selectOptions data.mystereTypes selected=data.system.mystere_type valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.mystere.prerequisite_skill'}}
|
||||
<input type="text" name="system.prerequisite_skill" value="{{data.system.prerequisite_skill}}" />
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.mystere.prerequisite_condition'}}
|
||||
<input type="text" name="system.prerequisite_condition" value="{{data.system.prerequisite_condition}}" />
|
||||
</label>
|
||||
</article>
|
||||
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}
|
||||
</section>
|
||||
</form>
|
||||
@@ -42,6 +42,20 @@
|
||||
{{localize 'l5r5e.dice.dicepicker.difficulty_title'}}
|
||||
<input class="select-on-focus" type="text" name="system.difficulty" value="{{data.system.difficulty}}" data-dtype="String"/>
|
||||
</label>
|
||||
{{#if data.isMotInvocation}}
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.technique.invocation_type'}}
|
||||
<select name="system.invocation_type">
|
||||
{{selectOptions data.invocationTypes selected=data.system.invocation_type valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.technique.mode_invocation'}}
|
||||
<select name="system.mode_invocation_str">
|
||||
{{selectOptions data.modeInvocationValues selected=data.system.mode_invocation_str valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
</label>
|
||||
{{/if}}
|
||||
</article>
|
||||
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}
|
||||
</section>
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
{{> 'systems/l5r5e/templates/items/item/item-value.html'}}
|
||||
<label class="category">
|
||||
{{localize 'l5r5e.weapons.category'}}
|
||||
<input type="text" name="system.category" value="{{data.system.category}}" />
|
||||
<select name="system.category">
|
||||
{{selectOptions data.weaponCategories selected=data.system.category valueAttr='id' labelAttr='label'}}
|
||||
</select>
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'chiaroscuro.weapon.bonus'}}
|
||||
<input class="select-on-focus" type="number" name="system.bonus" value="{{data.system.bonus}}" data-dtype="Number" placeholder="0"/>
|
||||
</label>
|
||||
<label class="skillType">
|
||||
{{localize 'l5r5e.skills.label'}}
|
||||
|
||||
Reference in New Issue
Block a user