Add Templates Html + Gulp Sass + Css + Basic Tree and Files

- Add Templates Html
- Gulp Sass
- Css
- Basic Tree and Files
This commit is contained in:
Mandar
2020-12-04 20:17:51 +01:00
parent 9332985ec7
commit a0a99eb08c
60 changed files with 7771 additions and 34 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules

21
LICENSE.txt Normal file
View File

@@ -0,0 +1,21 @@
# Copyright (c) 2018 - 2020 Fantasy Flight Games. Legend of the Five Rings est TM de Fantasy Flight Games.
# Copyright (c) 2020 Foundry Network
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,43 +1,51 @@
![alt text](/l5r02_anc_slider.jpg) # Legend of the Five Rings (5th Edition) by [Edge Studio](https://edge-studio.net/)
# Legend of the Five Rings 5th Edition by [Edge Studio](https://edge-studio.net/)
## Installation ![Banner Legend of the Five Rings](/l5rBan.jpg)
1. Copy this link and use it in Foundrys system manager to install the system. Copier ce lien et chargez-le dans le menu système de Foundry # English
This is a game system for [Foundry Virtual Tabletop](https://foundryvtt.com/) provides a character sheet and basic systems to play [Edge Studio's](https://edge-studio.net/) Legend of the Five Rings 5th edition.
This version is authorized by Edge Studio, all texts, images and copyrights are the property of their respective owners.
## Install with the manifest
1. Copy this link and use it in Foundrys system manager to install the system.
> Manifest: https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json > Manifest: https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json
## Remerciements, vielen danke & Many thanks to : ## Remerciements, vielen danke & Many thanks to :
1. 1. José Ladislao Lainez Ortega Aka L4D15, for his first version
2. 2. Sasmira and LeRatierBretonnien for their work on the [Francophone community of Foundry](https://discord.gg/pPSDNJk)
3. 3. The entire L5R Team for its work.
## Contribute
You are free to contribute and propose corrections, modifications after fork. Try to respect 3 rules:
1. Make sure you are up to date with the referent branch.
2. Clear and precise commit messages allow a quick review of the code.
3. If possible, limit yourself to one Feature per Merge request so as not to block the process.
# French
Il s'agit d'un système de jeu pour [Foundry Virtual Tabletop](https://foundryvtt.com/) qui fournit une fiche de personnage et des systèmes de base pour jouer à Legend of the Five Rings 5e édition de [Edge Studio](https://edge-studio.net/).
Cette version est autorisée par Edge Studio, tous les textes, images et droits d'auteur reviennent à leur propriétaires respectifs.
## Installer avec le manifeste
Copier ce lien et chargez-le dans le menu système de Foundry
> Manifest: https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json
## Nous rejoindre ## Nous rejoindre
1. Vous pouvez retrouver toutes les mises à jour en français pour FoundryVTT sur le discord officiel francophone 1. Vous pouvez retrouver toutes les mises à jour en français pour FoundryVTT sur le discord officiel francophone
2. Lien vers [Discord Francophone](https://discord.gg/pPSDNJk) 2. Lien vers [Discord Francophone](https://discord.gg/pPSDNJk)
## Modifier le système ## Remerciements, vielen danke & Many thanks to :
Avant de pousser une nouvelle Release, il faut : 1. José Ladislao Lainez Ortega Aka L4D15, pour sa première version
1. Modifier le/les fichiers avec les changements, puis valider : commit changes 2. Sasmira et LeRatierBretonnien pour leur travail sur la [communauté Francophone de Foundry](https://discord.gg/pPSDNJk)
2. Puis éditer system.json en changeant à deux endroits les numéros de la version. 3. L'ensemble de la Team L5R pour son travail.
3. Puis valider : commit changes
## Pousser une nouvelle Release ## Contribuer
En ce qui concerne la nomenclature du numéro de version Vous êtes libre de contribuer et proposer après fork des corrections, modifications. Essayez de respecter 3 règles :
1. Mettre le numéro de version avec v collé devant : par ex : v1.8.0A 1. Assurez-vous de bien être à jour par rapport à la branche référente.
2. Puis éditer system.json en changeant à deux endroits les numéros de la version. 2. Des messages de commit clair et précis permettent une relecture rapide du code.
7. Remplir les renseignements sur les raisons du changements. 3. Limitez-vous si possible à une Feature par demande de Merge pour ne pas bloquer le processus.
Une fois que vous avez fait tous les changements, il faut mettre à jour le master afin de créer la nouvelle Release. # Update/Mise à jour
1. Aller dans tags/étiquette - 04/12/2020 - Add Templates Html + Gulp Sass + Css + Basic Tree and Files - mise à jour des informations de contributions - Mandar.
2. tag name : mettre le numéro de version avec v collé devant : par ex : v1.8.0A - 03/12/2020 - Init template and Workspace for Beginning of Great Adventure - Sasmira.
3. notes de version : détailler les modifications apportées par le changement. Par ex. correction sur tel aspect, ajout de telle fonctionnalité, mise à jour...
4. Créer le tag/étiquette
5. Aller dans Graph
6. Pour que votre nouvelle release soit valide, il faut que la toute première ligne du graphique soit le "numéro de version de la release" suivi de "master".
## Déclarer sur Foundry les changements
- Soon
## Mise à jour du readme.md
- 03/11/2020 par Sasmira.

67
gulpfile.js Normal file
View File

@@ -0,0 +1,67 @@
// Requires
const gulp = require('gulp');
const prefix = require('gulp-autoprefixer');
const sass = require('gulp-sass');
const browserSync = require('browser-sync');
/* ----------------------------------------- */
/* Compile Sass
/* ----------------------------------------- */
// Small error handler helper function.
function handleError(err) {
console.log(err.toString());
this.emit('end');
}
const SYSTEM_SCSS = ["system/styles/conf/**/*.scss"];
function compileScss() {
// Configure options for sass output. For example, 'expanded' or 'nested'
let options = {
outputStyle: 'compressed'
};
return gulp.src(SYSTEM_SCSS)
.pipe(
sass(options)
.on('error', handleError)
)
.pipe(prefix({
cascade: false
}))
.pipe(gulp.dest("system/styles"))
.pipe(browserSync.reload({
stream: true
}))
}
const css = gulp.series(compileScss);
/* ----------------------------------------- */
/* Watch Updates
/* ----------------------------------------- */
function watchUpdates() {
gulp.watch(SYSTEM_SCSS, css);
}
/* ----------------------------------------- */
/* BrowserSync
/* ----------------------------------------- */
function bSync() {
browserSync({
server: {
baseDir: 'system/styles'
},
})
}
/* ----------------------------------------- */
/* Export Tasks
/* ----------------------------------------- */
exports.default = gulp.series(
compileScss,
watchUpdates,
bSync
);
exports.css = css;

View File

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

5870
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

27
package.json Normal file
View File

@@ -0,0 +1,27 @@
{
"name": "l5r5e",
"version": "1.0.0",
"description": "This is a game system for Legend of the Five Rings (5th edition) by Edge Studio",
"main": "index.js",
"scripts": {
"compile": "gulp css",
"watch": "gulp watch",
"prettier": "prettier --quote-props=preserve --print-width=5000 --write"
},
"repository": {
"type": "git",
"url": "git+https://gitlab.com/teaml5r/l5r5e.git"
},
"author": "Team L5r",
"license": "ISC",
"bugs": {
"url": "https://gitlab.com/teaml5r/l5r5e/issues"
},
"homepage": "https://gitlab.com/teaml5r/l5r5e#readme",
"devDependencies": {
"browser-sync": "^2.26.13",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^7.0.1",
"gulp-sass": "^4.1.0"
}
}

Binary file not shown.

View File

@@ -0,0 +1,157 @@
{
"SETTINGS.SimpleMacroShorthandN": "Shortened Macro Syntax",
"SETTINGS.SimpleMacroShorthandL": "Enable a shortened macro syntax which allows referencing attributes directly, for example @str instead of @attributes.str.value. Disable this setting if you need the ability to reference the full attribute model, for example @attributes.str.label.",
"SETTINGS.SimpleInitFormulaN": "Initiative Formula",
"SETTINGS.SimpleInitFormulaL": "Enter an initiative formula, such as d20+@dex",
"SIMPLE.NotifyInitFormulaUpdated": "Initiative formula was updated to:",
"SIMPLE.NotifyInitFormulaInvalid": "Initiative formula was invalid:",
"L5r5e": {
"Rings": {
"Title": "Rings",
"Earth": "Earth",
"Air": "Air",
"Water": "Water",
"Fire": "Fire",
"Void": "Void"
},
"Narrative": "Narrative",
"Experience": "Experience",
"Clan": "Clan",
"Family": "Family",
"School": "School",
"SchoolRank": "Rank",
"Roles": "Roles",
"Distinctions": "Distinctions",
"DistinctionsTip": "Reroll up to two dice of your choice when a distinction helps you on a check.",
"Adversities": "Adversities",
"AdversitiesTip": "Reroll two dice containing Success or Explosive Success symbols when an adversity hinders you on a check. If you fail, gain 1 Void point.",
"Anxieties": "Anxieties",
"AnxietiesTip": "After performing a check related to your anxiety, receive 3 strife. Then, gain 1 Void point (limit once per scene).",
"Passions": "Passions",
"PassionsTip": "After performing a check related to your passion, remove 3 strife.",
"Personality": "Personality",
"Max": "Max",
"Current": "Current",
"Quantity": "Quantity",
"Weight": "Weight",
"Damage": "Damage",
"Range": "Range",
"Properties": "Properties",
"Weapons": "Weapons",
"Items": "Items",
"Feats": "Feats",
"Skill": "Skill",
"Level": "Level",
"Approaches": "Approaches",
"FeatPlaceholderName": "New Feat",
"Notes": "Notes",
"Inventory": "Inventory",
"Rank": "Rank",
"Name": "Name",
"SocialStanding": {
"Title": "Social Standing",
"Honor": "Honor",
"Glory": "Glory",
"Status": "Status",
"Ninjo": "Ninjo",
"Giri": "Giri",
"SocialTitles": "Titles"
},
"Skills": {
"Title": "Skills",
"artisan": {
"Title": "Artisan",
"Aesthetics": "Aesthetics",
"Composition": "Composition",
"Design": "Design",
"Smithing": "Smithing",
"Air": "Refine",
"Earth": "Restore",
"Fire": "Invent",
"Water": "Adapt",
"Void": "Attune"
},
"martial": {
"Title": "Martial",
"Fitness": "Fitness",
"Melee": "Martial Arts [Melee]",
"Ranged": "Martial Arts [Melee]",
"Unarmed": "Martial Arts [Unarmed]",
"Meditation": "Meditation",
"Tactics": "Tactics",
"Air": "Feint",
"Earth": "Withstand",
"Fire": "Overwelm",
"Water": "Shift",
"Void": "Sacrifice"
},
"scholar": {
"Title": "Scholar",
"Culture": "Culture",
"Government": "Government",
"Medicine": "Medicine",
"Sentiment": "Sentiment",
"Theology": "Theology",
"Air": "Analyze",
"Earth": "Recall",
"Fire": "Theorize",
"Water": "Survey",
"Void": "Sense"
},
"social": {
"Title": "Social",
"Command": "Command",
"Courtesy": "Courtesy",
"Games": "Games",
"Performance": "Performance",
"Air": "Trick",
"Earth": "Reason",
"Fire": "Incite",
"Water": "Charm",
"Void": "Enlighten"
},
"trade": {
"Title": "Trade",
"Commerce": "Commerce",
"Labor": "Labor",
"Seafaring": "Seafaring",
"Skulduggery": "Skulduggery",
"Survival": "Survival",
"Air": "Con",
"Earth": "Produce",
"Fire": "Innovate",
"Water": "Exchange",
"Void": "Subsist"
}
},
"Conflict": {
"Title": "Conflict",
"Endurance": "Endurance",
"EnduranceTip": "(Earth + Fire) x2",
"Composure": "Composure",
"ComposureTip": "(Earth + Water) x2",
"Focus": "Focus",
"FocusTip": "Air + Fire",
"Vigilante": "Vigilante",
"VigilanteTip": "(Air + Water) /2",
"VoidPoints": "Void Points",
"Stance": "Stance",
"Fatigue": "Fatigue",
"Strife": "Strife",
"Stances": {
"AirTip": "+1 to TN of Attack and Scheme checks targeting you (+2 at rank 4+).",
"EarthTip": "Others cannot spend Opportunity to inflict critical strikes or conditions on you.",
"FireTip": "If you succeed, +1 bonus success per Strife symbol.",
"WaterTip": "Perform a second action on your turn that does not require a check or share a type with first action.",
"VoidTip": "You do not receive strife from Strife symbols on checks."
}
},
"XP": {
"Total": "Total",
"Spent": "Used",
"Saved": "Saved",
"Adquisitions": "Adquisitions"
}
}
}

View File

@@ -0,0 +1,157 @@
{
"SETTINGS.SimpleMacroShorthandN": "Shortened Macro Syntax",
"SETTINGS.SimpleMacroShorthandL": "Enable a shortened macro syntax which allows referencing attributes directly, for example @str instead of @attributes.str.value. Disable this setting if you need the ability to reference the full attribute model, for example @attributes.str.label.",
"SETTINGS.SimpleInitFormulaN": "Initiative Formula",
"SETTINGS.SimpleInitFormulaL": "Enter an initiative formula, such as d20+@dex",
"SIMPLE.NotifyInitFormulaUpdated": "Initiative formula was updated to:",
"SIMPLE.NotifyInitFormulaInvalid": "Initiative formula was invalid:",
"L5r5e": {
"Rings": {
"Title": "Anneaux",
"Earth": "Terre",
"Air": "Air",
"Water": "Eau",
"Fire": "Feu",
"Void": "Vide"
},
"Narrative": "Mode Narratif",
"Experience": "Expérience",
"Clan": "Clan",
"Family": "Famille",
"School": "Ecole",
"SchoolRank": "Rang",
"Roles": "Rôles",
"Distinctions": "Aptitudes",
"DistinctionsTip": "Lorsque vous effectuez un test auquel s'applique une aptitude, vous pouvez relancer jusqu'à 2 dés.",
"Adversities": "Coups du sort",
"AdversitiesTip": " lorsque vous effectuez un test auquel s'applique un coup du sort, vous relancez jusqu'à 2 dés dont le résultat contient Succès ou Succès explosif. Vous regagnez 1 point de Vide si vous ratez ce test.",
"Anxieties": "Défaillances",
"AnxietiesTip": "Lorsque vous effectuez un test auquel s'applique une défaillance, vous recevez 2 points de Conflit. S'il s'agit de la première fois dans la scène, vous regagnez 1 point de Vide.",
"Passions": "Passions",
"PassionsTip": "Lorsque vous effectuez un test auquel s'applique une passion, éliminez 3 points de Conflit.",
"Personality": "Personalité",
"Max": "Max",
"Current": "Actuel",
"Quantity": "Quantité",
"Weight": "Poids",
"Damage": "Dommage",
"Range": "Distance",
"Properties": "Propriétés",
"Weapons": "Armement",
"Items": "Equipement",
"Feats": "Techniques",
"Skill": "Compétence",
"Level": "Niveau",
"Approaches": "Approches",
"FeatPlaceholderName": "Nouvelle technique",
"Notes": "Notes",
"Inventory": "Inventaire",
"Rank": "Rang",
"Name": "Nom",
"SocialStanding": {
"Title": "Position Social",
"Honor": "Honneur",
"Glory": "Gloire",
"Status": "Status",
"Ninjo": "Ninjo",
"Giri": "Giri",
"SocialTitles": "Titres"
},
"Skills": {
"Title": "Compétences",
"artisan": {
"Title": "Artisanales",
"Aesthetics": "Esthétique",
"Composition": "Composition",
"Design": "Stylisme",
"Smithing": "Forge",
"Air": "Raffiner",
"Earth": "Restaurer",
"Fire": "Inventer",
"Water": "Adapter",
"Void": "Sharmoniser"
},
"martial": {
"Title": "Martiales",
"Fitness": "Forme",
"Melee": "Arts martiaux (corps à corps)",
"Ranged": "Arts martiaux (distance)",
"Unarmed": "Arts martiaux (mains nues)",
"Meditation": "Méditation",
"Tactics": "Tactique",
"Air": "Feinter",
"Earth": "Résister",
"Fire": "Submerger",
"Water": "Détourner",
"Void": "Lâcher prise"
},
"scholar": {
"Title": "Savantes",
"Culture": "Culture",
"Government": "Gouvernement",
"Medicine": "Médecine",
"Sentiment": "Sentiments",
"Theology": "Théologie",
"Air": "Analyser",
"Earth": "Se remémorer",
"Fire": "Théoriser",
"Water": "Observer",
"Void": "Ressentir"
},
"social": {
"Title": "Sociales",
"Command": "Commandement",
"Courtesy": "Courtoisie",
"Games": "Jeux",
"Performance": "Représentations",
"Air": "Duper",
"Earth": "Raisonner",
"Fire": "Inciter",
"Water": "Charmer",
"Void": "Illuminer"
},
"trade": {
"Title": "Professionnelles",
"Commerce": "Commerce",
"Labor": "Travail manuel",
"Seafaring": "Navigation",
"Skulduggery": "Magouilles",
"Survival": "Survie",
"Air": "Escroquer",
"Earth": "Produire",
"Fire": "Innover",
"Water": "Échanger",
"Void": "Subsister"
}
},
"Conflict": {
"Title": "Conflit",
"Endurance": "Endurance",
"EnduranceTip": "(Terre + Feu) x2",
"Composure": "Sang Froid",
"ComposureTip": "(Earth + Eau) x2",
"Focus": "Attention",
"FocusTip": "Air + Feu",
"Vigilante": "Vigilance",
"VigilanteTip": "(Air + Eau) /2",
"VoidPoints": "Points de Vide",
"Stance": "Posture",
"Fatigue": "Fatigue",
"Strife": "Conflit",
"Stances": {
"AirTip": "Augmentez de 1 le ND des tests d'Attaque et de Manipulation dont vous êtes la cible. Si votre rang d'école est au moins égal à 4, augmentez le ND de 2 au lieu de 1.",
"EarthTip": "Quand vous êtes la cible d'un test d'Attaque ou de Manipulation, votre adversaire ne peut pas dépenser d'Aubaine pour vous infliger des coups critiques ou des états.",
"FireTip": "Lorsque vous réussissez un test, chaque Conflit obtenu sur vos dés gardés compte comme un succès bonus.",
"WaterTip": "Pendant votre tour, vous pouvez effectuer une action supplémentaire qui ne nécessite pas de test, et dont le type est différent de l'action que vous avez déjà effectuée à ce tour.",
"VoidTip": "Tant que vous êtes dans cette posture, vous ne subissez aucun point de Conflit en cas de Conflit."
}
},
"XP": {
"Total": "Totale",
"Spent": "Dépensée",
"Saved": "Restante",
"Adquisitions": "Acquisitions"
}
}
}

View File

@@ -0,0 +1,34 @@
/**
* Extends the actor to process special things from L5R.
*/
export class ActorL5r5e extends Actor {
/** @override */
static async create(data, options={}) {
if(!Object.keys(data).includes("type")) data.type = "character";
await super.create(data, options);
}
prepareData() {
super.prepareData();
const actorData = this.data;
const data = actorData.data;
const isCharacter = actorData.type === "character";
if (isCharacter) {
data.endurance = (Number(data.rings.earth) + Number(data.rings.fire)) * 2;
data.composure = (Number(data.rings.earth) + Number(data.rings.water)) * 2;
data.focus = Number(data.rings.air) + Number(data.rings.fire);
data.vigilante = Math.floor((Number(data.rings.air) + Number(data.rings.water)) / 2);
data.void_points.max = data.rings.void;
// Make sure void points are never greater than max
if (data.void_points.current > data.void_points.max) {
data.void_points.current = data.void_points.max;
}
}
}
}

View File

@@ -0,0 +1,142 @@
export class ActorSheetL5r5e extends ActorSheet {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "actor"],
template: "systems/l5r5e/templates/sheets/actor-sheet.html",
width: 600,
height: 600,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}],
dragDrop: [{dragSelector: ".item-list .item", dropSelector: null}]
});
}
getData() {
const sheetData = super.getData();
this._prepareItems(sheetData);
const feats = sheetData.items.filter((item) => item.type === "feat");
sheetData.data.feats = feats;
return sheetData;
}
/**
* Update the actor.
* @param event
* @param formData
*/
_updateObject(event, formData) {
return this.object.update(formData);
}
/**
* Prepare item data to be displayed in the actor sheet.
* @param sheetData Data of the actor been displayed in the sheet.
*/
_prepareItems(sheetData) {
for (let item of sheetData.items) {
if (item.type === "weapon") {
item.isWeapon = true;
item.isEquipment = true;
} else if (item.type === "feat"){
item.isFeat = true;
}
else {
item.isEquipment = true;
}
}
}
_prepareFeats() {
}
/**
* Subscribe to events from the sheet.
* @param html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
// Update Inventory Item
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
const item = this.actor.getOwnedItem(itemId);
item.sheet.render(true);
});
// Delete Inventory Item
html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
this.actor.deleteOwnedItem(itemId);
});
html.find('.feat-add').click(ev => {
this._createFeat();
});
html.find('.feat-delete').click(ev => {
const li = $(ev.currentTarget).parents(".feat");
const featId = li.data("featId");
console.log("Remove feat" + featId + " clicked");
this.actor.deleteOwnedItem(featId);
});
html.find('.feat-edit').click(ev => {
const li = $(ev.currentTarget).parents(".feat");
const featId = li.data("featId");
const feat = this.actor.getOwnedItem(featId);
feat.sheet.render(true);
});
html.find('.skill-name').click(ev => {
const li = $(ev.currentTarget).parents(".skill");
const skillId = li.data("skill");
this._onSkillClicked(skillId);
});
html.find('.adquisition-add').click(ev => {
this._createFeat();
});
}
/**
* Creates a new feat for the character and shows a window to edit it.
*/
async _createFeat() {
const data = {
name: game.i18n.localize('L5r5e.FeatPlaceholderName'),
type: "feat"
};
const created = await this.actor.createEmbeddedEntity("OwnedItem", data);
const feat = this.actor.getOwnedItem(created._id);
// Default values
//feat.rank = 1;
//feat.xp_used = 0;
feat.sheet.render(true);
return feat;
}
/**
* React to a skill from the skills list been clicked.
* @param {string} skillId Unique ID of the skill been clicked.
*/
async _onSkillClicked(skillId) {
console.log("Clicked on skill " + skillId);
// TODO
}
}

View File

@@ -0,0 +1,17 @@
/**
* Establish each L5r5e dice type here as extensions of DiceTerm.
* @extends {DiceTerm}
*/
export { AbilityDie } from "./dice/dietype/AbilityDie.js";
export { RingsDie } from "./dice/dietype/RingsDie.js";
/**
* New extension of the core DicePool class for evaluating rolls with the L5r5e DiceTerms
*/
export { RollL5r5e } from "./dice/roll.js";
/**
* Dice pool utility specializing in the L5r5e special dice
*/
export { DicePoolL5r5e } from "./dice/pool.js";

View File

@@ -0,0 +1,63 @@
export class AbilityDie extends DiceTerm {
constructor(termData) {
super(termData);
this.faces = 8;
}
/* -------------------------------------------- */
/** @override */
static DENOMINATION = "a";
/* -------------------------------------------- */
/** @override */
get formula() {
return `${this.number}${this.constructor.DENOMINATION}${this.modifiers.join("")}`;
}
/* -------------------------------------------- */
/** @override */
evaluate({ minimize = false, maximize = false } = {}) {
if (this._evaluated) {
throw new Error(`This ${this.constructor.name} has already been evaluated and is immutable`);
}
// Roll the initial number of dice
for (let n = 1; n <= this.number; n++) {
this.roll({ minimize, maximize });
}
// Apply modifiers
this._evaluateModifiers();
// Combine all FFG results.
this.ffg = { success: 0, failure: 0, advantage: 0, threat: 0, triumph: 0, despair: 0, light: 0, dark: 0 };
this.results.forEach((result) => {
this.ffg.success += parseInt(result.ffg.success);
this.ffg.failure += parseInt(result.ffg.failure);
this.ffg.advantage += parseInt(result.ffg.advantage);
this.ffg.threat += parseInt(result.ffg.threat);
this.ffg.triumph += parseInt(result.ffg.triumph);
this.ffg.despair += parseInt(result.ffg.despair);
this.ffg.light += parseInt(result.ffg.light);
this.ffg.dark += parseInt(result.ffg.dark);
});
// Return the evaluated term
this._evaluated = true;
this._isFFG = true;
return this;
}
/* -------------------------------------------- */
/** @override */
roll(options) {
const roll = super.roll(options);
roll.ffg = CONFIG.FFG.ABILITY_RESULTS[roll.result];
return roll;
}
/* -------------------------------------------- */
/** @override */
static getResultLabel(result) {
return CONFIG.FFG.ABILITY_RESULTS[result].label;
}
}

View File

@@ -0,0 +1,63 @@
export class RingsDie extends DiceTerm {
constructor(termData) {
super(termData);
this.faces = 12;
}
/* -------------------------------------------- */
/** @override */
static DENOMINATION = "p";
/* -------------------------------------------- */
/** @override */
get formula() {
return `${this.number}${this.constructor.DENOMINATION}${this.modifiers.join("")}`;
}
/* -------------------------------------------- */
/** @override */
evaluate({ minimize = false, maximize = false } = {}) {
if (this._evaluated) {
throw new Error(`This ${this.constructor.name} has already been evaluated and is immutable`);
}
// Roll the initial number of dice
for (let n = 1; n <= this.number; n++) {
this.roll({ minimize, maximize });
}
// Apply modifiers
this._evaluateModifiers();
// Combine all FFG results.
this.ffg = { success: 0, failure: 0, advantage: 0, threat: 0, triumph: 0, despair: 0, light: 0, dark: 0 };
this.results.forEach((result) => {
this.ffg.success += parseInt(result.ffg.success);
this.ffg.failure += parseInt(result.ffg.failure);
this.ffg.advantage += parseInt(result.ffg.advantage);
this.ffg.threat += parseInt(result.ffg.threat);
this.ffg.triumph += parseInt(result.ffg.triumph);
this.ffg.despair += parseInt(result.ffg.despair);
this.ffg.light += parseInt(result.ffg.light);
this.ffg.dark += parseInt(result.ffg.dark);
});
// Return the evaluated term
this._evaluated = true;
this._isFFG = true;
return this;
}
/* -------------------------------------------- */
/** @override */
roll(options) {
const roll = super.roll(options);
roll.ffg = CONFIG.FFG.PROFICIENCY_RESULTS[roll.result];
return roll;
}
/* -------------------------------------------- */
/** @override */
static getResultLabel(result) {
return CONFIG.FFG.PROFICIENCY_RESULTS[result].label;
}
}

View File

@@ -0,0 +1,8 @@
/**
* Dice pool utility specializing in the FFG special dice
*/
export class DicePoolL5r5e {
}

View File

@@ -0,0 +1,8 @@
/**
* New extension of the core DicePool class for evaluating rolls with the FFG DiceTerms
*/
export class RollL5r5e extends Roll {
}

View File

@@ -0,0 +1,51 @@
import { L5RItemSheet } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class L5RFeatSheet extends L5RItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r", "sheet", "feat"],
template: "systems/l5r/templates/item/feat-sheet.html",
width: 520,
height: 480,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}]
});
}
/** @override */
getData() {
const sheetData = super.getData();
sheetData.data.dtypes = ["String", "Number", "Boolean"];
sheetData.data.isFeat = true;
sheetData.data.isEquipment = false;
return sheetData;
}
/**
* Subscribe to events from the sheet.
* @param html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
}
/**
* Update feat with the data from the sheet.
* @param event
* @param formData
*/
_updateObject(event, formData) {
// Update the Item
return this.object.update(formData);
}
}

View File

@@ -0,0 +1,47 @@
/**
* Extend the basic ItemSheet with some very simple modifications
* @extends {ItemSheet}
*/
export class L5RItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r", "sheet", "item"],
template: "systems/l5r/templates/item/item-sheet.html",
width: 520,
height: 480,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}]
});
}
getData() {
const sheetData = super.getData();
sheetData.data.dtypes = ["String", "Number", "Boolean"];
sheetData.data.isEquipment = true;
return sheetData;
}
/**
* Subscribe to events from the sheet.
* @param html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
}
/**
* Update the item with data from the sheet.
* @param event
* @param formData
*/
_updateObject(event, formData) {
return this.object.update(formData);
}
}

View File

@@ -0,0 +1,4 @@
export class L5RItem extends Item {
}

View File

@@ -0,0 +1,48 @@
import { L5RItemSheet } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class L5RWeaponSheet extends L5RItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r", "sheet", "weapon"],
template: "systems/l5r/templates/item/weapon-sheet.html",
width: 520,
height: 480,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}]
});
}
getData() {
const sheetData = super.getData();
sheetData.data.dtypes = ["String", "Number", "Boolean"];
sheetData.data.isWeapon = true;
sheetData.data.isEquipment = true;
return sheetData;
}
/**
* Subscribe to events from the sheet.
* @param html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
}
/**
* Update item with values from the sheet.
* @param event
* @param formData
*/
_updateObject(event, formData) {
return this.object.update(formData);
}
}

View File

@@ -0,0 +1,75 @@
// Import Modules
import { RegisterSettings } from './settings.js';
import { PreloadTemplates } from './preloadTemplates.js';
import { ActorL5r5e } from "./actor-l5r5e.js";
import { ActorSheetL5r5e } from './sheets/actor-sheet.js';
// Import Dice Types
/* ------------------------------------ */
/* Initialize system */
/* ------------------------------------ */
Hooks.once('init', async function() {
console.log('l5r5e | Initializing l5r5e');
// Assign custom classes and constants here
CONFIG.Actor.entityClass = ActorL5r5e;
CONFIG.Actor.sheetClasses = ActorSheetL5r5e;
// Register custom system settings
RegisterSettings();
// Preload Handlebars templates
await PreloadTemplates();
// Register custom sheets (if any)
// Actors sheet
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("l5r5e", ActorSheetL5r5e, { types: ["character"], makeDefault: true });
Handlebars.registerHelper('localizeSkillCategory', function(skillName) {
const key = 'L5r5e.Skills.' + skillName + '.Title';
return game.i18n.localize(key);
});
Handlebars.registerHelper('localizeSkill', function(skillCategory, skillName) {
const key = 'L5r5e.Skills.' + skillCategory + '.' + skillName;
return game.i18n.localize(key);
});
Handlebars.registerHelper('localizeRing', function(ringName) {
const key = 'L5r5e.Rings.' + ringName.charAt(0).toUpperCase() + ringName.slice(1);
return game.i18n.localize(key);
});
Handlebars.registerHelper('localizeRingTip', function(ringName) {
const key = 'L5r5e.Rings.' + ringName.charAt(0).toUpperCase() + ringName.slice(1) + "Tip";
return game.i18n.localize(key);
});
Handlebars.registerHelper('localizeStanceTip', function(ringName) {
const key = 'L5r5e.Conflict.Stances.' + ringName.charAt(0).toUpperCase() + ringName.slice(1) + "Tip";
return game.i18n.localize(key);
});
});
/* ------------------------------------ */
/* Setup system */
/* ------------------------------------ */
Hooks.once('setup', function() {
// Do anything after initialization but before
// ready
});
/* ------------------------------------ */
/* Actor Dialog */
/* ------------------------------------ */
/* ------------------------------------ */
/* When ready */
/* ------------------------------------ */
Hooks.once('ready', function() {
// Do anything once the system is ready
});
// Add any additional hooks if necessary

View File

@@ -0,0 +1,25 @@
export const PreloadTemplates = async function() {
const templatePaths = [
// Add paths to "systems/l5r5e/templates"
'systems/l5r5e/templates/sheets/actor/rings.html',
'systems/l5r5e/templates/sheets/actor/identity.html',
'systems/l5r5e/templates/sheets/actor/category.html',
'systems/l5r5e/templates/sheets/actor/skill.html',
'systems/l5r5e/templates/sheets/actor/social.html',
'systems/l5r5e/templates/sheets/actor/conflict.html',
'systems/l5r5e/templates/sheets/actor/stance.html',
'systems/l5r5e/templates/sheets/actor/feats.html',
'systems/l5r5e/templates/sheets/actor/experience.html',
'systems/l5r5e/templates/sheets/actor/adquisition.html',
// items
'systems/l5r5e/templates/item/weapon-sheet.html',
'systems/l5r5e/templates/item/items.html',
'systems/l5r5e/templates/item/item-entry.html',
'systems/l5r5e/templates/item/weapons.html',
'systems/l5r5e/templates/item/weapon-entry.html',
'systems/l5r5e/templates/item/feat-sheet.html',
'systems/l5r5e/templates/item/feat-entry.html'
];
return loadTemplates(templatePaths);
}

View File

@@ -0,0 +1,4 @@
export const RegisterSettings = function() {
// Register any custom system settings here
}

View File

@@ -0,0 +1,142 @@
export class ActorSheetL5r5e extends ActorSheet {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "actor"],
template: "systems/l5r5e/templates/sheets/actor-sheet.html",
width: 600,
height: 600,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}],
dragDrop: [{dragSelector: ".item-list .item", dropSelector: null}]
});
}
getData() {
const sheetData = super.getData();
this._prepareItems(sheetData);
const feats = sheetData.items.filter((item) => item.type === "feat");
sheetData.data.feats = feats;
return sheetData;
}
/**
* Update the actor.
* @param event
* @param formData
*/
_updateObject(event, formData) {
return this.object.update(formData);
}
/**
* Prepare item data to be displayed in the actor sheet.
* @param sheetData Data of the actor been displayed in the sheet.
*/
_prepareItems(sheetData) {
for (let item of sheetData.items) {
if (item.type === "weapon") {
item.isWeapon = true;
item.isEquipment = true;
} else if (item.type === "feat"){
item.isFeat = true;
}
else {
item.isEquipment = true;
}
}
}
_prepareFeats() {
}
/**
* Subscribe to events from the sheet.
* @param html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
// Update Inventory Item
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
const item = this.actor.getOwnedItem(itemId);
item.sheet.render(true);
});
// Delete Inventory Item
html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
this.actor.deleteOwnedItem(itemId);
});
html.find('.feat-add').click(ev => {
this._createFeat();
});
html.find('.feat-delete').click(ev => {
const li = $(ev.currentTarget).parents(".feat");
const featId = li.data("featId");
console.log("Remove feat" + featId + " clicked");
this.actor.deleteOwnedItem(featId);
});
html.find('.feat-edit').click(ev => {
const li = $(ev.currentTarget).parents(".feat");
const featId = li.data("featId");
const feat = this.actor.getOwnedItem(featId);
feat.sheet.render(true);
});
html.find('.skill-name').click(ev => {
const li = $(ev.currentTarget).parents(".skill");
const skillId = li.data("skill");
this._onSkillClicked(skillId);
});
html.find('.adquisition-add').click(ev => {
this._createFeat();
});
}
/**
* Creates a new feat for the character and shows a window to edit it.
*/
async _createFeat() {
const data = {
name: game.i18n.localize('L5r5e.FeatPlaceholderName'),
type: "feat"
};
const created = await this.actor.createEmbeddedEntity("OwnedItem", data);
const feat = this.actor.getOwnedItem(created._id);
// Default values
//feat.rank = 1;
//feat.xp_used = 0;
feat.sheet.render(true);
return feat;
}
/**
* React to a skill from the skills list been clicked.
* @param {string} skillId Unique ID of the skill been clicked.
*/
async _onSkillClicked(skillId) {
console.log("Clicked on skill " + skillId);
// TODO
}
}

View File

View File

@@ -0,0 +1,13 @@
/* Global */
@import "../scss/fonts";
@import "../scss/colors";
@import "../scss/ui";
@import "../scss/dices";
.l5r5e {
@import "../scss/sheet";
@import "../scss/nav";
@import "../scss/rings";
@import "../scss/skills";
@import "../scss/items";
}

1
system/styles/l5r5e.css Normal file
View File

@@ -0,0 +1 @@
.testing{width:14.28571%}.testing{width:28.57143%}.testing{width:14.28571%}.testing{width:28.57143%}.testing{width:14.28571%}.testing{width:28.57143%}.testing{width:14.28571%}.testing{width:28.57143%}.l5r5e .testing{width:14.28571%}.l5r5e .testing{width:28.57143%}.l5r5e .testing{width:14.28571%}.l5r5e .testing{width:28.57143%}.l5r5e .testing{width:14.28571%}.l5r5e .testing{width:28.57143%}.l5r5e .testing{width:14.28571%}.l5r5e .testing{width:28.57143%}.l5r5e .testing{width:14.28571%}.l5r5e .testing{width:28.57143%}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -0,0 +1,9 @@
//SCSS
// l5re5.scss
.testing {
width: percentage(1/7);
}
// test
.testing {
width: percentage(2/7);
}

View File

@@ -1,14 +1,14 @@
{ {
"name": "l5r5e", "name": "l5r5e",
"title": "Legend of the Five Rings (5th Edition)", "title": "Legend of the Five Rings (5th Edition)",
"description": "Legend of the Five Rings 5 Edition by <a href='https://edge-studio.net/'> Edge Studio </a>. <p> *** Rejoignez la communauté Discord FR :<a href='https://discord.gg/pPSDNJk'> https://discord.gg/pPSDNJk </a></p>", "description": "This is a game system for Legend of the Five Rings (5th Edition) by <a href='https://edge-studio.net/'>Edge Studio</a> - EN/FR - <p> - Foundry <a href='https://discord.gg/foundryvtt'>Discord EN</a></p><p> - Rejoignez la communauté Francophone <a href='https://discord.gg/pPSDNJk'>Discord FR - https://discord.gg/pPSDNJk</a></p>",
"version": "0.0.1", "version": "0.0.1",
"minimumCoreVersion": "0.7.7", "minimumCoreVersion": "0.7.7",
"compatibleCoreVersion": "1.0.0", "compatibleCoreVersion": "1.0.0",
"author": "Team L5R", "author": "Team L5R",
"esmodules": [],
"styles": [],
"scripts": [], "scripts": [],
"esmodules" : ["./scripts/dice-l5r5e.js", "./scripts/main-l5r5e.js"],
"styles": ["./styles/l5r5e.css"],
"languages": [ "languages": [
{ {
"lang": "en", "lang": "en",

134
system/template.json Normal file
View File

@@ -0,0 +1,134 @@
{
"Actor": {
"types": ["character"],
"templates": {
"identity" : {
"clan": "",
"family": "",
"school": "",
"school_rank": 0,
"roles": ""
},
"rings": {
"rings": {
"earth": 1,
"air": 1,
"water": 1,
"fire": 1,
"void": 1
}
},
"social_standing": {
"social_standing": {
"honor": 0,
"glory": 0,
"status": 0,
"ninjo": "",
"giri": "",
"titles": ""
}
},
"skills": {
"skills": {
"artisan": {
"aesthetics": 0,
"composition": 0,
"design": 0,
"smithing": 0
},
"martial": {
"fitness": 0,
"melee": 0,
"ranged": 0,
"unarmed": 0,
"meditation": 0,
"tactics": 0
},
"scholar": {
"culture": 0,
"government": 0,
"medicine": 0,
"sentiment": 0,
"theology": 0
},
"social": {
"command": 0,
"courtesy": 0,
"games": 0,
"performance": 0
},
"trade": {
"commerce": 0,
"labor": 0,
"seafaring": 0,
"skulduggery": 0,
"survival": 0
}
}
},
"conflict": {
"endurance": 0,
"composure": 0,
"focus": 0,
"vigilante": 0,
"void_points": {
"max": 0,
"current": 0
},
"fatigue": 0,
"strife": 0,
"stances": {
"air": {
"isSelected": false
},
"earth": {
"isSelected": false
},
"fire": {
"isSelected": false
},
"water": {
"isSelected": false
},
"void": {
"isSelected": false
}
}
},
"xp": {
"xp_total": 0,
"xp_spent": 0,
"xp_saved": 0
}
},
"character": {
"templates": ["identity", "rings", "social", "category", "conflict", "experience"],
"notes": "",
"feats": []
}
},
"Item": {
"types": ["item", "weapon", "feat"],
"item": {
"description": "",
"quantity": 1,
"weight": 0
},
"weapon" : {
"quantity": 1,
"weight": 0,
"description": "",
"damage": 0,
"range": 0,
"properties": ""
},
"feat": {
"feat_type": "",
"xp_used": 0,
"rank": 0,
"ring": "",
"description": ""
}
}
}

View File

@@ -0,0 +1,13 @@
<li class="feat flexcolumn" data-feat-id="{{feat._id}}">
<div class="feat-header">
<img src="{{feat.img}}" title="{{feat.name}}" width="32px" height="32px"/>
<h4 class="feat-name">{{ feat.name }}</h4>
<div class="feat-controls" style="margin-left: auto;">
<a class="feat-control feat-edit" title="Edit Feat"><i class="fas fa-edit"></i></a>
<a class="faet-control feat-delete" title="Delete Feat"><i class="fas fa-trash"></i></a>
</div>
</div>
<div class="feat-description">
{{{ feat.data.description }}}
</div>
</li>

View File

@@ -0,0 +1,37 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name"/></h1>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="description">Description</a>
<a class="item" data-tab="attributes">Attributes</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Description Tab --}}
<div class="tab" data-group="primary" data-tab="description">
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
{{!-- Attributes Tab --}}
<div class="tab attributes" data-group="primary" data-tab="attributes">
<div class="flexrow">
<div class="attribute-container">
<label class="attribute-label">{{ localize 'L5r5e.XP.Spent' }}</label>
<input type="text" name="data.xp_used" value="{{data.xp_used}}" data-dtype="Number" placeholder="0"/>
</div>
<div class="attribute-container">
<label class="attribute-label">{{ localize 'L5r5e.Rank' }}</label>
<input type="text" name="data.rank" value="{{data.rank}}" data-dtype="Number" placeholder="0"/>
</div>
</div>
</div>
</section>
</form>

View File

@@ -0,0 +1,8 @@
<li class="item flexrow" data-item-id="{{item._id}}" style="height: auto !important; align-items: center;">
<img src="{{item.img}}" title="{{item.name}}" width="32px" height="32px"/>
<h4 class="item-name">{{ item.name }} x{{ item.data.quantity }}</h4>
<div class="item-controls">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>

View File

@@ -0,0 +1,64 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name"/></h1>
<div class="resource">
<label>Quantity</label>
<input type="text" name="data.quantity" value="{{data.quantity}}" data-dtype="Number"/>
</div>
<div class="resource">
<label>Weight</label>
<input type="text" name="data.weight" value="{{data.weight}}" data-dtype="Number"/>
</div>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="description">Description</a>
<a class="item" data-tab="attributes">Attributes</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Description Tab --}}
<div class="tab" data-group="primary" data-tab="description">
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
{{!-- Attributes Tab --}}
<div class="tab attributes" data-group="primary" data-tab="attributes">
<header class="attributes-header flexrow">
<span class="attribute-key">Attribute Key</span>
<span class="attribute-value">Value</span>
<span class="attribute-label">Label</span>
<span class="attribute-dtype">Data Type</span>
<a class="attribute-control" data-action="create"><i class="fas fa-plus"></i></a>
</header>
<ol class="attributes-list">
{{#each data.attributes as |attr key|}}
<li class="attribute flexrow" data-attribute="{{key}}">
<input class="attribute-key" type="text" name="data.attributes.{{key}}.key" value="{{key}}"/>
{{#if attr.isCheckbox}}
<label class="attribute-value checkbox"><input type="checkbox" name="data.attributes.{{key}}.value" {{checked attr.value}}/></label>
{{else}}
<input class="attribute-value" type="text" name="data.attributes.{{key}}.value" value="{{attr.value}}" data-dtype="{{attr.dtype}}"/>
{{/if}}
<input class="attribute-label" type="text" name="data.attributes.{{key}}.label" value="{{attr.label}}"/>
<select class="attribute-dtype" name="data.attributes.{{key}}.dtype">
{{#select attr.dtype}}
{{#each ../dtypes as |t|}}
<option value="{{t}}">{{t}}</option>
{{/each}}
{{/select}}
</select>
<a class="attribute-control" data-action="delete"><i class="fas fa-trash"></i></a>
</li>
{{/each}}
</ol>
</div>
</section>
</form>

View File

@@ -0,0 +1,9 @@
<div class="items-content">
<ul class="item-list">
{{#each actor.items as |item id|}}
{{#if item.isEquipment }}
{{> 'systems/l5r5e/templates/item/item-entry.html' item=item id=id }}
{{/if}}
{{/each}}
</ul>
</div>

View File

@@ -0,0 +1,16 @@
<li class="item flexrow" data-item-id="{{item._id}}" style="height: auto !important; align-items: center;">
<img src="{{item.img}}" title="{{item.name}}" width="32px" height="32px"/>
<h4 class="item-name">{{ item.name }}</h4>
<div class="icon-stat-container">
<i class="fas fa-certificate"></i>
<span class="centered-input" style="width: 32px;">{{item.data.damage}}</span>
</div>
<div class="icon-stat-container">
<i class="fas fa-arrows-alt-h"></i>
<span class="centered-input" style="width: 32px;">{{item.data.range}}</span>
</div>
<div class="item-controls">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>

View File

@@ -0,0 +1,41 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name"/></h1>
<div class="resource">
<label>{{ localize 'L5r5e.Quantity' }}</label>
<input type="text" name="data.quantity" value="{{data.quantity}}" data-dtype="Number"/>
</div>
<div class="resource">
<label>{{ localize 'L5r5e.Weight' }}</label>
<input type="text" name="data.weight" value="{{data.weight}}" data-dtype="Number"/>
</div>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="description">Description</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Description Tab --}}
<div class="tab" data-group="primary" data-tab="description">
<div class="weapon-stats-content">
<div>
<label class="attribute-label">{{ localize 'L5r5e.Damage' }}</label>
<input type="text" name="data.damage" value="{{data.damage}}" data-dtype="Number" placeholder="0"/>
</div>
<div>
<label class="attribute-label">{{ localize 'L5r5e.Range' }}</label>
<input type="text" name="data.range" value="{{data.range}}" data-dtype="Number" placeholder="0"/>
</div>
</div>
<h4 class="text-block-header">{{ localize 'L5r5e.Properties' }}</h4>
{{editor content=data.properties target="data.properties" button=true owner=owner editable=editable}}
</div>
</section>
</form>

View File

@@ -0,0 +1,10 @@
<div class="weapons-content">
<h4 class="section-header">{{ localize 'L5r5e.Weapons' }}</h4>
<ul class="item-list">
{{#each actor.items as |item id|}}
{{#if item.isWeapon }}
{{> 'systems/l5r5e/templates/item/weapon-entry.html' item=item id=id }}
{{/if}}
{{/each}}
</ul>
</div>

View File

@@ -0,0 +1,54 @@
<form class="{{cssClass}}" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
{{> 'systems/l5r5e/templates/sheets/actor/rings.html' }}
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="narrative">{{ localize 'L5r5e.Narrative' }}</a>
<a class="item" data-tab="skills">{{ localize 'L5r5e.Skills.Title' }}</a>
<a class="item" data-tab="conflict">{{ localize 'L5r5e.Conflict.Title' }}</a>
<a class="item" data-tab="inventory">{{ localize 'L5r5e.Inventory' }}</a>
<a class="item" data-tab="experience">{{ localize 'L5r5e.Experience' }}</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Narrative Tab --}}
<article class="tab narrative" data-group="primary" data-tab="narrative">
{{> 'systems/l5r5e/templates/sheets/actor/identity.html' }}
{{> 'systems/l5r5e/templates/sheets/actor/social.html' }}
<h4 class="text-block-header">{{ localize 'L5r5e.Notes' }}</h4>
{{ editor content=data.notes.value target="data.notes.value" button=true editable=editable }}
</article>
{{!-- Skills Tab --}}
<article class="tab skills" data-group="primary" data-tab="skills">
<ul class="skills-wrapper">
{{#each data.skills as |category id|}}
{{> 'systems/l5r/templates/sheets/actor/category.html' category=category categoryId=id}}
{{/each}}
</ul>
{{> 'systems/l5r5e/templates/sheets/actor/feats.html' }}
</article>
{{!-- Conflict Tab --}}
<article class="tab conflict" data-group="primary" data-tab="conflict">
{{> 'systems/l5r5e/templates/sheets/actor/conflict.html' }}
</article>
<article class="tab narrative" data-group="primary" data-tab="inventory">
{{> 'systems/l5r5e/templates/item/items.html' }}
</article>
{{!-- Experience Tab --}}
<article class="tab experience" data-group="primary" data-tab="experience">
{{> 'systems/l5r5e/templates/sheets/actor/experience.html' }}
</article>
</section>
</form>

View File

@@ -0,0 +1,5 @@
<div class="flexrow row">
<span class="name" name="adquisition.name">{{ adquisition.name }}</span>
<span class="xp" name="adquisition.xp">{{ adquisition.data.xp_used }}</span>
<span class="rank" name="adquisition.rank">{{ adquisition.data.rank }}</span>
</div>

View File

@@ -0,0 +1,15 @@
<li class="category-wrapper category-content">
<h4 class="section-header">{{ localizeSkillCategory categoryId }}</h4>
<ul class="skill-category-skills-list">
{{#each category as |skill id| }}
{{> 'systems/l5r/templates/sheets/actor/skill.html' categoryId=../categoryId skill=skill skillId=id }}
{{/each}}
</ul>
<div class="skill-category-ring-actions">
<label name="air" class="air"><i class="i_air"></i> {{ localizeSkill categoryId 'Air' }} </label>
<label name="earth" class="earth"><i class="i_earth"></i> {{ localizeSkill categoryId 'Earth' }} </label>
<label name="fire" class="fire"><i class="i_fire"></i> {{ localizeSkill categoryId 'Fire' }} </label>
<label name="water" class="water"><i class="i_water"></i> {{ localizeSkill categoryId 'Water' }} </label>
<label name="void" class="void"><i class="i_void"></i> {{ localizeSkill categoryId 'Void' }} </label>
</div>
</li>

View File

@@ -0,0 +1,70 @@
<div class="conflict-wrapper">
<div class="conflict-top-content">
<div class="conflict-stats-content">
<div>
<div class="endurance-content">
<div>
<label class="attribute-label">{{ localize 'L5r5e.Conflict.Endurance' }}</label>
<input class="centered-input" type="text" name="data.endurance" value="{{data.endurance}}" data-dtype="Number" disabled/>
</div>
<div>
<label class="attribute-label">{{ localize 'L5r5e.Conflict.Fatigue' }}</label>
<input class="centered-input" type="text" name="data.fatigue" value="{{data.fatigue}}" data-dtype="Number"/>
</div>
</div>
<p class="quick-rules"> {{ localize 'L5r5e.Conflict.EnduranceTip' }}</p>
</div>
<div>
<div class="composure-content">
<div>
<label class="attribute-label">{{ localize 'L5r5e.Conflict.Composure' }}</label>
<input class="centered-input" type="text" name="data.composure" value="{{data.composure}}" data-dtype="Number" disabled/>
</div>
<div>
<label class="attribute-label">{{ localize 'L5r5e.Conflict.Strife' }}</label>
<input class="centered-input" type="text" name="data.strife" value="{{data.strife}}" data-dtype="Number"/>
</div>
</div>
<p class="quick-rules"> {{ localize 'L5r5e.Conflict.ComposureTip' }}</p>
</div>
<div>
<div class="focus-content">
<div>
<label class="attribute-label">{{ localize 'L5r5e.Conflict.Focus' }}</label>
<input class="centered-input" type="text" name="data.focus" value="{{data.focus}}" data-dtype="Number" disabled/>
</div>
</div>
<p class="quick-rules"> {{ localize 'L5r5e.Conflict.FocusTip' }}</p>
</div>
<div>
<div class="vigilante-content">
<div>
<label class="attribute-label">{{ localize 'L5r5e.Conflict.Vigilante' }}</label>
<input class="centered-input" type="text" name="data.vigilante" value="{{data.vigilante}}" data-dtype="Number" disabled/>
</div>
</div>
<p class="quick-rules"> {{ localize 'L5r5e.Conflict.VigilanteTip' }}</p>
</div>
<div>
<div class="void-points-content">
<div>
<label class="attribute-label"> {{ localize 'L5r5e.Conflict.VoidPoints' }}</label>
<input class="centered-input" type="text" name="data.void_points.current" value="{{data.void_points.current}}" data-dtype="Number"/>
</div>
<div>
<label class="attribute-label"> {{ localize 'L5r5e.Max' }}</label>
<input class="centered-input" type="text" name="data.void_points.max" value="{{data.void_points.max}}" data-dtype="Number" disabled/>
</div>
</div>
</div>
</div>
<div class="conflict-stances-content">
<h4 class="section-header">{{ localize 'L5r5e.Conflict.Stance' }}</h4>
{{#each data.stances as |stance stanceId|}}
{{> 'systems/l5r5e/templates/sheets/actor/stance.html' stance=stance stanceId=stanceId }}
{{/each}}
</div>
{{> 'systems/l5r5e/templates/item/weapons.html' }}
</div>
</div>
</div>

View File

@@ -0,0 +1,31 @@
<div class="tab-container">
<div class="flexrow" style="flex: 0 0 100px; justify-content: center;">
<div class="short-attribute-container">
<h4 class="attribute-label center">{{ localize 'L5r5e.XP.Total' }}</h4>
<input type="text" name="data.xp_total" value="{{ data.xp_total }}" data-dtype="Number" placeholder="0"/>
</div>
<div class="short-attribute-container">
<h4 class="attribute-label">{{ localize 'L5r5e.XP.Spent' }}</h4>
<input type="text" name="data.xp_spent" value="{{ data.xp_spent }}" data-dtype="Number" placeholder="0"/>
</div>
<div class="short-attribute-container">
<h4 class="attribute-label">{{ localize 'L5r5e.XP.Saved' }}</h4>
<input type="text" name="data.xp_saved" value="{{ data.xp_saved }}" data-dtype="Number" placeholder="0"/>
</div>
</div>
<div class="adquisitions">
<h4 class="section-header flexrow">{{ localize 'L5r5e.XP.Adquisitions'}}</h4>
<header class="flexrow row">
<h4 class="name">{{ localize 'L5r5e.Name' }}</h4>
<h4 class="xp">{{ localize 'L5r5e.XP.Spent' }}</h4>
<h4 class="rank">{{ localize 'L5r5e.Rank' }}</h4>
</header>
{{#each data.feats as |feat featId| }}
{{> 'systems/l5r5e/templates/sheets/actor/adquisition.html' adquisition=feat }}
{{/each}}
<div class="tools">
<a class="adquisition-control adquisition-add" title="{{ localize 'L5r5e.Add'}}"><i class="fas fa-plus"></i></a>
</div>
</div>
</div>

View File

@@ -0,0 +1,15 @@
<div class="feats-wrapper">
<div class="section-header flexrow">
<h4 style="margin: 0; font-weight: bold;">{{ localize 'L5r5e.Feats' }}</h4>
<div class="feat-controls">
<a class="feat-control feat-add" title="Add Item"><i class="fas fa-plus"></i></a>
</div>
</div>
<ul class="item-list">
{{#each actor.items as |item id|}}
{{#if item.isFeat }}
{{> 'systems/l5r5e/templates/item/feat-entry.html' feat=item }}
{{/if}}
{{/each}}
</ul>
</div>

View File

@@ -0,0 +1,22 @@
<ul class="identity-wrapper">
<li>
<label class="attribute-label">{{ localize 'L5r5e.Clan' }}</label>
<input type="text" name="data.identity.clan" value="{{data.identity.clan}}"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.Family' }}</label>
<input type="text" name="data.identity.family" value="{{data.identity.family}}"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.School' }}</label>
<input type="text" name="data.identity.school" value="{{data.identity.school}}"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.SchoolRank' }}</label>
<input type="text" name="data.identity.school_rank" value="{{data.identity.school_rank}}" data-dtype="Number" placeholder="0"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.Roles' }}</label>
<input type="text" name="data.identity.roles" value="{{data.identity.roles}}"/>
</li>
</ul>

View File

@@ -0,0 +1,22 @@
<ul class="rings">
<li id="earth">
<label class="attribute-label earth centered-input"><i class="i_earth"></i> {{ localizeRing 'Earth' }}</label>
<input class="centered-input" type="text" name="data.rings.earth" value="{{data.rings.earth}}" data-dtype="Number" placeholder="0"/>
</li>
<li id="air">
<label class="attribute-label air centered-input"><i class="i_air"></i> {{ localizeRing 'Air' }}</label>
<input class="centered-input" type="text" name="data.rings.air" value="{{data.rings.air}}" data-dtype="Number" placeholder="0"/>
</li>
<li id="water">
<label class="attribute-label water centered-input"><i class="i_water"></i> {{ localizeRing 'Water' }}</label>
<input class="centered-input" type="text" name="data.rings.water" value="{{data.rings.water}}" data-dtype="Number" placeholder="0"/>
</li>
<li id="fire">
<label class="attribute-label fire centered-input"><i class="i_fire"></i> {{ localizeRing 'Fire' }}</label>
<input class="centered-input" type="text" name="data.rings.fire" value="{{data.rings.fire}}" data-dtype="Number" placeholder="0"/>
</li>
<li id="void">
<label class="attribute-label void centered-input"><i class="i_void"></i> {{ localizeRing 'Void' }}</label>
<input class="centered-input" type="text" name="data.rings.void" value="{{data.rings.void}}" data-dtype="Number" placeholder="0"/>
</li>
</ul>

View File

@@ -0,0 +1,6 @@
<li class="skill skill-wrapper skill-content" data-skill="{{skillId}}">
<label class="skill-name attribute-label rollable">{{ localizeSkill categoryId skillId }}
<input type="text" name="data.skills.{{categoryId}}.{{skillId}}.value" value="{{skill.value}}" data-dtype="Number" placeholder="0"/>
</label>
<!-- Roll button -->
</li>

View File

@@ -0,0 +1,26 @@
<ul class="social-wrapper">
<li>
<label class="attribute-label centered-input">{{ localize 'L5r5e.SocialStanding.Honor' }}</label>
<input class="centered-input" type="text" name="data.social_standing.honor" value="{{data.social_standing.honor}}" placeholder="0"/>
</li>
<li>
<label class="attribute-label centered-input">{{ localize 'L5r5e.SocialStanding.Glory' }}</label>
<input class="centered-input" type="text" name="data.social_standing.glory" value="{{data.social_standing.glory}}" placeholder="0"/>
</li>
<li>
<label class="attribute-label centered-input">{{ localize 'L5r5e.SocialStanding.Status' }}</label>
<input class="centered-input" type="text" name="data.social_standing.status" value="{{data.social_standing.status}}" placeholder="0"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.SocialStanding.Ninjo' }}</label>
<input type="text" name="data.social_standing.ninjo" value="{{data.social_standing.ninjo}}"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.SocialStanding.Giri' }}</label>
<input type="text" name="data.social_standing.giri" value="{{data.social_standing.giri}}"/>
</li>
<li>
<label class="attribute-label">{{ localize 'L5r5e.SocialStanding.SocialTitles' }}</label>
<input type="text" name="data.social_standing.titles" value="{{data.social_standing.titles}}"/>
</li>
</ul>

View File

@@ -0,0 +1,5 @@
<div class="stance-content">
<input type="checkbox" name="data.stances.{{stanceId}}.isSelected.value" {{ checked stance.isSelected.value }}/>
<label class="stance-title {{stanceId}}">{{ localizeRing stanceId }}</label>
<p class="quick-rules" style="display: inline;"> {{ localizeStanceTip stanceId }}</p>
</div>