WIP: Counters

master
U~man 2020-07-02 23:00:45 +02:00
parent c8be217e7e
commit 2dfdfdf986
10 changed files with 117 additions and 58 deletions

BIN
src/assets/heart_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
src/assets/heart_full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
src/assets/shield.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -53,6 +53,7 @@
"OSE.saves.spell.long": "Rod, Staff, Spell", "OSE.saves.spell.long": "Rod, Staff, Spell",
"OSE.Health": "Hit Points", "OSE.Health": "Hit Points",
"OSE.HealthMax": "Maximum Hit Points",
"OSE.HealthShort": "HP", "OSE.HealthShort": "HP",
"OSE.HitDice": "Hit Dice", "OSE.HitDice": "Hit Dice",
"OSE.HitDiceShort": "HD", "OSE.HitDiceShort": "HD",

18
src/module/helpers.js Normal file
View File

@ -0,0 +1,18 @@
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("counter", function (status, value, max) {
return status ? Math.clamped((100.0 * value) / max, 0, 100) : Math.clamped(100 - (100.0 * value) / max, 0, 100);
});
};

View File

@ -7,19 +7,7 @@ import { OseActor } from "./module/actor/entity.js";
import { OseItem } from "./module/item/entity.js"; import { OseItem } from "./module/item/entity.js";
import { OSE } from "./module/config.js"; import { OSE } from "./module/config.js";
import { registerSettings } from './module/settings.js'; import { registerSettings } from './module/settings.js';
import { registerHelpers } from './module/helpers.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);
});
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
@ -37,6 +25,9 @@ Hooks.once("init", async function () {
CONFIG.OSE = OSE; CONFIG.OSE = OSE;
// Custom Handlebars helpers
registerHelpers();
// Register custom system settings // Register custom system settings
registerSettings(); registerSettings();

View File

@ -81,8 +81,7 @@
.item { .item {
padding: 2px; padding: 2px;
&.active { &.active {
background: $colorTan; background: $colorCrimson;
text-shadow: none;
} }
} }
} }
@ -96,7 +95,7 @@
padding: 0; padding: 0;
.attribute { .attribute {
position: relative; position: relative;
margin: 10px 2px; margin: 10px;
border: 1px solid $colorTan; border: 1px solid $colorTan;
.attribute-name { .attribute-name {
color: whitesmoke; color: whitesmoke;
@ -109,6 +108,9 @@
padding: 4px; padding: 4px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
&.multiple input {
min-width: 28px;
}
} }
.attribute-mod { .attribute-mod {
position: absolute; position: absolute;
@ -120,6 +122,7 @@
} }
} }
.attribute-group { .attribute-group {
flex: 0 0 105px;
.attributes { .attributes {
.attribute { .attribute {
display: flex; display: flex;
@ -128,6 +131,17 @@
width: 40px; width: 40px;
margin: 0; margin: 0;
line-height: 28px; line-height: 28px;
a {
margin: auto;
}
}
&.saving-throw .attribute-name {
line-height: 16px;
width: 80px;
}
.attribute-value {
width: 45px;
flex-grow: 0;
} }
} }
} }

View File

@ -25,6 +25,45 @@
/* Sheet Body */ /* Sheet Body */
/* ----------------------------------------- */ /* ----------------------------------------- */
.sheet-body { .sheet-body {
.health {
&.armor-class {
background: url('/systems/ose/assets/shield.png') no-repeat center;
background-size: 90px;
}
margin: 10px 0;
height: 90px;
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: 28px;
width: 70px;
left: calc(50% - 35px);
}
.health-bottom {
border-bottom: none;
position: absolute;
bottom: 12px;
width: 40px;
right: calc(50% + -20px);
}
.health-empty {
background: url('/systems/ose/assets/heart_empty.png') no-repeat center;
background-size: 90px;
background-position: top;
}
.health-full {
background: url('/systems/ose/assets/heart_full.png') no-repeat center;
background-size: 90px;
background-position: bottom;
}
}
.inventory { .inventory {
overflow: auto; overflow: auto;
.header-spells { .header-spells {

View File

@ -3,7 +3,7 @@
/* Sheet Styles */ /* Sheet Styles */
/* ----------------------------------------- */ /* ----------------------------------------- */
$colorDark: #191813; $colorDark: rgba(0, 0, 0, 0.9);
$colorFaint: #c9c7b8; $colorFaint: #c9c7b8;
$colorBeige: #b5b3a4; $colorBeige: #b5b3a4;
$colorTan: #7a7971; $colorTan: #7a7971;

View File

@ -1,38 +1,11 @@
<section class="flexrow"> <section class="flexrow">
<ul class="attributes flexrow"> <ul class="attributes flexrow">
<li class="attribute"> <li class="attribute">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.HitDice' }}">{{ localize "OSE.HitDiceShort" }}</h4> <h4 class="attribute-name box-title" title="{{ localize 'OSE.HitDice' }}">{{ localize "OSE.HitDiceShort" }}
<div class="attribute-value">
<input name="data.hp.hd" type="text" value="{{data.hp.hd}}" placeholder="0"
data-dtype="String" />
</div>
</li>
<li class="attribute health">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Health' }}">{{ localize "OSE.HealthShort" }}
</h4> </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">
{{#if config.ascendingAC}}
<h4 class="attribute-name box-title" title="{{ localize 'OSE.ArmorClass' }}">
{{ localize "OSE.AscArmorClassShort" }}</h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.aac.value" type="text" value="{{data.aac.value}}" data-dtype="Number" placeholder="10" <input name="data.hp.hd" type="text" value="{{data.hp.hd}}" placeholder="0" data-dtype="String" />
data-dtype="Number" />
</div> </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>
<li class="attribute"> <li class="attribute">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.Thac0' }}">{{ localize "OSE.Thac0" }}</h4> <h4 class="attribute-name box-title" title="{{ localize 'OSE.Thac0' }}">{{ localize "OSE.Thac0" }}</h4>
@ -62,7 +35,8 @@
</li> </li>
{{/if}} {{/if}}
<li class="attribute"> <li class="attribute">
<h4 class="attribute-name box-title">{{ localize "OSE.MovementShort" }}</h4> <h4 class="attribute-name box-title" title="{{ localize 'OSE.Movement' }}">
{{ localize "OSE.MovementShort" }}</h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.movement.value" type="text" value="{{data.movement.value}}" placeholder="0" <input name="data.movement.value" type="text" value="{{data.movement.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
@ -80,7 +54,7 @@
<div class="attribute-value"> <div class="attribute-value">
<input name="data.scores.str.value" type="text" value="{{data.scores.str.value}}" placeholder="0" <input name="data.scores.str.value" type="text" value="{{data.scores.str.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
<span class="attribute-mod">{{mods.str}}</span> <span class="attribute-mod">{{mods.str}}</span>
</li> </li>
<li class="attribute ability-score" data-score="int"> <li class="attribute ability-score" data-score="int">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.int.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.int.long' }}">
@ -88,7 +62,7 @@
<div class="attribute-value"> <div class="attribute-value">
<input name="data.scores.int.value" type="text" value="{{data.scores.int.value}}" placeholder="0" <input name="data.scores.int.value" type="text" value="{{data.scores.int.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
<span class="attribute-mod">{{mods.int}}</span> <span class="attribute-mod">{{mods.int}}</span>
</li> </li>
<li class="attribute ability-score" data-score="wis"> <li class="attribute ability-score" data-score="wis">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.wis.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.wis.long' }}">
@ -96,7 +70,7 @@
<div class="attribute-value"> <div class="attribute-value">
<input name="data.scores.wis.value" type="text" value="{{data.scores.wis.value}}" placeholder="0" <input name="data.scores.wis.value" type="text" value="{{data.scores.wis.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
<span class="attribute-mod">{{mods.wis}}</span> <span class="attribute-mod">{{mods.wis}}</span>
</li> </li>
<li class="attribute ability-score" data-score="dex"> <li class="attribute ability-score" data-score="dex">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.dex.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.dex.long' }}">
@ -104,7 +78,7 @@
<div class="attribute-value"> <div class="attribute-value">
<input name="data.scores.dex.value" type="text" value="{{data.scores.dex.value}}" placeholder="0" <input name="data.scores.dex.value" type="text" value="{{data.scores.dex.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
<span class="attribute-mod">{{mods.dex}}</span> <span class="attribute-mod">{{mods.dex}}</span>
</li> </li>
<li class="attribute ability-score" data-score="con"> <li class="attribute ability-score" data-score="con">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.con.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.con.long' }}">
@ -112,7 +86,7 @@
<div class="attribute-value"> <div class="attribute-value">
<input name="data.scores.con.value" type="text" value="{{data.scores.con.value}}" placeholder="0" <input name="data.scores.con.value" type="text" value="{{data.scores.con.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
<span class="attribute-mod">{{mods.con}}</span> <span class="attribute-mod">{{mods.con}}</span>
</li> </li>
<li class="attribute ability-score" data-score="cha"> <li class="attribute ability-score" data-score="cha">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.cha.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.scores.cha.long' }}">
@ -120,44 +94,66 @@
<div class="attribute-value"> <div class="attribute-value">
<input name="data.scores.cha.value" type="text" value="{{data.scores.cha.value}}" placeholder="0" <input name="data.scores.cha.value" type="text" value="{{data.scores.cha.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
<span class="attribute-mod">{{mods.cha}}</span> <span class="attribute-mod">{{mods.cha}}</span>
</li> </li>
</ul> </ul>
</div> </div>
{{!-- Resource Tracking --}}
<div class="flex2">
<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 9 mods.dex}}" title="{{localize 'OSE.ArmorClass'}}" disabled/>
{{/if}}
</div>
</div>
{{!-- Saving throws --}} {{!-- Saving throws --}}
<div class="attribute-group"> <div class="attribute-group">
<ul class="attributes"> <ul class="attributes">
<li class="attribute saving-throw" data-save="death"> <li class="attribute saving-throw" data-save="death">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.death.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.death.long' }}">
<a>{{ localize "OSE.saves.death.short" }}</a></h4> <a>{{ localize "OSE.saves.death.long" }}</a></h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.saves.death.value" type="text" value="{{data.saves.death.value}}" placeholder="0" <input name="data.saves.death.value" type="text" value="{{data.saves.death.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
</li> </li>
<li class="attribute saving-throw" data-save="wand"> <li class="attribute saving-throw" data-save="wand">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.wand.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.wand.long' }}">
<a>{{ localize "OSE.saves.wand.short" }}</a></h4> <a>{{ localize "OSE.saves.wand.long" }}</a></h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.saves.wand.value" type="text" value="{{data.saves.wand.value}}" placeholder="0" <input name="data.saves.wand.value" type="text" value="{{data.saves.wand.value}}" placeholder="0"
data-dtype="Number" /> data-dtype="Number" />
</li> </li>
<li class="attribute saving-throw" data-save="paralysis"> <li class="attribute saving-throw" data-save="paralysis">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.paralysis.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.paralysis.long' }}">
<a>{{ localize "OSE.saves.paralysis.short" }}</a></h4> <a>{{ localize "OSE.saves.paralysis.long" }}</a></h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.saves.paralysis.value" type="text" value="{{data.saves.paralysis.value}}" <input name="data.saves.paralysis.value" type="text" value="{{data.saves.paralysis.value}}"
placeholder="0" data-dtype="Number" /> placeholder="0" data-dtype="Number" />
</li> </li>
<li class="attribute saving-throw" data-save="breath"> <li class="attribute saving-throw" data-save="breath">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.breath.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.breath.long' }}">
<a>{{ localize "OSE.saves.breath.short" }}</a></h4> <a>{{ localize "OSE.saves.breath.long" }}</a></h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.saves.breath.value" type="text" value="{{data.saves.breath.value}}" <input name="data.saves.breath.value" type="text" value="{{data.saves.breath.value}}"
placeholder="0" data-dtype="Number" /> placeholder="0" data-dtype="Number" />
</li> </li>
<li class="attribute saving-throw" data-save="spell"> <li class="attribute saving-throw" data-save="spell">
<h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.spell.long' }}"> <h4 class="attribute-name box-title" title="{{ localize 'OSE.saves.spell.long' }}">
<a>{{ localize "OSE.saves.spell.short" }}</a></h4> <a>{{ localize "OSE.saves.spell.long" }}</a></h4>
<div class="attribute-value"> <div class="attribute-value">
<input name="data.saves.spell.value" type="text" value="{{data.saves.spell.value}}" <input name="data.saves.spell.value" type="text" value="{{data.saves.spell.value}}"
placeholder="0" /> placeholder="0" />