Skip to content

Commit

Permalink
Feat/actor crafting app salvage (#231)
Browse files Browse the repository at this point in the history
  • Loading branch information
misterpotts authored Nov 14, 2023
1 parent 4a27cda commit 306d6ad
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 75 deletions.
2 changes: 1 addition & 1 deletion docs/_config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
title: Fabricate 0.10.12
title: Fabricate 0.10.13
email: [email protected]
description: >-
End user documentation for the Foundry Virtual Tabletop (VTT) Module, "Fabricate".
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fabricate",
"version": "0.10.12",
"version": "0.10.13",
"description": "A system-agnostic, flexible crafting module for FoundryVT",
"main": "index.js",
"type": "module",
Expand Down
42 changes: 38 additions & 4 deletions src/applications/actorCraftingApp/ActorCraftingApp.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@
import {onMount} from "svelte";
import type {CraftingAssessment} from "./CraftingAssessment";
import {type CraftingProcess, DefaultCraftingProcess, NoCraftingProcess} from "./CraftingProcess";
import {NoSalvageProcess, type SalvageOption, type SalvageProcess} from "./SalvageProcess";
import {NoSalvageProcess, type SalvageProcess} from "./SalvageProcess";
import type {SalvageAssessment} from "./SalvageAssessment";
import {DefaultSalvageProcess} from "./SalvageProcess.js";
import ActorCraftingAppHeader from "./ActorCraftingAppHeader.svelte";
import RecipeCraftingProcess from "./RecipeCraftingProcess.svelte";
import ComponentSalvageProcess from "./ComponentSalvageProcess.svelte";
import ActorInventoryBrowser from "./ActorInventoryBrowser.svelte";
import {DefaultSelectableOptions} from "../../scripts/common/SelectableOptions";
/*
* ===========================================================================
Expand All @@ -42,6 +40,7 @@
* ===========================================================================
*/
let batchSize: number = 1;
let targetActorDetails: ActorDetails = new PendingActorDetails({id: targetActorId})
let sourceActorDetails: ActorDetails = new PendingActorDetails({id: sourceActorId ?? targetActorId});
let craftingProcess: CraftingProcess = new NoCraftingProcess();
Expand Down Expand Up @@ -89,10 +88,43 @@
await load();
}
async function salvageComponent(event: CustomEvent<SalvageProcess>) {
const salvageResult = await fabricateAPI.crafting.salvageComponent({
sourceActorId: sourceActorDetails.id,
targetActorId: targetActorDetails.id,
componentId: event.detail.componentId,
salvageOptionId: event.detail.selectedOption.id,
batchSize: batchSize < event.detail.ownedQuantity ? batchSize : event.detail.ownedQuantity
});
await load();
if (salvageResult.remaining.isEmpty()) {
salvageProcess = new NoSalvageProcess();
return;
}
salvageProcess = await fabricateAPI.crafting.getSalvageProcess({
componentId: event.detail.componentId,
actorId: sourceActorDetails.id
});
}
function onKeyDown(event: KeyboardEvent) {
if (event.shiftKey) {
batchSize = 5;
}
}
function onKeyUp(event: KeyboardEvent) {
if (!event.shiftKey) {
batchSize = 1;
}
}
onMount(load);
</script>

<svelte:window on:keydown={onKeyDown} on:keyup={onKeyUp} />

<div class="flex flex-col w-full h-full">
<ActorCraftingAppHeader localization={localization}
targetActorDetails={targetActorDetails}
Expand All @@ -103,7 +135,9 @@
bind:craftingProcess={craftingProcess} />
{:else if salvageProcess.isReady}
<ComponentSalvageProcess localization={localization}
bind:salvageProcess={salvageProcess} />
bind:salvageProcess={salvageProcess}
on:salvageComponent={salvageComponent}
batchSize={batchSize} />
{:else}
<ActorInventoryBrowser localization={localization}
bind:craftingAssessments={craftingAssessments}
Expand Down
28 changes: 14 additions & 14 deletions src/applications/actorCraftingApp/ActorInventoryBrowser.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@

<div class="flex flex-row h-full">
<div class="flex flex-col w-4/5 p-4 h-[654px]">
<h2 class="text-center text-xl pb-4">Recipes</h2>
<h2 class="text-center text-xl pb-4 text-white">Recipes</h2>
<div class="bg-surface-700 text-white grid grid-cols-3 grid-rows-1 p-4 gap-2 h-[64px] rounded-md">
<div class="row-span-1 col-span-2 pb-1">
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
Expand Down Expand Up @@ -136,15 +136,15 @@
</div>
{#if craftingAssessment.isDisabled}
<div class="absolute e w-3/12 h-full bg-black bg-opacity-50 flex justify-center items-center">
<span class="text-warning-900 text-2xl badge-icon variant-filled-warning w-10 h-10">
<i class="fa-solid fa-lock"></i>
</span>
<span class="text-warning-900 text-2xl badge-icon variant-filled-warning w-10 h-10">
<i class="fa-solid fa-lock"></i>
</span>
</div>
{:else if !craftingAssessment.isCraftable}
<div class="absolute w-3/12 h-full bg-black bg-opacity-50 flex justify-center items-center">
<span class="text-error-900 text-2xl badge-icon variant-filled-error w-10 h-10">
<i class="fa-solid fa-circle-xmark"></i>
</span>
<span class="text-error-900 text-2xl badge-icon variant-filled-error w-10 h-10">
<i class="fa-solid fa-circle-xmark"></i>
</span>
</div>
{/if}
</div>
Expand All @@ -164,7 +164,7 @@
</div>
</div>
<div class="flex flex-col w-2/5 p-4 h-[654px]">
<h2 class="text-center text-xl pb-4">Components</h2>
<h2 class="text-center text-xl pb-4 text-white">Components</h2>
<div class="bg-surface-700 text-white grid grid-cols-2 grid-rows-3 p-4 gap-2 h-[156px] rounded-md">
<div class="row-span-1 col-span-2 pb-1">
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
Expand Down Expand Up @@ -197,13 +197,13 @@
class:cursor-pointer={salvageAssessment.hasSalvage}
on:click={() => startSalvageProcess(salvageAssessment)}>
{#if salvageAssessment.isSalvageable}
<span class="text-black text-lg badge-icon variant-filled-tertiary w-6 h-6 absolute left-1 top-1 z-10" data-tooltip="Salvageable">
<i class="fa-solid fa-recycle"></i>
</span>
<span class="text-black text-lg badge-icon variant-filled-success w-6 h-6 absolute left-1 top-1 z-10" data-tooltip="Salvageable">
<i class="fa-solid fa-recycle"></i>
</span>
{:else if salvageAssessment.hasSalvage}
<span class="text-error-900 text-lg badge-icon variant-filled-error w-6 h-6 absolute left-1 top-1 z-10" data-tooltip="Not salvageable">
<i class="fa-solid fa-recycle"></i>
</span>
<span class="text-black text-lg badge-icon variant-filled-error w-6 h-6 absolute left-1 top-1 z-10" data-tooltip="Not salvageable">
<i class="fa-solid fa-recycle"></i>
</span>
{/if}
<Avatar src="{salvageAssessment.imageUrl}"
fallback="{Properties.ui.defaults.componentImageUrl}"
Expand Down
122 changes: 105 additions & 17 deletions src/applications/actorCraftingApp/ComponentSalvageProcess.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import type {LocalizationService} from "../common/LocalizationService";
import Properties from "../../scripts/Properties";
import truncate from "../common/Truncate";
import {createEventDispatcher} from "svelte";
/*
* ===========================================================================
Expand All @@ -20,15 +21,19 @@
export let localization: LocalizationService;
export let salvageProcess: SalvageProcess = new NoSalvageProcess();
export let batchSize: number = 1;
/*
* ===========================================================================
* Private component properties
* ===========================================================================
*/
const dispatch = createEventDispatcher();
$: displayAmount = calculateDisplayAmount(batchSize, salvageProcess.ownedQuantity);
let selectedSalvageOption: SalvageOption = salvageProcess.selectedOption;
$: salvageProcessProducts = selectedSalvageOption.products;
$: salvageProcessCatalysts = selectedSalvageOption.catalysts;
$: selectedOptionName = selectedSalvageOption.name;
/*
Expand All @@ -53,18 +58,42 @@
window.open(Properties.module.repository.bugReportUrl, '_blank').focus();
}
function runSalvageProcess(salvageProcess: SalvageProcess) {
dispatch("salvageComponent", salvageProcess);
}
function calculateDisplayAmount(batchSize, ownedQuantity) {
if (batchSize <= 1 || ownedQuantity <= 1) {
return ""
}
if (ownedQuantity >= batchSize) {
return `(${batchSize})`
}
return `(${ownedQuantity})`
}
</script>

<AppBar background="bg-surface-700 text-white">
<svelte:fragment slot="lead">
<i class="fa-solid fa-circle-arrow-left text-lg text-primary-500 cursor-pointer" on:click={clearSalvageProcess}></i>
<i class="fa-solid fa-circle-arrow-left text-xl text-primary-500 cursor-pointer" on:click={clearSalvageProcess}></i>
</svelte:fragment>
<h2 class="text-lg">Salvaging {salvageProcess.componentName}</h2>
<div class="flex flex-row items-center">
<Avatar class="mr-2 ml-2 flex"
src="{salvageProcess.componentImageUrl}"
alt="{salvageProcess.componentName}"
fallback="{Properties.ui.defaults.componentImageUrl}"
width="w-10"
rounded="rounded-lg"/>
<span class="text-lg flex">Salvaging {salvageProcess.componentName} ({salvageProcess.ownedQuantity})</span>
</div>
<svelte:fragment slot="trail">
{#if salvageProcess.canStart}
<a class="btn variant-filled-success text-black"><i class="fa-solid fa-screwdriver-wrench mr-2"></i> Salvage</a>
<a class="btn variant-filled bg-primary-500 text-black" on:click={() => runSalvageProcess(salvageProcess)}>
<i class="fa-solid fa-screwdriver-wrench mr-2"></i> Salvage {displayAmount}
</a>
{:else}
<a class="btn variant-ghost-error text-error-600 cursor-not-allowed"> <i class="fa-solid fa-ban mr-2"></i>Salvage</a>
<a class="btn variant-ghost-error text-error-600 cursor-not-allowed"><i class="fa-solid fa-ban mr-2"></i> Salvage</a>
{/if}
</svelte:fragment>
</AppBar>
Expand Down Expand Up @@ -95,37 +124,96 @@
{:else}
<div class="flex flex-col p-4 h-full w-full">
{#if salvageProcess.hasOptions}
<div class="flex text-lg flex-row border-b border-surface-400">
<div class="flex text-lg flex-row items-center border-b border-surface-400 pb-4 mb-4 text-white">
<div class="flex flex-1 justify-start">
<a class="btn" on:click={selectPreviousOption}>
<a class="btn variant-filled bg-surface-600 border border-surface-400" on:click={selectPreviousOption}>
<i class="fa-solid fa-arrow-left mr-2"></i> Previous option
</a>
</div>
<div class="flex flex-1 justify-center">
{selectedOptionName}
</div>
<div class="flex flex-1 justify-end">
<a class="btn" on:click={selectNextOption}>
<a class="btn variant-filled bg-surface-600 border border-surface-400" on:click={selectNextOption}>
Next option <i class="fa-solid fa-arrow-right ml-2"></i>
</a>
</div>
</div>
{/if}
{#if selectedSalvageOption.requiresCatalysts}
<div class="flex flex-row w-full h-full">
<div class="flex flex-col w-1/2 h-full">
<h3>Products</h3>
<p>The following products are obtained by salvaging this component.</p>
<div class="flex flex-col w-2/3 h-full">
<div class="pb-8 text-white">
<h3 class="text-lg mb-2">Products</h3>
<p>The following products are obtained by salvaging this component.</p>
</div>
<div class="grid grid-cols-2 grid-rows-4 h-full gap-4">
{#each salvageProcessProducts.units as productUnit}
{#await productUnit.element.load()}
Loading...
{:then loadedComponent}
<div class="card snap-start h-full bg-surface-700 flex flex-row col-span-1 row-span-1 relative">
<Avatar class=""
src="{loadedComponent.imageUrl}"
alt="{loadedComponent.name}"
fallback="{Properties.ui.defaults.componentImageUrl}"
width="w-24"
rounded="rounded-r-none rounded-l-md"/>
{#if productUnit.quantity > 1}
<span class="text-black badge-icon text-lg font-light variant-filled-secondary w-7 h-7 absolute left-2 top-2 z-10">
{productUnit.quantity}
</span>
{/if}
<div class="flex flex-col p-2">
<p class="text-white mb-2 font-bold">
{truncate(loadedComponent.name, 18, 12)}
</p>
</div>
</div>
{/await}
{/each}
</div>
</div>
<div class="flex flex-col w-1/2 h-full">
<h3>Catalysts</h3>
<p>The following catalysts are required to salvage this component.</p>
<div class="flex flex-col w-1/3 h-full pl-8">
<div class="pb-4 text-white">
<h3 class="text-lg mb-2">Catalysts</h3>
<p>The following catalysts are required to salvage this component.</p>
</div>
<div class="grid grid-cols-1 grid-rows-4 h-full gap-4">
{#each salvageProcessCatalysts.units as catalystUnit}
{#await catalystUnit.target.element.load()}
Loading...
{:then loadedComponent}
<div class="card snap-start h-full bg-surface-700 flex flex-row col-span-1 row-span-1 relative">
<Avatar src="{loadedComponent.imageUrl}"
alt="{loadedComponent.name}"
fallback="{Properties.ui.defaults.componentImageUrl}"
width="w-24"
rounded="rounded-r-none rounded-l-md"/>
{#if catalystUnit.isSufficient}
<span class="absolute bottom-0 left-0 rounded-bl-lg w-24 bg-success-500 text-center text-black font-bold h-5 leading-5">
{catalystUnit.actual.quantity} / {catalystUnit.target.quantity}
</span>
{:else}
<span class="absolute bottom-0 left-0 rounded-bl-lg w-24 bg-error-500 text-center text-black font-bold h-5 leading-5">
{catalystUnit.actual.quantity} / {catalystUnit.target.quantity}
</span>
{/if}
<div class="flex flex-col p-2">
<p class="text-white mb-2 font-bold">
{truncate(loadedComponent.name, 18, 12)}
</p>
</div>
</div>
{/await}
{/each}
</div>
</div>
</div>
{:else}
<div class="pb-8 text-white">
<h3 class="text-lg mb-2">Products</h3>
<p class="">Salvaging this component produces the following components.</p>
<p>Salvaging this component produces the following components.</p>
</div>
<div class="overflow-y-auto overflow-x-hidden h-full snap-y snap-mandatory scroll-smooth scroll-secondary scroll-px-4">
<div class="grid grid-cols-3 grid-rows-4 h-full gap-4">
Expand All @@ -141,9 +229,9 @@
width="w-24"
rounded="rounded-r-none rounded-l-md"/>
{#if productUnit.quantity > 1}
<span class="text-error-900 text-lg badge-icon variant-filled-error w-6 h-6 absolute left-1 top-1 z-10" data-tooltip="Not salvageable">
<i class="fa-solid fa-recycle"></i>
</span>
<span class="text-black badge-icon text-lg font-light variant-filled-secondary w-7 h-7 absolute left-2 top-2 z-10">
{productUnit.quantity}
</span>
{/if}
<div class="flex flex-col p-2">
<p class="text-white mb-2 font-bold">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
</script>

<AppBar background="bg-surface-700 text-white">
<svelte:fragment slot="lead"><i class="fa-solid fa-circle-arrow-left text-lg text-primary-500 cursor-pointer" on:click={clearCraftingProcess}></i></svelte:fragment>
<svelte:fragment slot="lead">
<i class="fa-solid fa-circle-arrow-left text-xl text-primary-500 cursor-pointer" on:click={clearCraftingProcess}></i>
</svelte:fragment>
<h2 class="text-lg">Crafting {craftingProcess.recipeName}</h2>
</AppBar>
Loading

0 comments on commit 306d6ad

Please sign in to comment.