initial commit
This commit is contained in:
commit
91694af3e9
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Node Modules
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
7
.npmignore
Normal file
7
.npmignore
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Node Modules
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
7
.prettierrc
Normal file
7
.prettierrc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"printWidth": 120
|
||||||
|
}
|
396
css/ds4.css
Normal file
396
css/ds4.css
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Lora:wght@400;700&display=swap");
|
||||||
|
@font-face {
|
||||||
|
font-family: "Wood Stamp";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
src: local("Wood Stamp"), url("../fonts/Woodstamp.woff") format("woff");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global styles */
|
||||||
|
.window-app {
|
||||||
|
font-family: "Lora", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rollable:hover, .rollable:focus {
|
||||||
|
color: #000;
|
||||||
|
text-shadow: 0 0 10px red;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid,
|
||||||
|
.grid-2col {
|
||||||
|
display: grid;
|
||||||
|
grid-column: span 2 / span 2;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-3col {
|
||||||
|
grid-column: span 3 / span 3;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-4col {
|
||||||
|
grid-column: span 4 / span 4;
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-5col {
|
||||||
|
grid-column: span 5 / span 5;
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-6col {
|
||||||
|
grid-column: span 5 / span 5;
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-7col {
|
||||||
|
grid-column: span 7 / span 7;
|
||||||
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-8col {
|
||||||
|
grid-column: span 8 / span 8;
|
||||||
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-9col {
|
||||||
|
grid-column: span 9 / span 9;
|
||||||
|
grid-template-columns: repeat(9, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-10col {
|
||||||
|
grid-column: span 10 / span 10;
|
||||||
|
grid-template-columns: repeat(10, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-11col {
|
||||||
|
grid-column: span 11 / span 11;
|
||||||
|
grid-template-columns: repeat(11, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-12col {
|
||||||
|
grid-column: span 12 / span 12;
|
||||||
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-center,
|
||||||
|
.flex-group-left,
|
||||||
|
.flex-group-right {
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-left {
|
||||||
|
-webkit-box-pack: start;
|
||||||
|
-ms-flex-pack: start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-right {
|
||||||
|
-webkit-box-pack: end;
|
||||||
|
-ms-flex-pack: end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Flexbox */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
.flexrow {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
-ms-flex-wrap: wrap;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
-webkit-box-pack: start;
|
||||||
|
-ms-flex-pack: start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexrow > * {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexrow .flex1 {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexrow .flex2 {
|
||||||
|
-webkit-box-flex: 2;
|
||||||
|
-ms-flex: 2;
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexrow .flex3 {
|
||||||
|
-webkit-box-flex: 3;
|
||||||
|
-ms-flex: 3;
|
||||||
|
flex: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexrow .flex4 {
|
||||||
|
-webkit-box-flex: 4;
|
||||||
|
-ms-flex: 4;
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-ms-flex-wrap: nowrap;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol > * {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol .flex1 {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol .flex2 {
|
||||||
|
-webkit-box-flex: 2;
|
||||||
|
-ms-flex: 2;
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol .flex3 {
|
||||||
|
-webkit-box-flex: 3;
|
||||||
|
-ms-flex: 3;
|
||||||
|
flex: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol .flex4 {
|
||||||
|
-webkit-box-flex: 4;
|
||||||
|
-ms-flex: 4;
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-center {
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-between {
|
||||||
|
-webkit-box-pack: justify;
|
||||||
|
-ms-flex-pack: justify;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles limited to ds4 sheets */
|
||||||
|
.ds4 .window-content {
|
||||||
|
overflow-y: hidden;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .window-content form {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .window-content .tab {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
-ms-flex-line-pack: start;
|
||||||
|
align-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .item-form {
|
||||||
|
font-family: "Lora", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-header {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 210px;
|
||||||
|
flex: 0 0 210px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
-ms-flex-wrap: wrap;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
-webkit-box-pack: start;
|
||||||
|
-ms-flex-pack: start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-header .profile-img {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 100px;
|
||||||
|
flex: 0 0 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-header .header-fields {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-header h1.charname {
|
||||||
|
height: 50px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
font-family: "Wood Stamp", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-header h1.charname input {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-tabs {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0;
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .sheet-body,
|
||||||
|
.ds4 .sheet-body .tab,
|
||||||
|
.ds4 .sheet-body .tab .editor {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .tox .tox-editor-container {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .tox .tox-edit-area {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .basic-property-label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 nav.tabs {
|
||||||
|
height: 40px;
|
||||||
|
border-top: 2px groove #eeede0;
|
||||||
|
border-bottom: 2px groove #eeede0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 nav.tabs .item {
|
||||||
|
line-height: 40px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 nav.tabs .item.active {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 7px 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list .item-header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list .item {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding: 3px 0;
|
||||||
|
border-bottom: 1px solid #BBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list .item .item-image {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 24px;
|
||||||
|
flex: 0 0 24px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list .item img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list .item-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .items-list .item-controls {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 86px;
|
||||||
|
flex: 0 0 86px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .side-properties {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 150px;
|
||||||
|
flex: 0 0 150px;
|
||||||
|
margin: 5px 5px 5px 0;
|
||||||
|
padding-right: 5px;
|
||||||
|
border-right: 2px groove #eeede0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .side-properties .side-property {
|
||||||
|
margin: 0;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .side-properties .side-property label {
|
||||||
|
-webkit-box-flex: 2;
|
||||||
|
-ms-flex: 2;
|
||||||
|
flex: 2;
|
||||||
|
line-height: 26px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds4 .side-properties .side-property input {
|
||||||
|
text-align: right;
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
BIN
fonts/Woodstamp.otf
Normal file
BIN
fonts/Woodstamp.otf
Normal file
Binary file not shown.
BIN
fonts/Woodstamp.woff
Normal file
BIN
fonts/Woodstamp.woff
Normal file
Binary file not shown.
50
gulpfile.js
Normal file
50
gulpfile.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const prefix = require('gulp-autoprefixer');
|
||||||
|
const sourcemaps = require('gulp-sourcemaps');
|
||||||
|
const sass = require('gulp-sass');
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Compile Sass
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
// Small error handler helper function.
|
||||||
|
function handleError(err) {
|
||||||
|
console.log(err.toString());
|
||||||
|
this.emit('end');
|
||||||
|
}
|
||||||
|
|
||||||
|
const SYSTEM_SCSS = ["scss/**/*.scss"];
|
||||||
|
function compileScss() {
|
||||||
|
// Configure options for sass output. For example, 'expanded' or 'nested'
|
||||||
|
let options = {
|
||||||
|
outputStyle: 'expanded'
|
||||||
|
};
|
||||||
|
return gulp.src(SYSTEM_SCSS)
|
||||||
|
.pipe(
|
||||||
|
sass(options)
|
||||||
|
.on('error', handleError)
|
||||||
|
)
|
||||||
|
.pipe(prefix({
|
||||||
|
cascade: false
|
||||||
|
}))
|
||||||
|
.pipe(gulp.dest("./css"))
|
||||||
|
}
|
||||||
|
const css = gulp.series(compileScss);
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Watch Updates
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
function watchUpdates() {
|
||||||
|
gulp.watch(SYSTEM_SCSS, css);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Export Tasks
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
exports.default = gulp.series(
|
||||||
|
compileScss,
|
||||||
|
watchUpdates
|
||||||
|
);
|
||||||
|
exports.css = css;
|
15
lang/en.json
Normal file
15
lang/en.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"DS4.Description": "Description",
|
||||||
|
"DS4.Details": "Details",
|
||||||
|
"DS4.AttackType": "Attack Type",
|
||||||
|
"DS4.AttackTypeAbbr": "AT",
|
||||||
|
"DS4.WeaponBonus": "Weapon Bonus",
|
||||||
|
"DS4.WeaponBonusAbbr": "WB",
|
||||||
|
"DS4.OpponentDefense": "Opponent Defense",
|
||||||
|
"DS4.OpponentDefenseAbbr": "OD",
|
||||||
|
"DS4.AttackTypeMelee": "Melee",
|
||||||
|
"DS4.AttackTypeRanged": "Ranged",
|
||||||
|
"DS4.AttackTypeMeleeRanged": "Melee / Ranged",
|
||||||
|
"DS4.Quantity": "Quantity",
|
||||||
|
"DS4.PriceGold": "Price (Gold)"
|
||||||
|
}
|
0
lib/some-lib/some-lib.css
Normal file
0
lib/some-lib/some-lib.css
Normal file
0
lib/some-lib/some-lib.min.js
vendored
Normal file
0
lib/some-lib/some-lib.min.js
vendored
Normal file
107
module/actor/actor-sheet.js
Normal file
107
module/actor/actor-sheet.js
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
export class DS4ActorSheet extends ActorSheet {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
classes: ["ds4", "sheet", "actor"],
|
||||||
|
template: "systems/ds4/templates/actor/actor-sheet.html",
|
||||||
|
width: 600,
|
||||||
|
height: 600,
|
||||||
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
getData() {
|
||||||
|
const data = super.getData();
|
||||||
|
data.dtypes = ["String", "Number", "Boolean"];
|
||||||
|
for (let attr of Object.values(data.data.attributes)) {
|
||||||
|
attr.isCheckbox = attr.dtype === "Boolean";
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
// Everything below here is only needed if the sheet is editable
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
// Add Inventory Item
|
||||||
|
html.find('.item-create').click(this._onItemCreate.bind(this));
|
||||||
|
|
||||||
|
// Update Inventory Item
|
||||||
|
html.find('.item-edit').click(ev => {
|
||||||
|
const li = $(ev.currentTarget).parents(".item");
|
||||||
|
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||||
|
item.sheet.render(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete Inventory Item
|
||||||
|
html.find('.item-delete').click(ev => {
|
||||||
|
const li = $(ev.currentTarget).parents(".item");
|
||||||
|
this.actor.deleteOwnedItem(li.data("itemId"));
|
||||||
|
li.slideUp(200, () => this.render(false));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rollable abilities.
|
||||||
|
html.find('.rollable').click(this._onRoll.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset
|
||||||
|
* @param {Event} event The originating click event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_onItemCreate(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const header = event.currentTarget;
|
||||||
|
// Get the type of item to create.
|
||||||
|
const type = header.dataset.type;
|
||||||
|
// Grab any data associated with this control.
|
||||||
|
const data = duplicate(header.dataset);
|
||||||
|
// Initialize a default name.
|
||||||
|
const name = `New ${type.capitalize()}`;
|
||||||
|
// Prepare the item object.
|
||||||
|
const itemData = {
|
||||||
|
name: name,
|
||||||
|
type: type,
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
// Remove the type from the dataset since it's in the itemData.type prop.
|
||||||
|
delete itemData.data["type"];
|
||||||
|
|
||||||
|
// Finally, create the item!
|
||||||
|
return this.actor.createOwnedItem(itemData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle clickable rolls.
|
||||||
|
* @param {Event} event The originating click event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_onRoll(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const element = event.currentTarget;
|
||||||
|
const dataset = element.dataset;
|
||||||
|
|
||||||
|
if (dataset.roll) {
|
||||||
|
let roll = new Roll(dataset.roll, this.actor.data.data);
|
||||||
|
let label = dataset.label ? `Rolling ${dataset.label}` : '';
|
||||||
|
roll.roll().toMessage({
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
flavor: label
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
module/actor/actor.js
Normal file
37
module/actor/actor.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
|
||||||
|
* @extends {Actor}
|
||||||
|
*/
|
||||||
|
export class DS4Actor extends Actor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment the basic actor data with additional dynamic data.
|
||||||
|
*/
|
||||||
|
prepareData() {
|
||||||
|
super.prepareData();
|
||||||
|
|
||||||
|
const actorData = this.data;
|
||||||
|
const data = actorData.data;
|
||||||
|
const flags = actorData.flags;
|
||||||
|
|
||||||
|
// Make separate methods for each Actor type (character, npc, etc.) to keep
|
||||||
|
// things organized.
|
||||||
|
if (actorData.type === 'character') this._prepareCharacterData(actorData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare Character type specific data
|
||||||
|
*/
|
||||||
|
_prepareCharacterData(actorData) {
|
||||||
|
const data = actorData.data;
|
||||||
|
|
||||||
|
// Make modifications to data here. For example:
|
||||||
|
|
||||||
|
// Loop through ability scores, and add their modifiers to our sheet output.
|
||||||
|
for (let [key, ability] of Object.entries(data.abilities)) {
|
||||||
|
// Calculate the modifier using d20 rules.
|
||||||
|
ability.mod = Math.floor((ability.value - 10) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
module/config.js
Normal file
20
module/config.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
export const DS4 = {};
|
||||||
|
|
||||||
|
// ASCII Artwork
|
||||||
|
DS4.ASCII = `_____________________________________________________________________________________________
|
||||||
|
____ _ _ _ _ ____ _____ ___ _ _ ____ _ _ __ _______ ____ ____ _ _
|
||||||
|
| _ \\| | | | \\ | |/ ___| ____/ _ \\| \\ | / ___|| | / \\\\ \\ / / ____| _ \\/ ___| | || |
|
||||||
|
| | | | | | | \\| | | _| _|| | | | \\| \\___ \\| | / _ \\\\ V /| _| | |_) \\___ \\ | || |_
|
||||||
|
| |_| | |_| | |\\ | |_| | |__| |_| | |\\ |___) | |___ / ___ \\| | | |___| _ < ___) | |__ _|
|
||||||
|
|____/ \\___/|_| \\_|\\____|_____\\___/|_| \\_|____/|_____/_/ \\_\\_| |_____|_| \\_\\____/ |_|
|
||||||
|
=============================================================================================`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the set of acttack types that can be performed with weapon items
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
DS4.attackTypes = {
|
||||||
|
melee: "DS4.AttackTypeMelee",
|
||||||
|
ranged: "DS4.AttackTypeRanged",
|
||||||
|
meleeRanged: "DS4.AttackTypeMeleeRanged",
|
||||||
|
};
|
56
module/ds4.js
Normal file
56
module/ds4.js
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Import Modules
|
||||||
|
import { DS4Actor } from "./actor/actor.js";
|
||||||
|
import { DS4ActorSheet } from "./actor/actor-sheet.js";
|
||||||
|
import { DS4Item } from "./item/item.js";
|
||||||
|
import { DS4ItemSheet } from "./item/item-sheet.js";
|
||||||
|
import { DS4 } from "./config.js";
|
||||||
|
|
||||||
|
Hooks.once("init", async function () {
|
||||||
|
console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
|
||||||
|
|
||||||
|
game.ds4 = {
|
||||||
|
DS4Actor,
|
||||||
|
DS4Item,
|
||||||
|
DS4,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Record configuration
|
||||||
|
CONFIG.DS4 = DS4;
|
||||||
|
|
||||||
|
// Define custom Entity classes
|
||||||
|
CONFIG.Actor.entityClass = DS4Actor;
|
||||||
|
CONFIG.Item.entityClass = DS4Item;
|
||||||
|
|
||||||
|
// Register sheet application classes
|
||||||
|
Actors.unregisterSheet("core", ActorSheet);
|
||||||
|
Actors.registerSheet("ds4", DS4ActorSheet, { makeDefault: true });
|
||||||
|
Items.unregisterSheet("core", ItemSheet);
|
||||||
|
Items.registerSheet("ds4", DS4ItemSheet, { makeDefault: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Foundry VTT Setup */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function runs after game data has been requested and loaded from the servers, so entities exist
|
||||||
|
*/
|
||||||
|
Hooks.once("setup", function () {
|
||||||
|
// Localize CONFIG objects once up-front
|
||||||
|
const toLocalize = ["attackTypes"];
|
||||||
|
|
||||||
|
// Exclude some from sorting where the default order matters
|
||||||
|
const noSort = [];
|
||||||
|
|
||||||
|
// Localize and sort CONFIG objects
|
||||||
|
for (let o of toLocalize) {
|
||||||
|
const localized = Object.entries(CONFIG.DS4[o]).map((e) => {
|
||||||
|
return [e[0], game.i18n.localize(e[1])];
|
||||||
|
});
|
||||||
|
if (!noSort.includes(o)) localized.sort((a, b) => a[1].localeCompare(b[1]));
|
||||||
|
CONFIG.DS4[o] = localized.reduce((obj, e) => {
|
||||||
|
obj[e[0]] = e[1];
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
});
|
55
module/item/item-sheet.js
Normal file
55
module/item/item-sheet.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* Extend the basic ItemSheet with some very simple modifications
|
||||||
|
* @extends {ItemSheet}
|
||||||
|
*/
|
||||||
|
export class DS4ItemSheet extends ItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
width: 530,
|
||||||
|
height: 400,
|
||||||
|
classes: ["ds4", "sheet", "item"],
|
||||||
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
get template() {
|
||||||
|
const path = "systems/ds4/templates/item";
|
||||||
|
return `${path}/${this.item.data.type}-sheet.hbs`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
getData() {
|
||||||
|
const data = super.getData();
|
||||||
|
|
||||||
|
data.config = CONFIG.DS4;
|
||||||
|
console.log(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
setPosition(options = {}) {
|
||||||
|
const position = super.setPosition(options);
|
||||||
|
const sheetBody = this.element.find(".sheet-body");
|
||||||
|
const bodyHeight = position.height - 192;
|
||||||
|
sheetBody.css("height", bodyHeight);
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
// Everything below here is only needed if the sheet is editable
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
// Roll handlers, click handlers, etc. would go here.
|
||||||
|
}
|
||||||
|
}
|
17
module/item/item.js
Normal file
17
module/item/item.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Extend the basic Item with some very simple modifications.
|
||||||
|
* @extends {Item}
|
||||||
|
*/
|
||||||
|
export class DS4Item extends Item {
|
||||||
|
/**
|
||||||
|
* Augment the basic Item data model with additional dynamic data.
|
||||||
|
*/
|
||||||
|
prepareData() {
|
||||||
|
super.prepareData();
|
||||||
|
|
||||||
|
// Get the Item's data
|
||||||
|
const itemData = this.data;
|
||||||
|
const actorData = this.actor ? this.actor.data : {};
|
||||||
|
const data = itemData.data;
|
||||||
|
}
|
||||||
|
}
|
4079
package-lock.json
generated
Normal file
4079
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
23
package.json
Normal file
23
package.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"name": "ds4",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "CSS compiler for the Dungeonslayers 4 system",
|
||||||
|
"scripts": {
|
||||||
|
"build": "gulp",
|
||||||
|
"compile": "gulp css",
|
||||||
|
"watch": "gulp",
|
||||||
|
"gulp": "gulp"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"last 3 versions"
|
||||||
|
],
|
||||||
|
"author": "Saluu",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-autoprefixer": "^7.0.1",
|
||||||
|
"gulp-sass": "^4.1.0",
|
||||||
|
"gulp-sourcemaps": "^2.6.5"
|
||||||
|
}
|
||||||
|
}
|
16
scss/components/_apps.scss
Normal file
16
scss/components/_apps.scss
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
.window-content {
|
||||||
|
overflow-y: hidden;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
form {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
align-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
scss/components/_basic_property.scss
Normal file
4
scss/components/_basic_property.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.basic-property-label {
|
||||||
|
font-weight: bold;
|
||||||
|
// text-transform: uppercase;
|
||||||
|
}
|
23
scss/components/_description.scss
Normal file
23
scss/components/_description.scss
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
.side-properties {
|
||||||
|
flex: 0 0 150px;
|
||||||
|
margin: 5px 5px 5px 0;
|
||||||
|
padding-right: 5px;
|
||||||
|
border-right: 2px groove #eeede0;
|
||||||
|
|
||||||
|
.side-property {
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
label {
|
||||||
|
flex: 2;
|
||||||
|
line-height: 26px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
text-align: right;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
scss/components/_forms.scss
Normal file
56
scss/components/_forms.scss
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
.item-form {
|
||||||
|
font-family: $font-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-header {
|
||||||
|
flex: 0 0 210px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.profile-img {
|
||||||
|
flex: 0 0 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-fields {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.charname {
|
||||||
|
height: 50px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
font-family: $font-heading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-tabs {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-body,
|
||||||
|
.sheet-body .tab,
|
||||||
|
.sheet-body .tab .editor {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox {
|
||||||
|
.tox-editor-container {
|
||||||
|
background: $c-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox-edit-area {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
35
scss/components/_items.scss
Normal file
35
scss/components/_items.scss
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
.items-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 7px 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.item-header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding: 3px 0;
|
||||||
|
border-bottom: 1px solid #BBB;
|
||||||
|
|
||||||
|
.item-image {
|
||||||
|
flex: 0 0 24px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-controls {
|
||||||
|
flex: 0 0 86px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
14
scss/components/_tabs.scss
Normal file
14
scss/components/_tabs.scss
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
nav.tabs {
|
||||||
|
height: 40px;
|
||||||
|
border-top: 2px groove #eeede0;
|
||||||
|
border-bottom: 2px groove #eeede0;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
line-height: 40px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item.active {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
20
scss/ds4.scss
Normal file
20
scss/ds4.scss
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Import utilities.
|
||||||
|
@import "utils/typography";
|
||||||
|
@import "utils/colors";
|
||||||
|
@import "utils/mixins";
|
||||||
|
@import "utils/variables";
|
||||||
|
|
||||||
|
/* Global styles */
|
||||||
|
@import "global/window";
|
||||||
|
@import "global/grid";
|
||||||
|
@import "global/flex";
|
||||||
|
|
||||||
|
/* Styles limited to ds4 sheets */
|
||||||
|
.ds4 {
|
||||||
|
@import "components/apps";
|
||||||
|
@import "components/forms";
|
||||||
|
@import "components/basic_property";
|
||||||
|
@import "components/tabs";
|
||||||
|
@import "components/items";
|
||||||
|
@import "components/description";
|
||||||
|
}
|
60
scss/global/_flex.scss
Normal file
60
scss/global/_flex.scss
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Flexbox */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
.flexrow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.flex2 {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
.flex3 {
|
||||||
|
flex: 3;
|
||||||
|
}
|
||||||
|
.flex4 {
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexcol {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.flex2 {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
.flex3 {
|
||||||
|
flex: 3;
|
||||||
|
}
|
||||||
|
.flex4 {
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-center {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
79
scss/global/_grid.scss
Normal file
79
scss/global/_grid.scss
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
.grid,
|
||||||
|
.grid-2col {
|
||||||
|
display: grid;
|
||||||
|
grid-column: span 2 / span 2;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-3col {
|
||||||
|
grid-column: span 3 / span 3;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-4col {
|
||||||
|
grid-column: span 4 / span 4;
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-5col {
|
||||||
|
grid-column: span 5 / span 5;
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-6col {
|
||||||
|
grid-column: span 5 / span 5;
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-7col {
|
||||||
|
grid-column: span 7 / span 7;
|
||||||
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-8col {
|
||||||
|
grid-column: span 8 / span 8;
|
||||||
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-9col {
|
||||||
|
grid-column: span 9 / span 9;
|
||||||
|
grid-template-columns: repeat(9, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-10col {
|
||||||
|
grid-column: span 10 / span 10;
|
||||||
|
grid-template-columns: repeat(10, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-11col {
|
||||||
|
grid-column: span 11 / span 11;
|
||||||
|
grid-template-columns: repeat(11, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-12col {
|
||||||
|
grid-column: span 12 / span 12;
|
||||||
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-center,
|
||||||
|
.flex-group-left,
|
||||||
|
.flex-group-right {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-left {
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
12
scss/global/_window.scss
Normal file
12
scss/global/_window.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
.window-app {
|
||||||
|
font-family: $font-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rollable {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
color: #000;
|
||||||
|
text-shadow: 0 0 10px red;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
2
scss/utils/_colors.scss
Normal file
2
scss/utils/_colors.scss
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
$c-white: #fff;
|
||||||
|
$c-black: #000;
|
16
scss/utils/_mixins.scss
Normal file
16
scss/utils/_mixins.scss
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
@mixin element-invisible {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin hide {
|
||||||
|
display: none;
|
||||||
|
}
|
12
scss/utils/_typography.scss
Normal file
12
scss/utils/_typography.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Lora:wght@400;700&display=swap");
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Wood Stamp";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
src: local("Wood Stamp"), url("../fonts/Woodstamp.woff") format("woff");
|
||||||
|
}
|
||||||
|
|
||||||
|
$font-primary: "Lora", sans-serif;
|
||||||
|
$font-secondary: "Lora", sans-serif;
|
||||||
|
$font-heading: "Wood Stamp", sans-serif;
|
3
scss/utils/_variables.scss
Normal file
3
scss/utils/_variables.scss
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
$padding-sm: 5px;
|
||||||
|
$padding-md: 10px;
|
||||||
|
$padding-lg: 20px;
|
28
system.json
Normal file
28
system.json
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "ds4",
|
||||||
|
"title": "Dungeonslayers 4",
|
||||||
|
"description": "The Dungeonslayers 4 system for FoundryVTT!",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"minimumCoreVersion": "0.7.4",
|
||||||
|
"compatibleCoreVersion": "0.7.4",
|
||||||
|
"templateVersion": 2,
|
||||||
|
"author": "Saluu",
|
||||||
|
"esmodules": ["module/ds4.js"],
|
||||||
|
"styles": ["css/ds4.css"],
|
||||||
|
"scripts": [],
|
||||||
|
"packs": [],
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"lang": "en",
|
||||||
|
"name": "English",
|
||||||
|
"path": "lang/en.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gridDistance": 1,
|
||||||
|
"gridUnits": "m",
|
||||||
|
"primaryTokenAttribute": "hitPoints",
|
||||||
|
"url": "",
|
||||||
|
"manifest": "",
|
||||||
|
"download": "",
|
||||||
|
"license": "LICENSE.txt"
|
||||||
|
}
|
71
template.json
Normal file
71
template.json
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
{
|
||||||
|
"Actor": {
|
||||||
|
"types": ["character"],
|
||||||
|
"templates": {
|
||||||
|
"base": {
|
||||||
|
"health": {
|
||||||
|
"value": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 10
|
||||||
|
},
|
||||||
|
"power": {
|
||||||
|
"value": 5,
|
||||||
|
"min": 0,
|
||||||
|
"max": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"character": {
|
||||||
|
"templates": ["base"],
|
||||||
|
"biography": "",
|
||||||
|
"attributes": {
|
||||||
|
"level": {
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"abilities": {
|
||||||
|
"str": {
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"dex": {
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"con": {
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"int": {
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"wis": {
|
||||||
|
"value": 10
|
||||||
|
},
|
||||||
|
"cha": {
|
||||||
|
"value": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Item": {
|
||||||
|
"types": ["weapon", "equipment"],
|
||||||
|
"templates": {
|
||||||
|
"base": {
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"physical": {
|
||||||
|
"quantity": 1,
|
||||||
|
"price": 0,
|
||||||
|
"availability": "Hamlet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"weapon": {
|
||||||
|
"templates": ["base", "physical"],
|
||||||
|
"attackType": "melee",
|
||||||
|
"weaponBonus": 0,
|
||||||
|
"opponentDefense": 0,
|
||||||
|
"properties": {}
|
||||||
|
},
|
||||||
|
"equipment": {
|
||||||
|
"templates": ["base", "physical"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
templates/actor/actor-sheet.html
Normal file
86
templates/actor/actor-sheet.html
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<form class="{{cssClass}} flexcol" autocomplete="off">
|
||||||
|
|
||||||
|
{{!-- Sheet Header --}}
|
||||||
|
<header class="sheet-header">
|
||||||
|
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"/>
|
||||||
|
<div class="header-fields">
|
||||||
|
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
|
||||||
|
{{!-- The grid classes are defined in scss/global/_grid.scss. To use,
|
||||||
|
use both the "grid" and "grid-Ncol" class where "N" can be any number
|
||||||
|
from 1 to 12 and will create that number of columns. --}}
|
||||||
|
<div class="resources grid grid-2col">
|
||||||
|
{{!-- "flex-group-center" is also defined in the _grid.scss file
|
||||||
|
and it will add a small amount of padding, a border, and will
|
||||||
|
center all of its child elements content and text. --}}
|
||||||
|
<div class="resource flex-group-center">
|
||||||
|
<label for="data.health.value" class="resource-label">Health</label>
|
||||||
|
<div class="resource-content flexrow flex-center flex-between">
|
||||||
|
<input type="text" name="data.health.value" value="{{data.health.value}}" data-dtype="Number"/>
|
||||||
|
<span> / </span>
|
||||||
|
<input type="text" name="data.health.max" value="{{data.health.max}}" data-dtype="Number"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource flex-group-center">
|
||||||
|
<label for="data.power.value" class="resource-label">Power</label>
|
||||||
|
<div class="resource-content flexrow flex-center flex-between">
|
||||||
|
<input type="text" name="data.power.value" value="{{data.power.value}}" data-dtype="Number"/>
|
||||||
|
<span> / </span>
|
||||||
|
<input type="text" name="data.power.max" value="{{data.power.max}}" data-dtype="Number"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{!-- The grid classes are defined in scss/global/_grid.scss. To use,
|
||||||
|
use both the "grid" and "grid-Ncol" class where "N" can be any number
|
||||||
|
from 1 to 12 and will create that number of columns. --}}
|
||||||
|
<div class="abilities grid grid-3col">
|
||||||
|
{{#each data.abilities as |ability key|}}
|
||||||
|
<div class="ability flexrow flex-group-center">
|
||||||
|
<label for="data.abilities.{{key}}.value" class="resource-label">{{key}}</label>
|
||||||
|
<input type="text" name="data.abilities.{{key}}.value" value="{{ability.value}}" data-dtype="Number"/>
|
||||||
|
<span class="ability-mod rollable" data-roll="d20+@abilities.{{key}}.mod" data-label="{{key}}">{{numberFormat ability.mod decimals=0 sign=true}}</span>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{!-- Sheet Tab Navigation --}}
|
||||||
|
<nav class="sheet-tabs tabs" data-group="primary">
|
||||||
|
<a class="item" data-tab="description">Description</a>
|
||||||
|
<a class="item" data-tab="items">Items</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{{!-- Sheet Body --}}
|
||||||
|
<section class="sheet-body">
|
||||||
|
|
||||||
|
{{!-- Biography Tab --}}
|
||||||
|
<div class="tab biography" data-group="primary" data-tab="description">
|
||||||
|
{{editor content=data.biography target="data.biography" button=true owner=owner editable=editable}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Owned Items Tab --}}
|
||||||
|
<div class="tab items" data-group="primary" data-tab="items">
|
||||||
|
<ol class="items-list">
|
||||||
|
<li class="item flexrow item-header">
|
||||||
|
<div class="item-image"></div>
|
||||||
|
<div class="item-name">Name</div>
|
||||||
|
<div class="item-controls">
|
||||||
|
<a class="item-control item-create" title="Create item" data-type="item"><i class="fas fa-plus"></i> Add item</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{#each actor.items as |item id|}}
|
||||||
|
<li class="item flexrow" data-item-id="{{item._id}}">
|
||||||
|
<div class="item-image"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/></div>
|
||||||
|
<h4 class="item-name">{{item.name}}</h4>
|
||||||
|
<div class="item-controls">
|
||||||
|
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||||
|
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</form>
|
||||||
|
|
53
templates/item/weapon-sheet.hbs
Normal file
53
templates/item/weapon-sheet.hbs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<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-fields">
|
||||||
|
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1>
|
||||||
|
<div class="grid grid-3col">
|
||||||
|
<div class="basic-property">
|
||||||
|
<label class="basic-property-label">{{localize "DS4.AttackType"}}</label>
|
||||||
|
<div>{{lookup config.attackTypes data.attackType}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="basic-property">
|
||||||
|
<label class="basic-property-label">{{localize "DS4.WeaponBonus"}}</label>
|
||||||
|
<div>{{data.weaponBonus}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="basic-property">
|
||||||
|
<label class="basic-property-label">{{localize "DS4.OpponentDefense"}}</label>
|
||||||
|
<div>{{data.opponentDefense}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{!-- Sheet Tab Navigation --}}
|
||||||
|
<nav class="sheet-tabs tabs" data-group="primary">
|
||||||
|
<a class="item" data-tab="description">{{localize "DS4.Description"}}</a>
|
||||||
|
<a class="item" data-tab="details">{{localize "DS4.Details"}}</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{{!-- Sheet Body --}}
|
||||||
|
<section class="sheet-body">
|
||||||
|
|
||||||
|
{{!-- Description Tab --}}
|
||||||
|
<div class="tab flexrow" data-group="primary" data-tab="description">
|
||||||
|
<div class="side-properties">
|
||||||
|
<div class="side-property">
|
||||||
|
<label for="data.quantity">{{localize "DS4.Quantity"}}</label>
|
||||||
|
<input type="number" data-dtype="Number" name="data.quantity" value="{{data.quantity}}" />
|
||||||
|
</div>
|
||||||
|
<div class="side-property">
|
||||||
|
<label for="data.price">{{localize "DS4.PriceGold"}}</label>
|
||||||
|
<input type="number" data-dtype="Number" name="data.price" value="{{data.price}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Attributes Tab --}}
|
||||||
|
<div class="tab details" data-group="primary" data-tab="details">
|
||||||
|
{{!-- As you add new fields, add them in here! --}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</form>
|
Loading…
Reference in a new issue