Add rest dice tracking for the Sync actors
This commit is contained in:
parent
4544516c5c
commit
1002b1387c
8 changed files with 186 additions and 24 deletions
|
|
@ -1,37 +1,47 @@
|
||||||
const statDice = [ `d4`, `d6`, `d8`, `d10`, `d12`, `d20` ];
|
export const statDice = [ `d4`, `d6`, `d8`, `d10`, `d12`, `d20` ];
|
||||||
|
|
||||||
const trainingLevels = [``, `locked`, `+2`, `+4`];
|
export const trainingLevels = [``, `locked`, `+2`, `+4`];
|
||||||
|
|
||||||
const damageTypes = [ `slashing`, `piercing`, `smashing`, `gun`, `neon`, `shadow`, `solar` ];
|
export const damageTypes = [ `slashing`, `piercing`, `smashing`, `gun`, `neon`, `shadow`, `solar` ];
|
||||||
|
|
||||||
const ammoTypes = [`quivers`, `mags`, `cells`];
|
export const ammoTypes = [`quivers`, `mags`, `cells`];
|
||||||
|
|
||||||
const stats = [ `build`, `meta`, `presence`, `hands`, `tilt`, `rng` ];
|
export const stats = [ `build`, `meta`, `presence`, `hands`, `tilt`, `rng` ];
|
||||||
|
|
||||||
const buildSkills = [ `defense`, `magic`, `melee`, `platforming`, `strength`, ];
|
export const buildSkills = [ `defense`, `magic`, `melee`, `platforming`, `strength`, ];
|
||||||
const metaSkills = [ `alchemy`, `arcanum`, `dreams`, `lore`, `navigation`, ];
|
export const metaSkills = [ `alchemy`, `arcanum`, `dreams`, `lore`, `navigation`, ];
|
||||||
const presenceSkills = [ `animal_handling`, `perception`, `sneak`, `speech`, `vibes`, ];
|
export const presenceSkills = [ `animal_handling`, `perception`, `sneak`, `speech`, `vibes`, ];
|
||||||
const handsSkills = [ `accuracy`, `crafting`, `engineering`, `explosives`, `piloting`, ];
|
export const handsSkills = [ `accuracy`, `crafting`, `engineering`, `explosives`, `piloting`, ];
|
||||||
|
|
||||||
const allSkills = [
|
export const allSkills = [
|
||||||
...buildSkills,
|
...buildSkills,
|
||||||
...metaSkills,
|
...metaSkills,
|
||||||
...presenceSkills,
|
...presenceSkills,
|
||||||
...handsSkills,
|
...handsSkills,
|
||||||
];
|
];
|
||||||
|
|
||||||
const skills = {
|
export const skills = {
|
||||||
build: buildSkills,
|
build: buildSkills,
|
||||||
meta: metaSkills,
|
meta: metaSkills,
|
||||||
presence: presenceSkills,
|
presence: presenceSkills,
|
||||||
hands: handsSkills,
|
hands: handsSkills,
|
||||||
};
|
};
|
||||||
|
|
||||||
const itemTiers = [
|
export const itemTiers = [
|
||||||
`simple`, `greater`,
|
`simple`, `greater`,
|
||||||
`rare`, `legendary`
|
`rare`, `legendary`
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const syncMilestones = [
|
||||||
|
{ value: 20, andReturn: true },
|
||||||
|
{ value: 40, andReturn: false },
|
||||||
|
{ value: 60, andReturn: true },
|
||||||
|
{ value: 80, andReturn: false },
|
||||||
|
{ value: 100, andReturn: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const syncDice = "1d20";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
stats,
|
stats,
|
||||||
statDice,
|
statDice,
|
||||||
|
|
@ -45,4 +55,6 @@ export default {
|
||||||
allSkills,
|
allSkills,
|
||||||
skills,
|
skills,
|
||||||
itemTiers,
|
itemTiers,
|
||||||
};
|
syncMilestones,
|
||||||
|
syncDice,
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import PlayerActor from "./Player.mjs";
|
import PlayerActor from "./Player.mjs";
|
||||||
import MobActor from "./Mob.mjs";
|
import MobActor from "./Mob.mjs";
|
||||||
|
import SyncActor from "./Sync.mjs";
|
||||||
|
|
||||||
/** @extends {Actor} */
|
/** @extends {Actor} */
|
||||||
export class ActorHandler extends Actor {
|
export class ActorHandler extends Actor {
|
||||||
proxyTargets = {
|
proxyTargets = {
|
||||||
player: PlayerActor,
|
player: PlayerActor,
|
||||||
mob: MobActor,
|
mob: MobActor,
|
||||||
|
sync: SyncActor,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(data, ctx) {
|
constructor(data, ctx) {
|
||||||
|
|
@ -89,4 +91,10 @@ export class ActorHandler extends Actor {
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_preUpdate(...args) {
|
||||||
|
return this.proxyFunction("_preUpdate", ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
useRestDie() { return this.proxyFunction("useRestDie"); };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
60
module/documents/Actor/Sync.mjs
Normal file
60
module/documents/Actor/Sync.mjs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { syncMilestones, syncDice } from "../../config.mjs";
|
||||||
|
|
||||||
|
/** @this {Actor} */
|
||||||
|
async function useRestDie() {
|
||||||
|
let addToSync = await (new Roll(syncDice)).evaluate();
|
||||||
|
await addToSync.toMessage({
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
flavor: `Sync Restoration`,
|
||||||
|
});
|
||||||
|
this.update({
|
||||||
|
"system.rest_dice": this.system.rest_dice - 1,
|
||||||
|
"system.value": this.system.value + addToSync.total,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @this {Actor} */
|
||||||
|
async function _preUpdate(data, options) {
|
||||||
|
if (options.diff) {
|
||||||
|
if (data.system?.value != null) {
|
||||||
|
let currentSync = this.system.value;
|
||||||
|
let newSync = data.system.value;
|
||||||
|
|
||||||
|
let minSync = Math.min(currentSync, newSync);
|
||||||
|
let maxSync = Math.max(currentSync, newSync);
|
||||||
|
let milestones = syncMilestones.filter(
|
||||||
|
m => minSync < m.value && m.value <= maxSync
|
||||||
|
);
|
||||||
|
|
||||||
|
if (milestones.length > 0) data.system.rest_dice ??= this.system.rest_dice;
|
||||||
|
|
||||||
|
for (const milestone of milestones) {
|
||||||
|
// Damage
|
||||||
|
if (newSync < currentSync) {
|
||||||
|
if (!this.system.milestones_hit.has(milestone.value)) {
|
||||||
|
data.system.rest_dice += 1;
|
||||||
|
this.system.milestones_hit.add(milestone.value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Healing
|
||||||
|
else if (newSync > currentSync) {
|
||||||
|
if (
|
||||||
|
this.system.milestones_hit.has(milestone.value)
|
||||||
|
&& milestone.andReturn
|
||||||
|
&& milestone.value <= newSync
|
||||||
|
) {
|
||||||
|
this.system.milestones_hit.delete(milestone.value);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
data.system.milestones_hit = [ ...this.system.milestones_hit ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
_preUpdate,
|
||||||
|
useRestDie,
|
||||||
|
};
|
||||||
|
|
@ -3,10 +3,18 @@ export class SyncData extends foundry.abstract.TypeDataModel {
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
return {
|
return {
|
||||||
value: new fields.NumberField({
|
value: new fields.NumberField({
|
||||||
required: true,
|
|
||||||
integer: true,
|
integer: true,
|
||||||
initial: 100,
|
initial: 100,
|
||||||
}),
|
}),
|
||||||
|
rest_dice: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
min: 0,
|
||||||
|
}),
|
||||||
|
milestones_hit: new fields.SetField(
|
||||||
|
new fields.NumberField({ integer: true, }),
|
||||||
|
{ initial: [] },
|
||||||
|
),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export class AbstractSyncSheet extends GenericActorSheet {
|
||||||
super.defaultOptions,
|
super.defaultOptions,
|
||||||
{
|
{
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 200,
|
height: 275,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
opts.classes.push(
|
opts.classes.push(
|
||||||
|
|
@ -22,11 +22,12 @@ export class AbstractSyncSheet extends GenericActorSheet {
|
||||||
|
|
||||||
ctx.system = actor.system;
|
ctx.system = actor.system;
|
||||||
ctx.flags = actor.flags;
|
ctx.flags = actor.flags;
|
||||||
|
|
||||||
console.groupCollapsed(`SyncSheet.getData`);
|
|
||||||
console.log(`ctx`, ctx);
|
|
||||||
console.log(`actor`, actor);
|
|
||||||
console.groupEnd();
|
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
html.find(`.use-rest-die`)
|
||||||
|
.on(`click`, this.actor.useRestDie.bind(this.actor));
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
@use "../vars.scss" as *;
|
@use "../vars.scss" as *;
|
||||||
|
|
||||||
|
@use "sass:color" as color;
|
||||||
|
|
||||||
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content {
|
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content {
|
||||||
button {
|
button {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
@ -21,31 +23,52 @@
|
||||||
&.confirm {
|
&.confirm {
|
||||||
background: $colour-confirm;
|
background: $colour-confirm;
|
||||||
color: $text-on-confirm;
|
color: $text-on-confirm;
|
||||||
&:hover, &:focus-visible {
|
|
||||||
|
&:hover:not(:disabled),
|
||||||
|
&:focus-visible {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: $colour-confirm;
|
color: $colour-confirm;
|
||||||
border-color: $colour-confirm;
|
border-color: $colour-confirm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: color.adjust($colour-confirm, $lightness: -10%);
|
||||||
|
color: color.adjust($text-on-confirm, $lightness: -15%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.neutral {
|
&.neutral {
|
||||||
background: $colour-neutral;
|
background: $colour-neutral;
|
||||||
color: $text-on-neutral;
|
color: $text-on-neutral;
|
||||||
&:hover, &:focus-visible {
|
|
||||||
|
&:hover:not(:disabled),
|
||||||
|
&:focus-visible {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: $colour-neutral;
|
color: $colour-neutral;
|
||||||
border-color: $colour-neutral;
|
border-color: $colour-neutral;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: color.adjust($colour-neutral, $lightness: -10%);
|
||||||
|
color: color.adjust($text-on-neutral, $lightness: -15%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.danger {
|
&.danger {
|
||||||
background: $colour-danger;
|
background: $colour-danger;
|
||||||
color: $text-on-danger;
|
color: $text-on-danger;
|
||||||
&:hover, &:focus-visible {
|
|
||||||
|
&:hover:not(:disabled),
|
||||||
|
&:focus-visible {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: $colour-danger;
|
color: $colour-danger;
|
||||||
border-color: $colour-danger;
|
border-color: $colour-danger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: color.adjust($colour-danger, $lightness: -10%);
|
||||||
|
color: color.adjust($text-on-danger, $lightness: -15%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.reduced-padding {
|
&.reduced-padding {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,22 @@
|
||||||
width: 60%;
|
width: 60%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rest-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.button-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--sync-sheet {
|
&--sync-sheet {
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,38 @@
|
||||||
value="{{system.value}}"
|
value="{{system.value}}"
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
<div class="rest-container">
|
||||||
|
Rest Dice:
|
||||||
|
<div class="button-row">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="neutral equal-padding"
|
||||||
|
data-decrement="system.rest_dice"
|
||||||
|
{{disabled (eq system.rest_dice 0)}}
|
||||||
|
>
|
||||||
|
<div aria-hidden="true" class="icon icon--14">
|
||||||
|
{{{ icons.minus }}}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<span class="value">
|
||||||
|
{{system.rest_dice}}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="neutral equal-padding"
|
||||||
|
data-increment="system.rest_dice"
|
||||||
|
>
|
||||||
|
<div aria-hidden="true" class="icon icon--14">
|
||||||
|
{{{ icons.create }}}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="confirm use-rest-die"
|
||||||
|
{{disabled (eq system.rest_dice 0)}}
|
||||||
|
>
|
||||||
|
Use a Rest Dice
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue