Implement the most basic version of a dice pool configuration
This commit is contained in:
parent
c62d3cae2f
commit
a95412ad2e
19 changed files with 465 additions and 30 deletions
|
|
@ -6,3 +6,6 @@ Soetarman Atmodjo:
|
||||||
|
|
||||||
SuperNdre:
|
SuperNdre:
|
||||||
- icons/edit.svg (https://thenounproject.com/icon/edit-5208207/) : Rights Purchased
|
- icons/edit.svg (https://thenounproject.com/icon/edit-5208207/) : Rights Purchased
|
||||||
|
|
||||||
|
YANDI RS:
|
||||||
|
- icons/d8-outline (https://thenounproject.com/icon/d8-7272826/) : Rights Purchased
|
||||||
3
assets/icons/d8-outline.svg
Normal file
3
assets/icons/d8-outline.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m51.176 1.332 20.191 11.656 0.11719 0.074219 20.094 11.602c0.73438 0.42188 1.1445 1.1914 1.1484 1.9844h0.007813v46.699c0 0.92578-0.55078 1.7266-1.3438 2.0898l-20.027 11.562 0.003907 0.007812-20.223 11.672c-0.74219 0.43359-1.6328 0.39453-2.3203-0.015626l-20.191-11.656-0.11719-0.074218-20.094-11.602c-0.73438-0.42188-1.1445-1.1914-1.1484-1.9844h-0.007813v-46.699c0-0.92578 0.55078-1.7266 1.3438-2.0898l20.027-11.562-0.003907-0.007813 20.223-11.672c0.74219-0.43359 1.6328-0.39453 2.3203 0.015625zm4.4375 7.8516 16.27 28.18 0.003907-0.003906 16.262 28.168v-37.562l-18.945-10.938-0.12891-0.070313zm26.922 66.09h-65.066l13.332 7.6953 0.12891 0.070312 19.074 11.012 19.074-11.012 0.003906 0.007813 13.457-7.7695zm-70.676-9.7461 16.262-28.168 0.070312-0.12109 16.199-28.055-13.461 7.7734-0.003907-0.007812-19.07 11.012v37.562zm56.066-25.879-17.918-31.035-17.852 30.918-0.070312 0.12891-17.914 31.027h71.66l-17.914-31.027 0.003906-0.003906-0.003906-0.007812z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
|
|
@ -90,7 +90,18 @@
|
||||||
"long-range": "Long @RipCrypt.common.range",
|
"long-range": "Long @RipCrypt.common.range",
|
||||||
"current-wear": "Current @RipCrypt.common.wear",
|
"current-wear": "Current @RipCrypt.common.wear",
|
||||||
"max-wear": "Maximum @RipCrypt.common.wear",
|
"max-wear": "Maximum @RipCrypt.common.wear",
|
||||||
"location-placeholder": "New Location..."
|
"location-placeholder": "New Location...",
|
||||||
|
"numberOfDice": "# of Dice",
|
||||||
|
"rollTarget": "Target",
|
||||||
|
"difficulty": "(DC: {dc})"
|
||||||
|
},
|
||||||
|
"notifs": {
|
||||||
|
"error": {
|
||||||
|
"invalid-delta": "The delta for \"{name}\" is not a number, cannot finish processing the action."
|
||||||
|
},
|
||||||
|
"warn": {
|
||||||
|
"cannot-go-negative": "\"{name}\" is unable to be a negative number."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
158
module/Apps/DicePool.mjs
Normal file
158
module/Apps/DicePool.mjs
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
import { filePath } from "../consts.mjs";
|
||||||
|
import { GenericAppMixin } from "./GenericApp.mjs";
|
||||||
|
import { localizer } from "../utils/Localizer.mjs";
|
||||||
|
import { Logger } from "../utils/Logger.mjs";
|
||||||
|
|
||||||
|
const { Roll } = foundry.dice;
|
||||||
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
export class DicePool extends GenericAppMixin(HandlebarsApplicationMixin(ApplicationV2)) {
|
||||||
|
// #region Options
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: [
|
||||||
|
`ripcrypt--DicePool`,
|
||||||
|
],
|
||||||
|
window: {
|
||||||
|
title: `Dice Pool`,
|
||||||
|
frame: true,
|
||||||
|
positioned: true,
|
||||||
|
resizable: false,
|
||||||
|
minimizable: true,
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
width: `auto`,
|
||||||
|
height: `auto`,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
diceCountDelta: this.#diceCountDelta,
|
||||||
|
targetDelta: this.#targetDelta,
|
||||||
|
roll: this.#roll,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
numberOfDice: {
|
||||||
|
template: filePath(`templates/Apps/DicePool/numberOfDice.hbs`),
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
template: filePath(`templates/Apps/DicePool/target.hbs`),
|
||||||
|
},
|
||||||
|
buttons: {
|
||||||
|
template: filePath(`templates/Apps/DicePool/buttons.hbs`),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Instance Data
|
||||||
|
_diceCount;
|
||||||
|
_target;
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
diceCount = 1,
|
||||||
|
target,
|
||||||
|
flavor = ``,
|
||||||
|
...opts
|
||||||
|
} = {}) {
|
||||||
|
super(opts);
|
||||||
|
|
||||||
|
this._flavor = flavor;
|
||||||
|
this._diceCount = diceCount;
|
||||||
|
this._target = target ?? game.settings.get(`ripcrypt`, `dc`) ?? 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
if (!this._flavor) {
|
||||||
|
return super.title;
|
||||||
|
}
|
||||||
|
return `${super.title}: ${this._flavor}`;
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Lifecycle
|
||||||
|
async _preparePartContext(partId, ctx, _opts) {
|
||||||
|
ctx = {};
|
||||||
|
|
||||||
|
switch (partId) {
|
||||||
|
case `numberOfDice`: {
|
||||||
|
this._prepareNumberOfDice(ctx);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case `target`: {
|
||||||
|
this._prepareTarget(ctx);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case `buttons`: {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug(`${partId} Context:`, ctx);
|
||||||
|
return ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareNumberOfDice(ctx) {
|
||||||
|
ctx.numberOfDice = this._diceCount;
|
||||||
|
ctx.decrementDisabled = this._diceCount <= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareTarget(ctx) {
|
||||||
|
ctx.target = this._target;
|
||||||
|
ctx.incrementDisabled = this._target >= 8;
|
||||||
|
ctx.decrementDisabled = this._target <= 1;
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
static async #diceCountDelta(_event, element) {
|
||||||
|
const delta = parseInt(element.dataset.delta);
|
||||||
|
if (Number.isNaN(delta)) {
|
||||||
|
ui.notifications.error(
|
||||||
|
localizer(`RipCrypt.notifs.error.invalid-delta`, { name: `@RipCrypt.Apps.numberOfDice` }),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let newCount = this._diceCount + delta;
|
||||||
|
|
||||||
|
if (newCount < 0) {
|
||||||
|
ui.notifications.warn(
|
||||||
|
localizer(`RipCrypt.notifs.warn.cannot-go-negative`, { name: `@RipCrypt.Apps.numberOfDice` }),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._diceCount = Math.max(newCount, 0);
|
||||||
|
this.render({ parts: [`numberOfDice`] });
|
||||||
|
};
|
||||||
|
|
||||||
|
static async #targetDelta(_event, element) {
|
||||||
|
const delta = parseInt(element.dataset.delta);
|
||||||
|
if (Number.isNaN(delta)) {
|
||||||
|
ui.notifications.error(
|
||||||
|
localizer(`RipCrypt.notifs.error.invalid-delta`, { name: `@RipCrypt.Apps.rollTarget` }),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
this._target += delta;
|
||||||
|
this.render({ parts: [`target`] });
|
||||||
|
};
|
||||||
|
|
||||||
|
static async #roll() {
|
||||||
|
const formula = `${this._diceCount}d8rc${this._target}`;
|
||||||
|
Logger.debug(`Attempting to roll formula: ${formula}`);
|
||||||
|
|
||||||
|
let flavor = this._flavor;
|
||||||
|
if (this._flavor) {
|
||||||
|
flavor += ` ` + localizer(`RipCrypt.Apps.difficulty`, { dc: this._target });
|
||||||
|
}
|
||||||
|
|
||||||
|
const roll = new Roll(formula);
|
||||||
|
await roll.evaluate();
|
||||||
|
await roll.toMessage({
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
flavor,
|
||||||
|
});
|
||||||
|
this.close();
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import { localizer } from "../utils/Localizer.mjs";
|
import { DicePool } from "./DicePool.mjs";
|
||||||
import { Logger } from "../utils/Logger.mjs";
|
|
||||||
|
|
||||||
const { Roll } = foundry.dice;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mixin that takes the class from HandlebarsApplicationMixin and
|
* A mixin that takes the class from HandlebarsApplicationMixin and
|
||||||
|
|
@ -46,20 +43,11 @@ export function GenericAppMixin(HandlebarsApp) {
|
||||||
/** @this {GenericRipCryptApp} */
|
/** @this {GenericRipCryptApp} */
|
||||||
static async rollDice(_$e, el) {
|
static async rollDice(_$e, el) {
|
||||||
const data = el.dataset;
|
const data = el.dataset;
|
||||||
const formula = data.formula;
|
const diceCount = parseInt(data.diceCount);
|
||||||
Logger.debug(`Attempting to roll formula: ${formula}`);
|
const flavor = data.flavor;
|
||||||
|
|
||||||
let flavor;
|
const dp = new DicePool({ diceCount, flavor });
|
||||||
if (data.flavor) {
|
dp.render({ force: true });
|
||||||
flavor = localizer(data.flavor);
|
|
||||||
}
|
|
||||||
|
|
||||||
const roll = new Roll(formula);
|
|
||||||
await roll.evaluate();
|
|
||||||
await roll.toMessage({
|
|
||||||
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
|
||||||
flavor,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
};
|
};
|
||||||
|
|
|
||||||
55
module/Apps/elements/RipCryptBorder.mjs
Normal file
55
module/Apps/elements/RipCryptBorder.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { StyledShadowElement } from "./mixins/StyledShadowElement.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attributes:
|
||||||
|
*/
|
||||||
|
export class RipCryptBorder extends StyledShadowElement(HTMLElement) {
|
||||||
|
static elementName = `rc-border`;
|
||||||
|
static formAssociated = false;
|
||||||
|
|
||||||
|
/* Stuff for the mixin to use */
|
||||||
|
static _stylePath = `css/components/rc-border.css`;
|
||||||
|
#container;
|
||||||
|
|
||||||
|
_mounted = false;
|
||||||
|
async connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (this._mounted) { return };
|
||||||
|
|
||||||
|
/*
|
||||||
|
This converts all of the double-dash prefixed properties on the element to
|
||||||
|
CSS variables so that they don't all need to be provided by doing style=""
|
||||||
|
*/
|
||||||
|
for (const attrVar of this.attributes) {
|
||||||
|
if (attrVar.name?.startsWith(`var:`)) {
|
||||||
|
const prop = attrVar.name.replace(`var:`, ``);
|
||||||
|
this.style.setProperty(`--` + prop, attrVar.value);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
this.#container = document.createElement(`div`);
|
||||||
|
this.#container.classList = `rc-border`;
|
||||||
|
|
||||||
|
const titleContainer = document.createElement(`div`);
|
||||||
|
titleContainer.classList = `title`;
|
||||||
|
const titleSlot = document.createElement(`slot`);
|
||||||
|
titleSlot.innerHTML = `No Title`;
|
||||||
|
titleSlot.name = `title`;
|
||||||
|
titleContainer.appendChild(titleSlot.cloneNode(true));
|
||||||
|
this.#container.appendChild(titleContainer.cloneNode(true));
|
||||||
|
|
||||||
|
const contentSlot = document.createElement(`slot`);
|
||||||
|
contentSlot.name = `content`;
|
||||||
|
this.#container.appendChild(contentSlot.cloneNode(true));
|
||||||
|
|
||||||
|
this._shadow.appendChild(this.#container);
|
||||||
|
|
||||||
|
this._mounted = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
if (!this._mounted) { return };
|
||||||
|
this._mounted = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import { Logger } from "../../utils/Logger.mjs";
|
import { Logger } from "../../utils/Logger.mjs";
|
||||||
|
import { RipCryptBorder } from "./RipCryptBorder.mjs";
|
||||||
import { RipCryptIcon } from "./Icon.mjs";
|
import { RipCryptIcon } from "./Icon.mjs";
|
||||||
import { RipCryptSVGLoader } from "./svgLoader.mjs";
|
import { RipCryptSVGLoader } from "./svgLoader.mjs";
|
||||||
|
|
||||||
const components = [
|
const components = [
|
||||||
RipCryptIcon,
|
RipCryptIcon,
|
||||||
RipCryptSVGLoader,
|
RipCryptSVGLoader,
|
||||||
|
RipCryptBorder,
|
||||||
];
|
];
|
||||||
|
|
||||||
export function registerCustomComponents() {
|
export function registerCustomComponents() {
|
||||||
|
|
|
||||||
22
module/api.mjs
Normal file
22
module/api.mjs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { CombinedHeroSheet } from "./Apps/ActorSheets/CombinedHeroSheet.mjs";
|
||||||
|
import { DicePool } from "./Apps/DicePool.mjs";
|
||||||
|
import { HeroSkillsCardV1 } from "./Apps/ActorSheets/HeroSkillsCardV1.mjs";
|
||||||
|
import { HeroSummaryCardV1 } from "./Apps/ActorSheets/HeroSummaryCardV1.mjs";
|
||||||
|
|
||||||
|
const { deepFreeze } = foundry.utils;
|
||||||
|
|
||||||
|
Object.defineProperty(
|
||||||
|
globalThis,
|
||||||
|
`ripcrypt`,
|
||||||
|
{
|
||||||
|
value: deepFreeze({
|
||||||
|
Apps: {
|
||||||
|
DicePool,
|
||||||
|
CombinedHeroSheet,
|
||||||
|
HeroSummaryCardV1,
|
||||||
|
HeroSkillsCardV1,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
writable: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
@ -2,3 +2,6 @@
|
||||||
import "./hooks/init.mjs";
|
import "./hooks/init.mjs";
|
||||||
import "./hooks/ready.mjs";
|
import "./hooks/ready.mjs";
|
||||||
import "./hooks/hotReload.mjs";
|
import "./hooks/hotReload.mjs";
|
||||||
|
|
||||||
|
// Global API
|
||||||
|
import "./api.mjs";
|
||||||
|
|
|
||||||
8
module/settings/metaSettings.mjs
Normal file
8
module/settings/metaSettings.mjs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
export function registerMetaSettings() {
|
||||||
|
game.settings.register(`ripcrypt`, `dc`, {
|
||||||
|
scope: `world`,
|
||||||
|
type: Number,
|
||||||
|
config: false,
|
||||||
|
requiresReload: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
8
templates/Apps/DicePool/buttons.hbs
Normal file
8
templates/Apps/DicePool/buttons.hbs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="button-row">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-action="roll"
|
||||||
|
>
|
||||||
|
Roll
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
33
templates/Apps/DicePool/numberOfDice.hbs
Normal file
33
templates/Apps/DicePool/numberOfDice.hbs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<rc-border
|
||||||
|
var:border-color="var(--accent-1)"
|
||||||
|
var:padding-top="16px"
|
||||||
|
>
|
||||||
|
<div slot="title">
|
||||||
|
{{ rc-i18n "RipCrypt.Apps.numberOfDice" }}
|
||||||
|
</div>
|
||||||
|
<div slot="content" class="d8-incrementer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-action="diceCountDelta"
|
||||||
|
data-delta="1"
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
<div class="dice-count-row">
|
||||||
|
<rc-icon
|
||||||
|
name="icons/d8-outline"
|
||||||
|
var:size="35px"
|
||||||
|
var:fill="var(--accent-1)"
|
||||||
|
></rc-icon>
|
||||||
|
<span><span aria-hidden="true">x</span>{{ numberOfDice }}</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-action="diceCountDelta"
|
||||||
|
data-delta="-1"
|
||||||
|
{{#if decrementDisabled}}disabled{{/if}}
|
||||||
|
>
|
||||||
|
-
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</rc-border>
|
||||||
68
templates/Apps/DicePool/style.css
Normal file
68
templates/Apps/DicePool/style.css
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
.ripcrypt.ripcrypt--DicePool {
|
||||||
|
> .window-content {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
grid-template-rows: auto min-content;
|
||||||
|
background: var(--base-background);
|
||||||
|
padding: 8px;
|
||||||
|
gap: 8px;
|
||||||
|
width: 250px;
|
||||||
|
height: 185px;
|
||||||
|
}
|
||||||
|
|
||||||
|
--button-background: var(--alt-row-background);
|
||||||
|
--button-text: var(--alt-row-text);
|
||||||
|
button {
|
||||||
|
border-radius: 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 4px 8px;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.d8-incrementer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-count-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-target {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: white;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-row {
|
||||||
|
--button-background: var(--header-background);
|
||||||
|
--button-text: var(--header-text);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
templates/Apps/DicePool/target.hbs
Normal file
32
templates/Apps/DicePool/target.hbs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<rc-border
|
||||||
|
var:border-color="var(--accent-1)"
|
||||||
|
var:padding-top="16px"
|
||||||
|
>
|
||||||
|
<div slot="title">Target</div>
|
||||||
|
<div slot="content" class="d8-incrementer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-action="targetDelta"
|
||||||
|
data-delta="1"
|
||||||
|
{{#if incrementDisabled}}disabled{{/if}}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
<div class="dice-target">
|
||||||
|
<rc-icon
|
||||||
|
name="icons/d8-outline"
|
||||||
|
var:size="35px"
|
||||||
|
var:fill="var(--accent-1)"
|
||||||
|
></rc-icon>
|
||||||
|
<div class="value">{{target}}</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-action="targetDelta"
|
||||||
|
data-delta="-1"
|
||||||
|
{{#if decrementDisabled}}disabled{{/if}}
|
||||||
|
>
|
||||||
|
-
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</rc-border>
|
||||||
|
|
@ -261,8 +261,8 @@
|
||||||
type="button"
|
type="button"
|
||||||
class="roll icon"
|
class="roll icon"
|
||||||
data-action="roll"
|
data-action="roll"
|
||||||
data-formula="{{ability.value}}d8rc4"
|
data-dice-count="{{ability.value}}"
|
||||||
data-flavor="{{ability.name}} Roll (Difficulty: 4)"
|
data-flavor="{{ability.name}} Roll"
|
||||||
>
|
>
|
||||||
<rc-icon
|
<rc-icon
|
||||||
var:size="20px"
|
var:size="20px"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
@import url("./AllItemSheetV1/style.css");
|
@import url("./AllItemSheetV1/style.css");
|
||||||
@import url("./CombinedHeroSheet/style.css");
|
@import url("./CombinedHeroSheet/style.css");
|
||||||
|
@import url("./DicePool/style.css");
|
||||||
@import url("./HeroSummaryCardV1/style.css");
|
@import url("./HeroSummaryCardV1/style.css");
|
||||||
@import url("./HeroSkillsCardV1/style.css");
|
@import url("./HeroSkillsCardV1/style.css");
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
.ripcrypt {
|
.ripcrypt {
|
||||||
.window-content {
|
.window-content {
|
||||||
|
flex: initial;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
37
templates/css/components/rc-border.css
Normal file
37
templates/css/components/rc-border.css
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
--vertical-displacement: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rc-border {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
padding: var(--padding, 4px);
|
||||||
|
border-width: 2px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
position: relative;
|
||||||
|
margin-top: var(--margin-top, var(--vertical-displacement));
|
||||||
|
padding-top: var(--padding-top, var(--vertical-displacement));
|
||||||
|
|
||||||
|
.title {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(-1 * var(--vertical-displacement));
|
||||||
|
left: 50%;
|
||||||
|
height: minmax(var(--title-height, 20px), auto);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--title-background, var(--border-color));
|
||||||
|
padding: 4px 6px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: max-content;
|
||||||
|
max-width: 75%;
|
||||||
|
min-width: 50px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
.ripcrypt > .window-content button {
|
.ripcrypt > .window-content button {
|
||||||
all: revert;
|
all: revert;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
background: var(--button-background);
|
background: var(--button-background);
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
|
|
||||||
&.icon {
|
|
||||||
padding: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
@ -20,5 +14,13 @@
|
||||||
&:disabled {
|
&:disabled {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.icon {
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue