Final v0.0.2

This commit is contained in:
2020-11-30 06:23:35 +01:00
parent 512d0de4e5
commit 6f030bd6b5
20 changed files with 884 additions and 135 deletions

View File

@@ -1,4 +1,5 @@
import KHDiceRoller from "../helpers/dice-helper.js"
import ActorHelpers from "../helpers/actor-helper.js";
/**
* Extend the basic ActorSheet with some very simple modifications
@@ -9,12 +10,23 @@ export class ActorSheetKH extends ActorSheet {
/** @override */
static get defaultOptions() {
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
return mergeObject(super.defaultOptions, {
classes: ["kopparhavet", "sheet", "actor"],
template: "systems/kopparhavet/templates/actors/ht-character-sheet.html",
width: 710,
height: 650,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "main" }],
scrollY: [".skills-tab .skills", ".talent-tab .items"],
});
}
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" }],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "main" }],
scrollY: [".skills-tab .skills", ".talent-tab .items"],
});
}
@@ -22,7 +34,13 @@ export class ActorSheetKH extends ActorSheet {
/** @override */
get template() {
const path = "systems/kopparhavet/templates/actors";
return `${path}/${this.actor.data.type}-sheet.html`;
let prefix = "";
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
prefix = "ht-";
}
return `${path}/${prefix}${this.actor.data.type}-sheet.html`;
}
/* -------------------------------------------- */
@@ -278,15 +296,17 @@ export class ActorSheetKH extends ActorSheet {
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
if(game.settings.get("kopparhavet", "gameSystem") === "kopparhavet") {
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;
@@ -314,8 +334,6 @@ export class ActorSheetKH extends ActorSheet {
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)
@@ -357,6 +375,104 @@ export class ActorSheetKH extends ActorSheet {
this.khRoller.rollArmorInChat(regexMatch[1], hasHelmet, this.actor)
}
});
// Add or Remove relationship
html.find(".learning-control").click(this._onClickLearningControl.bind(this));
html.find(".learning-click").click(this._onClickLearingLearned.bind(this));
/* Hjältarnas Tid specefic */
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
// Add or Remove relationship
html.find(".relation-control").click(this._onClickRelationshipControl.bind(this));
html.find(".relation-click").click(this._onClickRelationshipUsed.bind(this));
}
}
async _onClickLearingLearned(event) {
event.stopPropagation();
const li1 = $(event.currentTarget);
const li2 = $(event.currentTarget).parents(".learning");
let box = li1.data("num")
let learingKey = li2.data("attribute");
const clickedValue = (this.actor.data.data.learning[learingKey][box] == undefined ? false : this.actor.data.data.learning[learingKey][box]);
let dataName = "data.learning." + learingKey + "." + box
let tempData = {}
tempData[dataName] = !clickedValue
this.actor.update(tempData);
this._render();
}
async _onClickLearningControl(event) {
event.preventDefault();
const a = event.currentTarget;
const action = a.dataset.action;
const attrs = this.object.data.data.learning;
const form = this.form;
// Add new modification
if (action === "create") {
const nk = new Date().getTime();
let newKey = document.createElement("div");
newKey.innerHTML = `<input class="learning-key" type="text" name="data.learning.attr${nk}.key" value="attr${nk}" style="display: none;" /><input class="learning-key" type="text" name="data.learning.attr${nk}.value" value="" style="display: none;" />`;
form.appendChild(newKey);
await this._onSubmit(event);
}
// Remove existing modification
else if (action === "delete") {
const li = a.closest(".learning");
li.parentElement.removeChild(li);
await this._onSubmit(event);
}
}
async _onClickRelationshipControl(event) {
event.preventDefault();
const a = event.currentTarget;
const action = a.dataset.action;
const attrs = this.object.data.data.relationships;
const form = this.form;
// Add new modification
if (action === "create") {
const nk = new Date().getTime();
let newKey = document.createElement("div");
newKey.innerHTML = `<input class="relation-key" type="text" name="data.relationships.attr${nk}.key" value="attr${nk}" style="display: none;" /><input class="relation-key" type="text" name="data.relationships.attr${nk}.value" value="" style="display: none;" />`;
form.appendChild(newKey);
await this._onSubmit(event);
}
// Remove existing modification
else if (action === "delete") {
const li = a.closest(".relation");
li.parentElement.removeChild(li);
await this._onSubmit(event);
}
}
async _onClickRelationshipUsed(event) {
event.stopPropagation();
const li = $(event.currentTarget).parents(".relation");
let relationshipKey = li.data("attribute");
const clickedValue = (this.actor.data.data.relationships[relationshipKey].check == undefined ? false : this.actor.data.data.relationships[relationshipKey].check);
let dataName = "data.relationships." + relationshipKey + ".check"
let tempData = {}
tempData[dataName] = !clickedValue
this.actor.update(tempData);
this._render();
}
async _toggleEquippedItem(event) {
@@ -469,6 +585,13 @@ export class ActorSheetKH extends ActorSheet {
}
}
/** @override */
_updateObject(event, formData) {
const actorUpdate = ActorHelpers.actorUpdate.bind(this);
actorUpdate(event, formData);
}
/**
* Send details of an item to chat.
* @private

View File

@@ -0,0 +1,54 @@
export default class ActorHelpers {
static async actorUpdate(event, formData) {
formData = expandObject(formData);
// Handle the free-form relationship list
const formAttrs = expandObject(formData)?.data?.relationships || {};
const relationships = 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?.relationships) {
for (let k of Object.keys(this.object.data.data.relationships)) {
if (!relationships.hasOwnProperty(k)) relationships[`-=${k}`] = null;
}
}
// recombine modifications to formData
if (Object.keys(relationships).length > 0) {
setProperty(formData, `data.relationships`, relationships);
}
// Handle the free-form learnign list
const formAttrsLearning = expandObject(formData)?.data?.learning || {};
const learning = Object.values(formAttrsLearning).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?.learning) {
for (let k of Object.keys(this.object.data.data.learning)) {
if (!learning.hasOwnProperty(k)) learning[`-=${k}`] = null;
}
}
// recombine modifications to formData
if (Object.keys(learning).length > 0) {
setProperty(formData, `data.learning`, learning);
}
// Update the Item
this.actor.data.flags.loaded = false;
this.object.update(formData);
}
}

View File

@@ -8,7 +8,7 @@ export class ItemSheetKH extends ItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["starwarsffg", "sheet", "item"],
classes: ["kopparhavet", "sheet", "item"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
scrollY: [".sheet-body", ".tab"],
});
@@ -139,6 +139,7 @@ export class ItemSheetKH extends ItemSheet {
/** @override */
_updateObject(event, formData) {
const itemUpdate = ItemHelpers.itemUpdate.bind(this);
itemUpdate(event, formData);
}

View File

@@ -23,4 +23,82 @@ KH.armor_types = {
"label": "ARMOR.HEAVY",
"ac": 30,
},
};
};
KH.baseSkills = [
"Smidighet",
"Trolldom",
"Fingerfärdighet",
"Finna dolda ting",
"Förleda",
"Gömma sig",
"Handel",
"Hantverk",
"Insikt",
"Jakt",
"Kastvapen",
"Knivar",
"Lagkunskap",
"Legender",
"Läkekonst",
"Lärdom",
"Musik",
"Rida",
"Sjömanskap",
"Skytte",
"Sköldar",
"Slagsmål",
"Spana",
"Spel",
"Spjut",
"Språk",
"Status",
"Stigvana",
"Styrka",
"Svärd",
"Taktik",
"Uthållighet",
"Utstrålning",
"Viljestyrka",
"Väderkunskap",
"Yxor"
]
KH.baseSkillsHT = [
"Fingerfärdighet",
"Gömma sig",
"Handel",
"Härkonst",
"Jakt",
"Lagkunskap",
"Ledarskap",
"Leta",
"Läkekonst",
"Lärdom",
"Manövrer",
"Rida",
"Sjömannaskap",
"Skaldekonst",
"Skapa",
"Spana",
"Spel",
"Spelmannaskap",
"Språk",
"Status",
"Stigvana",
"Styrkeprov",
"Trolldom",
"Uthållighet",
"Viljestyrka",
"Väderkunskap",
"Vältalighet",
"Wyrd",
"Kastvapen",
"Knivkamp",
"Skytte",
"Sköldkamp",
"Slagsmål",
"Spjutkamp",
"Svärdskamp",
"Yxkamp"
]

View File

@@ -1,15 +1,22 @@
export default class KHHooks {
static async onCreateActor(actor, options, userId) {
if (actor.data.type == "character") {
const actorbaseSkills = actor.data.data.baseSkills;
// Load Skills Compendium skills
let skillIndex;
let actorbaseSkills;
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
actorbaseSkills = CONFIG.KH.baseSkillsHT
skillIndex = await game.packs.get("kopparhavet.skills-ht").getContent();
} else {
actorbaseSkills = CONFIG.KH.baseSkills;
skillIndex = await game.packs.get("kopparhavet.skills").getContent();
}
// 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));

View File

@@ -14,10 +14,6 @@ Hooks.once("init", () => {
// 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.",
@@ -26,10 +22,36 @@ Hooks.once("init", () => {
default: 0,
type: Number,
});
game.settings.register("kopparhavet", "gameSystem", {
name: "Game System",
hint: "Select what game system is being used..",
scope: "world",
config: true,
default: "kopparhavet",
choices: {
"kopparhavet": "Kopparhavets Hjältar",
"hjaltarnas-tid": "Hjältarnas Tid"
},
type: String,
onChange: (rule) => {
window.location.reload();
},
});
//registerFonts();
registerSheets();
if(game.settings.get("kopparhavet", "gameSystem") === "hjaltarnas-tid") {
preloadHandlebarsTemplatesHT();
} else {
preloadHandlebarsTemplates();
}
registerHandlebarsHelpers();
});
Hooks.once("ready", () => {
//migrateWorld();
migrateWorld();
});
/* POPULATE CHARACTER WITH DEFAULT SKILLS */
@@ -66,6 +88,7 @@ function preloadHandlebarsTemplates() {
"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/main.html",
"systems/kopparhavet/templates/parts/actor/bio.html",
"systems/kopparhavet/templates/parts/actor/combat.html",
"systems/kopparhavet/templates/parts/actor/gear.html",
@@ -76,6 +99,29 @@ function preloadHandlebarsTemplates() {
return loadTemplates(templatePaths);
}
function preloadHandlebarsTemplatesHT() {
const templatePaths = [
"systems/kopparhavet/templates/chat/item-card.html",
"systems/kopparhavet/templates/actors/ht-adversary-sheet.html",
"systems/kopparhavet/templates/actors/ht-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/ht-main.html",
"systems/kopparhavet/templates/parts/actor/ht-combat.html",
"systems/kopparhavet/templates/parts/actor/gear.html",
"systems/kopparhavet/templates/parts/actor/ht-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();
@@ -128,4 +174,15 @@ function registerHandlebarsHelpers() {
// strip tags, add <br/> tags
return new Handlebars.SafeString(value.replace(/(<([^>]+)>)/gi, "").replace(/(?:\r\n|\r|\n)/g, '<br/>'));
});
}
function migrateWorld() {
game.actors.forEach((actor) => {
// Migrate to v0.0.2 from v0.0.1
if(actor.data.type === "character") {
if(!actor.data?.data?.bio?.appearance) {
actor.update({"data.bio.appearance.label": "BIO.APPEARANCE", "data.bio.appearance.value": ""});
}
}
});
}