Merge branch 'development'
commit
7801ae290c
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
|
|
@ -2,6 +2,14 @@
|
|||
"OSE.Edit": "Edit",
|
||||
"OSE.Delete": "Delete",
|
||||
"OSE.Add": "Add",
|
||||
"OSE.Ok": "Ok",
|
||||
"OSE.Cancel": "Cancel",
|
||||
"OSE.Roll": "Roll",
|
||||
|
||||
"OSE.Formula": "Formula",
|
||||
"OSE.SitMod": "Situational Modifier",
|
||||
"OSE.RollMode": "Roll Mode",
|
||||
"OSE.RollExample": "Roll Example",
|
||||
|
||||
"OSE.Name": "Name",
|
||||
"OSE.Class": "Class",
|
||||
|
|
@ -9,11 +17,18 @@
|
|||
"OSE.Alignment": "Alignment",
|
||||
"OSE.Level": "Level",
|
||||
"OSE.Experience": "Experience",
|
||||
"OSE.ExperienceBonus": "Bonus Experience",
|
||||
"OSE.Treasure": "Treasure type",
|
||||
"OSE.Size": "Size",
|
||||
"OSE.Morale": "Morale",
|
||||
"OSE.Retainer": "Retainer",
|
||||
"OSE.Appearing": "NA",
|
||||
"OSE.Attack": "Attack",
|
||||
|
||||
"OSE.Loyalty": "Loyalty Rating",
|
||||
"OSE.LoyaltyShort": "LR",
|
||||
|
||||
"OSE.AbilityCheck": "Ability Check",
|
||||
"OSE.scores.str.long": "Strength",
|
||||
"OSE.scores.str.short": "STR",
|
||||
"OSE.scores.wis.long": "Wisdom",
|
||||
|
|
@ -27,39 +42,95 @@
|
|||
"OSE.scores.cha.long": "Charisma",
|
||||
"OSE.scores.cha.short": "CHA",
|
||||
|
||||
"OSE.SavingThrow": "Save",
|
||||
"OSE.saves.death.short": "D",
|
||||
"OSE.saves.death.long": "Death",
|
||||
"OSE.saves.wands.short": "W",
|
||||
"OSE.saves.wands.long": "Wands",
|
||||
"OSE.saves.death.long": "Death, Poison",
|
||||
"OSE.saves.wand.short": "W",
|
||||
"OSE.saves.wand.long": "Wand",
|
||||
"OSE.saves.paralysis.short": "P",
|
||||
"OSE.saves.paralysis.long": "Paralysis",
|
||||
"OSE.saves.paralysis.long": "Paralysis, Petrify",
|
||||
"OSE.saves.breath.short": "B",
|
||||
"OSE.saves.breath.long": "Breath",
|
||||
"OSE.saves.spells.short": "S",
|
||||
"OSE.saves.spells.long": "Spells",
|
||||
"OSE.saves.breath.long": "Dragon Breath",
|
||||
"OSE.saves.spell.short": "S",
|
||||
"OSE.saves.spell.long": "Rod, Staff, Spell",
|
||||
|
||||
"OSE.Health": "Hit Points",
|
||||
"OSE.HealthMax": "Maximum Hit Points",
|
||||
"OSE.HealthShort": "HP",
|
||||
"OSE.HitDice": "Hit Dice",
|
||||
"OSE.HitDiceShort": "HD",
|
||||
"OSE.Movement": "Movement",
|
||||
"OSE.MovementShort": "MOV",
|
||||
"OSE.SpecialMovement": "Special Movement",
|
||||
"OSE.Movement": "Movement Rate",
|
||||
"OSE.MovementEncounter": "Encounter Movement Rate",
|
||||
"OSE.MovementEncounterShort": "ENC",
|
||||
"OSE.MovementOverland": "Overland Movement Rate",
|
||||
"OSE.MovementOverlandShort": "OVE",
|
||||
"OSE.MovementShort": "MV",
|
||||
"OSE.ArmorClass": "Armor Class",
|
||||
"OSE.ArmorClassShort": "AC",
|
||||
"OSE.SpellDC": "DC",
|
||||
"OSE.AscArmorClassShort": "AAC",
|
||||
"OSE.SpellDC": "Spell DC",
|
||||
"OSE.SpellDCShort": "DC",
|
||||
"OSE.Thac0": "THAC0",
|
||||
"OSE.ABShort": "AB",
|
||||
"OSE.AB": "Attack Bonus",
|
||||
"OSE.MeleeShort": "MEL",
|
||||
"OSE.Melee": "Melee",
|
||||
"OSE.MeleeBonus": "Melee Bonus",
|
||||
"OSE.MissileShort": "MIS",
|
||||
"OSE.Missile": "Missile",
|
||||
"OSE.MissileBonus": "Missile Bonus",
|
||||
"OSE.Initiative": "Initiative",
|
||||
"OSE.InitiativeShort": "INIT",
|
||||
"OSE.Attacks": "Attacks Usable per Round",
|
||||
"OSE.AttacksShort": "ATT",
|
||||
"OSE.Spellcaster": "Spellcaster",
|
||||
|
||||
|
||||
"OSE.category.attributes": "Attributes",
|
||||
"OSE.category.inventory": "Inventory",
|
||||
"OSE.category.abilities": "Abilities",
|
||||
"OSE.category.spells": "Spells",
|
||||
"OSE.category.notes": "Notes",
|
||||
|
||||
"OSE.panel.abilities": "Abilities",
|
||||
"OSE.panel.equipment": "Equipment"
|
||||
"OSE.panel.equipment": "Equipment",
|
||||
|
||||
"OSE.Setting.IndividualInit": "Individual Initiative",
|
||||
"OSE.Setting.IndividualInitHint": "Initiative is rolled for each actor and modified by its DEX score",
|
||||
"OSE.Setting.AscendingAC": "Ascending Armor Class",
|
||||
"OSE.Setting.AscendingACHint": "The more the better",
|
||||
"OSE.Setting.Morale": "Enable Monster Morale checks",
|
||||
"OSE.Setting.MoraleHint": "Morale Rating is shown on monster sheets",
|
||||
"OSE.Setting.THAC0Attacks": "Attacks with THAC0",
|
||||
"OSE.Setting.THAC0AttacksHint": "Attacks are resolved using the THAC0 value, not compatible with AAC",
|
||||
"OSE.Setting.VariableWeaponDamage": "Variable Weapon Damage",
|
||||
"OSE.Setting.VariableWeaponDamageHint": "Weapons have different damage dice",
|
||||
|
||||
"OSE.items.Equip": "Equip",
|
||||
"OSE.items.Unequip": "Unequip",
|
||||
"OSE.items.Misc": "Misc",
|
||||
"OSE.items.Weapons": "Weapons",
|
||||
"OSE.items.Armors": "Armors",
|
||||
"OSE.items.Weight": "Wgt.",
|
||||
"OSE.items.Qualities": "Qualities",
|
||||
"OSE.items.Notes": "Notes",
|
||||
"OSE.items.Cost": "Cost",
|
||||
"OSE.items.Quantity": "Qt.",
|
||||
"OSE.items.Roll": "Roll",
|
||||
"OSE.items.Damage": "Damage",
|
||||
"OSE.items.Melee": "Melee",
|
||||
"OSE.items.Missile": "Missile",
|
||||
"OSE.items.Slow": "Slow",
|
||||
"OSE.items.ArmorAC": "AC",
|
||||
"OSE.items.ArmorAAC": "AAC",
|
||||
|
||||
"OSE.spells.Memorized": "Memorized",
|
||||
"OSE.spells.Cast": "Cast",
|
||||
"OSE.spells.Range": "Range",
|
||||
"OSE.spells.Slots": "Slots",
|
||||
"OSE.spells.Class": "Class",
|
||||
"OSE.spells.Duration": "Duration",
|
||||
"OSE.spells.Level": "Level",
|
||||
|
||||
"OSE.abilities.Requirements": "Requirements"
|
||||
}
|
||||
|
|
@ -44,7 +44,6 @@
|
|||
"OSE.HitDiceShort": "DV",
|
||||
"OSE.Movement": "Mouvement",
|
||||
"OSE.MovementShort": "MOUV",
|
||||
"OSE.SpecialMovement": "Mouvement Spécial",
|
||||
"OSE.ArmorClass": "Classe d'Armure",
|
||||
"OSE.ArmorClassShort": "CA",
|
||||
"OSE.SpellDC": "DF",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
import { OseActor } from "./entity.js";
|
||||
import { OseEntityTweaks } from "../dialog/entity-tweaks.js";
|
||||
|
||||
export class OseActorSheet extends ActorSheet {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
|
||||
data.config = CONFIG.OSE;
|
||||
// Settings
|
||||
data.config.ascendingAC = game.settings.get("ose", "ascendingAC");
|
||||
|
||||
// Prepare owned items
|
||||
this._prepareItems(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize and classify Owned Items for Character sheets
|
||||
* @private
|
||||
*/
|
||||
_prepareItems(data) {
|
||||
// Partition items by category
|
||||
let [items, weapons, armors, abilities, spells] = data.items.reduce(
|
||||
(arr, item) => {
|
||||
// Classify items into types
|
||||
if (item.type === "item") arr[0].push(item);
|
||||
else if (item.type === "weapon") arr[1].push(item);
|
||||
else if (item.type === "armor") arr[2].push(item);
|
||||
else if (item.type === "ability") arr[3].push(item);
|
||||
else if (item.type === "spell") arr[4].push(item);
|
||||
return arr;
|
||||
},
|
||||
[[], [], [], [], []]
|
||||
);
|
||||
|
||||
// Sort spells by level
|
||||
var sortedSpells = {};
|
||||
for (var i = 0; i < spells.length; i++) {
|
||||
let lvl = spells[i].data.lvl;
|
||||
if (!sortedSpells[lvl]) sortedSpells[lvl] = [];
|
||||
sortedSpells[lvl].push(spells[i]);
|
||||
}
|
||||
// Assign and return
|
||||
data.owned = {
|
||||
items: items,
|
||||
weapons: weapons,
|
||||
armors: armors,
|
||||
};
|
||||
data.abilities = abilities;
|
||||
data.spells = sortedSpells;
|
||||
}
|
||||
|
||||
_onItemSummary(event) {
|
||||
event.preventDefault();
|
||||
let li = $(event.currentTarget).parents(".item"),
|
||||
item = this.actor.getOwnedItem(li.data("item-id")),
|
||||
description = TextEditor.enrichHTML(item.data.data.description);
|
||||
// Toggle summary
|
||||
if (li.hasClass("expanded")) {
|
||||
let summary = li.parents(".item-entry").children(".item-summary");
|
||||
summary.slideUp(200, () => summary.remove());
|
||||
} else {
|
||||
let div = $(`<div class="item-summary">${description}</div>`);
|
||||
li.parents(".item-entry").append(div.hide());
|
||||
div.slideDown(200);
|
||||
}
|
||||
li.toggleClass("expanded");
|
||||
}
|
||||
|
||||
|
||||
activateListeners(html) {
|
||||
// Item summaries
|
||||
html
|
||||
.find(".item .item-name h4")
|
||||
.click((event) => this._onItemSummary(event));
|
||||
|
||||
html.find(".saving-throw .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let save = element.parentElement.parentElement.dataset.save;
|
||||
actorObject.rollSave(save, { event: event });
|
||||
});
|
||||
|
||||
//Toggle Spells
|
||||
html.find(".item-cast").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
await this.actor.updateOwnedItem({
|
||||
_id: li.data("itemId"),
|
||||
data: {
|
||||
cast: !item.data.data.cast,
|
||||
},
|
||||
});
|
||||
});
|
||||
//Toggle Equipment
|
||||
html.find(".item-memorize").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
await this.actor.updateOwnedItem({
|
||||
_id: li.data("itemId"),
|
||||
data: {
|
||||
memorized: !item.data.data.memorized,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
html.find(".item-image").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
item.roll();
|
||||
});
|
||||
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
||||
// Override to set resizable initial size
|
||||
async _renderInner(...args) {
|
||||
const html = await super._renderInner(...args);
|
||||
this.form = html[0];
|
||||
|
||||
// Resize resizable classes
|
||||
let resizable = html.find(".resizable");
|
||||
if (resizable.length == 0) {
|
||||
return;
|
||||
}
|
||||
resizable.each((_, el) => {
|
||||
let heightDelta = this.position.height - this.options.height;
|
||||
el.style.height = `${heightDelta + parseInt(el.dataset.baseSize)}px`;
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
async _onResize(event) {
|
||||
super._onResize(event);
|
||||
let html = $(event.path);
|
||||
let resizable = html.find(".resizable");
|
||||
resizable.each((_, el) => {
|
||||
let heightDelta = this.position.height - this.options.height;
|
||||
el.style.height = `${heightDelta + parseInt(el.dataset.baseSize)}px`;
|
||||
});
|
||||
}
|
||||
|
||||
_onConfigureActor(event) {
|
||||
event.preventDefault();
|
||||
new OseEntityTweaks(this.actor, {
|
||||
top: this.position.top + 40,
|
||||
left: this.position.left + (this.position.width - 400) / 2,
|
||||
}).render(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend and override the sheet header buttons
|
||||
* @override
|
||||
*/
|
||||
_getHeaderButtons() {
|
||||
let buttons = super._getHeaderButtons();
|
||||
|
||||
// Token Configuration
|
||||
const canConfigure = game.user.isGM || this.actor.owner;
|
||||
if (this.options.editable && canConfigure) {
|
||||
buttons = [
|
||||
{
|
||||
label: "Tweaks",
|
||||
class: "configure-actor",
|
||||
icon: "fas fa-dice",
|
||||
onclick: (ev) => this._onConfigureActor(ev),
|
||||
},
|
||||
].concat(buttons);
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import { OseActor } from "./entity.js";
|
||||
import { OseActorSheet } from "./actor-sheet.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
*/
|
||||
export class OseActorSheetCharacter extends ActorSheet {
|
||||
export class OseActorSheetCharacter extends OseActorSheet {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
|
@ -19,7 +20,7 @@ export class OseActorSheetCharacter extends ActorSheet {
|
|||
classes: ["ose", "sheet", "actor", "character"],
|
||||
template: "systems/ose/templates/actors/character-sheet.html",
|
||||
width: 450,
|
||||
height: 560,
|
||||
height: 530,
|
||||
resizable: true,
|
||||
tabs: [
|
||||
{
|
||||
|
|
@ -31,22 +32,6 @@ export class OseActorSheetCharacter extends ActorSheet {
|
|||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// Override to set resizable initial size
|
||||
async _renderInner(...args) {
|
||||
const html = await super._renderInner(...args);
|
||||
this.form = html[0];
|
||||
|
||||
// Resize resizable classes
|
||||
let resizable = html.find('.resizable');
|
||||
resizable.each((_, el) => {
|
||||
let heightDelta = this.position.height - (this.options.height);
|
||||
el.style.height = `${heightDelta + parseInt(el.dataset.baseSize)}px`;
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare data for rendering the Actor sheet
|
||||
* The prepared data object contains both the actor data as well as additional sheet options
|
||||
|
|
@ -54,58 +39,29 @@ export class OseActorSheetCharacter extends ActorSheet {
|
|||
getData() {
|
||||
const data = super.getData();
|
||||
|
||||
data.config = CONFIG.OSE;
|
||||
|
||||
for (let [a, score] of Object.entries(data.data.scores)) {
|
||||
data.data.scores[a].label = game.i18n.localize(`OSE.scores.${a}`);
|
||||
}
|
||||
// Prepare owned items
|
||||
this._prepareItems(data);
|
||||
|
||||
// DEBUG
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize and classify Owned Items for Character sheets
|
||||
* @private
|
||||
*/
|
||||
_prepareItems(data) {
|
||||
// Partition items by category
|
||||
let [inventory, abilities, spells] = data.items.reduce(
|
||||
(arr, item) => {
|
||||
// Classify items into types
|
||||
if (item.type === "item") arr[0].push(item);
|
||||
if (item.type === "ability") arr[1].push(item);
|
||||
else if (item.type === "spell") arr[2].push(item);
|
||||
return arr;
|
||||
},
|
||||
[[], [], [], []]
|
||||
// Settings
|
||||
data.config.variableWeaponDamage = game.settings.get(
|
||||
"ose",
|
||||
"variableWeaponDamage"
|
||||
);
|
||||
data.config.ascendingAC = game.settings.get("ose", "ascendingAC");
|
||||
data.config.individualInit = game.settings.get("ose", "individualInit");
|
||||
|
||||
// Assign and return
|
||||
data.inventory = inventory;
|
||||
data.spells = spells;
|
||||
data.abilities = abilities;
|
||||
data.mods = this.actor.computeModifiers();
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
_onItemSummary(event) {
|
||||
async _onQtChange(event) {
|
||||
event.preventDefault();
|
||||
let li = $(event.currentTarget).parents(".item"),
|
||||
item = this.actor.getOwnedItem(li.data("item-id")),
|
||||
description = TextEditor.enrichHTML(item.data.data.description);
|
||||
// Toggle summary
|
||||
if ( li.hasClass("expanded") ) {
|
||||
let summary = li.parents('.item-entry').children(".item-summary");
|
||||
summary.slideUp(200, () => summary.remove());
|
||||
} else {
|
||||
let div = $(`<div class="item-summary">${description}</div>`);
|
||||
li.parents('.item-entry').append(div.hide());
|
||||
div.slideDown(200);
|
||||
}
|
||||
li.toggleClass("expanded");
|
||||
const itemId = event.currentTarget.closest(".item").dataset.itemId;
|
||||
const item = this.actor.getOwnedItem(itemId);
|
||||
return item.update({ "data.quantity.value": parseInt(event.target.value) });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,20 +99,38 @@ export class OseActorSheetCharacter extends ActorSheet {
|
|||
return this.actor.createOwnedItem(itemData);
|
||||
});
|
||||
|
||||
// Item summaries
|
||||
html.find('.item .item-name h4').click(event => this._onItemSummary(event));
|
||||
//Toggle Equipment
|
||||
html.find(".item-toggle").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
await this.actor.updateOwnedItem({
|
||||
_id: li.data("itemId"),
|
||||
data: {
|
||||
equipped: !item.data.data.equipped,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
html
|
||||
.find(".quantity input")
|
||||
.click((ev) => ev.target.select())
|
||||
.change(this._onQtChange.bind(this));
|
||||
|
||||
html.find(".ability-score .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let score = element.parentElement.parentElement.dataset.score;
|
||||
actorObject.rollCheck(score, { event: event });
|
||||
});
|
||||
|
||||
html.find(".attack a").click(ev => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let attack = element.parentElement.parentElement.dataset.attack;
|
||||
actorObject.rollAttack(attack, { event: event });
|
||||
})
|
||||
|
||||
// Handle default listeners last so system listeners are triggered first
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
||||
async _onResize(event) {
|
||||
super._onResize(event);
|
||||
let html = $(event.path);
|
||||
let resizable = html.find('.resizable');
|
||||
resizable.each((_, el) => {
|
||||
let heightDelta = this.position.height - (this.options.height);
|
||||
el.style.height = `${heightDelta + parseInt(el.dataset.baseSize)}px`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,141 @@
|
|||
import { OseDice } from '../dice.js';
|
||||
|
||||
export class OseActor extends Actor {
|
||||
/**
|
||||
* Extends data from base Actor class
|
||||
*/
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Socket Listeners and Handlers
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async createOwnedItem(itemData, options) {
|
||||
return super.createOwnedItem(itemData, options);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
/* Rolls */
|
||||
/* -------------------------------------------- */
|
||||
rollSave(save, options = {}) {
|
||||
const label = game.i18n.localize(`OSE.saves.${save}.long`);
|
||||
const rollParts = ['1d20'];
|
||||
|
||||
const data = {...this.data, ...{
|
||||
rollData : {
|
||||
type: 'Save',
|
||||
stat: save
|
||||
}
|
||||
}};
|
||||
|
||||
// Roll and return
|
||||
return OseDice.Roll({
|
||||
event: options.event,
|
||||
parts: rollParts,
|
||||
data: data,
|
||||
speaker: ChatMessage.getSpeaker({ actor: this }),
|
||||
flavor: `${label} ${game.i18n.localize('OSE.SavingThrow')}`,
|
||||
title: `${label} ${game.i18n.localize('OSE.SavingThrow')}`,
|
||||
});
|
||||
}
|
||||
|
||||
rollCheck(score, options = {}) {
|
||||
const label = game.i18n.localize(`OSE.scores.${score}.long`);
|
||||
const rollParts = ['1d20'];
|
||||
|
||||
const data = {...this.data, ...{
|
||||
rollData : {
|
||||
type: 'Check',
|
||||
stat: score
|
||||
}
|
||||
}};
|
||||
|
||||
// Roll and return
|
||||
return OseDice.Roll({
|
||||
event: options.event,
|
||||
parts: rollParts,
|
||||
data: data,
|
||||
speaker: ChatMessage.getSpeaker({ actor: this }),
|
||||
flavor: `${label} ${game.i18n.localize('OSE.AbilityCheck')}`,
|
||||
title: `${label} ${game.i18n.localize('OSE.AbilityCheck')}`,
|
||||
});
|
||||
}
|
||||
|
||||
rollAttack(attack, options={}) {
|
||||
const label = game.i18n.localize(`OSE.${attack}`);
|
||||
const rollParts = ['1d20',];
|
||||
|
||||
const mods = this.computeModifiers();
|
||||
if (attack == 'Missile') {
|
||||
rollParts.push(
|
||||
'+',
|
||||
mods.dex.toString(),
|
||||
'+',
|
||||
this.data.data.thac0.mod.missile.toString()
|
||||
);
|
||||
} else if (attack == 'Melee') {
|
||||
rollParts.push(
|
||||
'+',
|
||||
mods.str.toString(),
|
||||
'+',
|
||||
this.data.data.thac0.mod.melee.toString()
|
||||
);
|
||||
}
|
||||
if (game.settings.get('ose', 'ascendingAC')) {
|
||||
rollParts.push('+', this.data.data.thac0.bba.toString());
|
||||
}
|
||||
|
||||
const data = {...this.data, ...{
|
||||
rollData : {
|
||||
type: 'Attack',
|
||||
stat: attack,
|
||||
mods: mods
|
||||
}
|
||||
}};
|
||||
|
||||
// Roll and return
|
||||
return OseDice.Roll({
|
||||
event: options.event,
|
||||
parts: rollParts,
|
||||
data: data,
|
||||
speaker: ChatMessage.getSpeaker({ actor: this }),
|
||||
flavor: `${label} ${game.i18n.localize('OSE.Attack')}`,
|
||||
title: `${label} ${game.i18n.localize('OSE.Attack')}`,
|
||||
});
|
||||
}
|
||||
|
||||
computeModifiers() {
|
||||
let _valueToMod = (val) => {
|
||||
switch (val) {
|
||||
case 3:
|
||||
return -3;
|
||||
case 4:
|
||||
case 5:
|
||||
return -2;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return -1;
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
return 0;
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
return 1;
|
||||
case 16:
|
||||
case 17:
|
||||
return 2;
|
||||
case 18:
|
||||
return 3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
return {
|
||||
str: _valueToMod(this.data.data.scores.str.value),
|
||||
int: _valueToMod(this.data.data.scores.int.value),
|
||||
dex: _valueToMod(this.data.data.scores.dex.value),
|
||||
cha: _valueToMod(this.data.data.scores.cha.value),
|
||||
wis: _valueToMod(this.data.data.scores.wis.value),
|
||||
con: _valueToMod(this.data.data.scores.con.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { OseActor } from "./entity.js";
|
||||
import { OseActorSheet } from "./actor-sheet.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
*/
|
||||
export class OseActorSheetMonster extends ActorSheet {
|
||||
export class OseActorSheetMonster extends OseActorSheet {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
|
@ -31,25 +32,6 @@ export class OseActorSheetMonster extends ActorSheet {
|
|||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// Override to set resizable initial size
|
||||
async _renderInner(...args) {
|
||||
const html = await super._renderInner(...args);
|
||||
this.form = html[0];
|
||||
|
||||
// Resize resizable classes
|
||||
let resizable = html.find('.resizable');
|
||||
if (resizable.length == 0) {
|
||||
return;
|
||||
}
|
||||
resizable.each((_, el) => {
|
||||
let heightDelta = this.position.height - (this.options.height);
|
||||
el.style.height = `${heightDelta + parseInt(el.dataset.baseSize)}px`;
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare data for rendering the Actor sheet
|
||||
* The prepared data object contains both the actor data as well as additional sheet options
|
||||
|
|
@ -57,58 +39,48 @@ export class OseActorSheetMonster extends ActorSheet {
|
|||
getData() {
|
||||
const data = super.getData();
|
||||
|
||||
data.config = CONFIG.OSE;
|
||||
// Settings
|
||||
data.config.morale = game.settings.get('ose', 'morale');
|
||||
|
||||
// Prepare owned items
|
||||
this._prepareItems(data);
|
||||
|
||||
// DEBUG
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize and classify Owned Items for Character sheets
|
||||
* @private
|
||||
*/
|
||||
_prepareItems(data) {
|
||||
// Partition items by category
|
||||
let [inventory, abilities, spells] = data.items.reduce(
|
||||
(arr, item) => {
|
||||
// Classify items into types
|
||||
if (item.type === "item") arr[0].push(item);
|
||||
if (item.type === "ability") arr[1].push(item);
|
||||
else if (item.type === "spell") arr[2].push(item);
|
||||
return arr;
|
||||
},
|
||||
[[], [], [], []]
|
||||
);
|
||||
|
||||
// Assign and return
|
||||
data.inventory = inventory;
|
||||
data.spells = spells;
|
||||
data.abilities = abilities;
|
||||
}
|
||||
|
||||
|
||||
_onItemSummary(event) {
|
||||
event.preventDefault();
|
||||
let li = $(event.currentTarget).parents(".item"),
|
||||
item = this.actor.getOwnedItem(li.data("item-id")),
|
||||
description = TextEditor.enrichHTML(item.data.data.description);
|
||||
// Toggle summary
|
||||
if ( li.hasClass("expanded") ) {
|
||||
let summary = li.parents('.item-entry').children(".item-summary");
|
||||
summary.slideUp(200, () => summary.remove());
|
||||
} else {
|
||||
let div = $(`<div class="item-summary">${description}</div>`);
|
||||
li.parents('.item-entry').append(div.hide());
|
||||
div.slideDown(200);
|
||||
}
|
||||
li.toggleClass("expanded");
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async _chooseItemType(
|
||||
choices = ['weapon', 'armor', 'shield', 'gear'],
|
||||
) {
|
||||
let templateData = { upper: '', lower: '', types: choices },
|
||||
dlg = await renderTemplate(
|
||||
'templates/sidebar/entity-create.html',
|
||||
templateData,
|
||||
);
|
||||
//Create Dialog window
|
||||
return new Promise((resolve) => {
|
||||
new Dialog({
|
||||
title: '',
|
||||
content: dlg,
|
||||
buttons: {
|
||||
ok: {
|
||||
label: game.i18n.localize('OSE.Ok'),
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
callback: (html) => {
|
||||
resolve({
|
||||
type: html.find('select[name="type"]').val(),
|
||||
name: html.find('input[name="name"]').val(),
|
||||
});
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize('OSE.Cancel'),
|
||||
},
|
||||
},
|
||||
default: 'ok',
|
||||
}).render(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate event listeners using the prepared sheet HTML
|
||||
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||
|
|
@ -135,30 +107,35 @@ export class OseActorSheetMonster extends ActorSheet {
|
|||
event.preventDefault();
|
||||
const header = event.currentTarget;
|
||||
const type = header.dataset.type;
|
||||
|
||||
// item creation helper func
|
||||
let createItem = function (
|
||||
type,
|
||||
name = `New ${type.capitalize()}`,
|
||||
) {
|
||||
const itemData = {
|
||||
name: `New ${type.capitalize()}`,
|
||||
name: name ? name : `New ${type.capitalize()}`,
|
||||
type: type,
|
||||
data: duplicate(header.dataset),
|
||||
};
|
||||
delete itemData.data["type"];
|
||||
return this.actor.createOwnedItem(itemData);
|
||||
});
|
||||
delete itemData.data['type'];
|
||||
return itemData;
|
||||
};
|
||||
|
||||
html.find(".item-name").click((event) => {
|
||||
this._onItemSummary(event);
|
||||
// Getting back to main logic
|
||||
if (type == 'choice') {
|
||||
const choices = header.dataset.choices.split(',');
|
||||
this._chooseItemType(choices).then((dialogInput) => {
|
||||
const itemData = createItem(dialogInput.type, dialogInput.name);
|
||||
this.actor.createOwnedItem(itemData, {});
|
||||
});
|
||||
return;
|
||||
}
|
||||
const itemData = createItem(type);
|
||||
return this.actor.createOwnedItem(itemData, {});
|
||||
});
|
||||
|
||||
// Handle default listeners last so system listeners are triggered first
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
||||
async _onResize(event) {
|
||||
super._onResize(event);
|
||||
let html = $(event.path);
|
||||
let resizable = html.find('.resizable');
|
||||
resizable.each((_, el) => {
|
||||
let heightDelta = this.position.height - (this.options.height);
|
||||
el.style.height = `${heightDelta + parseInt(el.dataset.baseSize)}px`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
import { OseActor } from '../actor/entity.js';
|
||||
|
||||
export class OseEntityTweaks extends FormApplication {
|
||||
static get defaultOptions() {
|
||||
const options = super.defaultOptions;
|
||||
options.id = 'sheet-tweaks';
|
||||
options.template =
|
||||
'systems/ose/templates/actors/dialogs/tweaks-dialog.html';
|
||||
options.width = 380;
|
||||
return options;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Add the Entity name into the window title
|
||||
* @type {String}
|
||||
*/
|
||||
get title() {
|
||||
return `${this.object.name}: OSE Tweaks`;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Construct and return the data object used to render the HTML template for this form application.
|
||||
* @return {Object}
|
||||
*/
|
||||
getData() {
|
||||
let data = this.object.data;
|
||||
if (this.object.data.type === 'character') {
|
||||
data.isCharacter = true;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called upon form submission after form data is validated
|
||||
* @param event {Event} The initial triggering submission event
|
||||
* @param formData {Object} The object of validated form data with which to update the object
|
||||
* @private
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
event.preventDefault();
|
||||
// Update the actor
|
||||
this.object.update(formData);
|
||||
// Re-draw the updated sheet
|
||||
this.object.sheet.render(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
export class OseDice {
|
||||
static digestResult(data, roll) {
|
||||
let details = "";
|
||||
|
||||
// ATTACKS
|
||||
let die = roll.parts[0].total;
|
||||
if (data.rollData.type == "Attack") {
|
||||
if (game.settings.get("ose", "ascendingAC")) {
|
||||
let bba = data.data.thac0.bba;
|
||||
bba +=
|
||||
data.rollData.stat == "Melee"
|
||||
? data.data.thac0.mod.melee + data.rollData.mods.str
|
||||
: data.data.thac0.mod.missile + data.rollData.mods.dex;
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${bba})</div>`;
|
||||
if (die == 1) {
|
||||
return details;
|
||||
}
|
||||
details = `<div class='roll-result'><b>Hits AC ${roll.total}</b> (${bba})</div>`;
|
||||
} else {
|
||||
// B/X Historic THAC0 Calculation
|
||||
let thac = data.data.thac0.value;
|
||||
thac -=
|
||||
data.rollData.stat == "Melee"
|
||||
? data.data.thac0.mod.melee + data.rollData.mods.str
|
||||
: data.data.thac0.mod.missile + data.rollData.mods.dex;
|
||||
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${thac})</div>`;
|
||||
if (thac - roll.total > 9) {
|
||||
return details;
|
||||
}
|
||||
details = `<div class='roll-result'><b>Hits AC ${Math.clamped(thac - roll.total,-3,9)}</b> (${thac})</div>`;
|
||||
}
|
||||
} else if (data.rollData.type == "Save") {
|
||||
// SAVING THROWS
|
||||
let sv = data.data.saves[data.rollData.stat].value;
|
||||
if (roll.total >= sv) {
|
||||
details = `<div class='roll-result roll-success'><b>Success!</b> (${sv})</div>`;
|
||||
} else {
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${sv})</div>`;
|
||||
}
|
||||
} else if (data.rollData.type == "Check") {
|
||||
// SCORE CHECKS
|
||||
let sc = data.data.scores[data.rollData.stat].value;
|
||||
if (die == 1 || (roll.total <= sc && die < 20)) {
|
||||
details = `<div class='roll-result roll-success'><b>Success!</b> (${sc})</div>`;
|
||||
} else {
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${sc})</div>`;
|
||||
}
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
static async sendRoll(
|
||||
parts = [],
|
||||
data = {},
|
||||
title = null,
|
||||
flavor = null,
|
||||
speaker = null,
|
||||
form = null
|
||||
) {
|
||||
const template = "systems/ose/templates/chat/roll-attack.html";
|
||||
|
||||
let chatData = {
|
||||
user: game.user._id,
|
||||
speaker: speaker,
|
||||
};
|
||||
|
||||
let templateData = {
|
||||
title: title,
|
||||
flavor: flavor,
|
||||
data: data,
|
||||
};
|
||||
|
||||
// Optionally include a situational bonus
|
||||
if (form !== null) data["bonus"] = form.bonus.value;
|
||||
if (data["bonus"]) parts.push(data["bonus"]);
|
||||
|
||||
const roll = new Roll(parts.join(""), data).roll();
|
||||
|
||||
// Convert the roll to a chat message and return the roll
|
||||
let rollMode = game.settings.get("core", "rollMode");
|
||||
rollMode = form ? form.rollMode.value : rollMode;
|
||||
|
||||
templateData.details = OseDice.digestResult(data, roll);
|
||||
roll.render().then((r) => {
|
||||
templateData.rollOSE = r;
|
||||
renderTemplate(template, templateData).then((content) => {
|
||||
chatData.content = content;
|
||||
chatData.sound = CONFIG.sounds.dice;
|
||||
if (game.dice3d) {
|
||||
game.dice3d
|
||||
.showForRoll(
|
||||
roll,
|
||||
game.user,
|
||||
true,
|
||||
chatData.whisper,
|
||||
chatData.blind
|
||||
)
|
||||
.then((displayed) => ChatMessage.create(chatData));
|
||||
} else {
|
||||
ChatMessage.create(chatData);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return roll;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
static async Roll({
|
||||
parts = [],
|
||||
data = {},
|
||||
options = {},
|
||||
event = null,
|
||||
speaker = null,
|
||||
flavor = null,
|
||||
title = null,
|
||||
item = false,
|
||||
} = {}) {
|
||||
let rollMode = game.settings.get("core", "rollMode");
|
||||
let rolled = false;
|
||||
|
||||
const template = "systems/ose/templates/chat/roll-dialog.html";
|
||||
let dialogData = {
|
||||
formula: parts.join(" "),
|
||||
data: data,
|
||||
rollMode: rollMode,
|
||||
rollModes: CONFIG.Dice.rollModes,
|
||||
};
|
||||
|
||||
let buttons = {
|
||||
ok: {
|
||||
label: game.i18n.localize("OSE.Roll"),
|
||||
icon: '<i class="fas fa-dice-d20"></i>',
|
||||
callback: (html) => {
|
||||
roll = OseDice.sendRoll(
|
||||
parts,
|
||||
data,
|
||||
title,
|
||||
flavor,
|
||||
speaker,
|
||||
html[0].children[0]
|
||||
);
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("OSE.Cancel"),
|
||||
},
|
||||
};
|
||||
|
||||
if (!item) delete buttons.raise;
|
||||
|
||||
const html = await renderTemplate(template, dialogData);
|
||||
let roll;
|
||||
|
||||
//Create Dialog window
|
||||
return new Promise((resolve) => {
|
||||
new Dialog({
|
||||
title: title,
|
||||
content: html,
|
||||
buttons: buttons,
|
||||
default: "ok",
|
||||
close: () => {
|
||||
resolve(rolled ? roll : false);
|
||||
},
|
||||
}).render(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
export const registerHelpers = async function () {
|
||||
// Handlebars template helpers
|
||||
Handlebars.registerHelper("eq", function (a, b) {
|
||||
return a == b;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("add", function (lh, rh) {
|
||||
return parseInt(lh) + parseInt(rh);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("subtract", function (lh, rh) {
|
||||
return parseInt(rh) - parseInt(lh);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("divide", function (lh, rh) {
|
||||
return Math.floor(parseFloat(lh) / parseFloat(rh));
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("mult", function (lh, rh) {
|
||||
return parseInt(lh) * parseInt(rh);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("counter", function (status, value, max) {
|
||||
return status ? Math.clamped((100.0 * value) / max, 0, 100) : Math.clamped(100 - (100.0 * value) / max, 0, 100);
|
||||
});
|
||||
};
|
||||
|
|
@ -12,4 +12,93 @@ export class OseItem extends Item {
|
|||
prepareData() {
|
||||
super.prepareData();
|
||||
}
|
||||
|
||||
getChatData(htmlOptions) {
|
||||
const data = duplicate(this.data.data);
|
||||
|
||||
// Rich text description
|
||||
data.description = TextEditor.enrichHTML(data.description, htmlOptions);
|
||||
|
||||
// Item properties
|
||||
const props = [];
|
||||
const labels = this.labels;
|
||||
|
||||
if (this.data.type == "weapon") {
|
||||
props.push(data.qualities);
|
||||
}
|
||||
if (this.data.type == "spell") {
|
||||
props.push(
|
||||
`${data.class} ${data.lvl}`,
|
||||
data.range,
|
||||
data.duration
|
||||
);
|
||||
}
|
||||
if (data.hasOwnProperty("equipped")) {
|
||||
props.push(data.equipped ? "Equipped" : "Not Equipped");
|
||||
}
|
||||
|
||||
// Filter properties and return
|
||||
data.properties = props.filter((p) => !!p);
|
||||
return data;
|
||||
}
|
||||
|
||||
rollWeapon() {
|
||||
if (this.data.data.missile) {
|
||||
this.actor.rollAttack('Missile');
|
||||
return true;
|
||||
} else if (this.data.data.melee) {
|
||||
this.actor.rollAttack('Melee');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll the item to Chat, creating a chat card which contains follow up attack or damage roll options
|
||||
* @return {Promise}
|
||||
*/
|
||||
async roll({ configureDialog = true } = {}) {
|
||||
console.log(this.data)
|
||||
if (this.data.type == 'weapon') {
|
||||
if (this.rollWeapon()) return;
|
||||
}
|
||||
// Basic template rendering data
|
||||
const token = this.actor.token;
|
||||
const templateData = {
|
||||
actor: this.actor,
|
||||
tokenId: token ? `${token.scene._id}.${token.id}` : null,
|
||||
item: this.data,
|
||||
data: this.getChatData(),
|
||||
labels: this.labels,
|
||||
isHealing: this.isHealing,
|
||||
hasDamage: this.hasDamage,
|
||||
isSpell: this.data.type === "spell",
|
||||
hasSave: this.hasSave,
|
||||
};
|
||||
|
||||
// Render the chat card template
|
||||
const template = `systems/ose/templates/chat/item-card.html`;
|
||||
const html = await renderTemplate(template, templateData);
|
||||
|
||||
// Basic chat message data
|
||||
const chatData = {
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
// Toggle default roll mode
|
||||
let rollMode = game.settings.get("core", "rollMode");
|
||||
if (["gmroll", "blindroll"].includes(rollMode))
|
||||
chatData["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
||||
if (rollMode === "blindroll") chatData["blind"] = true;
|
||||
|
||||
// Create the chat message
|
||||
return ChatMessage.create(chatData);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export const preloadHandlebarsTemplates = async function () {
|
|||
//Sheet tabs
|
||||
'systems/ose/templates/actors/partials/character-header.html',
|
||||
'systems/ose/templates/actors/partials/character-attributes-tab.html',
|
||||
'systems/ose/templates/actors/partials/character-abilities-tab.html',
|
||||
'systems/ose/templates/actors/partials/character-spells-tab.html',
|
||||
'systems/ose/templates/actors/partials/character-inventory-tab.html',
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
export const registerSettings = function () {
|
||||
game.settings.register('ose', 'individualInit', {
|
||||
name: game.i18n.localize('OSE.Setting.IndividualInit'),
|
||||
hint: game.i18n.localize('OSE.Setting.IndividualInitHint'),
|
||||
default: false,
|
||||
scope: 'world',
|
||||
type: Boolean,
|
||||
config: true
|
||||
});
|
||||
|
||||
game.settings.register('ose', 'ascendingAC', {
|
||||
name: game.i18n.localize('OSE.Setting.AscendingAC'),
|
||||
hint: game.i18n.localize('OSE.Setting.AscendingACHint'),
|
||||
default: false,
|
||||
scope: 'world',
|
||||
type: Boolean,
|
||||
config: true
|
||||
});
|
||||
|
||||
game.settings.register('ose', 'morale', {
|
||||
name: game.i18n.localize('OSE.Setting.Morale'),
|
||||
hint: game.i18n.localize('OSE.Setting.MoraleHint'),
|
||||
default: false,
|
||||
scope: 'world',
|
||||
type: Boolean,
|
||||
config: true
|
||||
});
|
||||
|
||||
game.settings.register('ose', 'thac0Attacks', {
|
||||
name: game.i18n.localize('OSE.Setting.THAC0Attacks'),
|
||||
hint: game.i18n.localize('OSE.Setting.THAC0AttacksHint'),
|
||||
default: false,
|
||||
scope: 'world',
|
||||
type: Boolean,
|
||||
config: true
|
||||
});
|
||||
|
||||
game.settings.register('ose', 'variableWeaponDamage', {
|
||||
name: game.i18n.localize('OSE.Setting.VariableWeaponDamage'),
|
||||
hint: game.i18n.localize('OSE.Setting.VariableWeaponDamageHint'),
|
||||
default: false,
|
||||
scope: 'world',
|
||||
type: Boolean,
|
||||
config: true
|
||||
});
|
||||
}
|
||||
|
||||
22
src/ose.js
22
src/ose.js
|
|
@ -6,19 +6,8 @@ import { preloadHandlebarsTemplates } from "./module/preloadTemplates.js";
|
|||
import { OseActor } from "./module/actor/entity.js";
|
||||
import { OseItem } from "./module/item/entity.js";
|
||||
import { OSE } from "./module/config.js";
|
||||
|
||||
// Handlebars template helpers
|
||||
Handlebars.registerHelper("eq", function (a, b) {
|
||||
return a == b;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("add", function (lh, rh) {
|
||||
return parseInt(lh) + parseInt(rh);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("subtract", function (lh, rh) {
|
||||
return parseInt(rh) - parseInt(lh);
|
||||
});
|
||||
import { registerSettings } from './module/settings.js';
|
||||
import { registerHelpers } from './module/helpers.js';
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
|
|
@ -35,6 +24,13 @@ Hooks.once("init", async function () {
|
|||
};
|
||||
|
||||
CONFIG.OSE = OSE;
|
||||
|
||||
// Custom Handlebars helpers
|
||||
registerHelpers();
|
||||
|
||||
// Register custom system settings
|
||||
registerSettings();
|
||||
|
||||
CONFIG.Actor.entityClass = OseActor;
|
||||
CONFIG.Item.entityClass = OseItem;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
border: 1px solid $colorDark;
|
||||
.panel-title {
|
||||
color: whitesmoke;
|
||||
background: $colorDark;
|
||||
background: $darkBackground;
|
||||
line-height: 14px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
|
|
@ -74,44 +74,79 @@
|
|||
}
|
||||
}
|
||||
.sheet-tabs {
|
||||
color: whitesmoke;
|
||||
background: $colorDark;
|
||||
margin: 4px 0 0;
|
||||
border: 1px solid $colorDark;
|
||||
position: absolute;
|
||||
transform: rotate(90deg);
|
||||
top: 365px;
|
||||
right: -169px;
|
||||
width: 320px;
|
||||
z-index: -1;
|
||||
.item {
|
||||
padding: 2px;
|
||||
padding: 2px 10px 0;
|
||||
margin-left: -5px;
|
||||
text-indent: 4px;
|
||||
background: url("/ui/parchment.jpg");
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 80px;
|
||||
box-shadow: 0 0 6px 1px $colorDark;
|
||||
font-size: 12px;
|
||||
filter: brightness(0.9);
|
||||
&.active {
|
||||
background: $colorTan;
|
||||
filter: none;
|
||||
z-index: 1;
|
||||
font-weight: bold;
|
||||
text-shadow: none;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet-body {
|
||||
padding: 5px 0;
|
||||
border: 1px solid $colorDark;
|
||||
border-top: none;
|
||||
height: calc(100% - 175px);
|
||||
height: calc(100% - 140px);
|
||||
.attributes {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.attribute {
|
||||
margin: 10px;
|
||||
position: relative;
|
||||
margin: 8px;
|
||||
border: 1px solid $colorTan;
|
||||
box-shadow: 0 0 2px $colorTan;
|
||||
.attribute-name {
|
||||
color: whitesmoke;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
background: $colorDark;
|
||||
border: 1px solid $colorDark;
|
||||
background: $darkBackground;
|
||||
text-align: center;
|
||||
}
|
||||
&.attribute-secondaries {
|
||||
margin: 10px 5px;
|
||||
}
|
||||
&.ability-score {
|
||||
height: 40px;
|
||||
.attribute-value {
|
||||
line-height: 36px;
|
||||
}
|
||||
}
|
||||
.attribute-value {
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.sep {
|
||||
flex: 0 0 5px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
.attribute-mod {
|
||||
position: absolute;
|
||||
color: $colorTan;
|
||||
right: 5px;
|
||||
top: -5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.attribute-group {
|
||||
flex: 0 0 105px;
|
||||
margin: auto 0;
|
||||
.attributes {
|
||||
.attribute {
|
||||
display: flex;
|
||||
|
|
@ -119,64 +154,151 @@
|
|||
.attribute-name {
|
||||
width: 40px;
|
||||
margin: 0;
|
||||
line-height: 28px;
|
||||
line-height: 35px;
|
||||
a {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
&.saving-throw .attribute-name {
|
||||
line-height: 16px;
|
||||
width: 80px;
|
||||
}
|
||||
.attribute-value {
|
||||
width: 45px;
|
||||
flex-grow: 0;
|
||||
input {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.inventory {
|
||||
overflow: auto;
|
||||
.header-spells {
|
||||
line-height: 30px;
|
||||
}
|
||||
.item-titles {
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
border: 1px solid $colorDark;
|
||||
box-shadow: 0 0 5px $colorDark;
|
||||
.item-name {
|
||||
text-align: left;
|
||||
text-indent: 8px;
|
||||
}
|
||||
font-weight: 300;
|
||||
font-size: 13px;
|
||||
background: $darkBackground;
|
||||
color: white;
|
||||
input {
|
||||
color: white;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
.item-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
& > * {
|
||||
line-height: 30px;
|
||||
}
|
||||
.item-summary {
|
||||
font-size: 13px;
|
||||
padding: 0 4px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.item-header {
|
||||
@extend %header-field !optional;
|
||||
padding: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.item-entry {
|
||||
&:nth-child(even) {
|
||||
.item {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.item-equipped {
|
||||
grid-area: item-equipped;
|
||||
justify-self: center;
|
||||
}
|
||||
.item-name {
|
||||
text-indent: 8px;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
height: 30px;
|
||||
margin: 0;
|
||||
line-height: 30px;
|
||||
&:hover .item-image {
|
||||
background-image: url("/icons/svg/d20-grey.svg") !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-image {
|
||||
flex-basis: 30px;
|
||||
flex-grow: 0;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
&:hover {
|
||||
background-image: url("/icons/svg/d20-black.svg") !important;
|
||||
}
|
||||
}
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.field-longer {
|
||||
text-indent: 8px;
|
||||
text-align: left;
|
||||
flex-basis: 150px;
|
||||
font-size: 12px;
|
||||
flex-grow: 0;
|
||||
}
|
||||
.field-long {
|
||||
flex-basis: 65px;
|
||||
flex-grow: 0;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
.field-short {
|
||||
font-size: 12px;
|
||||
flex-basis: 45px;
|
||||
flex-grow: 0;
|
||||
text-align: center;
|
||||
&.quantity {
|
||||
display: flex;
|
||||
input {
|
||||
margin: 3px 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-controls {
|
||||
font-size: 12px;
|
||||
flex-basis: 60px;
|
||||
flex-grow: 0;
|
||||
text-align: right;
|
||||
margin-right: 4px;
|
||||
.item-unequipped {
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
&.spells {
|
||||
.item-controls {
|
||||
flex-basis: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.editor {
|
||||
height: 300px;
|
||||
}
|
||||
.inventory {
|
||||
.item-entry {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
.item {
|
||||
.item-image {
|
||||
flex: 0 0 24px;
|
||||
height: 24px;
|
||||
background-size: cover;
|
||||
}
|
||||
.item-name {
|
||||
line-height: 24px;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
h4 {
|
||||
text-indent: 4px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: whitesmoke;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
rgba(0, 0, 0, 0.5),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-controls {
|
||||
line-height: 24px;
|
||||
flex: 0 0 32px;
|
||||
margin: 0 3px;
|
||||
.fas {
|
||||
color: $colorTan;
|
||||
font-size: 12px;
|
||||
&:hover {
|
||||
color: $colorDark;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-summary {
|
||||
font-size: 12px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
&:nth-child(odd) {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,124 @@
|
|||
.ose.chat-block {
|
||||
margin: 0;
|
||||
.chat-title {
|
||||
background: $darkBackground;
|
||||
border: 1px solid black;
|
||||
border-radius: 3px;
|
||||
color: white;
|
||||
padding: 2px;
|
||||
box-shadow: 0 0 2px #FFF inset;
|
||||
text-align: center;
|
||||
margin: 4px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
.chat-details {
|
||||
padding: 4px;
|
||||
font-size: 13px;
|
||||
.roll-result {
|
||||
text-align: center;
|
||||
&.roll-success {
|
||||
color: #18520b;
|
||||
}
|
||||
&.roll-fail {
|
||||
color: #aa0200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ose.chat-card {
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
|
||||
.card-header {
|
||||
padding: 3px 0;
|
||||
border-top: 2px groove #fff;
|
||||
border-bottom: 2px groove #fff;
|
||||
|
||||
img {
|
||||
flex: 0 0 36px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
line-height: 36px;
|
||||
color: $colorOlive;
|
||||
&:hover {
|
||||
color: #111;
|
||||
text-shadow: 0 0 10px red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
margin: 5px 0;
|
||||
|
||||
h3 {
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
> * {
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
}
|
||||
|
||||
.card-buttons {
|
||||
margin: 5px 0;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
border: 1px solid $colorTan;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 12px;
|
||||
height: 24px;
|
||||
line-height: 20px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
padding: 3px 0 0;
|
||||
border-top: 2px groove #fff;
|
||||
|
||||
span {
|
||||
border-right: 2px groove #fff;
|
||||
padding: 0 5px 0 0;
|
||||
font-size: 10px;
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dice-roll .dice-total {
|
||||
&.success {
|
||||
color: inherit;
|
||||
background: #c7d0c0;
|
||||
border: 1px solid #006c00;
|
||||
}
|
||||
&.failure {
|
||||
color: inherit;
|
||||
background: #ffdddd;
|
||||
border: 1px solid #6e0000;
|
||||
}
|
||||
&.critical {
|
||||
color: green;
|
||||
}
|
||||
&.fumble {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,34 +5,65 @@
|
|||
/* ----------------------------------------- */
|
||||
.ose.sheet.actor.character {
|
||||
min-width: 450px;
|
||||
min-height: 590px;
|
||||
min-height: 550px;
|
||||
|
||||
/* ----------------------------------------- */
|
||||
/* Sheet Header */
|
||||
/* ----------------------------------------- */
|
||||
|
||||
.sheet-header {
|
||||
.xp-bonus {
|
||||
top: -15px;
|
||||
right: 3px;
|
||||
color: $colorTan;
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------- */
|
||||
/* Sheet Body */
|
||||
/* ----------------------------------------- */
|
||||
.sheet-body {
|
||||
.health {
|
||||
&.armor-class {
|
||||
background: url('/systems/ose/assets/shield.png') no-repeat center;
|
||||
background-size: 70px;
|
||||
}
|
||||
|
||||
|
||||
.abilities {
|
||||
.panel-content {
|
||||
height: 250px;
|
||||
overflow: auto;
|
||||
margin: 10px 0;
|
||||
height: 70px;
|
||||
position: relative;
|
||||
input {
|
||||
font-size: 16px;
|
||||
font-weight: bolder;
|
||||
text-shadow: 0 0 2px white, 0 1px 2px white, 1px 0 2px white, 1px 1px 2px white;
|
||||
}
|
||||
.health-top {
|
||||
border-bottom: none;
|
||||
position: absolute;
|
||||
font-size: 24px;
|
||||
top: 10px;
|
||||
width: 70px;
|
||||
left: calc(50% - 35px);
|
||||
}
|
||||
.health-bottom {
|
||||
border-bottom: none;
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
width: 40px;
|
||||
right: calc(50% + -20px);
|
||||
}
|
||||
.health-empty {
|
||||
background: url('/systems/ose/assets/heart_empty.png') no-repeat center;
|
||||
background-size: 70px;
|
||||
background-position: top;
|
||||
}
|
||||
.health-full {
|
||||
background: url('/systems/ose/assets/heart_full.png') no-repeat center;
|
||||
background-size: 70px;
|
||||
background-position: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------- */
|
||||
/* Inventory */
|
||||
/* ----------------------------------------- */
|
||||
.inventory {
|
||||
|
||||
}
|
||||
/* ----------------------------------------- */
|
||||
/* Item Controls */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,37 @@
|
|||
.ose.sheet.item {
|
||||
.profile-img {
|
||||
border: none;
|
||||
flex: 0 0 84px;
|
||||
height: 84px;
|
||||
}
|
||||
.sheet-body {
|
||||
.stats {
|
||||
flex: 0 0 90px;
|
||||
border-right: 1px groove rgba(0, 0, 0, 0.2);
|
||||
padding-right: 2px;
|
||||
.form-group {
|
||||
margin: 2px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
label {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
padding: 0 4px;
|
||||
}
|
||||
input {
|
||||
border-bottom: none;
|
||||
margin: auto 0;
|
||||
}
|
||||
}
|
||||
.block-input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.editor {
|
||||
height: 255px;
|
||||
height: 240px;
|
||||
}
|
||||
.weapon-editor .editor {
|
||||
height: 215px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,17 +5,19 @@
|
|||
.editor {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
.abilities {
|
||||
.panel-content {
|
||||
height: 230px;
|
||||
overflow: auto;
|
||||
.attributes .attribute.health {
|
||||
min-width: 75px;
|
||||
}
|
||||
}
|
||||
.attribute-row {
|
||||
padding: 2px;
|
||||
.abilities {
|
||||
.attribute-group {
|
||||
.attacks-description {
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
label {
|
||||
color: $colorTan;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
/* Sheet Styles */
|
||||
/* ----------------------------------------- */
|
||||
|
||||
$colorDark: #191813;
|
||||
$darkBackground: url('/systems/ose/assets/back.png');
|
||||
$colorDark: rgba(0, 0, 0, 0.9);
|
||||
$colorFaint: #c9c7b8;
|
||||
$colorBeige: #b5b3a4;
|
||||
$colorTan: #7a7971;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,78 @@
|
|||
{
|
||||
"Actor": {
|
||||
"types": ["character", "monster"],
|
||||
"templates": {
|
||||
"common": {
|
||||
"retainer": {
|
||||
"enabled": false,
|
||||
"loyalty": 0
|
||||
},
|
||||
"hp": {
|
||||
"hd": "",
|
||||
"value": 20,
|
||||
"max": 20
|
||||
},
|
||||
"ac": {
|
||||
"naked": 0,
|
||||
"value": 0,
|
||||
"mod": 0
|
||||
},
|
||||
"aac": {
|
||||
"naked": 0,
|
||||
"value": 0,
|
||||
"mod": 0
|
||||
},
|
||||
"thac0": {
|
||||
"value": 19,
|
||||
"bba": 0,
|
||||
"mod": {
|
||||
"missile": 0,
|
||||
"melee": 0
|
||||
}
|
||||
},
|
||||
"saves": {
|
||||
"death": 10,
|
||||
"wand": 10,
|
||||
"paralysis": 10,
|
||||
"breath": 10,
|
||||
"spell": 10
|
||||
},
|
||||
"movement": {
|
||||
"base": 120
|
||||
}
|
||||
},
|
||||
"spellcaster": {
|
||||
"spells": {
|
||||
"enabled": false,
|
||||
"1": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"2": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"3": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"4": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"5": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"6": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"character": {
|
||||
"templates": ["common", "spellcaster"],
|
||||
"details": {
|
||||
"biography": "",
|
||||
"class": "",
|
||||
|
|
@ -9,7 +80,11 @@
|
|||
"alignment": "",
|
||||
"literate": false,
|
||||
"level": 1,
|
||||
"xp": 0
|
||||
"xp": {
|
||||
"next": 0,
|
||||
"value": 0,
|
||||
"bonus": 0
|
||||
}
|
||||
},
|
||||
"scores": {
|
||||
"str": {
|
||||
|
|
@ -42,53 +117,6 @@
|
|||
"silver": 0,
|
||||
"copper": 0
|
||||
},
|
||||
"spells": {
|
||||
"dc": 0,
|
||||
"lvl1": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl2": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl3": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl4": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl5": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
}
|
||||
},
|
||||
"hp": {
|
||||
"hd": "",
|
||||
"value": 20,
|
||||
"max": 20
|
||||
},
|
||||
"ac": {
|
||||
"value": 0,
|
||||
"mod": 0
|
||||
},
|
||||
"thac0": {
|
||||
"value": 19,
|
||||
"mod": 0
|
||||
},
|
||||
"saves": {
|
||||
"D": 10,
|
||||
"W": 10,
|
||||
"P": 10,
|
||||
"B": 10,
|
||||
"S": 10
|
||||
},
|
||||
"movement": {
|
||||
"base": 0,
|
||||
"encounter": 0
|
||||
},
|
||||
"initative": {
|
||||
"value": 0,
|
||||
"mod": 0
|
||||
|
|
@ -96,6 +124,7 @@
|
|||
"languages": []
|
||||
},
|
||||
"monster": {
|
||||
"templates": ["common", "spellcaster"],
|
||||
"details": {
|
||||
"biography": "",
|
||||
"alignment": "",
|
||||
|
|
@ -105,72 +134,52 @@
|
|||
"appearing": "",
|
||||
"morale": 0
|
||||
},
|
||||
"saves": {
|
||||
"D": 10,
|
||||
"W": 10,
|
||||
"P": 10,
|
||||
"B": 10,
|
||||
"S": 10
|
||||
},
|
||||
"thac0": {
|
||||
"value": 19,
|
||||
"mod": 0
|
||||
},
|
||||
"hp": {
|
||||
"hd": "",
|
||||
"max": 0,
|
||||
"value": 0
|
||||
},
|
||||
"ac": {
|
||||
"value": 0,
|
||||
"mod": 0
|
||||
},
|
||||
"attacks": {
|
||||
"value": 1
|
||||
},
|
||||
"movement": {
|
||||
"base": 0,
|
||||
"encounter": 0
|
||||
},
|
||||
"spells": {
|
||||
"dc": 0,
|
||||
"lvl1": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl2": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl3": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl4": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
},
|
||||
"lvl5": {
|
||||
"value": 0,
|
||||
"max": 0
|
||||
}
|
||||
}
|
||||
"attacks": ""
|
||||
}
|
||||
},
|
||||
"Item": {
|
||||
"types": ["item", "spell", "ability"],
|
||||
"types": ["item", "weapon", "armor", "spell", "ability"],
|
||||
"item": {
|
||||
"description": "",
|
||||
"quantity": 1,
|
||||
"quantity": {
|
||||
"value": 1,
|
||||
"max": 0
|
||||
},
|
||||
"cost": 0,
|
||||
"weight": 80
|
||||
},
|
||||
"weapon": {
|
||||
"description": "",
|
||||
"damage": "1d6",
|
||||
"qualities": "",
|
||||
"slow": false,
|
||||
"missile": true,
|
||||
"melee": true,
|
||||
"cost": 0,
|
||||
"equipped": false,
|
||||
"weight": 0
|
||||
},
|
||||
"armor": {
|
||||
"description": "",
|
||||
"ac": 9,
|
||||
"aac": 10,
|
||||
"cost": 0,
|
||||
"equipped": false,
|
||||
"weight": 0
|
||||
},
|
||||
"spell": {
|
||||
"lvl": 1,
|
||||
"class": "",
|
||||
"description": ""
|
||||
"class": "Magic-User",
|
||||
"duration": "",
|
||||
"range": "",
|
||||
"roll": "",
|
||||
"description": "",
|
||||
"memorized": false,
|
||||
"cast": false
|
||||
},
|
||||
"ability": {
|
||||
"requirements": "",
|
||||
"roll": "",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,17 @@
|
|||
<a class="item" data-tab="attributes">
|
||||
{{localize "OSE.category.attributes"}}
|
||||
</a>
|
||||
<a class="item" data-tab="inventory">
|
||||
{{localize "OSE.category.inventory"}}
|
||||
<a class="item" data-tab="abilities">
|
||||
{{localize "OSE.category.abilities"}}
|
||||
</a>
|
||||
{{#if data.spells.enabled}}
|
||||
<a class="item" data-tab="spells">
|
||||
{{localize "OSE.category.spells"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
<a class="item" data-tab="inventory">
|
||||
{{localize "OSE.category.inventory"}}
|
||||
</a>
|
||||
<a class="item" data-tab="notes">
|
||||
{{localize "OSE.category.notes"}}
|
||||
</a>
|
||||
|
|
@ -25,12 +30,17 @@
|
|||
<div class="tab" data-group="primary" data-tab="attributes">
|
||||
{{> "systems/ose/templates/actors/partials/character-attributes-tab.html"}}
|
||||
</div>
|
||||
<div class="tab" data-group="primary" data-tab="inventory">
|
||||
{{> "systems/ose/templates/actors/partials/character-inventory-tab.html"}}
|
||||
<div class="tab" data-group="primary" data-tab="abilities">
|
||||
{{> "systems/ose/templates/actors/partials/character-abilities-tab.html"}}
|
||||
</div>
|
||||
{{#if data.spells.enabled}}
|
||||
<div class="tab" data-group="primary" data-tab="spells">
|
||||
{{> "systems/ose/templates/actors/partials/character-spells-tab.html"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="tab" data-group="primary" data-tab="inventory">
|
||||
{{> "systems/ose/templates/actors/partials/character-inventory-tab.html"}}
|
||||
</div>
|
||||
<div class="tab" data-group="primary" data-tab="notes">
|
||||
{{editor content=data.details.biography target="data.details.biography"
|
||||
button=true owner=owner editable=editable}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
<form autocomplete="off">
|
||||
<div class="form-group">
|
||||
<label for="spellcaster">{{localize "OSE.Spellcaster"}}</label>
|
||||
<div class="form-fields">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="data.spells.enabled"
|
||||
id="spellcaster"
|
||||
{{checked
|
||||
data.spells.enabled}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="retainer">{{localize "OSE.Retainer"}}</label>
|
||||
<div class="form-fields">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="data.retainer.enabled"
|
||||
id="retainer"
|
||||
{{checked
|
||||
data.retainer.enabled}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{{#if (eq this.type 'character')}}
|
||||
<div class="form-group">
|
||||
<label>{{localize "OSE.ExperienceBonus"}} (%)</label>
|
||||
<div class="form-fields">
|
||||
<input
|
||||
type="text"
|
||||
name="data.details.xp.bonus"
|
||||
id="experience"
|
||||
value="{{data.details.xp.bonus}}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "OSE.MeleeBonus"}}</label>
|
||||
<div class="form-fields">
|
||||
<input
|
||||
type="text"
|
||||
name="data.thac0.mod.melee"
|
||||
id="melee"
|
||||
value="{{data.thac0.mod.melee}}"
|
||||
data-dtype="Number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "OSE.MissileBonus"}}</label>
|
||||
<div class="form-fields">
|
||||
<input
|
||||
type="text"
|
||||
name="data.thac0.mod.missile"
|
||||
id="missile"
|
||||
value="{{data.thac0.mod.missile}}"
|
||||
data-dtype="Number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<footer class="sheet-footer">
|
||||
<button type="submit">
|
||||
<i class="fas fa-save"></i>{{localize "Save Changes"}}
|
||||
</button>
|
||||
</footer>
|
||||
</form>
|
||||
|
||||
|
|
@ -9,9 +9,11 @@
|
|||
<a class="item" data-tab="attributes">
|
||||
{{localize "OSE.category.attributes"}}
|
||||
</a>
|
||||
{{#if data.spells.enabled}}
|
||||
<a class="item" data-tab="spells">
|
||||
{{localize "OSE.category.spells"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
<a class="item" data-tab="notes">
|
||||
{{localize "OSE.category.notes"}}
|
||||
</a>
|
||||
|
|
@ -22,9 +24,11 @@
|
|||
<div class="tab" data-group="primary" data-tab="attributes">
|
||||
{{> "systems/ose/templates/actors/partials/monster-attributes-tab.html"}}
|
||||
</div>
|
||||
{{#if data.spells.enabled}}
|
||||
<div class="tab" data-group="primary" data-tab="spells">
|
||||
{{> "systems/ose/templates/actors/partials/character-spells-tab.html"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="tab" data-group="primary" data-tab="notes">
|
||||
{{editor content=data.details.biography target="data.details.biography"
|
||||
button=true owner=owner editable=editable}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<div class="inventory abilities">
|
||||
<div class="item-titles flexrow">
|
||||
<div class="item-name">{{localize 'OSE.panel.abilities'}}</div>
|
||||
<div class="item-controls">
|
||||
{{#if owner}}
|
||||
<a class="item-control item-create" title='{{localize "OSE.Add"}}' data-type="ability"><i
|
||||
class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<ol class="item-list resizable" data-base-size="300">
|
||||
{{#each abilities as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-name flexrow">
|
||||
<div class="item-image" style="background-image: url({{item.img}})"></div>
|
||||
<a>
|
||||
<h4 title="{{item.name}}">
|
||||
{{item.name~}}
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="field-long">
|
||||
{{item.roll}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "Ose.Edit"}}'><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "Ose.Delete"}}'><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
|
|
@ -1,146 +1,237 @@
|
|||
<section class="flexrow">
|
||||
<ul class="attributes flexrow">
|
||||
<li class="attribute health">
|
||||
<h4 class="attribute-name box-title">{{ localize "OSE.HealthShort" }}</h4>
|
||||
<div class="attribute-value multiple">
|
||||
<input name="data.hp.value" type="text" value="{{data.hp.value}}" data-dtype="Number"
|
||||
placeholder="10" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.hp.max" type="text" value="{{data.hp.max}}" data-dtype="Number" placeholder="10" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{ localize "OSE.ArmorClassShort" }}</h4>
|
||||
{{!-- Scores --}}
|
||||
<div class="attribute-group">
|
||||
<ul class="attributes">
|
||||
<li class="attribute ability-score" data-score="str">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.str.long' }}">
|
||||
<a>{{ localize "OSE.scores.str.short" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.ac.value" type="text" value="{{data.ac.value}}" data-dtype="Number"
|
||||
placeholder="10" data-dtype="Number" />
|
||||
</div>
|
||||
<input name="data.scores.str.value" type="text" value="{{data.scores.str.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<span class="attribute-mod">{{mods.str}}</span>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{ localize "OSE.Thac0" }}</h4>
|
||||
<li class="attribute ability-score" data-score="int">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.int.long' }}">
|
||||
<a>{{ localize "OSE.scores.int.short" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.thac0.value" type="text" value="{{data.thac0.value}}" placeholder="0"
|
||||
<input name="data.scores.int.value" type="text" value="{{data.scores.int.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<span class="attribute-mod">{{mods.int}}</span>
|
||||
</li>
|
||||
<li class="attribute ability-score" data-score="wis">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.wis.long' }}">
|
||||
<a>{{ localize "OSE.scores.wis.short" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.wis.value" type="text" value="{{data.scores.wis.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<span class="attribute-mod">{{mods.wis}}</span>
|
||||
</li>
|
||||
<li class="attribute ability-score" data-score="dex">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.dex.long' }}">
|
||||
<a>{{ localize "OSE.scores.dex.short" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.dex.value" type="text" value="{{data.scores.dex.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<span class="attribute-mod">{{mods.dex}}</span>
|
||||
</li>
|
||||
<li class="attribute ability-score" data-score="con">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.con.long' }}">
|
||||
<a>{{ localize "OSE.scores.con.short" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.con.value" type="text" value="{{data.scores.con.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<span class="attribute-mod">{{mods.con}}</span>
|
||||
</li>
|
||||
<li class="attribute ability-score" data-score="cha">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.cha.long' }}">
|
||||
<a>{{ localize "OSE.scores.cha.short" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.cha.value" type="text" value="{{data.scores.cha.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<span class="attribute-mod">{{mods.cha}}</span>
|
||||
</li>
|
||||
{{#if data.retainer.enabled}}
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Loyalty' }}">
|
||||
{{ localize "OSE.LoyaltyShort" }}
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.retainer.loyalty" type="text" value="{{data.retainer.loyalty}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
||||
{{!-- Resource Tracking --}}
|
||||
<div class="flex2">
|
||||
<div class="flexrow">
|
||||
<div class="health">
|
||||
<input class="health-top" name="data.hp.value" type="text" value="{{data.hp.value}}" data-dtype="Number"
|
||||
placeholder="0" title="{{localize 'OSE.Health'}}" />
|
||||
<input class="health-bottom" name="data.hp.max" type="text" value="{{data.hp.max}}" data-dtype="Number"
|
||||
placeholder="0" title="{{localize 'OSE.HealthMax'}}" />
|
||||
<div class="health-empty" style="height:{{counter false data.hp.value data.hp.max}}%"></div>
|
||||
<div class="health-full" style="height:{{counter true data.hp.value data.hp.max}}%"></div>
|
||||
</div>
|
||||
<div class="health armor-class">
|
||||
{{#if config.ascendingAC}}
|
||||
<input class="health-top" name="data.aac.value" type="text" value="{{data.aac.value}}"
|
||||
data-dtype="Number" placeholder="0" title="{{localize 'OSE.ArmorClass'}}" />
|
||||
<input class="health-bottom" type="text" value="{{add 10 mods.dex}}"
|
||||
title="{{localize 'OSE.ArmorClass'}}" disabled />
|
||||
{{else}}
|
||||
<input class="health-top" name="data.ac.value" type="text" value="{{data.ac.value}}" data-dtype="Number"
|
||||
placeholder="0" title="{{localize 'OSE.ArmorClass'}}" />
|
||||
<input class="health-bottom" type="text" value="{{subtract mods.dex 9}}"
|
||||
title="{{localize 'OSE.ArmorClass'}}" disabled />
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flexrow">
|
||||
<ul class="attributes flexrow">
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{ localize "OSE.InitiativeShort" }}</h4>
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.HitDice' }}">
|
||||
{{ localize "OSE.HitDiceShort" }}
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.hp.hd" type="text" value="{{data.hp.hd}}" placeholder="0"
|
||||
data-dtype="String" />
|
||||
</div>
|
||||
</li>
|
||||
{{#if config.individualInit}}
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Initiative' }}">
|
||||
{{ localize "OSE.InitiativeShort" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.initiative.value" type="text" value="{{data.initiative.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{ localize "OSE.MovementShort" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.movement.value" type="text" value="{{data.movement.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="flexrow">
|
||||
{{!-- Scores --}}
|
||||
<div class="attribute-group">
|
||||
<ul class="attributes">
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.str.long' }}">{{ localize "OSE.scores.str.short" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.str.value" type="text" value="{{data.scores.str.value}}" placeholder="0" data-dtype="Number"/>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.int.long' }}">{{ localize "OSE.scores.int.short" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.int.value" type="text" value="{{data.scores.int.value}}" placeholder="0" data-dtype="Number"/>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.wis.long' }}">{{ localize "OSE.scores.wis.short" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.wis.value" type="text" value="{{data.scores.wis.value}}" placeholder="0" data-dtype="Number"/>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.dex.long' }}">{{ localize "OSE.scores.dex.short" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.dex.value" type="text" value="{{data.scores.dex.value}}" placeholder="0" data-dtype="Number"/>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.con.long' }}">{{ localize "OSE.scores.con.short" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.con.value" type="text" value="{{data.scores.con.value}}" placeholder="0" data-dtype="Number"/>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.cha.long' }}">{{ localize "OSE.scores.cha.short" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.scores.cha.value" type="text" value="{{data.scores.cha.value}}" placeholder="0" data-dtype="Number"/>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
||||
{{!-- Skills and abilities --}}
|
||||
<div class="flex3 panel abilities resizable" data-base-size="250">
|
||||
<div class="panel-title">
|
||||
<h4>{{localize 'OSE.panel.abilities'}}</h4>
|
||||
<div class="item-controls">
|
||||
{{#if owner}}
|
||||
<a class="item-control item-create" title='{{localize "OSE.Add"}}' data-type="ability"><i class="fas fa-plus"></i></a>
|
||||
<div class="flexrow">
|
||||
<ul class="attributes flexrow">
|
||||
<li class="attribute attribute-secondaries attack" data-attack="Melee">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Melee'}}">
|
||||
<a>{{localize 'OSE.MeleeShort'}}</a></h4>
|
||||
<div class="flexrow">
|
||||
<div class="attribute-value">
|
||||
{{#if config.ascendingAC}}
|
||||
{{add data.thac0.mod.melee (add mods.str data.thac0.bba)}}
|
||||
{{else}}
|
||||
{{subtract data.thac0.mod.melee (subtract mods.str data.thac0.value)}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="panel-content inventory resizable" data-base-size="225">
|
||||
<div class="">
|
||||
{{#each abilities as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-name flexrow">
|
||||
<div class="item-image" style="background-image: url({{item.img}})"></div>
|
||||
<h4 title="{{item.name}}">
|
||||
{{item.name~}}
|
||||
</li>
|
||||
{{#if config.ascendingAC}}
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.AB' }}">{{ localize "OSE.ABShort"}}
|
||||
</h4>
|
||||
<div class="flexrow">
|
||||
<div class="attribute-value">
|
||||
<input name="data.thac0.bba" type="text" value="{{data.thac0.bba}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "Ose.Edit"}}'><i
|
||||
class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "Ose.Delete"}}'><i
|
||||
class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Thac0' }}">{{ localize "OSE.Thac0"}}
|
||||
</h4>
|
||||
<div class="flexrow">
|
||||
<div class="attribute-value">
|
||||
<input name="data.thac0.value" type="text" value="{{data.thac0.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="attribute attribute-secondaries attack" data-attack="Missile">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Missile'}}">
|
||||
<a>{{localize 'OSE.MissileShort'}}</a></h4>
|
||||
<div class="flexrow">
|
||||
<div class="attribute-value">
|
||||
{{#if config.ascendingAC}}
|
||||
{{add data.thac0.mod.missile (add mods.dex data.thac0.bba)}}
|
||||
{{else}}
|
||||
{{subtract data.thac0.mod.missile (subtract mods.dex data.thac0.value)}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="flexrow">
|
||||
<ul class="attributes flexrow">
|
||||
<li class="attribute attribute-secondaries">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.MovementEncounter'}}">
|
||||
{{localize 'OSE.MovementEncounterShort'}}</h4>
|
||||
<div class="flexrow">
|
||||
<div class="attribute-value">
|
||||
{{divide data.movement.base 3}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Movement' }}">
|
||||
{{ localize "OSE.MovementShort" }}</h4>
|
||||
<div class="attribute-value flexrow">
|
||||
<input name="data.movement.base" type="text" value="{{data.movement.base}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute attribute-secondaries">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.MovementOverland'}}">
|
||||
{{localize 'OSE.MovementOverlandShort'}}</h4>
|
||||
<div class="flexrow">
|
||||
<div class="attribute-value">
|
||||
{{divide data.movement.base 5}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{!-- Saving throws --}}
|
||||
<div class="attribute-group">
|
||||
<ul class="attributes">
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.death.long' }}">{{ localize "OSE.saves.death.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="death">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.death.long' }}">
|
||||
<a>{{ localize "OSE.saves.death.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.d.value" type="text" value="{{data.saves.d.value}}" placeholder="0"
|
||||
<input name="data.saves.death.value" type="text" value="{{data.saves.death.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.wands.long' }}">{{ localize "OSE.saves.wands.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="wand">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.wand.long' }}">
|
||||
<a>{{ localize "OSE.saves.wand.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.w.value" type="text" value="{{data.saves.w.value}}" placeholder="0"
|
||||
<input name="data.saves.wand.value" type="text" value="{{data.saves.wand.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.paralysis.long' }}">{{ localize "OSE.saves.paralysis.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="paralysis">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.paralysis.long' }}">
|
||||
<a>{{ localize "OSE.saves.paralysis.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.p.value" type="text" value="{{data.saves.p.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<input name="data.saves.paralysis.value" type="text" value="{{data.saves.paralysis.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.breath.long' }}">{{ localize "OSE.saves.breath.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="breath">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.breath.long' }}">
|
||||
<a>{{ localize "OSE.saves.breath.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.b.value" type="text" value="{{data.saves.b.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<input name="data.saves.breath.value" type="text" value="{{data.saves.breath.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.spells.long' }}">{{ localize "OSE.saves.spells.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="spell">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.spell.long' }}">
|
||||
<a>{{ localize "OSE.saves.spell.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.s.value" type="text" value="{{data.saves.s.value}}" placeholder="0" />
|
||||
<input name="data.saves.spell.value" type="text" value="{{data.saves.spell.value}}"
|
||||
placeholder="0" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,9 +27,12 @@
|
|||
<label>{{localize 'OSE.Level'}}</label>
|
||||
</li>
|
||||
<li class="flex2">
|
||||
<input type="text" name="data.details.xp" value="{{data.details.xp}}"
|
||||
<input type="text" name="data.details.xp.value" value="{{data.details.xp.value}}"
|
||||
placeholder="{{ localize 'OSE.Experience' }}" />
|
||||
<label>{{localize 'OSE.Experience'}}</label>
|
||||
{{#if data.details.xp.bonus}}
|
||||
<span class="xp-bonus">+{{data.details.xp.bonus}}%</span>
|
||||
{{/if}}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
@ -1,29 +1,141 @@
|
|||
<section class="inventory resizable" data-base-size="320">
|
||||
<div class="">
|
||||
{{#each inventory as |item|}}
|
||||
<section class="inventory resizable" data-base-size="310">
|
||||
<div>
|
||||
<li class="item-titles flexrow">
|
||||
<div class="item-name">{{localize "OSE.items.Weapons"}}</div>
|
||||
{{#if config.variableWeaponDamage}}
|
||||
<div class="field-short">{{localize "OSE.items.Damage"}}</div>
|
||||
{{/if}}
|
||||
<div class="field-longer">{{localize "OSE.items.Qualities"}}</div>
|
||||
<div class="field-short">{{localize "OSE.items.Weight"}}</div>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-create" data-type="weapon" title="{{localize 'OSE.Add'}}"><i class="fa fa-plus"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
<ol class="item-list">
|
||||
{{#each owned.weapons as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-name flexrow">
|
||||
<div
|
||||
class="item-image"
|
||||
style="background-image: url({{item.img}})"
|
||||
></div>
|
||||
<div class="item-image" style="background-image: url({{item.img}})"></div>
|
||||
<a>
|
||||
<h4 title="{{item.name}}">
|
||||
{{item.name~}}
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
{{#if config.variableWeaponDamage}}
|
||||
<div class="field-short">
|
||||
{{item.data.damage}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="field-longer" title="{{item.data.qualities}}">
|
||||
{{item.data.qualities}}
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{item.data.weight}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "Ose.Edit"}}'
|
||||
><i class="fas fa-edit"></i
|
||||
></a>
|
||||
<a class="item-control item-delete" title='{{localize "Ose.Delete"}}'
|
||||
><i class="fas fa-trash"></i
|
||||
></a>
|
||||
<a class="item-control item-toggle {{#unless item.data.equipped}}item-unequipped{{/unless}}"
|
||||
title='{{localize "OSE.items.Equip"}}'>
|
||||
<i class="fas fa-tshirt"></i>
|
||||
</a>
|
||||
<a class="item-control item-edit" title='{{localize "OSE.Edit"}}'><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "OSE.Delete"}}'><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
<div>
|
||||
<li class="item-titles flexrow">
|
||||
<div class="item-name">{{localize "OSE.items.Armors"}}</div>
|
||||
{{#if config.ascendingAC}}
|
||||
<div class="field-short">{{localize "OSE.items.ArmorAAC"}}</div>
|
||||
{{else}}
|
||||
<div class="field-short">{{localize "OSE.items.ArmorAC"}}</div>
|
||||
{{/if}}
|
||||
<div class="field-short">{{localize "OSE.items.Weight"}}</div>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-create" data-type="armor" title="{{localize 'OSE.Add'}}"><i class="fa fa-plus"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
<ol class="item-list">
|
||||
{{#each owned.armors as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-name flexrow">
|
||||
<div class="item-image" style="background-image: url({{item.img}})"></div>
|
||||
<a>
|
||||
<h4 title="{{item.name}}">
|
||||
{{item.name~}}
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{#if config.ascendingAC}}
|
||||
{{item.data.aac}}
|
||||
{{else}}
|
||||
{{item.data.ac}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{item.data.weight}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-toggle {{#unless item.data.equipped}}item-unequipped{{/unless}}"
|
||||
title='{{localize "OSE.items.Equip"}}'>
|
||||
<i class="fas fa-tshirt"></i>
|
||||
</a>
|
||||
<a class="item-control item-edit" title='{{localize "OSE.Edit"}}'><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "OSE.Delete"}}'><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="">
|
||||
<li class="item-titles flexrow">
|
||||
<div class="item-name">{{localize "OSE.items.Misc"}}</div>
|
||||
<div class="field-short">{{localize "OSE.items.Quantity"}}</div>
|
||||
<div class="field-short">{{localize "OSE.items.Weight"}}</div>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-create" data-type="item" title="{{localize 'OSE.Add'}}"><i class="fa fa-plus"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
<ol class="item-list">
|
||||
{{#each owned.items as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-name flexrow">
|
||||
<div class="item-image" style="background-image: url({{item.img}})"></div>
|
||||
<a>
|
||||
<h4 title="{{item.name}}">
|
||||
{{item.name~}}
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="field-short quantity">
|
||||
<input value="{{item.data.quantity.value}}" type="text"
|
||||
placeholder="0" />{{#if item.data.quantity.max}}<span>/{{item.data.quantity.max}}</span>{{/if}}
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{item.data.weight}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "OSE.Edit"}}'><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "OSE.Delete"}}'><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -1,93 +1,42 @@
|
|||
<section class="flexrow">
|
||||
<ul class="attributes flexrow">
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'OSE.SpellDC'}}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.spells.dc" type="text" value="{{data.spells.dc}}" data-dtype="Number"
|
||||
placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'OSE.Level'}} 1</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.spells.lvl1.value" type="text" value="{{data.spells.lvl1.value}}" data-dtype="Number"
|
||||
placeholder="0" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.spells.lvl1.max" type="text" value="{{data.spells.lvl1.max}}" data-dtype="Number" placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'OSE.Level'}} 2</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.spells.lvl2.value" type="text" value="{{data.spells.lvl2.value}}" data-dtype="Number"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.spells.lvl2.max" type="text" value="{{data.spells.lvl2.max}}" data-dtype="Number" placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'OSE.Level'}} 3</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.spells.lvl3.value" type="text" value="{{data.spells.lvl3.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.spells.lvl3.max" type="text" value="{{data.spells.lvl3.max}}" data-dtype="Number" placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'OSE.Level'}} 4</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.spells.lvl4.value" type="text" value="{{data.spells.lvl4.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.spells.lvl4.max" type="text" value="{{data.spells.lvl4.max}}" data-dtype="Number" placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'OSE.Level'}} 5</h4>
|
||||
<div class="attribute-value multiple">
|
||||
<input name="data.spells.lvl5.value" type="text" value="{{data.spells.lvl5.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.spells.lvl5.max" type="text" value="{{data.spells.lvl5.max}}" data-dtype="Number" placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="panel inventory">
|
||||
<div class="panel-title">
|
||||
<h4>{{localize 'OSE.category.spells'}}</h4>
|
||||
<section class="inventory spells resizable" data-base-size="320">
|
||||
{{#each spells as |spellGroup id|}}
|
||||
<ol class="item-list">
|
||||
<li class="item-titles flexrow">
|
||||
<div class="item-name">{{localize "OSE.spells.Level"}} {{id}}</div>
|
||||
<div class="field-short">{{localize 'OSE.spells.Slots'}}</div>
|
||||
<div class="field-long flexrow"><input type="text" value="{{lookup (lookup ../actor.data.spells @key) 'value'}}" name="data.spells.{{id}}.value" data-dtype="Number"
|
||||
placeholder="0">/<input type="text" value="{{lookup (lookup ../actor.data.spells @key) 'max'}}" name="data.spells.{{id}}.max" data-dtype="Number"
|
||||
placeholder="0"></div>
|
||||
<div class="item-controls">
|
||||
{{#if owner}}
|
||||
<a class="item-control item-create" title='{{localize "OSE.Add"}}' data-type="spell"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
<a class="item-control item-create" data-type="spell" data-lvl="{{id}}" title="{{localize 'OSE.Add'}}"><i
|
||||
class="fa fa-plus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-content resizable" data-base-size="230">
|
||||
{{#each spells as |item|}}
|
||||
</li>
|
||||
{{#each spellGroup as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-cast {{#unless item.data.cast}}item-unequipped{{/unless}}" title="{{localize 'OSE.spells.Cast'}}"><i class="{{#if item.data.cast}}fas{{else}}far{{/if}} fa-sun"></i></a>
|
||||
<a class="item-control item-memorize {{#unless item.data.memorized}}item-unequipped{{/unless}}" title="{{localize 'OSE.spells.Memorized'}}"><i
|
||||
class="fas fa-book-open"></i></a>
|
||||
</div>
|
||||
<div class="item-name flexrow">
|
||||
<div
|
||||
class="item-image"
|
||||
style="background-image: url({{item.img}})"
|
||||
></div>
|
||||
<div class="item-image" style="background-image: url({{item.img}})"></div>
|
||||
<a>
|
||||
<h4 title="{{item.name}}">
|
||||
{{item.name~}}
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "Ose.Edit"}}'
|
||||
><i class="fas fa-edit"></i
|
||||
></a>
|
||||
<a class="item-control item-delete" title='{{localize "Ose.Delete"}}'
|
||||
><i class="fas fa-trash"></i
|
||||
></a>
|
||||
{{#if ../../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "OSE.Edit"}}'><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "OSE.Delete"}}'><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</div>
|
||||
</ol>
|
||||
{{/each}}
|
||||
</section>
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<ul class="attributes flexrow">
|
||||
<li class="attribute health">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Health'}}">{{ localize "OSE.HealthShort" }}</h4>
|
||||
<div class="attribute-value multiple">
|
||||
<div class="attribute-value flexrow">
|
||||
<input name="data.hp.value" type="text" value="{{data.hp.value}}" data-dtype="Number"
|
||||
placeholder="10" />
|
||||
<span class="sep"> / </span>
|
||||
|
|
@ -10,11 +10,28 @@
|
|||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.ArmorClass'}}">{{ localize "OSE.ArmorClassShort" }}</h4>
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.HitDice'}}">{{ localize "OSE.HitDiceShort" }}
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.ac.value" type="text" value="{{data.ac.value}}" data-dtype="Number" placeholder="10"
|
||||
<input name="data.hp.hd" type="text" value="{{data.hp.hd}}" placeholder="0" data-dtype="String" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
{{#if config.ascendingAC}}
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.ArmorClass' }}">
|
||||
{{ localize "OSE.AscArmorClassShort" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.aac.value" type="text" value="{{data.aac.value}}" data-dtype="Number" placeholder="10"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
{{else}}
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.ArmorClass' }}">
|
||||
{{ localize "OSE.ArmorClassShort" }}</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.ac.value" type="text" value="{{data.ac.value}}" data-dtype="Number" placeholder="9"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
{{/if}}
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Thac0'}}">{{ localize "OSE.Thac0" }}</h4>
|
||||
|
|
@ -23,15 +40,19 @@
|
|||
data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
{{#if data.retainer.enabled}}
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Attacks'}}">{{ localize "OSE.AttacksShort" }}</h4>
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Loyalty' }}">{{ localize "OSE.LoyaltyShort" }}
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.att.value" type="text" value="{{data.att.value}}" placeholder="0"
|
||||
<input name="data.retainer.loyalty" type="text" value="{{data.retainer.loyalty}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Movement'}}">{{ localize "OSE.MovementShort" }}</h4>
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Movement'}}">{{ localize "OSE.MovementShort" }}
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.movement.value" type="text" value="{{data.movement.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
|
|
@ -40,17 +61,18 @@
|
|||
</section>
|
||||
<section class="flexrow attribute-row">
|
||||
{{!-- Skills and abilities --}}
|
||||
<div class="flex3 panel abilities">
|
||||
<div class="panel-title">
|
||||
<h4>{{localize 'OSE.panel.abilities'}}</h4>
|
||||
<div class="flex3 panel inventory abilities">
|
||||
<div>
|
||||
<li class="item-titles flexrow panel-title">
|
||||
<div class="item-name">{{localize 'OSE.panel.abilities'}} & {{localize 'OSE.panel.equipment'}}</div>
|
||||
<div class="item-controls">
|
||||
{{#if owner}}
|
||||
<a class="item-control item-create" title='{{localize "OSE.Add"}}' data-type="ability"><i class="fas fa-plus"></i></a>
|
||||
<a class="item-control item-create" title='{{localize "OSE.Add"}}' data-type="choice"
|
||||
data-choices="weapon,ability,armor,item"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="panel-content inventory resizable" data-base-size="220">
|
||||
<div class="">
|
||||
</li>
|
||||
<ol class="item-list resizable" data-base-size="240">
|
||||
{{#each abilities as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
|
|
@ -62,31 +84,17 @@
|
|||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "Ose.Edit"}}'><i
|
||||
<a class="item-control item-edit" title='{{localize "OSE.Edit"}}'><i
|
||||
class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "Ose.Delete"}}'><i
|
||||
<a class="item-control item-delete" title='{{localize "OSE.Delete"}}'><i
|
||||
class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{{!-- Equipment --}}
|
||||
<div class="flex3 panel abilities">
|
||||
<div class="panel-title">
|
||||
<h4>{{localize 'OSE.panel.equipment'}}</h4>
|
||||
<div class="item-controls">
|
||||
{{#if owner}}
|
||||
<a class="item-control item-create" title='{{localize "OSE.Add"}}' data-type="item"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="panel-content inventory resizable" data-base-size="220">
|
||||
<div class="">
|
||||
{{#each inventory as |item|}}
|
||||
{{#each owned as |section| }}
|
||||
{{#each section as |item|}}
|
||||
<li class="item-entry">
|
||||
<div class="item flexrow" data-item-id="{{item._id}}">
|
||||
<div class="item-name flexrow">
|
||||
|
|
@ -96,50 +104,61 @@
|
|||
</h4>
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "Ose.Edit"}}'><i
|
||||
{{#if ../../owner}}
|
||||
<a class="item-control item-edit" title='{{localize "OSE.Edit"}}'><i
|
||||
class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title='{{localize "Ose.Delete"}}'><i
|
||||
<a class="item-control item-delete" title='{{localize "OSE.Delete"}}'><i
|
||||
class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{{!-- Saving throws --}}
|
||||
<div class="attribute-group">
|
||||
<div class="attacks-description">
|
||||
<label>{{ localize "OSE.Attacks" }}</label>
|
||||
<input name="data.att" type="text" value="{{data.att}}" placeholder="0" data-dtype="String" />
|
||||
</div>
|
||||
<ul class="attributes">
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.death.long' }}">{{ localize "OSE.saves.death.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="death">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.death.long' }}">
|
||||
<a>{{ localize "OSE.saves.death.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.d.value" type="text" value="{{data.saves.d.value}}" placeholder="0"
|
||||
<input name="data.saves.death.value" type="text" value="{{data.saves.death.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.wands.long' }}">{{ localize "OSE.saves.wands.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="wand">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.wand.long' }}">
|
||||
<a>{{ localize "OSE.saves.wand.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.w.value" type="text" value="{{data.saves.w.value}}" placeholder="0"
|
||||
<input name="data.saves.wand.value" type="text" value="{{data.saves.wand.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.paralysis.long' }}">{{ localize "OSE.saves.paralysis.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="paralysis">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.paralysis.long' }}">
|
||||
<a>{{ localize "OSE.saves.paralysis.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.p.value" type="text" value="{{data.saves.p.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<input name="data.saves.paralysis.value" type="text" value="{{data.saves.paralysis.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.breath.long' }}">{{ localize "OSE.saves.breath.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="breath">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.breath.long' }}">
|
||||
<a>{{ localize "OSE.saves.breath.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.b.value" type="text" value="{{data.saves.b.value}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
<input name="data.saves.breath.value" type="text" value="{{data.saves.breath.value}}"
|
||||
placeholder="0" data-dtype="Number" />
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.spells.long' }}">{{ localize "OSE.saves.spells.short" }}</h4>
|
||||
<li class="attribute saving-throw" data-save="spell">
|
||||
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.spell.long' }}">
|
||||
<a>{{ localize "OSE.saves.spell.long" }}</a></h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.saves.s.value" type="text" value="{{data.saves.s.value}}" placeholder="0" />
|
||||
<input name="data.saves.spell.value" type="text" value="{{data.saves.spell.value}}"
|
||||
placeholder="0" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,10 +31,12 @@
|
|||
placeholder="{{ localize 'OSE.Experience' }}" />
|
||||
<label>{{localize 'OSE.Experience'}}</label>
|
||||
</li>
|
||||
{{#if config.morale}}
|
||||
<li>
|
||||
<input type="text" name="data.details.morale" value="{{data.details.morale}}"
|
||||
placeholder="{{ localize 'OSE.Morale' }}" />
|
||||
<label>{{localize 'OSE.Morale'}}</label>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<div class="ose chat-card item-card" data-actor-id="{{actor._id}}" data-item-id="{{item._id}}"
|
||||
{{#if tokenId}}data-token-id="{{tokenId}}"{{/if}}>
|
||||
<header class="card-header flexrow">
|
||||
<img src="{{item.img}}" title="{{item.name}}" width="36" height="36"/>
|
||||
<h3 class="item-name">{{item.name}}</h3>
|
||||
</header>
|
||||
|
||||
<div class="card-content">
|
||||
{{{data.description}}}
|
||||
</div>
|
||||
|
||||
<div class="card-buttons">
|
||||
{{#if hasAttack}}<button data-action="attack">{{ localize "OSE.Attack" }}</button>{{/if}}
|
||||
|
||||
{{#if hasDamage}}
|
||||
<button data-action="damage">
|
||||
{{#if isHealing}}{{ localize "OSE.Healing" }}
|
||||
{{else}}{{localize "OSE.Damage" }}{{/if}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if hasSave}}
|
||||
<button data-action="save" data-ability="{{data.save.ability}}" disabled>
|
||||
{{ localize "OSE.SavingThrow" }} {{labels.save}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if data.formula}}
|
||||
<button data-action="formula">{{ localize "OSE.OtherFormula"}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<footer class="card-footer">
|
||||
{{#each data.properties}}
|
||||
<span>{{this}}</span>
|
||||
{{/each}}
|
||||
</footer>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<section class="ose chat-message">
|
||||
<div class="ose chat-block">
|
||||
<h2 class="chat-title">{{title}}</h2>
|
||||
{{#if details}}<div class="chat-details">{{{details}}}</div>{{/if}}
|
||||
{{#if rollOSE}}<div>{{{rollOSE}}}</div>{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<form>
|
||||
<div class="form-group">
|
||||
<label>{{localize "OSE.Formula"}}</label>
|
||||
<input type="text" name="formula" value="{{formula}}" disabled />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "OSE.SitMod"}}</label>
|
||||
<input type="text" name="bonus" value="" placeholder="{{localize 'OSE.RollExample'}}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "OSE.RollMode"}}</label>
|
||||
<select name="rollMode">
|
||||
{{#select rollMode}}
|
||||
{{#each rollModes as |label mode|}}
|
||||
<option value="{{mode}}">{{localize label}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -3,17 +3,30 @@
|
|||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<div class="header-col">
|
||||
<h1 class="charname">
|
||||
<input
|
||||
name="name"
|
||||
type="text"
|
||||
value="{{item.name}}"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<input name="name" type="text" value="{{item.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
{{editor content=data.description target="data.description"
|
||||
button=true owner=owner editable=editable}}
|
||||
<div class="flexrow">
|
||||
<div class="stats">
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.abilities.Requirements'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.requirements" value="{{data.requirements}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.items.Roll'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.roll" value="{{data.roll}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{editor content=data.description target="data.description" button=true
|
||||
owner=owner editable=editable}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<div class="header-col">
|
||||
<h1 class="charname">
|
||||
<input name="name" type="text" value="{{item.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
<div class="flexrow">
|
||||
<div class="stats">
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.ArmorAC'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.level" value="{{data.ac}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.ArmorAAC'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.class" value="{{data.aac}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Cost'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.cost" value="{{data.cost}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Weight'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.weight" value="{{data.weight}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{editor content=data.description target="data.description" button=true
|
||||
owner=owner editable=editable}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
|
@ -3,17 +3,36 @@
|
|||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<div class="header-col">
|
||||
<h1 class="charname">
|
||||
<input
|
||||
name="name"
|
||||
type="text"
|
||||
value="{{item.name}}"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<input name="name" type="text" value="{{item.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
{{editor content=data.description target="data.description"
|
||||
button=true owner=owner editable=editable}}
|
||||
<div class="flexrow">
|
||||
<div class="stats">
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Quantity'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.quantity.value" value="{{data.quantity.value}}" data-dtype="Number" />/<input type="text" name="data.quantity.max" value="{{data.quantity.max}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Cost'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.cost" value="{{data.cost}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Weight'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.weight" value="{{data.weight}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description weapon-editor">
|
||||
{{editor content=data.description target="data.description" button=true
|
||||
owner=owner editable=editable}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
|
@ -3,17 +3,48 @@
|
|||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<div class="header-col">
|
||||
<h1 class="charname">
|
||||
<input
|
||||
name="name"
|
||||
type="text"
|
||||
value="{{item.name}}"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<input name="name" type="text" value="{{item.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
{{editor content=data.description target="data.description"
|
||||
button=true owner=owner editable=editable}}
|
||||
<div class="flexrow">
|
||||
<div class="stats">
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.spells.Level'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.lvl" value="{{data.lvl}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.spells.Class'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.class" value="{{data.class}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.spells.Range'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.range" value="{{data.range}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.spells.Duration'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.duration" value="{{data.duration}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.items.Roll'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.roll" value="{{data.roll}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{editor content=data.description target="data.description" button=true
|
||||
owner=owner editable=editable}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<div class="header-col">
|
||||
<h1 class="charname">
|
||||
<input name="name" type="text" value="{{item.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
<div class="flexrow">
|
||||
<input name="data.qualities" type="text" value="{{data.qualities}}" placeholder="Qualities" />
|
||||
</div>
|
||||
<div class="flexrow">
|
||||
<div class="stats">
|
||||
<div class="form-group block-input">
|
||||
<label>{{localize 'OSE.items.Damage'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.damage" value="{{data.damage}}" data-dtype="String" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Slow'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="checkbox" name="data.slow" value="{{data.level}}" {{checked data.slow}} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Missile'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="checkbox" name="data.missile" {{checked data.missile}} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Melee'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="checkbox" name="data.melee" {{checked data.melee}} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Cost'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.cost" value="{{data.cost}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize 'OSE.items.Weight'}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.weight" value="{{data.weight}}" data-dtype="Number" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description weapon-editor">
|
||||
{{editor content=data.description target="data.description" button=true
|
||||
owner=owner editable=editable}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
Loading…
Reference in New Issue