first commit
commit
c3a7388592
|
@ -0,0 +1,6 @@
|
|||
.idea/
|
||||
*.code-workspace
|
||||
.history/
|
||||
deploy
|
||||
createRelease
|
||||
TODO
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"ADVERSARY.ATTACKSKILL": "Attack rating",
|
||||
"ADVERSARY.DEFENCE": "Defence",
|
||||
"ADVERSARY.HASHELMET": "Has a helmet",
|
||||
|
||||
"ARMOR.HELMET": "Helmet",
|
||||
"ARMOR.LIGHT": "Light",
|
||||
"ARMOR.MEDIUM": "Medium",
|
||||
"ARMOR.HEAVY": "Heavy",
|
||||
|
||||
"BACKGROUND.TITLE": "Background",
|
||||
"BACKGROUND.BIRTHPLACE": "Birthplace",
|
||||
"BACKGROUND.SOCIALSTANDING": "Social standing",
|
||||
"BACKGROUND.EVENTS": "Events",
|
||||
"BACKGROUND.CONTACTS": "Contacts",
|
||||
|
||||
"BIO.AGE": "Age",
|
||||
"BIO.KIN": "Kin",
|
||||
"BIO.NAME": "Name",
|
||||
"BIO.PROFESSION": "Profession",
|
||||
|
||||
"CURRENCY.QUARTER": "Quarter",
|
||||
"CURRENCY.SHEKEL": "Shekel",
|
||||
"CURRENCY.TITLE": "Currency",
|
||||
|
||||
"DICE.ROLL": "Dice roll",
|
||||
|
||||
"DIFFICULTY.SIMPLE": "Simple",
|
||||
"DIFFICULTY.EASY": "Easy",
|
||||
"DIFFICULTY.AVERAGE": "Average",
|
||||
"DIFFICULTY.HARD": "Hard",
|
||||
"DIFFICULTY.DAUNTING": "Daunting",
|
||||
|
||||
"FEATURES.TITLE": "Features",
|
||||
|
||||
"ITEM.ARMOR": "Rustning",
|
||||
"ITEM.ATTACK": "Attack",
|
||||
"ITEM.DAMAGE": "Damage",
|
||||
"ITEM.DEFENCE": "Defence",
|
||||
"ITEM.DESCRIPTION": "Description",
|
||||
"ITEM.EQUIPABLE": "Equipable",
|
||||
"ITEM.EQUIPPED": "Equipped",
|
||||
"ITEM.GEAR": "Gear",
|
||||
"ITEM.PRICE": "Price",
|
||||
"ITEM.QUANTITY": "Quantity",
|
||||
"ITEM.SKILL": "Skill",
|
||||
"ITEM.SPELL": "Spell",
|
||||
"ITEM.TALENT": "Talent",
|
||||
"ITEM.WEAPON": "Weapon",
|
||||
|
||||
"MENU.SENTTOCHAT": "Send To Chat",
|
||||
|
||||
"MOD.INIT": "Initiative",
|
||||
"MOD.TYPE": "Modification",
|
||||
"MOD.VALUE": "Value",
|
||||
|
||||
"ROLL.SUCCESS": "Success",
|
||||
"ROLL.FAILURE": "Failure",
|
||||
|
||||
"SKILL.TYPE": "Type",
|
||||
"SKILL.BASE": "Basic",
|
||||
"SKILL.ADVENTURE": "Adventure",
|
||||
"SKILL.COMBAT": "Combat",
|
||||
"SKILL.STARTVALUE": "Start value",
|
||||
"SKILL.LANGUAGE": "Language",
|
||||
|
||||
"SPELL.DIFFICULTY": "Difficulty",
|
||||
"SPELL.ROLL": "Roll",
|
||||
"SPELL.COST": "Cost",
|
||||
|
||||
"STATS.HEALTH": "Health",
|
||||
"STATS.MANA": "Mana",
|
||||
"STATS.STAMINA": "Stamina",
|
||||
|
||||
"TAB.BIO": "Background",
|
||||
"TAB.COMBAT": "Combat",
|
||||
"TAB.DESCRIPTION": "Description",
|
||||
"TAB.GEAR": "Gear",
|
||||
"TAB.MODIFICATION": "Modifications",
|
||||
"TAB.NOTE": "Note",
|
||||
"TAB.SKILLS": "Skills",
|
||||
"TAB.TALENTS": "Talents and Spells",
|
||||
|
||||
"WEAPON.CATEGORY": "Category",
|
||||
"WEAPON.MELEE": "Melee",
|
||||
"WEAPON.RANGED": "Ranged"
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"ADVERSARY.ATTACKSKILL": "Färdighetsvärde",
|
||||
"ADVERSARY.DEFENCE": "Försvar",
|
||||
"ADVERSARY.HASHELMET": "Har en hjälm",
|
||||
|
||||
"ARMOR.HELMET": "Hjälm",
|
||||
"ARMOR.LIGHT": "Lätt",
|
||||
"ARMOR.MEDIUM": "Medel",
|
||||
"ARMOR.HEAVY": "Tung",
|
||||
|
||||
"BACKGROUND.TITLE": "Bakgrund",
|
||||
"BACKGROUND.BIRTHPLACE": "Födelseort",
|
||||
"BACKGROUND.SOCIALSTANDING": "Socialt stånd",
|
||||
"BACKGROUND.EVENTS": "Händelser",
|
||||
"BACKGROUND.CONTACTS": "Kontakter",
|
||||
|
||||
"BIO.AGE": "Ålder",
|
||||
"BIO.KIN": "Folkslag",
|
||||
"BIO.NAME": "Namn",
|
||||
"BIO.PROFESSION": "Värv",
|
||||
|
||||
"CURRENCY.QUARTER": "Kvarting",
|
||||
"CURRENCY.SHEKEL": "Shekel",
|
||||
"CURRENCY.TITLE": "Mynt",
|
||||
|
||||
"DICE.ROLL": "Tärningsslag",
|
||||
|
||||
"DIFFICULTY.SIMPLE": "Mycket Lätt",
|
||||
"DIFFICULTY.EASY": "Lätt",
|
||||
"DIFFICULTY.AVERAGE": "Utmanande",
|
||||
"DIFFICULTY.HARD": "Svår",
|
||||
"DIFFICULTY.DAUNTING": "Mycket svårt",
|
||||
|
||||
"FEATURES.TITLE": "Särdrag",
|
||||
|
||||
"ITEM.ARMOR": "Rustning",
|
||||
"ITEM.ATTACK": "Anfall",
|
||||
"ITEM.DAMAGE": "Skada",
|
||||
"ITEM.DEFENCE": "Skydd",
|
||||
"ITEM.DESCRIPTION": "Beskrivning",
|
||||
"ITEM.EQUIPABLE": "Bärbar",
|
||||
"ITEM.EQUIPPED": "Utrustad",
|
||||
"ITEM.GEAR": "Utrustning",
|
||||
"ITEM.PRICE": "Pris",
|
||||
"ITEM.QUANTITY": "Antal",
|
||||
"ITEM.SKILL": "Färdighet",
|
||||
"ITEM.SPELL": "Besvärjelse",
|
||||
"ITEM.TALENT": "Förmåga",
|
||||
"ITEM.WEAPON": "Vapen",
|
||||
|
||||
"MENU.SENTTOCHAT": "Skicka till chat",
|
||||
|
||||
"MOD.INIT": "Turordning",
|
||||
"MOD.TYPE": "Modifikation",
|
||||
"MOD.VALUE": "Värde",
|
||||
|
||||
"ROLL.SUCCESS": "Lyckat",
|
||||
"ROLL.FAILURE": "Misslyckat",
|
||||
|
||||
"SKILL.TYPE": "Typ",
|
||||
"SKILL.BASE": "Grundfärdigheter",
|
||||
"SKILL.ADVENTURE": "Äventyrsfärdigheter",
|
||||
"SKILL.COMBAT": "Stridsfärdigheter",
|
||||
"SKILL.STARTVALUE": "Grundvärde",
|
||||
"SKILL.LANGUAGE": "Språk",
|
||||
|
||||
"SPELL.DIFFICULTY": "Svårighet",
|
||||
"SPELL.ROLL": "Slag",
|
||||
"SPELL.COST": "Kostnad",
|
||||
|
||||
"STATS.HEALTH": "Hälsa",
|
||||
"STATS.MANA": "Skuld",
|
||||
"STATS.STAMINA": "Gard",
|
||||
|
||||
"TAB.BIO": "Bakgrund",
|
||||
"TAB.COMBAT": "Strid",
|
||||
"TAB.DESCRIPTION": "Beskrivning",
|
||||
"TAB.GEAR": "Utrustning",
|
||||
"TAB.MODIFICATION": "Modifikationer",
|
||||
"TAB.NOTE": "Anteckning",
|
||||
"TAB.SKILLS": "Färdigheter",
|
||||
"TAB.TALENTS": "Förmågor och Besvärjelser",
|
||||
|
||||
"WEAPON.CATEGORY": "Vapentyp",
|
||||
"WEAPON.MELEE": "Närstrid",
|
||||
"WEAPON.RANGED": "Avstånd"
|
||||
}
|
|
@ -0,0 +1,501 @@
|
|||
import KHDiceRoller from "../helpers/dice-helper.js"
|
||||
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
* @extends {ActorSheet}
|
||||
*/
|
||||
export class ActorSheetKH extends ActorSheet {
|
||||
khRoller = new KHDiceRoller();
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
classes: ["kopparhavet", "sheet", "actor"],
|
||||
template: "systems/kopparhavet/templates/actors/character-sheet.html",
|
||||
width: 710,
|
||||
height: 650,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "skills" }],
|
||||
scrollY: [".skills-tab .skills", ".talent-tab .items"],
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
get template() {
|
||||
const path = "systems/kopparhavet/templates/actors";
|
||||
return `${path}/${this.actor.data.type}-sheet.html`;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
data.dtypes = ["String", "Number", "Boolean"];
|
||||
|
||||
// Prepare items.
|
||||
this._prepareCharacterItems(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize and classify Items for Character sheets.
|
||||
* @param {Object} actorData The actor to prepare.
|
||||
* @return {undefined}
|
||||
*/
|
||||
_prepareCharacterItems(sheetData) {
|
||||
const actorData = sheetData.actor;
|
||||
|
||||
// Initialize containers.
|
||||
const skills = [];
|
||||
const talents = [];
|
||||
const weapons = [];
|
||||
const armor = [];
|
||||
const gear = [];
|
||||
const spells = [];
|
||||
const attacks = [];
|
||||
|
||||
// Iterate through items, allocating to containers
|
||||
for (let i of sheetData.items) {
|
||||
i.img = i.img || DEFAULT_TOKEN;
|
||||
|
||||
// Append to gear.
|
||||
if (i.type === "skill") {
|
||||
i.hasBase = i.data.type.value === "base";
|
||||
i.hasAdventure = i.data.type.value === "adventure";
|
||||
i.hasCombat = i.data.type.value === "combat";
|
||||
|
||||
skills.push(i);
|
||||
} else if (i.type === "talent") {
|
||||
talents.push(i);
|
||||
} else if (i.type === "weapon") {
|
||||
weapons.push(i);
|
||||
} else if (i.type === "armor") {
|
||||
armor.push(i);
|
||||
} else if (i.type === "gear") {
|
||||
gear.push(i);
|
||||
} else if (i.type === "spell") {
|
||||
spells.push(i);
|
||||
} else if (i.type === "adversaryAttack") {
|
||||
attacks.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign and return
|
||||
actorData.skills = skills;
|
||||
actorData.talents = talents;
|
||||
actorData.weapons = weapons;
|
||||
actorData.armor = armor;
|
||||
actorData.gear = gear;
|
||||
actorData.spells = spells;
|
||||
actorData.attacks = attacks;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
/* Send item Details to chat */
|
||||
new ContextMenu(html, "li.item", [
|
||||
{
|
||||
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, "div.item", [
|
||||
{
|
||||
name: game.i18n.localize("MENU.SENTTOCHAT"),
|
||||
icon: '<i class="far fa-comment"></i>',
|
||||
callback: (li) => {
|
||||
let itemId = li.data("itemId");
|
||||
this._itemDetailsToChat(itemId);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
html.find(".feature").click(async (ev) => {
|
||||
const featureName = $(ev.currentTarget).data("feature");
|
||||
const featureValue = this.actor.data.data.feature[featureName].value;
|
||||
if (featureName === "one") {
|
||||
this.actor.update({ "data.feature.one.value": !featureValue });
|
||||
} else if (featureName === "two") {
|
||||
this.actor.update({ "data.feature.two.value": !featureValue });
|
||||
} else if (featureName === "three") {
|
||||
this.actor.update({ "data.feature.three.value": !featureValue });
|
||||
} else if (featureName === "four") {
|
||||
this.actor.update({ "data.feature.four.value": !featureValue });
|
||||
}
|
||||
this._render();
|
||||
});
|
||||
|
||||
// Delete Inventory Item
|
||||
html.find(".item-delete").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
|
||||
this.actor.deleteOwnedItem(li.data("itemId"));
|
||||
|
||||
li.slideUp(200, () => this.render(false));
|
||||
});
|
||||
|
||||
// Edit Inventory Item
|
||||
html.find(".item-edit").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let itemId = li.data("itemId");
|
||||
let item = this.actor.getOwnedItem(itemId);
|
||||
|
||||
if (!item) {
|
||||
item = game.items.get(itemId);
|
||||
|
||||
if (!item) {
|
||||
console.log("IMPORT ERROR")
|
||||
}
|
||||
}
|
||||
|
||||
if (item?.sheet) {
|
||||
item.sheet.render(true);
|
||||
}
|
||||
});
|
||||
|
||||
/* Roll spell cost */
|
||||
html.find(".roll-spell-cost").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
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 cost = spell.data.data.cost.value;
|
||||
|
||||
let regex = /([0-9]*)t([0-9]*)/g;
|
||||
let regexMatch;
|
||||
|
||||
while (regexMatch = regex.exec(cost.toLowerCase())) {
|
||||
this.khRoller.rollSpellCostInChat(regexMatch[1], this.actor)
|
||||
}
|
||||
});
|
||||
|
||||
/* Roll skill */
|
||||
html.find(".roll-skill").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
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.rollSkillInChat(skillName, skillValue, showValue, this.actor)
|
||||
});
|
||||
|
||||
/* Roll weapon skill */
|
||||
html.find(".roll-weapon-skill").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve skill based on name
|
||||
let skill = this.actor.items.find((element) => element.name === weapon.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.rollSkillInChat(skillName, skillValue, showValue, this.actor)
|
||||
});
|
||||
|
||||
/* Roll weapon damage */
|
||||
html.find(".roll-damage").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
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)
|
||||
}
|
||||
});
|
||||
|
||||
/* Roll armor */
|
||||
html.find(".roll-armor").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let itemId = li.data("itemId");
|
||||
let armor = this.actor.getOwnedItem(itemId);
|
||||
|
||||
if (!armor) {
|
||||
armor = game.items.get(itemId);
|
||||
|
||||
if (!armor) {
|
||||
console.log("IMPORT ERROR")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let defence = armor.data.data.defence.value;
|
||||
let hasHelmet = false;
|
||||
|
||||
this.actor.items.map((i) => {
|
||||
if(i.type === "armor") {
|
||||
if(i.data.data.equipable.equipped && i.data.data.helmet.value) {
|
||||
if(CONFIG.KH.armor_types[i.data.data.type.value]?.ac >= CONFIG.KH.armor_types[armor.data.data.type.value]?.ac) {
|
||||
hasHelmet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let regex = /([0-9]*)t([0-9]*)/g;
|
||||
let regexMatch;
|
||||
|
||||
while (regexMatch = regex.exec(defence.toLowerCase())) {
|
||||
this.khRoller.rollArmorInChat(regexMatch[1], hasHelmet, this.actor)
|
||||
}
|
||||
});
|
||||
|
||||
/* Toggle item equipped */
|
||||
html.find(".items .item a.toggle-equipped").click(this._toggleEquippedItem.bind(this));
|
||||
|
||||
/* Handle increase of items in inventory */
|
||||
html.find(".item-quantity .quantity.increase").click(this._increaseQuantity.bind((this)));
|
||||
|
||||
/* Handle decrease of items in inventory */
|
||||
html.find(".item-quantity .quantity.decrease").click(this._decreaseQuantity.bind(this));
|
||||
|
||||
/* CHANGE SKILL VALUE */
|
||||
html.find(".skill-value").change(this._onChangeSkillValue.bind(this));
|
||||
html.find(".click-skill").click(this._onClickSkill.bind(this));
|
||||
|
||||
/* Adversary specific */
|
||||
html.find(".roll-adversary-attack").click((ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let skillValue = li.data("ability");
|
||||
|
||||
console.log(skillValue)
|
||||
|
||||
let skillName = "ITEM.ATTACK";
|
||||
|
||||
this.khRoller.rollSkillInChat(skillName, skillValue, false, this.actor)
|
||||
});
|
||||
|
||||
html.find(".roll-defence").click((ev) => {
|
||||
const skillValue = $(ev.currentTarget).data("defence");
|
||||
|
||||
let skillName = "ADVERSARY.DEFENCE";
|
||||
|
||||
this.khRoller.rollSkillInChat(skillName, skillValue, false, this.actor)
|
||||
});
|
||||
|
||||
html.find(".adversary-helmet-click").click((ev) => {
|
||||
ev.preventDefault();
|
||||
|
||||
let helmetValue = this.actor.data.data.combat.helmet;
|
||||
|
||||
if(helmetValue === undefined || helmetValue === null) {
|
||||
helmetValue = false
|
||||
}
|
||||
|
||||
this.actor.update({ "data.combat.helmet": !helmetValue });
|
||||
});
|
||||
|
||||
html.find(".roll-adversary-armor").click((ev) => {
|
||||
const armor = $(ev.currentTarget).data("armor");
|
||||
|
||||
let hasHelmet = this.actor.data.data.combat.helmet;
|
||||
|
||||
if(hasHelmet === undefined || hasHelmet === null) {
|
||||
hasHelmet = false;
|
||||
}
|
||||
|
||||
let regex = /([0-9]*)t([0-9]*)/g;
|
||||
let regexMatch;
|
||||
|
||||
while (regexMatch = regex.exec(armor.toLowerCase())) {
|
||||
this.khRoller.rollArmorInChat(regexMatch[1], hasHelmet, this.actor)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _toggleEquippedItem(event) {
|
||||
const li = $(event.currentTarget);
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
const actor = this.actor;
|
||||
|
||||
if (item) {
|
||||
if(item.type === "armor") {
|
||||
let initValue = -1
|
||||
|
||||
if(item.data.data.equipable.equipped) {
|
||||
initValue = 4
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (item.data?.data?.modifications) {
|
||||
for(let k of Object.keys(item.data.data.modifications)) {
|
||||
if(item.data.data.modifications[k].modtype === "init") {
|
||||
initValue = item.data.data.modifications[k].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(initValue > 0) {
|
||||
actor.update({ ["data.combat.init"]: initValue });
|
||||
}
|
||||
}
|
||||
|
||||
item.update({ ["data.equipable.equipped"]: !item.data.data.equipable.equipped });
|
||||
} else {
|
||||
console.log("Could not find item")
|
||||
}
|
||||
}
|
||||
|
||||
async _increaseQuantity(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
let itemId = li.data("itemId");
|
||||
let item = this.actor.getOwnedItem(itemId);
|
||||
|
||||
if (!item) {
|
||||
console.log("IMPORT ERROR")
|
||||
}
|
||||
|
||||
item.update({ ["data.quantity.value"]: item.data.data.quantity.value + 1 });
|
||||
}
|
||||
|
||||
async _decreaseQuantity(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
let itemId = li.data("itemId");
|
||||
let item = this.actor.getOwnedItem(itemId);
|
||||
|
||||
if (!item) {
|
||||
console.log("IMPORT ERROR")
|
||||
}
|
||||
|
||||
let count = item.data.data.quantity.value - 1 > 0 ? item.data.data.quantity.value - 1 : 0;
|
||||
|
||||
item.update({ ["data.quantity.value"]: count });
|
||||
}
|
||||
|
||||
async _onChangeSkillValue(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const itemId = $(event.currentTarget).data("item-id");
|
||||
let _item = this.actor.items.find((element) => element._id == itemId);
|
||||
|
||||
if (_item) {
|
||||
let update = {
|
||||
_id: _item._id,
|
||||
data: { value: $(event.currentTarget).val() },
|
||||
};
|
||||
await this.actor.updateEmbeddedEntity("OwnedItem", update);
|
||||
}
|
||||
}
|
||||
|
||||
async _onClickSkill(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const itemId = $(event.currentTarget).data("item-id");
|
||||
let _item = this.actor.items.find((element) => element._id == itemId);
|
||||
|
||||
if (_item) {
|
||||
let newVal = true;
|
||||
|
||||
if(_item.data.data.used !== undefined) {
|
||||
newVal = !_item.data.data.used;
|
||||
}
|
||||
|
||||
let update = {
|
||||
_id: _item._id,
|
||||
data: { used: newVal },
|
||||
};
|
||||
await this.actor.updateEmbeddedEntity("OwnedItem", update);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send details of an item to chat.
|
||||
* @private
|
||||
*/
|
||||
async _itemDetailsToChat(itemId) {
|
||||
let item = this.actor.getOwnedItem(itemId);
|
||||
|
||||
if (!item) {
|
||||
item = game.items.get(itemId);
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
console.log("IMPORT ERROR")
|
||||
return
|
||||
}
|
||||
|
||||
const itemDetails = item?.getItemDetails();
|
||||
const html = await renderTemplate("systems/kopparhavet/templates/chat/item-card.html", itemDetails);
|
||||
|
||||
const messageData = {
|
||||
user: game.user._id,
|
||||
type: CONST.CHAT_MESSAGE_TYPES.OTHER,
|
||||
content: html,
|
||||
speaker: {
|
||||
actor: this.actor._id,
|
||||
token: this.actor.token,
|
||||
alias: this.actor.name,
|
||||
},
|
||||
};
|
||||
ChatMessage.create(messageData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Extend the base Actor entity.
|
||||
* @extends {Actor}
|
||||
*/
|
||||
export class ActorKH extends Actor {
|
||||
/**
|
||||
* Augment the basic actor data with additional dynamic data.
|
||||
*/
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
const actorData = this.data;
|
||||
const data = actorData.data;
|
||||
const flags = actorData.flags;
|
||||
data.type = actorData.type;
|
||||
|
||||
console.log("ACTOR DATA")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
export default class KHDiceRoller {
|
||||
async rollSpellCostInChat(cost, speaker) {
|
||||
let formula = cost + "d6"
|
||||
|
||||
const roll = new Roll(formula);
|
||||
|
||||
let res = roll.roll();
|
||||
|
||||
let rollData = {
|
||||
name: "SPELL.COST",
|
||||
res: res,
|
||||
showFormula: 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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async rollDamageInChat(facesNr, speaker) {
|
||||
let formula = facesNr + "d6x6"
|
||||
|
||||
const roll = new Roll(formula);
|
||||
|
||||
let res = roll.roll();
|
||||
|
||||
let rollData = {
|
||||
name: "ITEM.DAMAGE",
|
||||
res: res,
|
||||
showFormula: 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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async rollArmorInChat(armor, hasHelmet, speaker) {
|
||||
let formula = armor + "d6"
|
||||
|
||||
if(hasHelmet) {
|
||||
formula += "x6"
|
||||
}
|
||||
|
||||
const roll = new Roll(formula);
|
||||
|
||||
let res = roll.roll();
|
||||
|
||||
let rollData = {
|
||||
name: "ITEM.DEFENCE",
|
||||
res: res,
|
||||
showFormula: 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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async rollSkillInChat(skillName, skillValue, showValue, speaker) {
|
||||
const roll = new Roll(`1d100`);
|
||||
|
||||
let res = roll.roll();
|
||||
|
||||
let computedName = skillName
|
||||
|
||||
if(showValue) {
|
||||
computedName += " (" + skillValue + ")"
|
||||
}
|
||||
|
||||
let rollData = {
|
||||
name: computedName,
|
||||
res: res
|
||||
};
|
||||
|
||||
if(skillValue > 0) {
|
||||
if(res.total <= skillValue) {
|
||||
rollData.success = true
|
||||
} else {
|
||||
rollData.failure = 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,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
export default class ItemHelpers {
|
||||
static async itemUpdate(event, formData) {
|
||||
formData = expandObject(formData);
|
||||
|
||||
if (this.object.isOwned && this.object.actor?.compendium?.metadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the free-form modifications list
|
||||
const formAttrs = expandObject(formData)?.data?.modifications || {};
|
||||
|
||||
const modifications = Object.values(formAttrs).reduce((obj, v) => {
|
||||
let k = v["key"].trim();
|
||||
delete v["key"];
|
||||
obj[k] = v;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
// Remove modifications which are no longer used
|
||||
if (this.object.data?.data?.modifications) {
|
||||
for (let k of Object.keys(this.object.data.data.modifications)) {
|
||||
if (!modifications.hasOwnProperty(k)) modifications[`-=${k}`] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// recombine modifications to formData
|
||||
if (Object.keys(modifications).length > 0) {
|
||||
setProperty(formData, `data.modifications`, modifications);
|
||||
}
|
||||
|
||||
// Update the Item
|
||||
this.item.data.flags.loaded = false;
|
||||
this.object.update(formData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* Extend the basic ItemSheet
|
||||
* @extends {ItemSheet}
|
||||
*/
|
||||
import ItemHelpers from "../helpers/item-helpers.js";
|
||||
|
||||
export class ItemSheetKH extends ItemSheet {
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
classes: ["starwarsffg", "sheet", "item"],
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
|
||||
scrollY: [".sheet-body", ".tab"],
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
get template() {
|
||||
const path = "systems/kopparhavet/templates/items";
|
||||
return `${path}/${this.item.data.type}-sheet.html`;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async getData() {
|
||||
const data = super.getData();
|
||||
let skillList = [];
|
||||
|
||||
data.dtypes = ["String", "Number", "Boolean"];
|
||||
|
||||
if (data?.data?.modifications) {
|
||||
for (let attr of Object.values(data.data.modifications)) {
|
||||
attr.isCheckbox = attr.dtype === "Boolean";
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.object.data.type) {
|
||||
case "weapon":
|
||||
// Load Skills Compendium skills
|
||||
let skillList2 = await game.packs.get("kopparhavet.skills").getContent();
|
||||
|
||||
for (let item of skillList2) {
|
||||
if(item.data.type === "skill" && item.data.data.type.value === "combat") {
|
||||
skillList.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve any created skills as well
|
||||
for (let item of game.items.entities) {
|
||||
if(item.data.type === "skill" && item.data.data.type.value === "combat") {
|
||||
skillList.push(item)
|
||||
}
|
||||
}
|
||||
this.position.width = 530;
|
||||
this.position.height = 750;
|
||||
break;
|
||||
case "armor":
|
||||
this.position.width = 385;
|
||||
this.position.height = 628;
|
||||
break;
|
||||
case "gear":
|
||||
case "skill":
|
||||
this.position.width = 385;
|
||||
this.position.height = 606;
|
||||
break;
|
||||
case "talent":
|
||||
this.position.width = 405;
|
||||
this.position.height = 570;
|
||||
break;
|
||||
default:
|
||||
this.position.width = 450;
|
||||
this.position.height = 605;
|
||||
break;
|
||||
}
|
||||
|
||||
data.khskills = skillList;
|
||||
data.KH = CONFIG.KH;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Armor related
|
||||
html.find(".item-bool-click").click(async (ev) => {
|
||||
const clickedName = $(ev.currentTarget).data("name");
|
||||
|
||||
if(clickedName === "equipped") {
|
||||
const equppiedValue = this.item.data.data.equipable.equipped;
|
||||
|
||||
this.item.update({ "data.equipped.equipped": !equppiedValue });
|
||||
} else {
|
||||
const clickedValue = (this.item.data.data[clickedName].value == undefined ? false : this.item.data.data[clickedName].value);
|
||||
let dataName = "data." + clickedName + ".value"
|
||||
let tempData = {}
|
||||
|
||||
tempData[dataName] = !clickedValue
|
||||
|
||||
this.item.update(tempData);
|
||||
}
|
||||
|
||||
this._render();
|
||||
});
|
||||
|
||||
// Add or Remove modification
|
||||
html.find(".modification-control").click(this._onClickModificationControl.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* DOM event
|
||||
* @param {object} event
|
||||
*/
|
||||
async _onClickModificationControl(event) {
|
||||
event.preventDefault();
|
||||
const a = event.currentTarget;
|
||||
const action = a.dataset.action;
|
||||
const attrs = this.object.data.data.modifications;
|
||||
const form = this.form;
|
||||
|
||||
// Add new modification
|
||||
if (action === "create") {
|
||||
const nk = new Date().getTime();
|
||||
let newKey = document.createElement("div");
|
||||
|
||||
newKey.innerHTML = `<input type="text" name="data.modifications.attr${nk}.key" value="attr${nk}" style="display:none;"/><select class="modification-modtype" name="data.modifications.attr${nk}.modtype"><option value="init">Turordning</option></select><input class="modification-value" type="text" name="data.modifications.attr${nk}.value" value="0" data-dtype="Number" placeholder="0"/>`;
|
||||
|
||||
form.appendChild(newKey);
|
||||
await this._onSubmit(event);
|
||||
}
|
||||
|
||||
// Remove existing modification
|
||||
else if (action === "delete") {
|
||||
const li = a.closest(".modification");
|
||||
li.parentElement.removeChild(li);
|
||||
await this._onSubmit(event);
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
const itemUpdate = ItemHelpers.itemUpdate.bind(this);
|
||||
itemUpdate(event, formData);
|
||||
}
|
||||
|
||||
_getHeaderButtons() {
|
||||
let buttons = super._getHeaderButtons();
|
||||
buttons = [
|
||||
{
|
||||
label: "Post Item",
|
||||
class: "item-post",
|
||||
icon: "fas fa-comment",
|
||||
onclick: (ev) => this.item.sendToChat(),
|
||||
}
|
||||
].concat(buttons);
|
||||
return buttons;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Extend the basic Item.
|
||||
* @extends {Item}
|
||||
*/
|
||||
export class ItemKH extends Item {
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
}
|
||||
|
||||
async sendToChat() {
|
||||
const itemData = duplicate(this.data);
|
||||
|
||||
if(itemData.img.includes("/mystery-man")) {
|
||||
itemData.img = null;
|
||||
}
|
||||
|
||||
itemData.isArmor = itemData.type === "armor";
|
||||
itemData.isGear = itemData.type === "gear";
|
||||
itemData.isAdversaryAttack = itemData.type === "adversaryAttack";
|
||||
itemData.isSkill = itemData.type === "skill";
|
||||
itemData.isSpell = itemData.type === "spell";
|
||||
itemData.isTalent = itemData.type === "talent";
|
||||
itemData.isWeapon = itemData.type === "weapon";
|
||||
|
||||
const html = await renderTemplate("systems/kopparhavet/templates/chat/item-card.html", itemData);
|
||||
|
||||
const chatData = {
|
||||
user: game.user._id,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
content: html,
|
||||
};
|
||||
|
||||
if (["gmroll", "blindroll"].includes(chatData.rollMode)) {
|
||||
chatData.whisper = ChatMessage.getWhisperRecipients("GM");
|
||||
} else if (chatData.rollMode === "selfroll") {
|
||||
chatData.whisper = [game.user];
|
||||
}
|
||||
|
||||
ChatMessage.create(chatData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare and return details of the item for display in inventory or chat.
|
||||
*/
|
||||
getItemDetails() {
|
||||
const itemData = duplicate(this.data);
|
||||
|
||||
if(itemData.img.includes("/mystery-man")) {
|
||||
itemData.img = null;
|
||||
}
|
||||
|
||||
itemData.isArmor = itemData.type === "armor";
|
||||
itemData.isGear = itemData.type === "gear";
|
||||
itemData.isAdversaryAttack = itemData.type === "adversaryAttack";
|
||||
itemData.isSkill = itemData.type === "skill";
|
||||
itemData.isSpell = itemData.type === "spell";
|
||||
itemData.isTalent = itemData.type === "talent";
|
||||
itemData.isWeapon = itemData.type === "weapon";
|
||||
|
||||
return itemData
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
export const KH = {};
|
||||
|
||||
KH.armor_mod_types = {
|
||||
"init": {
|
||||
"value": "init",
|
||||
"label": "MOD.INIT",
|
||||
},
|
||||
};
|
||||
|
||||
KH.armor_types = {
|
||||
"light": {
|
||||
"value": "light",
|
||||
"label": "ARMOR.LIGHT",
|
||||
"ac": 10,
|
||||
},
|
||||
"medium": {
|
||||
"value": "medium",
|
||||
"label": "ARMOR.MEDIUM",
|
||||
"ac": 20,
|
||||
},
|
||||
"heavy": {
|
||||
"value": "heavy",
|
||||
"label": "ARMOR.HEAVY",
|
||||
"ac": 30,
|
||||
},
|
||||
};
|
|
@ -0,0 +1,96 @@
|
|||
class KHDice {
|
||||
static async Init(controls, html) {
|
||||
const diceRollbtn = $(
|
||||
`
|
||||
<li class="scene-control sdr-scene-control">
|
||||
<i class="fas fa-dice-d20"></i>
|
||||
<ol class="control-tools">
|
||||
<div id="SDRpopup" class="kh-dice-roller-popup" style="display: none;">
|
||||
<ul>
|
||||
<li data-dice-type="6" data-dice-roll="1" class="sdr-col1"><i class="df-d6-6" data-dice-type="6" data-dice-roll="1"></i> d6</li>
|
||||
<li data-dice-type="6" data-dice-roll="2">2</li>
|
||||
<li data-dice-type="6" data-dice-roll="3">3</li>
|
||||
<li data-dice-type="6" data-dice-roll="4">4</li>
|
||||
<li data-dice-type="6" data-dice-roll="5" class="sdr-lastcol">5</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li data-dice-type="10" data-dice-roll="1" class="sdr-col1"><i class="df-d10-10" data-dice-type="10" data-dice-roll="1"></i> d10</li>
|
||||
<li data-dice-type="10" data-dice-roll="2">2</li>
|
||||
<li data-dice-type="10" data-dice-roll="3">3</li>
|
||||
<li data-dice-type="10" data-dice-roll="4">4</li>
|
||||
<li data-dice-type="10" data-dice-roll="5" class="sdr-lastcol">5</li>
|
||||
</ul>
|
||||
<ul class="sdr-lastrow">
|
||||
<li data-dice-type="100" data-dice-roll="1" class="sdr-col1"><i class="df-d10-10" data-dice-type="100" data-dice-roll="1"></i><i class="df-d10-10" data-dice-type="100" data-dice-roll="1"></i> d100</li>
|
||||
<li data-dice-type="100" data-dice-roll="2">2</li>
|
||||
<li data-dice-type="100" data-dice-roll="3">3</li>
|
||||
<li data-dice-type="100" data-dice-roll="4">4</li>
|
||||
<li data-dice-type="100" data-dice-roll="5" class="sdr-lastcol">5</li>
|
||||
</ul>
|
||||
</div>
|
||||
</ol>
|
||||
</li>
|
||||
`
|
||||
);
|
||||
|
||||
html.append(diceRollbtn);
|
||||
|
||||
html.find('.kh-dice-roller-popup li').click(ev => this._rollDice(ev, html));
|
||||
|
||||
diceRollbtn[0].addEventListener('click', ev => this.PopupSheet(ev, html));
|
||||
}
|
||||
|
||||
static async _rollDice(event, html) {
|
||||
var diceType = event.target.dataset.diceType;
|
||||
var diceRoll = event.target.dataset.diceRoll;
|
||||
var formula = diceRoll + "d" + diceType;
|
||||
|
||||
let r = new Roll(formula);
|
||||
|
||||
let res = r.roll();
|
||||
|
||||
let rollData = {
|
||||
name: "DICE.ROLL",
|
||||
res: res
|
||||
};
|
||||
|
||||
const html2 = await renderTemplate("systems/kopparhavet/templates/dice/roll.html", rollData);
|
||||
|
||||
await r.toMessage({
|
||||
user: game.user._id,
|
||||
create: true,
|
||||
content: html2
|
||||
});
|
||||
|
||||
this._close(html);
|
||||
|
||||
}
|
||||
|
||||
static async PopupSheet(evt, html) {
|
||||
evt.stopPropagation();
|
||||
|
||||
if (html.find('.sdr-scene-control').hasClass('active')) {
|
||||
this._close(html);
|
||||
} else {
|
||||
this._open(html);
|
||||
}
|
||||
}
|
||||
|
||||
static async _close(html) {
|
||||
html.find('#SDRpopup').hide();
|
||||
html.find('.sdr-scene-control').removeClass('active');
|
||||
html.find('.scene-control').first().addClass('active');
|
||||
}
|
||||
|
||||
static async _open(html) {
|
||||
html.find('.scene-control').removeClass('active');
|
||||
html.find('#SDRpopup').show();
|
||||
html.find('.sdr-scene-control').addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
Hooks.on('renderSceneControls', (controls, html) => {
|
||||
KHDice.Init(controls, html);
|
||||
});
|
||||
|
||||
console.log("Kopparhavet | Dice Roller loaded");
|
|
@ -0,0 +1,23 @@
|
|||
export default class KHHooks {
|
||||
static async onCreateActor(actor, options, userId) {
|
||||
if (actor.data.type == "character") {
|
||||
const actorbaseSkills = actor.data.data.baseSkills;
|
||||
|
||||
// Check if skill already exists by some chance
|
||||
const existingSkills = actor.items.filter((i) => i.type === ItemType.Skill).map((i) => i.name);
|
||||
const skillsToAdd = actorbaseSkills.filter((s) => !existingSkills.includes(s));
|
||||
|
||||
// Load Skills Compendium skills
|
||||
const skillIndex = await game.packs.get("kopparhavet.skills").getContent();
|
||||
|
||||
// Filter skillIndex array to include only skills for Actor Type.
|
||||
let _skillsList = skillIndex.filter((i) => skillsToAdd.includes(i.data.name));
|
||||
|
||||
await actor.createEmbeddedEntity("OwnedItem", _skillsList);
|
||||
} else {
|
||||
setTimeout(async function () {
|
||||
await actor.sheet.render(true);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
import { ItemSheetKH } from "./items/item-sheet.js";
|
||||
import { ItemKH } from "./items/item.js";
|
||||
import KHHooks from "./kh-hooks.js";
|
||||
import { ActorKH } from "./actors/actor.js";
|
||||
import { ActorSheetKH } from "./actors/actor-sheet.js";
|
||||
import { KH } from "./kh-config.js";
|
||||
|
||||
Hooks.once("init", () => {
|
||||
CONFIG.Combat.initiative = { formula: "(@combat.init)d6kh2", decimals: 0 };
|
||||
|
||||
CONFIG.Actor.entityClass = ActorKH;
|
||||
CONFIG.Item.entityClass = ItemKH;
|
||||
|
||||
// Give global access to FFG config.
|
||||
CONFIG.KH = KH;
|
||||
|
||||
//registerFonts();
|
||||
registerSheets();
|
||||
preloadHandlebarsTemplates();
|
||||
registerHandlebarsHelpers();
|
||||
game.settings.register("kopparhavet", "worldSchemaVersion", {
|
||||
name: "World Version",
|
||||
hint: "Used to automatically upgrade worlds data when the system is upgraded.",
|
||||
scope: "world",
|
||||
config: true,
|
||||
default: 0,
|
||||
type: Number,
|
||||
});
|
||||
});
|
||||
|
||||
Hooks.once("ready", () => {
|
||||
//migrateWorld();
|
||||
});
|
||||
|
||||
/* POPULATE CHARACTER WITH DEFAULT SKILLS */
|
||||
Hooks.on("createActor", async (actor, options, userId) => KHHooks.onCreateActor(actor, options, userId));
|
||||
|
||||
function registerSheets() {
|
||||
// Register sheet application classes
|
||||
console.log("Registerting sheets")
|
||||
|
||||
Actors.unregisterSheet("core", ActorSheet);
|
||||
Actors.registerSheet("kopparhavet", ActorSheetKH, { types: ["character"], makeDefault: true });
|
||||
Actors.registerSheet("kopparhavet", ActorSheetKH, { types: ["adversary"], makeDefault: true });
|
||||
|
||||
Items.unregisterSheet("core", ItemSheet);
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["weapon"], makeDefault: true });
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["armor"], makeDefault: true });
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["gear"], makeDefault: true });
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["skill"], makeDefault: true });
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["spell"], makeDefault: true });
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["talent"], makeDefault: true });
|
||||
Items.registerSheet("kopparhavet", ItemSheetKH, { types: ["adversaryAttack"], makeDefault: true });
|
||||
}
|
||||
|
||||
function preloadHandlebarsTemplates() {
|
||||
const templatePaths = [
|
||||
"systems/kopparhavet/templates/chat/item-card.html",
|
||||
"systems/kopparhavet/templates/actors/adversary-sheet.html",
|
||||
"systems/kopparhavet/templates/actors/character-sheet.html",
|
||||
"systems/kopparhavet/templates/dice/roll.html",
|
||||
"systems/kopparhavet/templates/items/adversaryAttack-sheet.html",
|
||||
"systems/kopparhavet/templates/items/armor-sheet.html",
|
||||
"systems/kopparhavet/templates/items/gear-sheet.html",
|
||||
"systems/kopparhavet/templates/items/skill-sheet.html",
|
||||
"systems/kopparhavet/templates/items/spell-sheet.html",
|
||||
"systems/kopparhavet/templates/items/talent-sheet.html",
|
||||
"systems/kopparhavet/templates/items/weapon-sheet.html",
|
||||
"systems/kopparhavet/templates/parts/actor/bio.html",
|
||||
"systems/kopparhavet/templates/parts/actor/combat.html",
|
||||
"systems/kopparhavet/templates/parts/actor/gear.html",
|
||||
"systems/kopparhavet/templates/parts/actor/skills.html",
|
||||
"systems/kopparhavet/templates/parts/actor/talent.html",
|
||||
"systems/kopparhavet/templates/parts/shared/modifications.html",
|
||||
];
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
function normalize(data, defaultValue) {
|
||||
if (data) {
|
||||
return data.toLowerCase();
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
function registerHandlebarsHelpers() {
|
||||
Handlebars.registerHelper("weaponCategory", function (category) {
|
||||
category = normalize(category, "melee");
|
||||
switch (category) {
|
||||
case "melee":
|
||||
return game.i18n.localize("WEAPON.MELEE");
|
||||
case "ranged":
|
||||
return game.i18n.localize("WEAPON.RANGED");
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("rollDifficulty", function (difficulty) {
|
||||
difficulty = normalize(difficulty, "average");
|
||||
switch (difficulty) {
|
||||
case "simple":
|
||||
return game.i18n.localize("DIFFICULTY.SIMPLE");
|
||||
case "easy":
|
||||
return game.i18n.localize("DIFFICULTY.EASY");
|
||||
case "average":
|
||||
return game.i18n.localize("DIFFICULTY.AVERAGE");
|
||||
case "hard":
|
||||
return game.i18n.localize("DIFFICULTY.HARD");
|
||||
case "daunting":
|
||||
return game.i18n.localize("DIFFICULTY.DAUNTING");
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("skillType", function (skillType) {
|
||||
skillType = normalize(skillType, "base");
|
||||
|
||||
switch (skillType) {
|
||||
case "base":
|
||||
return game.i18n.localize("SKILL.BASE");
|
||||
case "adventure":
|
||||
return game.i18n.localize("SKILL.ADVENTURE");
|
||||
case "combat":
|
||||
return game.i18n.localize("SKILL.COMBAT");
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('plaintextToHTML', function(value) {
|
||||
// strip tags, add <br/> tags
|
||||
return new Handlebars.SafeString(value.replace(/(<([^>]+)>)/gi, "").replace(/(?:\r\n|\r|\n)/g, '<br/>'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{"name":"Smidighet","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"base","label":"SKILL.TYPE"},"value":"25","used":false},"flags":{"core":{"sourceId":"Item.tmNI5YIYYjGuZK5i"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"INlHwwv9wG4VA13D"}
|
||||
{"name":"Trolldom","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.Ewo6mu7WdoOcF6DD"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"kIu2AL79urDjZV8z"}
|
||||
{"name":"Fingerfärdighet","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.syxeJlio8vIrx0Lr"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"9gkb0ONyCuBcWwoB"}
|
||||
{"name":"Finna dolda ting","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.Yvy3Ej3tDNhp0VVA"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"PaieUawcyfKhfSCv"}
|
||||
{"name":"Förleda","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.orNrL49vWUePhLaU"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"JN1b5A5QHoinB5Gd"}
|
||||
{"name":"Gömma sig","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.b9U8BXjNvI4LwlRX"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"A8DBqRLBJ0yU3Ebp"}
|
||||
{"name":"Handel","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.DDZkgceLisZOYHEi"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"GS4NknpWIKYWceky"}
|
||||
{"name":"Hantverk","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.0m5bA14oR16bB2Gt"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"imcYcYl21T4xewNa"}
|
||||
{"name":"Insikt","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.bVEJBtXhXOkqIBek"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"NXJMfsrhYeCCEFP2"}
|
||||
{"name":"Jakt","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.5wz37ypKMn6tgtTr"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"3EuThKpVWrtV1Myy"}
|
||||
{"name":"Kastvapen","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.XF2eNRo6uMhDs5Uv"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"33aM81M73ZyO1NNT"}
|
||||
{"name":"Knivar","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.boR4AGF8LD12ykoc"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"dGpYfI8CLwxKSzas"}
|
||||
{"name":"Lagkunskap","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.8org0OaWuKO6rCqm"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"SYa97JM5u0aCNJMA"}
|
||||
{"name":"Legender","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.dYcVgFgx6WmBWCeZ"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"JcmDWE2GxJ9HKIuT"}
|
||||
{"name":"Läkekonst","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.DSWruhUT6DT9kY7Z"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"DqnFfN91ovo86QOn"}
|
||||
{"name":"Lärdom","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.5oQCvQNiDSeIe8vI"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"Y6kDWokNA81POqvG"}
|
||||
{"name":"Musik","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.bcRVOx8M3Ue6tgGz"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"5nMScpCnMbb77QfD"}
|
||||
{"name":"Rida","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.eFeMJtv30eImpUMn"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"lqRRrd1Qdmbv5Nay"}
|
||||
{"name":"Sjömanskap","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.BkCe8HPX1wVYlsmV"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"JIEl6a3sIkH2V5wX"}
|
||||
{"name":"Skytte","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.5NCkdBZ4lWwLzGwk"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"jEoMTkqoxQ9iSaoB"}
|
||||
{"name":"Sköldar","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.NBRV1tzrIV9AmGka"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"OkDh0xCD26hUrthN"}
|
||||
{"name":"Slagsmål","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.IC2RGKp9cEYzyIln"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"afCvHSTrmDWNkj31"}
|
||||
{"name":"Spana","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.EVCN4lxeferZYP0P"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"Z0pWniEH3MBU69g6"}
|
||||
{"name":"Spel","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.Uc9XLdzkI7mGMTLL"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"HigGBE4oUC9yYMYw"}
|
||||
{"name":"Spjut","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.qbi9SN1V4bPT3T3Y"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"Ab22ZgWUiHl83kLQ"}
|
||||
{"name":"Språk","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.elGMSOQROaYXCEPA"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"VZx4zxd72g4tKvAd"}
|
||||
{"name":"Status","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.F5lkuwhO3WGl5yWk"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"eaooVeqja7pzzC1X"}
|
||||
{"name":"Stigvana","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.TjVsmOs0PqbAzNUf"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"dR4UbIXYyCovTGzA"}
|
||||
{"name":"Styrka","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"base","label":"SKILL.TYPE"},"value":"25","used":false},"flags":{"core":{"sourceId":"Item.YpheXmaKsX9omtBA"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"anObCIyX3DdSjNPY"}
|
||||
{"name":"Svärd","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.uctwxo07FCKCk2K4"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"IketG7YFZuGHnihF"}
|
||||
{"name":"Taktik","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.KJLF5fDrZaA1DKg1"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"5xTZzjUd7x2EgmG2"}
|
||||
{"name":"Uthållighet","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"base","label":"SKILL.TYPE"},"value":"25","used":false},"flags":{"core":{"sourceId":"Item.VWaRRqiUlMw1nPUn"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"4yFL38tdvBenZKBQ"}
|
||||
{"name":"Viljestyrka","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"base","label":"SKILL.TYPE"},"value":"25","used":false},"flags":{"core":{"sourceId":"Item.UkwUABDT8NB8y1mQ"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"vyW9DUMDPYqBSCtz"}
|
||||
{"name":"Väderkunskap","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"adventure","label":"SKILL.TYPE"},"value":"15","used":false},"flags":{"core":{"sourceId":"Item.GxkoQ2KdPh9ogGuJ"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"TEOcwEm0Z9GzJS6h"}
|
||||
{"name":"Yxor","permission":{"default":0,"tSnD115pP1EPBAXK":3},"type":"skill","data":{"description":{"value":"","type":"String","label":"ITEM.DESCRIPTION"},"type":{"value":"combat","label":"SKILL.TYPE"},"value":"30","used":false},"flags":{"core":{"sourceId":"Item.b9no6ZeE5KyG9AfT"}},"img":"icons/svg/mystery-man.svg","effects":[],"_id":"BKu4BwEspAMQ5Yn3"}
|
|
@ -0,0 +1,191 @@
|
|||
.kopparhavet .character {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.kopparhavet .adversary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.actor-avatar-img {
|
||||
max-width: 200px;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.charname {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.skill-value {
|
||||
max-width: 50px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/*
|
||||
.kopparhavet .note .editor {
|
||||
min-height: 302px;
|
||||
}
|
||||
|