Template and raw sheet for npc

This commit is contained in:
Vlyan
2020-12-13 16:28:25 +01:00
parent 903229c25b
commit ec2acf1648
14 changed files with 352 additions and 48 deletions

View File

@@ -37,7 +37,7 @@ Hooks.once("ready", async function () {
//----logo image
var logo = document.getElementById("logo");
logo.setAttribute("src", "systems/l5r5e/assets/l5r-logo.webp");
logo.setAttribute("src", CONFIG.L5r5e.paths.assets + "l5r-logo.webp");
//--------------ouvrir le menu lien sur click logo
logo.setAttribute("title", "Aide en Ligne");

View File

@@ -1,22 +1,26 @@
/**
* Extends the actor to process special things from L5R.
*/
export class ActorL5r5e extends Actor {
/** @override */
/**
* Create a new entity using provided input data
* @override
*/
static async create(data, options = {}) {
if(!Object.keys(data).includes("type")) data.type = "character";
if (!Object.keys(data).includes("type")) {
data.type = "character";
}
await super.create(data, options);
}
/** @override */
prepareData() {
super.prepareData();
const actorData = this.data;
const data = actorData.data;
const isCharacter = actorData.type === "character";
const isCharacter = ["character", "npc"].includes(actorData.type);
if (isCharacter) {
data.endurance = (Number(data.rings.earth) + Number(data.rings.fire)) * 2;

View File

@@ -5,8 +5,6 @@
import { RollL5r5e } from "./roll.js";
export class DicePickerDialog extends Application {
static stances = ["earth", "air", "water", "fire", "void"];
/**
* Current Actor
*/
@@ -43,7 +41,7 @@ export class DicePickerDialog extends Application {
return mergeObject(super.defaultOptions, {
id: "l5r5e-dice-picker-dialog",
classes: ["l5r5e", "dice-picker-dialog"],
template: "systems/l5r5e/templates/dice/dice-picker-dialog.html",
template: CONFIG.L5r5e.paths.templates + "dice/dice-picker-dialog.html",
title: "L5R Dice Roller",
width: 660,
height: 460,
@@ -106,7 +104,7 @@ export class DicePickerDialog extends Application {
* @param ringId
*/
set ringId(ringId) {
this._ringId = DicePickerDialog.stances.includes(ringId) || null;
this._ringId = CONFIG.L5r5e.stances.includes(ringId) || null;
}
/**
@@ -131,7 +129,20 @@ export class DicePickerDialog extends Application {
}
this._skillData.cat = cat;
this._skillData.name = game.i18n.localize("l5r5e.skills." + cat + "." + this._skillData.id);
this._skillData.value = this._actor?.data?.data?.skills[cat]?.[this._skillData.id].value || 0;
if (!this._actor) {
return;
}
switch (this._actor.data.type) {
case "character":
this._skillData.value = this._actor.data.data.skills[cat]?.[this._skillData.id]?.value || 0;
break;
case "npc":
// Skill value is in categories for npc
this._skillData.value = this._actor.data.data.skills[cat] || 0;
break;
}
}
/**
@@ -174,6 +185,7 @@ export class DicePickerDialog extends Application {
dicesList: [0, 1, 2, 3, 4, 5, 6],
skillData: this._skillData,
actor: this._actor,
actorIsPc: !this._actor || this._actor.data?.type === "character",
difficulty: this._difficulty,
canUseVoidPoint: !this._actor || this._actor.data.data.void_points.current > 0,
};
@@ -362,7 +374,7 @@ export class DicePickerDialog extends Application {
* @private
*/
_getElements() {
return DicePickerDialog.stances.map((e) => {
return CONFIG.L5r5e.stances.map((e) => {
return {
id: e,
label: game.i18n.localize(`l5r5e.rings.${e}`),

View File

@@ -4,11 +4,8 @@ import { L5rBaseDie } from "./dietype/l5r-base-die.js";
* Roll for L5R5e
*/
export class RollL5r5e extends Roll {
static CHAT_TEMPLATE = "systems/l5r5e/templates/dice/chat-roll.html";
static TOOLTIP_TEMPLATE = "systems/l5r5e/templates/dice/tooltip.html";
// static CHAT_TEMPLATE = `${CONFIG.L5r5e.pathTemplates}dice/chat-roll.html`;
// static TOOLTIP_TEMPLATE = `${CONFIG.L5r5e.pathTemplates}dice/tooltip.html`;
static CHAT_TEMPLATE = "dice/chat-roll.html";
static TOOLTIP_TEMPLATE = "dice/tooltip.html";
constructor(...args) {
super(...args);
@@ -175,7 +172,7 @@ export class RollL5r5e extends Roll {
displaySummary: contexte?.from !== "render",
};
return renderTemplate(this.constructor.TOOLTIP_TEMPLATE, { chatData });
return renderTemplate(CONFIG.L5r5e.paths.templates + this.constructor.TOOLTIP_TEMPLATE, { chatData });
}
/**
@@ -187,7 +184,7 @@ export class RollL5r5e extends Roll {
{
user: game.user._id,
flavor: null,
template: this.constructor.CHAT_TEMPLATE,
template: CONFIG.L5r5e.paths.templates + this.constructor.CHAT_TEMPLATE,
blind: false,
},
chatOptions

View File

@@ -8,7 +8,7 @@ export class FeatSheetL5r5e extends ItemSheetL5r5e {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "feat"],
template: "systems/l5r5e/templates/item/feat-sheet.html",
template: CONFIG.L5r5e.paths.templates + "item/feat-sheet.html",
width: 520,
height: 480,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],

View File

@@ -7,7 +7,7 @@ export class ItemSheetL5r5e extends ItemSheet {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "item"],
template: "systems/l5r5e/templates/item/item-sheet.html",
template: CONFIG.L5r5e.paths.templates + "item/item-sheet.html",
width: 520,
height: 480,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],

View File

@@ -8,7 +8,7 @@ export class WeaponSheetL5r5e extends ItemSheetL5r5e {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "weapon"],
template: "systems/l5r5e/templates/item/weapon-sheet.html",
template: CONFIG.L5r5e.paths.templates + "item/weapon-sheet.html",
width: 520,
height: 480,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],

View File

@@ -0,0 +1,8 @@
export const L5R5E = {};
L5R5E.stances = ["earth", "air", "water", "fire", "void"];
L5R5E.paths = {
assets: `systems/l5r5e/assets/`,
templates: `systems/l5r5e/templates/`,
};

View File

@@ -1,8 +1,10 @@
// Import Modules
import { L5R5E } from "./l5r5e-config.js";
import { RegisterSettings } from "./settings.js";
import { PreloadTemplates } from "./preloadTemplates.js";
import { ActorL5r5e } from "./actor-l5r5e.js";
import { ActorSheetL5r5e } from "./sheets/actor-sheet.js";
import { NpcSheetL5r5e } from "./sheets/npc-sheet.js";
import { RollL5r5e, AbilityDie, RingDie, DicePickerDialog } from "./dice-l5r5e.js";
import { ItemL5r5e } from "./items/item.js";
import { ItemSheetL5r5e } from "./items/item-sheet.js";
@@ -15,7 +17,18 @@ import { FeatSheetL5r5e } from "./items/feat-sheet.js";
/* Initialize system */
/* ------------------------------------ */
Hooks.once("init", async function () {
console.log("l5r5e | Initializing l5r5e");
// console.log("L5R5e | Initializing l5r5e");
// Ascii art
console.log(
" _ ___ ___ ___\n" +
" | | | __| _ \\ | __| ___ \n" +
" | |__|__ \\ / |__ \\/ -_)\n" +
" |____|___/_|_\\ |___/\\___|\n" +
" "
);
// Global access to L5R Config
CONFIG.L5r5e = L5R5E;
// Assign custom classes and constants here
CONFIG.Actor.entityClass = ActorL5r5e;
@@ -35,14 +48,6 @@ Hooks.once("init", async function () {
DicePickerDialog,
};
// Define L5R Paths
CONFIG.L5r5e = {
paths: {
assets: `systems/l5r5e/assets/`,
templates: `systems/l5r5e/templates/`,
},
};
// Register custom system settings
RegisterSettings();
@@ -53,6 +58,7 @@ Hooks.once("init", async function () {
// Actors sheet
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("l5r5e", ActorSheetL5r5e, { types: ["character"], makeDefault: true });
Actors.registerSheet("l5r5e", NpcSheetL5r5e, { types: ["npc"], makeDefault: false });
// Items sheet
Items.unregisterSheet("core", ItemSheet);

View File

@@ -2,7 +2,7 @@ export class ActorSheetL5r5e extends ActorSheet {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "actor"],
template: "systems/l5r5e/templates/sheets/actor-sheet.html",
template: CONFIG.L5r5e.paths.templates + "sheets/actor-sheet.html",
width: 600,
height: 800,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
@@ -61,7 +61,7 @@ export class ActorSheetL5r5e extends ActorSheet {
if (!this.options.editable) return;
// Update Inventory Item
html.find(".item-edit").click((ev) => {
html.find(".item-edit").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
const item = this.actor.getOwnedItem(itemId);
@@ -69,17 +69,17 @@ export class ActorSheetL5r5e extends ActorSheet {
});
// Delete Inventory Item
html.find(".item-delete").click((ev) => {
html.find(".item-delete").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
this.actor.deleteOwnedItem(itemId);
});
html.find(".feat-add").click((ev) => {
html.find(".feat-add").on("click", (ev) => {
this._createFeat();
});
html.find(".feat-delete").click((ev) => {
html.find(".feat-delete").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".feat");
const featId = li.data("featId");
console.log("Remove feat" + featId + " clicked");
@@ -87,21 +87,21 @@ export class ActorSheetL5r5e extends ActorSheet {
this.actor.deleteOwnedItem(featId);
});
html.find(".feat-edit").click((ev) => {
html.find(".feat-edit").on("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) => {
html.find(".skill-name").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".skill");
const skillId = li.data("skill");
this._onSkillClicked(skillId);
});
html.find(".acquisition-add").click((ev) => {
html.find(".acquisition-add").on("click", (ev) => {
this._createFeat();
});
}

View File

@@ -0,0 +1,141 @@
// TODO extend ActorSheetL5r5e ?
export class NpcSheetL5r5e extends ActorSheet {
static types = ["minion", "adversary"];
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "npc"],
template: CONFIG.L5r5e.paths.templates + "sheets/npc-sheet.html",
width: 600,
height: 800,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
});
}
getData() {
const sheetData = super.getData();
this._prepareItems(sheetData);
sheetData.data.feats = sheetData.items.filter((item) => item.type === "feat");
sheetData.data.types = NpcSheetL5r5e.types;
sheetData.data.stances = CONFIG.L5r5e.stances;
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").on("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").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("itemId");
this.actor.deleteOwnedItem(itemId);
});
html.find(".feat-add").on("click", (ev) => {
this._createFeat();
});
html.find(".feat-delete").on("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").on("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").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".skill");
const skillId = li.data("skill");
this._onSkillClicked(skillId);
});
html.find(".acquisition-add").on("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);
new game.l5r5e.DicePickerDialog({ skillId: skillId, actor: this.actor }).render();
}
}

View File

@@ -1,6 +1,6 @@
{
"Actor": {
"types": ["character"],
"types": ["character", "npc"],
"templates": {
"identity": {
"clan": "",
@@ -89,6 +89,35 @@
"templates": ["identity", "rings", "social", "skills", "conflict", "xp"],
"notes": "",
"feats": []
},
"npc": {
"templates": ["rings", "social", "conflict"],
"name": "",
"type": "minion",
"attitude": "",
"notes": "",
"conflict_rank": {
"martial": 0,
"social": 0
},
"rings_affinities": {
"strength": {
"ring": "fire",
"value": 2
},
"weakness": {
"ring": "water",
"value": -2
}
},
"skills": {
"artisan": 0,
"martial": 0,
"scholar": 0,
"social": 0,
"trade": 0
},
"feats": []
}
},
"Item": {

View File

@@ -35,9 +35,13 @@
<div>
<label>{{localizeSkill skillData.cat 'title'}}</label>
</div>
{{#if actorIsPc}}
<div>
<label>{{skillData.name}}</label>
</div>
{{/if}}
<div>
<label id="stance_label">unknown</label>
</div>

View File

@@ -0,0 +1,103 @@
<form class="{{cssClass}}" autocomplete="off">
{{json this}}
{{!-- Sheet Header --}}
<header class="sheet-header">
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="150" width="150"/>
<div class="header-fields identity-wrapper">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
</div>
<div class="header-fields">
{{> 'systems/l5r5e/templates/sheets/actor/social.html' }}
<h2>{{ localize 'l5r5e.attributes.title' }}</h2>
{{> 'systems/l5r5e/templates/sheets/actor/rings.html' }}
{{> 'systems/l5r5e/templates/sheets/actor/attributes.html' }}
</div>
</header>
<div>
conflict rank
<br>martial : <input type="text" name="data.conflict_rank.martial" value="{{data.conflict_rank.martial}}" data-dtype="Number" placeholder="0"/>
<br>social : <input type="text" name="data.conflict_rank.social" value="{{data.conflict_rank.social}}" data-dtype="Number" placeholder="0"/>
</div>
<div>
Npc Type
<br>
<!-- Npc Type (minion / adversary) -->
<select class="attribute-dtype" name="data.type">
{{#select data.type}}
{{#each data.types as |t|}}
<option value="{{t}}">{{t}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div>
attitude:
<input type="text" name="data.attitude" value="{{data.attitude}}" data-dtype="String" placeholder=""/>
</div>
<div>
Skills
<ul>
{{#each data.skills as |skillValue skillCatId|}}
<li>
{{localizeSkill skillCatId "title"}} :
<input type="text" name="data.skills.{{skillCatId}}" value="{{skillValue}}" data-dtype="Number" placeholder="0"/>
</li>
{{/each}}
</ul>
</div>
<div>
rings_affinities
<br>
strengths :
<select class="attribute-dtype" name="data.rings_affinities.strength.ring">
{{#select data.rings_affinities.strength.ring}}
{{#each data.stances as |stance|}}
<option value="{{stance}}">{{localizeRing stance}}</option>
{{/each}}
{{/select}}
</select>
<input type="text" name="data.rings_affinities.strength.value" value="{{data.rings_affinities.strength.value}}" data-dtype="Number" placeholder="0"/>
<br>
weakness :
<select class="attribute-dtype" name="data.rings_affinities.weakness.ring">
{{#select data.rings_affinities.weakness.ring}}
{{#each data.stances as |stance|}}
<option value="{{stance}}">{{localizeRing stance}}</option>
{{/each}}
{{/select}}
</select>
<input type="text" name="data.rings_affinities.weakness.value" value="{{data.rings_affinities.weakness.value}}" data-dtype="Number" placeholder="0"/>
</div>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Skills Tab --}}
<article class="tab skills" data-group="primary" data-tab="skills">
<ul class="skills-wrapper">
{{#each data.skills as |category id|}}
{{> 'systems/l5r5e/templates/sheets/actor/category.html' category=category categoryId=id}}
{{/each}}
</ul>
{{> 'systems/l5r5e/templates/sheets/actor/feats.html' }}
</article>
{{> 'systems/l5r5e/templates/sheets/actor/narrative.html' }}
{{> 'systems/l5r5e/templates/item/items.html' }}
{{> 'systems/l5r5e/templates/item/weapons.html' }}
</section>
</form>