Add crafts into the Combined Hero sheet
This commit is contained in:
parent
1535e07f77
commit
f6ff3247e3
6 changed files with 269 additions and 12 deletions
|
|
@ -3,6 +3,7 @@ import { GenericAppMixin } from "../GenericApp.mjs";
|
||||||
import { HeroSkillsCardV1 } from "./HeroSkillsCardV1.mjs";
|
import { HeroSkillsCardV1 } from "./HeroSkillsCardV1.mjs";
|
||||||
import { HeroSummaryCardV1 } from "./HeroSummaryCardV1.mjs";
|
import { HeroSummaryCardV1 } from "./HeroSummaryCardV1.mjs";
|
||||||
import { Logger } from "../../utils/Logger.mjs";
|
import { Logger } from "../../utils/Logger.mjs";
|
||||||
|
import { HeroCraftCardV1 } from "./HeroCraftCardV1.mjs";
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
||||||
const { ActorSheetV2 } = foundry.applications.sheets;
|
const { ActorSheetV2 } = foundry.applications.sheets;
|
||||||
|
|
@ -38,6 +39,9 @@ export class CombinedHeroSheet extends GenericAppMixin(HandlebarsApplicationMixi
|
||||||
skills: {
|
skills: {
|
||||||
template: filePath(`templates/Apps/HeroSkillsCardV1/content.hbs`),
|
template: filePath(`templates/Apps/HeroSkillsCardV1/content.hbs`),
|
||||||
},
|
},
|
||||||
|
craft: {
|
||||||
|
template: filePath(`templates/Apps/CombinedHeroSheet/crafts.hbs`),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
|
@ -64,25 +68,47 @@ export class CombinedHeroSheet extends GenericAppMixin(HandlebarsApplicationMixi
|
||||||
isEditable: this.isEditable,
|
isEditable: this.isEditable,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const craftsElement = this.element.querySelector(`.crafts-summary`);
|
||||||
|
HeroCraftCardV1._onRender.bind(this)(
|
||||||
|
context,
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
element: craftsElement,
|
||||||
|
isEditable: this.isEditable,
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
async _preparePartContext(partId, ctx, opts) {
|
async _preparePartContext(partId, ctx, opts) {
|
||||||
ctx = await super._preparePartContext(partId, ctx, opts);
|
ctx = await super._preparePartContext(partId, ctx, opts);
|
||||||
ctx.actor = this.document;
|
ctx.actor = this.document;
|
||||||
|
Logger.debug(`partID:`, partId);
|
||||||
|
|
||||||
ctx = await HeroSummaryCardV1.prepareGuts(ctx);
|
switch (partId) {
|
||||||
ctx = await HeroSummaryCardV1.prepareWeapons(ctx);
|
case `summary`: {
|
||||||
ctx = await HeroSummaryCardV1.prepareArmor(ctx);
|
ctx = await HeroSummaryCardV1.prepareGuts(ctx);
|
||||||
ctx = await HeroSummaryCardV1.prepareFatePath(ctx);
|
ctx = await HeroSummaryCardV1.prepareWeapons(ctx);
|
||||||
ctx = await HeroSummaryCardV1.prepareAbilityRow(ctx);
|
ctx = await HeroSummaryCardV1.prepareArmor(ctx);
|
||||||
ctx = await HeroSummaryCardV1.prepareSpeed(ctx);
|
ctx = await HeroSummaryCardV1.prepareFatePath(ctx);
|
||||||
ctx = await HeroSummaryCardV1.prepareLevelData(ctx);
|
ctx = await HeroSummaryCardV1.prepareAbilityRow(ctx);
|
||||||
|
ctx = await HeroSummaryCardV1.prepareSpeed(ctx);
|
||||||
|
ctx = await HeroSummaryCardV1.prepareLevelData(ctx);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case `skills`: {
|
||||||
|
ctx = await HeroSkillsCardV1.prepareGear(ctx);
|
||||||
|
ctx = await HeroSkillsCardV1.prepareAmmo(ctx);
|
||||||
|
ctx = await HeroSkillsCardV1.prepareSkills(ctx);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case `craft`: {
|
||||||
|
ctx = await HeroCraftCardV1.prepareCraft(ctx);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
ctx = await HeroSkillsCardV1.prepareGear(ctx);
|
Logger.debug(`Context keys:`, Object.keys(ctx));
|
||||||
ctx = await HeroSkillsCardV1.prepareAmmo(ctx);
|
|
||||||
ctx = await HeroSkillsCardV1.prepareSkills(ctx);
|
|
||||||
|
|
||||||
Logger.debug(`Context:`, ctx);
|
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
|
||||||
125
module/Apps/ActorSheets/HeroCraftCardV1.mjs
Normal file
125
module/Apps/ActorSheets/HeroCraftCardV1.mjs
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
import { deleteItemFromElement, editItemFromElement } from "../utils.mjs";
|
||||||
|
import { documentSorter, filePath } from "../../consts.mjs";
|
||||||
|
import { gameTerms } from "../../gameTerms.mjs";
|
||||||
|
import { GenericAppMixin } from "../GenericApp.mjs";
|
||||||
|
import { localizer } from "../../utils/Localizer.mjs";
|
||||||
|
import { Logger } from "../../utils/Logger.mjs";
|
||||||
|
|
||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
||||||
|
const { ActorSheetV2 } = foundry.applications.sheets;
|
||||||
|
const { ContextMenu } = foundry.applications.ui;
|
||||||
|
|
||||||
|
export class HeroCraftCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) {
|
||||||
|
|
||||||
|
// #region Options
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: [
|
||||||
|
`ripcrypt--actor`,
|
||||||
|
`ripcrypt--HeroCraftCardV1`,
|
||||||
|
],
|
||||||
|
position: {
|
||||||
|
width: `auto`,
|
||||||
|
height: `auto`,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
resizable: false,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
submitOnChange: true,
|
||||||
|
closeOnSubmit: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
content: {
|
||||||
|
template: filePath(`templates/Apps/HeroCraftCardV1/content.hbs`),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Lifecycle
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options);
|
||||||
|
HeroCraftCardV1._onRender.bind(this)(context, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
static async _onRender(_context, options) {
|
||||||
|
const {
|
||||||
|
element = this.element,
|
||||||
|
isEditable = this.isEditable,
|
||||||
|
} = options;
|
||||||
|
new ContextMenu(
|
||||||
|
element,
|
||||||
|
`[data-ctx-menu="craft"]`,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: localizer(`RipCrypt.common.edit`),
|
||||||
|
condition: (el) => {
|
||||||
|
const itemId = el.dataset.itemId;
|
||||||
|
return isEditable && itemId !== ``;
|
||||||
|
},
|
||||||
|
callback: editItemFromElement,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: localizer(`RipCrypt.common.delete`),
|
||||||
|
condition: (el) => {
|
||||||
|
const itemId = el.dataset.itemId;
|
||||||
|
return isEditable && itemId !== ``;
|
||||||
|
},
|
||||||
|
callback: deleteItemFromElement,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{ jQuery: false, fixed: true },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
async _preparePartContext(partId, ctx, opts) {
|
||||||
|
ctx = await super._preparePartContext(partId, ctx, opts);
|
||||||
|
ctx.actor = this.document;
|
||||||
|
|
||||||
|
ctx = await HeroCraftCardV1.prepareCraft(ctx);
|
||||||
|
|
||||||
|
Logger.debug(`Context:`, ctx);
|
||||||
|
return ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
static async prepareCraft(ctx) {
|
||||||
|
ctx.craft = {};
|
||||||
|
const aspects = Object.values(gameTerms.Aspects);
|
||||||
|
const heroRank = ctx.actor.system.level.rank;
|
||||||
|
const embeddedCrafts = ctx.actor.itemTypes.craft;
|
||||||
|
const limit = 4;
|
||||||
|
|
||||||
|
for (const aspect of aspects) {
|
||||||
|
let crafts = [];
|
||||||
|
for (const craft of embeddedCrafts) {
|
||||||
|
if (craft.system.aspect !== aspect) { continue };
|
||||||
|
crafts.push({
|
||||||
|
uuid: craft.uuid,
|
||||||
|
name: craft.name,
|
||||||
|
sort: craft.sort,
|
||||||
|
use: craft.system.advances[heroRank],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure limit isn't surpassed
|
||||||
|
const length = crafts.length;
|
||||||
|
if (length >= limit) {
|
||||||
|
crafts = crafts.slice(0, limit);
|
||||||
|
} else {
|
||||||
|
crafts = crafts
|
||||||
|
.concat(Array(limit - length).fill(null))
|
||||||
|
.slice(0, limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.craft[aspect] = crafts.sort(documentSorter);
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
// #endregion
|
||||||
|
};
|
||||||
36
templates/Apps/CombinedHeroSheet/crafts.css
Normal file
36
templates/Apps/CombinedHeroSheet/crafts.css
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
.ripcrypt.ripcrypt--CombinedHeroSheet .crafts-summary {
|
||||||
|
display: grid;
|
||||||
|
column-gap: var(--col-gap);
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 3fr));
|
||||||
|
grid-template-rows: repeat(5, minmax(0, 1fr));
|
||||||
|
grid-auto-flow: column;
|
||||||
|
|
||||||
|
.col-header {
|
||||||
|
background: var(--section-header-background);
|
||||||
|
color: var(--section-header-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
label, .label {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 2px 4px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: var(--font-size-14);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.craft-list {
|
||||||
|
grid-row: span 4;
|
||||||
|
display: contents;
|
||||||
|
|
||||||
|
> :nth-child(odd) {
|
||||||
|
background: var(--alt-row-background);
|
||||||
|
color: var(--alt-row-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.name {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
templates/Apps/CombinedHeroSheet/crafts.hbs
Normal file
67
templates/Apps/CombinedHeroSheet/crafts.hbs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
<div class="crafts-summary">
|
||||||
|
<div class="label col-header">Focus</div>
|
||||||
|
<ol class="craft-list num-before">
|
||||||
|
{{#each craft.focus as | craft |}}
|
||||||
|
{{#if craft}}
|
||||||
|
<li data-item-id="{{craft.uuid}}" data-ctx-menu="craft">
|
||||||
|
<span class="name">{{ craft.name }}</span>
|
||||||
|
{{#if craft.use}}
|
||||||
|
<rc-icon
|
||||||
|
name="icons/info-circle"
|
||||||
|
var:size="16px"
|
||||||
|
var:fill="currentColor"
|
||||||
|
data-tooltip="{{ craft.use }}"
|
||||||
|
data-tooltip-direction="UP"
|
||||||
|
></rc-icon>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li></li>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="label col-header">Fract</div>
|
||||||
|
<ol class="craft-list num-before">
|
||||||
|
{{#each craft.fract as | craft |}}
|
||||||
|
{{#if craft}}
|
||||||
|
<li data-item-id="{{craft.uuid}}" data-ctx-menu="craft">
|
||||||
|
<span class="name">{{ craft.name }}</span>
|
||||||
|
{{#if craft.use}}
|
||||||
|
<rc-icon
|
||||||
|
name="icons/info-circle"
|
||||||
|
var:size="16px"
|
||||||
|
var:fill="currentColor"
|
||||||
|
data-tooltip="{{ craft.use }}"
|
||||||
|
data-tooltip-direction="UP"
|
||||||
|
></rc-icon>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li></li>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="label col-header">Flect</div>
|
||||||
|
<ol class="craft-list num-before">
|
||||||
|
{{#each craft.flect as | craft |}}
|
||||||
|
{{#if craft}}
|
||||||
|
<li data-item-id="{{craft.uuid}}" data-ctx-menu="craft">
|
||||||
|
<span class="name">{{ craft.name }}</span>
|
||||||
|
{{#if craft.use}}
|
||||||
|
<rc-icon
|
||||||
|
name="icons/info-circle"
|
||||||
|
var:size="16px"
|
||||||
|
var:fill="currentColor"
|
||||||
|
data-tooltip="{{ craft.use }}"
|
||||||
|
data-tooltip-direction="UP"
|
||||||
|
></rc-icon>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li></li>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@import url("./crafts.css");
|
||||||
|
|
||||||
.ripcrypt.ripcrypt--CombinedHeroSheet {
|
.ripcrypt.ripcrypt--CombinedHeroSheet {
|
||||||
> .window-content {
|
> .window-content {
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
counter-increment: list-index 1;
|
counter-increment: list-index 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
padding: 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.num-before > li::before,
|
&.num-before > li::before,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue