Finishing v0.0.3

Layout fixes
Added support for rolling skill on spells
Fixed migration
Cleaned up the code
Fixed Hjältarnas Tid skill error, updated layout, fixed buttons not working
Fixed right click menu for weapons
Added roll dialog and exceptional rolls
Updated skills styling
Co-Authored-By: erebus <erebus@rikspolisen.se>
Co-Committed-By: erebus <erebus@rikspolisen.se>
pull/3/head^2 v0.0.3
erebus 2020-12-01 16:30:39 +00:00
parent 6f030bd6b5
commit 2e389704ea
23 changed files with 702 additions and 89 deletions

View File

@ -23,6 +23,7 @@
"CURRENCY.QUARTER": "Quarter", "CURRENCY.QUARTER": "Quarter",
"CURRENCY.SHEKEL": "Shekel", "CURRENCY.SHEKEL": "Shekel",
"CURRENCY.TITLE": "Currency", "CURRENCY.TITLE": "Currency",
"CURRENCY.SILVER": "Silver",
"DICE.ROLL": "Dice roll", "DICE.ROLL": "Dice roll",
@ -62,6 +63,14 @@
"ROLL.SUCCESS": "Success", "ROLL.SUCCESS": "Success",
"ROLL.FAILURE": "Failure", "ROLL.FAILURE": "Failure",
"ROLL.TITLE": "Roll dice",
"BUTTON.ROLL": "Roll",
"BUTTON.CANCEL": "Cancel",
"ROLL.CLOSED": "Closed",
"ROLL.OPENED": "Opened",
"MENU.SHOWROLLDIALOG": "Show diceroller dialog",
"ROLL.OPENCLOSE": "Open / Close",
"ROLL.EXCEPTIONAL": "Exceptional",
"SKILL.TYPE": "Type", "SKILL.TYPE": "Type",
"SKILL.BASE": "Basic", "SKILL.BASE": "Basic",
@ -73,6 +82,9 @@
"SPELL.DIFFICULTY": "Difficulty", "SPELL.DIFFICULTY": "Difficulty",
"SPELL.ROLL": "Roll", "SPELL.ROLL": "Roll",
"SPELL.COST": "Cost", "SPELL.COST": "Cost",
"SPELL.ATTACKROLL": "Attack roll",
"SPELL.OPPOSITE": "Opposite",
"SPELL.RITUAL": "Ritual",
"STATS.HEALTH": "Health", "STATS.HEALTH": "Health",
"STATS.MANA": "Mana", "STATS.MANA": "Mana",

View File

@ -24,6 +24,7 @@
"CURRENCY.QUARTER": "Kvarting", "CURRENCY.QUARTER": "Kvarting",
"CURRENCY.SHEKEL": "Shekel", "CURRENCY.SHEKEL": "Shekel",
"CURRENCY.TITLE": "Mynt", "CURRENCY.TITLE": "Mynt",
"CURRENCY.SILVER": "Silver",
"DICE.ROLL": "Tärningsslag", "DICE.ROLL": "Tärningsslag",
@ -64,6 +65,15 @@
"ROLL.SUCCESS": "Lyckat", "ROLL.SUCCESS": "Lyckat",
"ROLL.FAILURE": "Misslyckat", "ROLL.FAILURE": "Misslyckat",
"ROLL.TITLE": "Slå tärningar",
"BUTTON.ROLL": "Slå",
"BUTTON.CANCEL": "Avbryt",
"ROLL.CLOSED": "Stängd",
"ROLL.OPENED": "Öppnad",
"MENU.SHOWROLLDIALOG": "Visa tärningsdialog",
"ROLL.OPENCLOSE": "Öppna / Stäng",
"ROLL.EXCEPTIONAL": "Exceptionellt",
"SKILL.TYPE": "Typ", "SKILL.TYPE": "Typ",
"SKILL.BASE": "Grundfärdigheter", "SKILL.BASE": "Grundfärdigheter",
"SKILL.ADVENTURE": "Äventyrsfärdigheter", "SKILL.ADVENTURE": "Äventyrsfärdigheter",
@ -72,8 +82,12 @@
"SKILL.LANGUAGE": "Språk", "SKILL.LANGUAGE": "Språk",
"SPELL.DIFFICULTY": "Svårighet", "SPELL.DIFFICULTY": "Svårighet",
"SPELL.ROLL": "Slag", "SPELL.ROLLTITLE": "Slag",
"SPELL.COST": "Kostnad", "SPELL.COST": "Kostnad",
"SPELL.ROLL": "Färdighetsslag",
"SPELL.ATTACKROLL": "Anfallsslag",
"SPELL.OPPOSITE": "Motsatt",
"SPELL.RITUAL": "Ritual",
"STATS.HEALTH": "Hälsa", "STATS.HEALTH": "Hälsa",
"STATS.MANA": "Skuld", "STATS.MANA": "Skuld",

View File

@ -139,6 +139,186 @@ export class ActorSheetKH extends ActorSheet {
}, },
]); ]);
new ContextMenu(html, "li.item-weapon", [
{
name: game.i18n.localize("MENU.SHOWROLLDIALOG"),
icon: '<i class="far dice"></i>',
callback: (li) => {
let itemId = li.data("itemId");
let _item = this.actor.items.find((element) => element._id == itemId);
// Retrieve skill based on name
let skill = this.actor.items.find((element) => element.name === _item.data.data.skill.value);
let skillName = skill.name
let skillValue = skill.data.data.value
let showValue = false
if(this.actor.data.type === "character") {
showValue = true
}
this.khRoller.rollSkillDialogInChat(skillName, skillValue, showValue, this.actor)
},
},
{
name: game.i18n.localize("MENU.SENTTOCHAT"),
icon: '<i class="far fa-comment"></i>',
callback: (li) => {
let itemId = li.data("itemId");
this._itemDetailsToChat(itemId);
},
},
]);
new ContextMenu(html, "li.item-skill", [
{
name: game.i18n.localize("MENU.SHOWROLLDIALOG"),
icon: '<i class="far dice"></i>',
callback: (li) => {
let itemId = li.data("itemId");
let _item = this.actor.items.find((element) => element._id == itemId);
let skillName = _item.name
let skillValue = _item.data.data.value
let showValue = false
if(this.actor.data.type === "character") {
showValue = true
}
this.khRoller.rollSkillDialogInChat(skillName, skillValue, showValue, this.actor)
},
},
{
name: game.i18n.localize("MENU.SENTTOCHAT"),
icon: '<i class="far fa-comment"></i>',
callback: (li) => {
let itemId = li.data("itemId");
this._itemDetailsToChat(itemId);
},
},
]);
new ContextMenu(html, "li.item-spell", [
{
name: game.i18n.localize("MENU.SHOWROLLDIALOG"),
icon: '<i class="far dice"></i>',
callback: (li) => {
let itemId = li.data("itemId");
let _item = this.actor.items.find((element) => element._id == itemId);
if (!_item) {
_item = game.items.get(itemId);
if (!_item) {
console.log("IMPORT ERROR")
return
}
}
let showValue = false
let difficulty = 0
if(this.actor.data.type === "character") {
showValue = true
}
switch (_item.data.data.difficulty.value) {
case "simple":
difficulty = 5
break;
case "easy":
difficulty = 2
break;
case "hard":
difficulty = -2
break;
case "daunting":
difficulty = -5
break;
}
if(_item.data.data.roll.value === "roll" || _item.data.data.roll.value === "attackroll") {
// Retrieve skill based on name
let skill = this.actor.items.find((element) => element.name === _item.data.data.roll.skill);
let skillName = _item.name
let skillValue = skill.data.data.value
if(this.actor.data.type === "character") {
skillName = _item.name + " (" + skill.name + ")"
}
this.khRoller.rollSkillDialogInChat(skillName, skillValue, showValue, this.actor, difficulty)
} else if(_item.data.data.roll.value === "opposite") {
// Retrieve skill based on name
let skill = this.actor.items.find((element) => element.name === _item.data.data.roll.skill);
let skillName = _item.name
let skillValue = skill.data.data.value
if(this.actor.data.type === "character") {
skillName = _item.name + " (" + skill.name + ")"
}
this.khRoller.rollSkillDialogInChat(skillName, skillValue, showValue, this.actor, difficulty)
} else if(_item.data.data.roll.value === "ritual") {
console.log("Not supported yet")
this.khRoller.rollSkillDialogInChat("Ritual", -1, showValue, this.actor, difficulty)
}
},
},
{
name: game.i18n.localize("MENU.SENTTOCHAT"),
icon: '<i class="far fa-comment"></i>',
callback: (li) => {
let itemId = li.data("itemId");
this._itemDetailsToChat(itemId);
},
},
]);
new ContextMenu(html, "li.item-attack", [
{
name: game.i18n.localize("MENU.SHOWROLLDIALOG"),
icon: '<i class="far dice"></i>',
callback: (li) => {
let skillValue = li.data("ability");
let skillName = "ITEM.ATTACK";
let showValue = false
if(this.actor.data.type === "character") {
showValue = true
}
this.khRoller.rollSkillDialogInChat(skillName, skillValue, showValue, this.actor)
},
},
{
name: game.i18n.localize("MENU.SENTTOCHAT"),
icon: '<i class="far fa-comment"></i>',
callback: (li) => {
let itemId = li.data("itemId");
this._itemDetailsToChat(itemId);
},
},
]);
new ContextMenu(html, "li.item-defence", [
{
name: game.i18n.localize("MENU.SHOWROLLDIALOG"),
icon: '<i class="far dice"></i>',
callback: (li) => {
const skillValue = li.data("defence");
let skillName = "ADVERSARY.DEFENCE";
this.khRoller.rollSkillDialogInChat(skillName, skillValue, false, this.actor)
},
}
]);
html.find(".feature").click(async (ev) => { html.find(".feature").click(async (ev) => {
const featureName = $(ev.currentTarget).data("feature"); const featureName = $(ev.currentTarget).data("feature");
const featureValue = this.actor.data.data.feature[featureName].value; const featureValue = this.actor.data.data.feature[featureName].value;
@ -156,7 +336,35 @@ export class ActorSheetKH extends ActorSheet {
// Delete Inventory Item // Delete Inventory Item
html.find(".item-delete").click((ev) => { html.find(".item-delete").click((ev) => {
const li = $(ev.currentTarget).parents(".item"); let parent = $(ev.currentTarget).data("parent")
const li = $(ev.currentTarget).parents(parent);
const item = this.actor.getOwnedItem(li.data("itemId"));
if(item) {
if (item.type === "armor") {
let initValue = -1
if (item.data.data.equipable.equipped) {
initValue = 4
this.actor.items.map((i) => {
if (i.type === "armor") {
if (i._id !== item._id && i.data.data.equipable.equipped && i.data?.data?.modifications) {
for (let k of Object.keys(i.data.data.modifications)) {
if (i.data.data.modifications[k].modtype === "init") {
initValue = i.data.data.modifications[k].value;
}
}
}
}
});
}
if (initValue > 0) {
this.actor.update({["data.combat.init"]: initValue});
}
}
}
this.actor.deleteOwnedItem(li.data("itemId")); this.actor.deleteOwnedItem(li.data("itemId"));
@ -165,7 +373,8 @@ export class ActorSheetKH extends ActorSheet {
// Edit Inventory Item // Edit Inventory Item
html.find(".item-edit").click(async (ev) => { html.find(".item-edit").click(async (ev) => {
const li = $(ev.currentTarget).parents(".item"); let parent = $(ev.currentTarget).data("parent")
let li = $(ev.currentTarget).parents(parent);
let itemId = li.data("itemId"); let itemId = li.data("itemId");
let item = this.actor.getOwnedItem(itemId); let item = this.actor.getOwnedItem(itemId);
@ -184,7 +393,7 @@ export class ActorSheetKH extends ActorSheet {
/* Roll spell cost */ /* Roll spell cost */
html.find(".roll-spell-cost").click((ev) => { html.find(".roll-spell-cost").click((ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item-spell");
let itemId = li.data("itemId"); let itemId = li.data("itemId");
let spell = this.actor.getOwnedItem(itemId); let spell = this.actor.getOwnedItem(itemId);
@ -207,9 +416,74 @@ export class ActorSheetKH extends ActorSheet {
} }
}); });
html.find(".roll-spell-skill").click((ev) => {
const li = $(ev.currentTarget).parents(".item-spell");
let itemId = li.data("itemId");
let spell = this.actor.getOwnedItem(itemId);
if (!spell) {
spell = game.items.get(itemId);
if (!spell) {
console.log("IMPORT ERROR")
return
}
}
let showValue = false
let difficulty = 0
if(this.actor.data.type === "character") {
showValue = true
}
switch (spell.data.data.difficulty.value) {
case "simple":
difficulty = 5
break;
case "easy":
difficulty = 2
break;
case "hard":
difficulty = -2
break;
case "daunting":
difficulty = -5
break;
}
if(spell.data.data.roll.value === "roll" || spell.data.data.roll.value === "attackroll") {
// Retrieve skill based on name
let skill = this.actor.items.find((element) => element.name === spell.data.data.roll.skill);
let skillName = spell.name
let skillValue = skill.data.data.value
if(this.actor.data.type === "character") {
skillName = spell.name + " (" + skill.name + ")"
}
this.khRoller.rollSkillInChat(skillName, skillValue, showValue, this.actor, difficulty)
} else if(spell.data.data.roll.value === "opposite") {
// Retrieve skill based on name
let skill = this.actor.items.find((element) => element.name === spell.data.data.roll.skill);
let skillName = spell.name
let skillValue = skill.data.data.value
if(this.actor.data.type === "character") {
skillName = spell.name + " (" + skill.name + ")"
}
this.khRoller.rollSkillInChat(skillName, skillValue, showValue, this.actor, difficulty)
} else if(spell.data.data.roll.value === "ritual") {
console.log("Not supported yet")
}
});
/* Roll skill */ /* Roll skill */
html.find(".roll-skill").click((ev) => { html.find(".roll-skill").click((ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item-skill");
let itemId = li.data("itemId"); let itemId = li.data("itemId");
let _item = this.actor.items.find((element) => element._id == itemId); let _item = this.actor.items.find((element) => element._id == itemId);
@ -226,7 +500,7 @@ export class ActorSheetKH extends ActorSheet {
/* Roll weapon skill */ /* Roll weapon skill */
html.find(".roll-weapon-skill").click((ev) => { html.find(".roll-weapon-skill").click((ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item-weapon");
let itemId = li.data("itemId"); let itemId = li.data("itemId");
let weapon = this.actor.getOwnedItem(itemId); let weapon = this.actor.getOwnedItem(itemId);
@ -255,7 +529,7 @@ export class ActorSheetKH extends ActorSheet {
/* Roll weapon damage */ /* Roll weapon damage */
html.find(".roll-damage").click((ev) => { html.find(".roll-damage").click((ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item-weapon");
let itemId = li.data("itemId"); let itemId = li.data("itemId");
let weapon = this.actor.getOwnedItem(itemId); let weapon = this.actor.getOwnedItem(itemId);
@ -318,6 +592,7 @@ export class ActorSheetKH extends ActorSheet {
/* Toggle item equipped */ /* Toggle item equipped */
html.find(".items .item a.toggle-equipped").click(this._toggleEquippedItem.bind(this)); html.find(".items .item a.toggle-equipped").click(this._toggleEquippedItem.bind(this));
html.find(".items .item-weapon a.toggle-equipped").click(this._toggleEquippedItem.bind(this));
/* Handle increase of items in inventory */ /* Handle increase of items in inventory */
html.find(".item-quantity .quantity.increase").click(this._increaseQuantity.bind((this))); html.find(".item-quantity .quantity.increase").click(this._increaseQuantity.bind((this)));
@ -331,7 +606,7 @@ export class ActorSheetKH extends ActorSheet {
/* Adversary specific */ /* Adversary specific */
html.find(".roll-adversary-attack").click((ev) => { html.find(".roll-adversary-attack").click((ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item-attack");
let skillValue = li.data("ability"); let skillValue = li.data("ability");
let skillName = "ITEM.ATTACK"; let skillName = "ITEM.ATTACK";
@ -339,6 +614,30 @@ export class ActorSheetKH extends ActorSheet {
this.khRoller.rollSkillInChat(skillName, skillValue, false, this.actor) this.khRoller.rollSkillInChat(skillName, skillValue, false, this.actor)
}); });
html.find(".roll-attack-damage").click((ev) => {
const li = $(ev.currentTarget).parents(".item-attack");
let itemId = li.data("itemId");
let weapon = this.actor.getOwnedItem(itemId);
if (!weapon) {
weapon = game.items.get(itemId);
if (!weapon) {
console.log("IMPORT ERROR")
return
}
}
let damage = weapon.data.data.damage.value;
let regex = /([0-9]*)t([0-9]*)/g;
let regexMatch;
while (regexMatch = regex.exec(damage.toLowerCase())) {
this.khRoller.rollDamageInChat(regexMatch[1], this.actor)
}
});
html.find(".roll-defence").click((ev) => { html.find(".roll-defence").click((ev) => {
const skillValue = $(ev.currentTarget).data("defence"); const skillValue = $(ev.currentTarget).data("defence");
@ -480,7 +779,7 @@ export class ActorSheetKH extends ActorSheet {
const item = this.actor.getOwnedItem(li.data("itemId")); const item = this.actor.getOwnedItem(li.data("itemId"));
const actor = this.actor; const actor = this.actor;
if (item) { if(item) {
if(item.type === "armor") { if(item.type === "armor") {
let initValue = -1 let initValue = -1

View File

@ -12,7 +12,5 @@ export class ActorKH extends Actor {
const data = actorData.data; const data = actorData.data;
const flags = actorData.flags; const flags = actorData.flags;
data.type = actorData.type; data.type = actorData.type;
console.log("ACTOR DATA")
} }
} }

View File

@ -84,7 +84,7 @@ export default class KHDiceRoller {
}); });
} }
async rollSkillInChat(skillName, skillValue, showValue, speaker) { async rollSkillInChat(skillName, skillValue, showValue, speaker, openclosed) {
const roll = new Roll(`1d100`); const roll = new Roll(`1d100`);
let res = roll.roll(); let res = roll.roll();
@ -95,16 +95,43 @@ export default class KHDiceRoller {
computedName += " (" + skillValue + ")" computedName += " (" + skillValue + ")"
} }
if(openclosed === undefined) {
openclosed = 0
}
let rollData = { let rollData = {
name: computedName, name: computedName,
res: res res: res
}; };
if(skillValue > 0) { if(skillValue > 0) {
if(res.total <= skillValue) { let oneRes = Math.floor((res.total / 1) % 10);
let tenRes = Math.floor((res.total / 10) % 10);
if(openclosed < 0) {
rollData.closed = Math.abs(openclosed)
}
if(openclosed > 0) {
rollData.opened = Math.abs(openclosed)
}
if(openclosed < 0 && oneRes !== 0 && Math.abs(openclosed) >= oneRes) {
// roll is closed
rollData.failure = true
} else if(openclosed > 0 && oneRes !== 0 && Math.abs(openclosed) >= oneRes){
// roll is opened
rollData.success = true rollData.success = true
} else { } else {
rollData.failure = true if (res.total <= skillValue) {
rollData.success = true
} else {
rollData.failure = true
}
}
if(oneRes === tenRes) {
rollData.excetional = true
} }
} }
@ -121,4 +148,101 @@ export default class KHDiceRoller {
}, },
}); });
} }
async rollSkillDialogInChat(skillName, skillValue, showValue, speaker, startopen) {
const id = randomID();
if(startopen === undefined) {
startopen = 0
}
const content = await renderTemplate("systems/kopparhavet/templates/roll-dialog.html", {
id,
startopen,
skillName,
skillValue,
});
await new Dialog({
title: game.i18n.localize("ROLL.TITLE"),
content,
buttons: {
one: {
icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize("BUTTON.ROLL"),
callback: async () => {
const container = document.getElementById(id);
let openclosed = container.querySelector('[name="openclosed"]').value
const roll = new Roll(`1d100`);
let res = roll.roll();
let computedName = skillName
if(showValue) {
computedName += " (" + skillValue + ")"
}
let rollData = {
name: computedName,
res: res
};
// Evaluate result only if we have a positive skillvalue
if(skillValue > 0) {
let oneRes = Math.floor((res.total / 1) % 10);
let tenRes = Math.floor((res.total / 10) % 10);
if(openclosed < 0) {
rollData.closed = Math.abs(openclosed)
}
if(openclosed > 0) {
rollData.opened = Math.abs(openclosed)
}
if(openclosed < 0 && oneRes !== 0 && Math.abs(openclosed) >= oneRes) {
// roll is closed
rollData.failure = true
} else if(openclosed > 0 && oneRes !== 0 && Math.abs(openclosed) >= oneRes){
// roll is opened
rollData.success = true
} else {
if (res.total <= skillValue) {
rollData.success = true
} else {
rollData.failure = true
}
}
if(oneRes === tenRes) {
rollData.excetional = true
}
}
const html = await renderTemplate("systems/kopparhavet/templates/dice/roll.html", rollData);
await roll.toMessage({
create: true,
content: html,
user: game.user._id,
speaker: {
actor: speaker._id,
token: speaker.token,
alias: speaker.name,
},
});
},
},
two: {
icon: '<i class="fas fa-times"></i>',
label: game.i18n.localize("BUTTON.CANCEL"),
},
},
},
{
classes: ["dialog", "kopparhavet"],
}).render(true);
}
} }

View File

@ -0,0 +1,21 @@
/**
* Perform a system migration for the entire World, applying migrations for Actors, Items, and Compendium packs
* @return {Promise} A Promise which resolves once the migration is completed
*/
export const migrateWorld = async function () {
ui.notifications.info(
`Applying System Migration for version ${game.system.data.version}. Please be patient and do not close your game or shut down your server.`,
{permanent: true}
);
// Migrate to v0.0.3 from v0.0.2 and v0.0.1
game.items.forEach((item) => {
if(item.data.type === "spell") {
item.update({"data.roll.label": "SPELL.ROLLTITLE"});
}
});
// Set the migration as complete
game.settings.set("kopparhavet", "worldSchemaVersion", game.system.data.version);
ui.notifications.info(`System Migration to version ${game.system.data.version} completed!`, { permanent: true });
};

View File

@ -36,7 +36,13 @@ export class ItemSheetKH extends ItemSheet {
switch (this.object.data.type) { switch (this.object.data.type) {
case "weapon": case "weapon":
// Load Skills Compendium skills // Load Skills Compendium skills
let skillList2 = await game.packs.get("kopparhavet.skills").getContent(); let skillList2
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
skillList2 = await game.packs.get("kopparhavet.skills-ht").getContent();
} else {
skillList2 = await game.packs.get("kopparhavet.skills").getContent();
}
for (let item of skillList2) { for (let item of skillList2) {
if(item.data.type === "skill" && item.data.data.type.value === "combat") { if(item.data.type === "skill" && item.data.data.type.value === "combat") {
@ -66,6 +72,28 @@ export class ItemSheetKH extends ItemSheet {
this.position.width = 405; this.position.width = 405;
this.position.height = 570; this.position.height = 570;
break; break;
case "spell":
// Load Skills Compendium skills
let skillList3
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
skillList3 = await game.packs.get("kopparhavet.skills-ht").getContent();
} else {
skillList3 = await game.packs.get("kopparhavet.skills").getContent();
}
for (let item of skillList3) {
if(item.data.type === "skill") {
skillList.push(item)
}
}
// Retrieve any created skills as well
for (let item of game.items.entities) {
if(item.data.type === "skill") {
skillList.push(item)
}
}
default: default:
this.position.width = 450; this.position.width = 450;
this.position.height = 605; this.position.height = 605;

View File

@ -6,6 +6,9 @@ export default class KHHooks {
let actorbaseSkills; let actorbaseSkills;
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") { if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
// Set currency name
actor.update({ "data.currency.shekel.label": "CURRENCY.SILVER" });
actorbaseSkills = CONFIG.KH.baseSkillsHT actorbaseSkills = CONFIG.KH.baseSkillsHT
skillIndex = await game.packs.get("kopparhavet.skills-ht").getContent(); skillIndex = await game.packs.get("kopparhavet.skills-ht").getContent();
} else { } else {

View File

@ -4,6 +4,7 @@ import KHHooks from "./kh-hooks.js";
import { ActorKH } from "./actors/actor.js"; import { ActorKH } from "./actors/actor.js";
import { ActorSheetKH } from "./actors/actor-sheet.js"; import { ActorSheetKH } from "./actors/actor-sheet.js";
import { KH } from "./kh-config.js"; import { KH } from "./kh-config.js";
import * as migrations from "./helpers/migration-helper.js";
Hooks.once("init", () => { Hooks.once("init", () => {
CONFIG.Combat.initiative = { formula: "(@combat.init)d6kh2", decimals: 0 }; CONFIG.Combat.initiative = { formula: "(@combat.init)d6kh2", decimals: 0 };
@ -20,7 +21,7 @@ Hooks.once("init", () => {
scope: "world", scope: "world",
config: true, config: true,
default: 0, default: 0,
type: Number, type: String,
}); });
game.settings.register("kopparhavet", "gameSystem", { game.settings.register("kopparhavet", "gameSystem", {
name: "Game System", name: "Game System",
@ -59,8 +60,6 @@ Hooks.on("createActor", async (actor, options, userId) => KHHooks.onCreateActor(
function registerSheets() { function registerSheets() {
// Register sheet application classes // Register sheet application classes
console.log("Registerting sheets")
Actors.unregisterSheet("core", ActorSheet); Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("kopparhavet", ActorSheetKH, { types: ["character"], makeDefault: true }); Actors.registerSheet("kopparhavet", ActorSheetKH, { types: ["character"], makeDefault: true });
Actors.registerSheet("kopparhavet", ActorSheetKH, { types: ["adversary"], makeDefault: true }); Actors.registerSheet("kopparhavet", ActorSheetKH, { types: ["adversary"], makeDefault: true });
@ -170,6 +169,20 @@ function registerHandlebarsHelpers() {
} }
}); });
Handlebars.registerHelper("spellRoll", function (roll) {
roll = normalize(roll, "roll");
switch (roll) {
case "roll":
return game.i18n.localize("SPELL.ROLL");
case "attackroll":
return game.i18n.localize("SPELL.ATTACKROLL");
case "opposite":
return game.i18n.localize("SPELL.OPPOSITE");
case "ritual":
return game.i18n.localize("SPELL.RITUAL");
}
});
Handlebars.registerHelper('plaintextToHTML', function(value) { Handlebars.registerHelper('plaintextToHTML', function(value) {
// strip tags, add <br/> tags // strip tags, add <br/> tags
return new Handlebars.SafeString(value.replace(/(<([^>]+)>)/gi, "").replace(/(?:\r\n|\r|\n)/g, '<br/>')); return new Handlebars.SafeString(value.replace(/(<([^>]+)>)/gi, "").replace(/(?:\r\n|\r|\n)/g, '<br/>'));
@ -177,12 +190,21 @@ function registerHandlebarsHelpers() {
} }
function migrateWorld() { function migrateWorld() {
game.actors.forEach((actor) => { // Determine whether a system migration is required and feasible
// Migrate to v0.0.2 from v0.0.1 const currentVersion = game.settings.get("kopparhavet", "worldSchemaVersion");
if(actor.data.type === "character") { const NEEDS_MIGRATION_VERSION = "0.0.3";
if(!actor.data?.data?.bio?.appearance) { const COMPATIBLE_MIGRATION_VERSION = '0' || isNaN('NaN');
actor.update({"data.bio.appearance.label": "BIO.APPEARANCE", "data.bio.appearance.value": ""}); let needMigration = currentVersion < NEEDS_MIGRATION_VERSION || currentVersion === null;
}
// Perform the migration
if (needMigration && game.user.isGM) {
if (currentVersion && currentVersion < COMPATIBLE_MIGRATION_VERSION) {
ui.notifications.error(
`Your system data is from a version that cannot be reliably migrated to the latest version. The process will be attempted, but errors may occur.`,
{ permanent: true }
);
} }
});
migrations.migrateWorld();
}
} }

View File

@ -188,6 +188,7 @@
} }
.sheet-tabs { .sheet-tabs {
min-height: 36px;
} }
.relation-list li:not(:last-child) { .relation-list li:not(:last-child) {

View File

@ -97,17 +97,24 @@
margin: auto; margin: auto;
} }
.items .items-list .item { .items .items-list .item,
.items .items-list .item-spell,
.items .items-list .item-weapon,
.items .items-list .item-skill,
.items .items-list .item-nor,
.items .items-list .item-defence {
line-height: 24px; line-height: 24px;
padding: 3px 0; padding: 3px 0;
border-bottom: 1px solid #bbb; border-bottom: 1px solid #bbb;
text-align: center; text-align: center;
} }
.items .items-list .item .toggle-equipped { .items .items-list .item .toggle-equipped,
.items .items-list .item-weapon .toggle-equipped {
color: #888; color: #888;
} }
.items .items-list .item .toggle-equipped.active { .items .items-list .item .toggle-equipped.active,
.items .items-list .item-weapon .toggle-equipped.active{
color: #191813; color: #191813;
} }

View File

@ -2,10 +2,10 @@
"name": "kopparhavet", "name": "kopparhavet",
"title": "Kopparhavets Hjältar", "title": "Kopparhavets Hjältar",
"description": "The Molten Sea is a dangerous but exciting place, where pirates, sorcerers and secretive orders of knighthood struggle for power, wealth and ancient lore.", "description": "The Molten Sea is a dangerous but exciting place, where pirates, sorcerers and secretive orders of knighthood struggle for power, wealth and ancient lore.",
"version": "0.0.2", "version": "0.0.3",
"minimumCoreVersion": "0.7.5", "minimumCoreVersion": "0.7.5",
"compatibleCoreVersion": "0.7.7", "compatibleCoreVersion": "0.7.7",
"templateVersion": 3, "templateVersion": 4,
"author": "Erebus", "author": "Erebus",
"scripts": [], "scripts": [],
"esmodules": [ "esmodules": [
@ -53,6 +53,6 @@
"url": "https://pi.rikspolisen.se/foundryvtt/kopparhavet", "url": "https://pi.rikspolisen.se/foundryvtt/kopparhavet",
"socket": true, "socket": true,
"manifest": "https://pi.rikspolisen.se/foundryvtt/kopparhavet/raw/branch/master/system.json", "manifest": "https://pi.rikspolisen.se/foundryvtt/kopparhavet/raw/branch/master/system.json",
"download": "https://pi.rikspolisen.se/foundryvtt/kopparhavet/archive/v0.0.2.zip", "download": "https://pi.rikspolisen.se/foundryvtt/kopparhavet/archive/v0.0.3.zip",
"license": "" "license": ""
} }

View File

@ -230,9 +230,12 @@
"core" "core"
], ],
"roll": { "roll": {
"value": "", "value": "roll",
"type": "String", "type": "String",
"label": "SPELL.ROLL" "label": "SPELL.ROLLTITLE",
"skill": "Trolldom",
"oppositeskill": "",
"ritual": {}
}, },
"cost": { "cost": {
"value": "", "value": "",

View File

@ -74,8 +74,7 @@
<strong>{{localize data.cost.label}}:</strong> {{data.cost.value}} <strong>{{localize data.cost.label}}:</strong> {{data.cost.value}}
<strong>{{localize data.difficulty.label}}:</strong> {{rollDifficulty data.difficulty.value}} <strong>{{localize data.difficulty.label}}:</strong> {{rollDifficulty data.difficulty.value}}
<div style="grid-column-start: 1; grid-column-end: 5;"> <div style="grid-column-start: 1; grid-column-end: 5;">
<strong>{{localize data.roll.label}}</strong> <strong>{{localize data.roll.label}}:</strong> {{spellRoll data.roll.value}}
{{data.roll.value}}
</div> </div>
</div> </div>
{{#if data.description}} {{#if data.description}}

View File

@ -4,6 +4,16 @@
<div class="roll"> <div class="roll">
<div class="dice-roll"> <div class="dice-roll">
{{#if closed}}
<div style="text-align: center; margin-bottom: 0.5rem;">
{{localize "ROLL.CLOSED"}}: {{closed}}
</div>
{{/if}}
{{#if opened}}
<div style="text-align: center; margin-bottom: 0.5rem;">
{{localize "ROLL.OPENED"}}: {{opened}}
</div>
{{/if}}
<div class="dice-result"> <div class="dice-result">
{{#if showFormula}} {{#if showFormula}}
<div class="dice-formula-kh">{{res.formula}}</div> <div class="dice-formula-kh">{{res.formula}}</div>
@ -13,14 +23,14 @@
</div> </div>
</div> </div>
{{#if success}} {{#if success}}
<div style="text-align: center; width: 100%; font-weight: bold; color: limegreen;"> <h2 style="border: none; text-align: center; width: 100%; font-weight: bold; color: limegreen;">
{{localize "ROLL.SUCCESS"}} {{#if excetional}}{{localize "ROLL.EXCEPTIONAL"}}{{/if}} {{localize "ROLL.SUCCESS"}}
</div> </h2>
{{/if}} {{/if}}
{{#if failure}} {{#if failure}}
<div style="text-align: center; width: 100%; font-weight: bold; color: darkred;"> <h2 style="border: none; text-align: center; width: 100%; font-weight: bold; color: darkred;">
{{localize "ROLL.FAILURE"}} {{#if excetional}}{{localize "ROLL.EXCEPTIONAL"}}{{/if}} {{localize "ROLL.FAILURE"}}
</div> </h2>
{{/if}} {{/if}}
</div> </div>
</div> </div>

View File

@ -26,7 +26,24 @@
</div> </div>
<div style="grid-column-start: 1; grid-column-end: 3;"> <div style="grid-column-start: 1; grid-column-end: 3;">
<label>{{localize data.roll.label}}</label> <label>{{localize data.roll.label}}</label>
<input name="data.roll.value" type="text" value="{{data.roll.value}}" /> <select class="item-weapon-cat-select" name="data.roll.value">
{{#select data.roll.value}}
<option value="roll">{{localize "SPELL.ROLL"}}</option>
<option value="attackroll">{{localize "SPELL.ATTACKROLL"}}</option>
<option value="opposite">{{localize "SPELL.OPPOSITE"}}</option>
<option value="ritual">{{localize "SPELL.RITUAL"}}</option>
{{/select}}
</select>
</div>
<div style="grid-column-start: 1; grid-column-end: 3;">
<label>{{localize "ITEM.SKILL"}}</label>
<select class="item-weapon-skill-select" name="data.roll.skill">
{{#select data.roll.skill}}
{{#each this.khskills as |t|}}
<option value="{{t.name}}">{{t.name}}</option>
{{/each}}
{{/select}}
</select>
</div> </div>
</div> </div>
<div class="item"> <div class="item">
@ -39,4 +56,4 @@
</div> </div>
</div> </div>
</div> </div>
</form> </form>

View File

@ -2,16 +2,16 @@
<div class="combat border"> <div class="combat border">
<ul class="items"> <ul class="items">
<ul class="items-list"> <ul class="items-list">
<li class="item flexrow"> <li class="item-nor flexrow">
<div class="item-name" style="flex-grow: 8;">{{localize "MOD.INIT"}}</div> <div class="item-name" style="flex-grow: 8;">{{localize "MOD.INIT"}}</div>
<div class="item-value" style="flex: none;"><input name="data.combat.init" class="skill-value" type="number" value="{{data.combat.init}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input name="data.combat.init" class="skill-value" type="number" value="{{data.combat.init}}" data-dtype="Number" /></div>
</li> </li>
<li class="item flexrow"> <li class="item-defence flexrow" data-defence="{{data.combat.defence}}">
<div class="item-name roll-defence rollable" data-defence="{{data.combat.defence}}" style="flex-grow: 8;">{{localize "ADVERSARY.DEFENCE"}}</div> <div class="item-name roll-defence rollable" data-defence="{{data.combat.defence}}" style="flex-grow: 8;">{{localize "ADVERSARY.DEFENCE"}}</div>
<div class="item-value" style="flex: none;"><input name="data.combat.defence" class="skill-value" type="text" value="{{data.combat.defence}}" /></div> <div class="item-value" style="flex: none;"><input name="data.combat.defence" class="skill-value" type="text" value="{{data.combat.defence}}" /></div>
</li> </li>
<li class="item flexrow"> <li class="item-nor flexrow">
<div class="item-name" style="flex-grow: 8;">{{localize "ADVERSARY.HASHELMET"}}</div> <div class="item-name" style="flex-grow: 8;">{{localize "ADVERSARY.HASHELMET"}}</div>
<div style="align-self: flex-end"> <div style="align-self: flex-end">
<a style="margin: auto;" class="adversary-helmet-click {{#if data.combat.helmet}}active{{/if}}"> <a style="margin: auto;" class="adversary-helmet-click {{#if data.combat.helmet}}active{{/if}}">
@ -20,7 +20,7 @@
</div> </div>
</li> </li>
<li class="item flexrow"> <li class="item-nor flexrow">
<div class="item-name roll-adversary-armor rollable" data-armor="{{data.combat.armor}}" style="flex-grow: 8;">{{localize "ITEM.DEFENCE"}}</div> <div class="item-name roll-adversary-armor rollable" data-armor="{{data.combat.armor}}" style="flex-grow: 8;">{{localize "ITEM.DEFENCE"}}</div>
<div class="item-value" style="flex: none;"><input name="data.combat.armor" class="skill-value" type="text" value="{{data.combat.armor}}" /></div> <div class="item-value" style="flex: none;"><input name="data.combat.armor" class="skill-value" type="text" value="{{data.combat.armor}}" /></div>
</li> </li>
@ -33,7 +33,7 @@
<ul class="items"> <ul class="items">
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
</li> </li>
@ -52,7 +52,7 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.attacks as |item key|}} {{#each actor.attacks as |item key|}}
<li class="item flexrow" data-item-id="{{item._id}}" data-ability="{{item.data.skill.value}}"> <li class="item-attack flexrow" data-item-id="{{item._id}}" data-ability="{{item.data.skill.value}}">
<div class="item-name">{{item.name}}</div> <div class="item-name">{{item.name}}</div>
<div class="skill-roll"> <div class="skill-roll">
<div class="roll-button"> <div class="roll-button">
@ -61,12 +61,12 @@
</div> </div>
<div class="skill-roll"> <div class="skill-roll">
<div class="roll-button"> <div class="roll-button">
<div class="roll-damage rollable">{{item.data.damage.value}}</div> <div class="roll-attack-damage rollable">{{item.data.damage.value}}</div>
</div> </div>
</div> </div>
<div class="item-controls"> <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-edit" data-parent=".item-attack" 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> <a class="item-control item-delete" data-parent=".item-attack" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -20,7 +20,7 @@
</li> </li>
<ul class="items-list"> <ul class="items-list">
{{#each actor.weapons as |item id|}} {{#each actor.weapons as |item id|}}
<li class="item flexrow" data-item-id="{{item._id}}" data-ability="{{item.data.skill.value}}"> <li class="item-weapon flexrow" data-item-id="{{item._id}}" data-ability="{{item.data.skill.value}}">
<div class="item-name">{{item.name}}</div> <div class="item-name">{{item.name}}</div>
<div> <div>
{{#if item.data.equipable.equipped}} {{#if item.data.equipable.equipped}}
@ -40,8 +40,8 @@
</div> </div>
</div> </div>
<div class="item-controls"> <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-edit" data-parent=".item-weapon" 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> <a class="item-control item-delete" data-parent=".item-weapon" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}
@ -79,8 +79,8 @@
</div> </div>
{{/if}} {{/if}}
<div class="item-controls"> <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-edit" data-parent=".item" 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> <a class="item-control item-delete" data-parent=".item" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}
@ -105,8 +105,8 @@
<div class="quantity decrease"><i class="far fa-minus-square"></i></div> <div class="quantity decrease"><i class="far fa-minus-square"></i></div>
</div> </div>
<div class="item-controls"> <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-edit" data-parent=".item" 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> <a class="item-control item-delete" data-parent=".item" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -2,17 +2,17 @@
<div class="combat border"> <div class="combat border">
<ul class="items"> <ul class="items">
<ul class="items-list"> <ul class="items-list">
<li class="item flexrow"> <li class="item-nor flexrow">
<div class="item-name" style="flex-grow: 8;">{{localize "MOD.INIT"}}</div> <div class="item-name" style="flex-grow: 8;">{{localize "MOD.INIT"}}</div>
<div class="item-value" style="flex: none;"><input name="data.combat.init" class="skill-value" type="number" value="{{data.combat.init}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input name="data.combat.init" class="skill-value" type="number" value="{{data.combat.init}}" data-dtype="Number" /></div>
</li> </li>
<li class="item flexrow"> <li class="item-defence flexrow" data-defence="{{data.combat.defence}}">
<div class="item-name roll-defence rollable" data-defence="{{data.combat.defence}}" style="flex-grow: 8;">{{localize "ADVERSARY.DEFENCE"}}</div> <div class="item-name roll-defence rollable" data-defence="{{data.combat.defence}}" style="flex-grow: 8;">{{localize "ADVERSARY.DEFENCE"}}</div>
<div class="item-value" style="flex: none;"><input name="data.combat.defence" class="skill-value" type="text" value="{{data.combat.defence}}" /></div> <div class="item-value" style="flex: none;"><input name="data.combat.defence" class="skill-value" type="text" value="{{data.combat.defence}}" /></div>
</li> </li>
<li class="item flexrow"> <li class="item-nor flexrow">
<div class="item-name roll-adversary-armor rollable" data-armor="{{data.combat.armor}}" style="flex-grow: 8;">{{localize "ITEM.DEFENCE"}}</div> <div class="item-name roll-adversary-armor rollable" data-armor="{{data.combat.armor}}" style="flex-grow: 8;">{{localize "ITEM.DEFENCE"}}</div>
<div class="item-value" style="flex: none;"><input name="data.combat.armor" class="skill-value" type="text" value="{{data.combat.armor}}" /></div> <div class="item-value" style="flex: none;"><input name="data.combat.armor" class="skill-value" type="text" value="{{data.combat.armor}}" /></div>
</li> </li>
@ -25,7 +25,7 @@
<ul class="items"> <ul class="items">
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
</li> </li>
@ -44,7 +44,7 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.attacks as |item key|}} {{#each actor.attacks as |item key|}}
<li class="item flexrow" data-item-id="{{item._id}}" data-ability="{{item.data.skill.value}}"> <li class="item-attack flexrow" data-item-id="{{item._id}}" data-ability="{{item.data.skill.value}}">
<div class="item-name">{{item.name}}</div> <div class="item-name">{{item.name}}</div>
<div class="skill-roll"> <div class="skill-roll">
<div class="roll-button"> <div class="roll-button">
@ -53,12 +53,12 @@
</div> </div>
<div class="skill-roll"> <div class="skill-roll">
<div class="roll-button"> <div class="roll-button">
<div class="roll-damage rollable">{{item.data.damage.value}}</div> <div class="roll-attack-damage rollable">{{item.data.damage.value}}</div>
</div> </div>
</div> </div>
<div class="item-controls"> <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-edit" data-parent=".item-attack" 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> <a class="item-control item-delete" data-parent=".item-attack" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -5,10 +5,10 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
{{#if skill.hasAdventure}} {{#if skill.hasAdventure}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
<div style="align-self: flex-end"> <div style="align-self: flex-end; margin-top: auto; margin-bottom: auto;">
<a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}"> <a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}">
<i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i> <i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i>
</a> </a>
@ -25,10 +25,10 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
{{#if skill.hasCombat}} {{#if skill.hasCombat}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
<div style="align-self: flex-end"> <div style="align-self: flex-end; margin-top: auto; margin-bottom: auto;">
<a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}"> <a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}">
<i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i> <i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i>
</a> </a>

View File

@ -5,10 +5,10 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
{{#if skill.hasBase}} {{#if skill.hasBase}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
<div style="align-self: flex-end"> <div style="align-self: flex-end; margin-top: auto; margin-bottom: auto;">
<a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}"> <a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}">
<i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i> <i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i>
</a> </a>
@ -25,10 +25,10 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
{{#if skill.hasAdventure}} {{#if skill.hasAdventure}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
<div style="align-self: flex-end"> <div style="align-self: flex-end; margin-top: auto; margin-bottom: auto;">
<a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}"> <a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}">
<i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i> <i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i>
</a> </a>
@ -45,10 +45,10 @@
<ul class="items-list"> <ul class="items-list">
{{#each actor.skills as |skill key|}} {{#each actor.skills as |skill key|}}
{{#if skill.hasCombat}} {{#if skill.hasCombat}}
<li class="item flexrow" data-item-id="{{skill._id}}"> <li class="item-skill flexrow" data-item-id="{{skill._id}}">
<div class="item-name roll-skill" style="flex-grow: 8;">{{skill.name}}</div> <div class="item-name roll-skill rollable" style="flex-grow: 8;">{{skill.name}}</div>
<div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div> <div class="item-value" style="flex: none;"><input class="skill-value" type="number" value="{{skill.data.value}}" min="0" data-item-id="{{skill._id}}" data-dtype="Number" /></div>
<div style="align-self: flex-end"> <div style="align-self: flex-end; margin-top: auto; margin-bottom: auto;">
<a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}"> <a style="margin: auto;" class="click-skill {{#if skill.data.used}}active{{/if}}" data-item-id="{{skill._id}}">
<i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i> <i class="far {{#if skill.data.used}}fa-times-circle{{else}}fa-circle{{/if}}"></i>
</a> </a>

View File

@ -9,8 +9,8 @@
<li class="item flexrow" data-item-id="{{talent._id}}"> <li class="item flexrow" data-item-id="{{talent._id}}">
<div class="item-name">{{talent.name}}</div> <div class="item-name">{{talent.name}}</div>
<div class="item-controls"> <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-edit" data-parent=".item" 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> <a class="item-control item-delete" data-parent=".item" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}
@ -25,13 +25,13 @@
<ul class="items"> <ul class="items">
<ul class="items-list"> <ul class="items-list">
{{#each actor.spells as |spell key|}} {{#each actor.spells as |spell key|}}
<li class="item flexrow" data-item-id="{{spell._id}}"> <li class="item-spell flexrow" data-item-id="{{spell._id}}">
<div class="item-name">{{spell.name}}</div> <div class="item-name roll-spell-skill rollable" style="margin-top: auto; margin-bottom: auto;">{{spell.name}}</div>
<div class="cost roll-spell-cost rollable">{{spell.data.cost.value}}</div> <div class="cost roll-spell-cost rollable">{{spell.data.cost.value}}</div>
<div class="difficulty">{{rollDifficulty spell.data.difficulty.value}}</div> <div class="difficulty">{{rollDifficulty spell.data.difficulty.value}}</div>
<div class="item-controls"> <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-edit" data-parent=".item-spell" 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> <a class="item-control item-delete" data-parent=".item-spell" title="Delete Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -0,0 +1,55 @@
<div id="{{id}}" class="roll-dialog">
<h1 style="text-align: center;">{{localize skillName}} ({{skillValue}})</h1>
<div class="flexrow" style="margin-bottom: 10px;">
<label style="margin: auto;">{{localize "ROLL.OPENCLOSE"}}</label>
<input type="button" name="openclosed" min="0" value="{{startopen}}" style="min-height: 30px; min-width: 45px;" />
<label name="notopenedorclosed" style="margin: auto; display: inline-block;">&nbsp;</label>
<label name="closed" style="margin: auto; display: none; text-align: center;">{{localize "ROLL.CLOSED"}}</label>
<label name="opened" style="margin: auto; display: none; text-align: center;">{{localize "ROLL.OPENED"}}</label>
</div>
</div>
<script>
(function() {
const scope = document.getElementById("{{{id}}}");
const input = scope.querySelector(`[name="openclosed"`);
const closed = scope.querySelector(`[name="closed"`);
const opened = scope.querySelector(`[name="opened"`);
const none = scope.querySelector(`[name="notopenedorclosed"`);
input.addEventListener("click", (event) => {
event.target.value++;
if(event.target.value > 0) {
closed.style.display = "none"
none.style.display = "none"
opened.style.display = "inline-block"
} else if(event.target.value < 0) {
opened.style.display = "none"
none.style.display = "none"
closed.style.display = "inline-block"
} else {
opened.style.display = "none"
closed.style.display = "none"
none.style.display = "inline-block"
}
});
input.addEventListener("contextmenu", (event) => {
event.target.value--;
if(event.target.value > 0) {
closed.style.display = "none"
none.style.display = "none"
opened.style.display = "inline-block"
} else if(event.target.value < 0) {
opened.style.display = "none"
none.style.display = "none"
closed.style.display = "inline-block"
} else {
opened.style.display = "none"
closed.style.display = "none"
none.style.display = "inline-block"
}
});
})();
</script>