From 23847ab7024334a7c70562e797a08b86d2bbf41a Mon Sep 17 00:00:00 2001 From: Kyle Kemp Date: Thu, 15 Aug 2024 09:50:02 -0500 Subject: [PATCH] closes #26 --- app/handlers/moddata.ts | 37 +-------- src/app/helpers/droptable.ts | 9 +- src/app/helpers/validators/item.ts | 4 +- src/app/services/electron.service.ts | 2 +- src/app/services/mod.service.ts | 22 ++--- .../input-map/input-map.component.ts | 2 +- .../input-region/input-region.component.ts | 2 +- .../droptables-editor.component.html | 83 ++++++++++++++----- .../droptables-editor.component.ts | 38 ++++++++- .../tabs/droptables/droptables.component.ts | 24 ------ src/interfaces/droptable.ts | 21 ++--- src/interfaces/modkit.ts | 21 +---- 12 files changed, 124 insertions(+), 141 deletions(-) diff --git a/app/handlers/moddata.ts b/app/handlers/moddata.ts index cc660c4..cfe0208 100644 --- a/app/handlers/moddata.ts +++ b/app/handlers/moddata.ts @@ -1,9 +1,4 @@ -import { groupBy } from 'lodash'; import { - IDroptable, - IDroptableMap, - IDroptableRegion, - IExportedModKit, IItemDefinition, IModKit, INPCDefinition, @@ -45,32 +40,6 @@ function formatNPCs(npcs: INPCDefinition[]): INPCDefinition[] { }); } -function formatDroptables(droptables: IDroptable[]): { - regions: IDroptableRegion[]; - maps: IDroptableMap[]; -} { - const globalDrops = droptables.filter((f) => f.isGlobal); - const regionDrops = groupBy( - droptables.filter((f) => f.regionName), - 'regionName' - ); - const mapDrops = groupBy( - droptables.filter((f) => f.mapName), - 'mapName' - ); - - return { - maps: Object.keys(mapDrops).map((mapName) => ({ - mapName, - drops: [...mapDrops[mapName], ...globalDrops], - })), - regions: Object.keys(regionDrops).map((regionName) => ({ - regionName, - drops: [...regionDrops[regionName], ...globalDrops], - })), - }; -} - function formatItems(items: IItemDefinition[]): IItemDefinition[] { return items.map((item: any) => { if (!item.sellValue) delete item.sellValue; @@ -109,10 +78,10 @@ function stripIds(modData: IModKit) { }); } -export function formatMod(modData: IModKit): IExportedModKit { +export function formatMod(modData: IModKit): IModKit { stripIds(modData); - const exported: IExportedModKit = { + const exported: IModKit = { meta: { ...structuredClone(modData.meta), _backup: structuredClone(modData), @@ -120,7 +89,7 @@ export function formatMod(modData: IModKit): IExportedModKit { npcs: formatNPCs(modData.npcs), items: formatItems(modData.items), - drops: formatDroptables(modData.drops), + drops: modData.drops, dialogs: modData.dialogs, maps: modData.maps, quests: modData.quests, diff --git a/src/app/helpers/droptable.ts b/src/app/helpers/droptable.ts index edb425d..1ad4d30 100644 --- a/src/app/helpers/droptable.ts +++ b/src/app/helpers/droptable.ts @@ -4,10 +4,7 @@ import { id } from './id'; export const defaultDroptable: () => IDroptable = () => ({ _id: id(), isGlobal: false, - mapName: null as unknown as string, - maxChance: 0, - noLuckBonus: false, - regionName: null as unknown as string, - requireHoliday: null as unknown as string, - result: null as unknown as string, + mapName: undefined as unknown as string, + regionName: undefined as unknown as string, + drops: [], }); diff --git a/src/app/helpers/validators/item.ts b/src/app/helpers/validators/item.ts index 8f06050..3122c94 100644 --- a/src/app/helpers/validators/item.ts +++ b/src/app/helpers/validators/item.ts @@ -61,7 +61,9 @@ export function checkItemUses(mod: IModKit): ValidationMessageGroup { // count item usages by type mod.drops.forEach((droptable) => { - addItemCount(droptable.result); + droptable.drops.forEach((drop) => { + addItemCount(drop.result); + }); }); mod.recipes.forEach((recipe) => { diff --git a/src/app/services/electron.service.ts b/src/app/services/electron.service.ts index 46b5a89..39517b1 100644 --- a/src/app/services/electron.service.ts +++ b/src/app/services/electron.service.ts @@ -69,7 +69,7 @@ export class ElectronService { }); // the mod has no backup, which means it was a clean export. it might need some reformatting to get it back in - window.api.receive('loadmod', (mod: IModKit) => { + window.api.receive('loadmod', () => { // this.modService.updateMod(mod); }); diff --git a/src/app/services/mod.service.ts b/src/app/services/mod.service.ts index c02906b..1835804 100644 --- a/src/app/services/mod.service.ts +++ b/src/app/services/mod.service.ts @@ -214,7 +214,7 @@ export class ModService { if (droptable.mapName !== oldName) return; console.log( - `[Propagate Map] Updated droptable "${droptable.result}" Map: ${oldName} -> ${newName}` + `[Propagate Map] Updated droptable "${droptable.mapName}" Map: ${oldName} -> ${newName}` ); droptable.mapName = newName; }); @@ -284,17 +284,19 @@ export class ModService { }); mod.drops.forEach((droptable) => { - if (droptable.result !== oldName) return; + droptable.drops.forEach((drop) => { + if (drop.result !== oldName) return; - console.log( - `[Propagate Item] Updated droptable for "${ - droptable.mapName || - droptable.regionName || - (droptable.isGlobal ? 'global' : '') - }" item: ${oldName} -> ${newName}` - ); + console.log( + `[Propagate Item] Updated droptable for "${ + droptable.mapName || + droptable.regionName || + (droptable.isGlobal ? 'global' : '') + }" item: ${oldName} -> ${newName}` + ); - droptable.result = newName; + drop.result = newName; + }); }); mod.quests.forEach((quest) => { diff --git a/src/app/shared/components/input-map/input-map.component.ts b/src/app/shared/components/input-map/input-map.component.ts index 428db87..dfe0a98 100644 --- a/src/app/shared/components/input-map/input-map.component.ts +++ b/src/app/shared/components/input-map/input-map.component.ts @@ -10,7 +10,7 @@ import { ModService } from '../../../services/mod.service'; export class InputMapComponent { private modService = inject(ModService); - public map = model.required(); + public map = model.required(); public change = output(); public values = computed(() => diff --git a/src/app/shared/components/input-region/input-region.component.ts b/src/app/shared/components/input-region/input-region.component.ts index 8bafa28..00d6379 100644 --- a/src/app/shared/components/input-region/input-region.component.ts +++ b/src/app/shared/components/input-region/input-region.component.ts @@ -10,7 +10,7 @@ import { ModService } from '../../../services/mod.service'; export class InputRegionComponent { private modService = inject(ModService); - public region = model.required(); + public region = model.required(); public change = output(); public values = computed(() => diff --git a/src/app/tabs/droptables/droptables-editor/droptables-editor.component.html b/src/app/tabs/droptables/droptables-editor/droptables-editor.component.html index bd12d6e..9ab921d 100644 --- a/src/app/tabs/droptables/droptables-editor/droptables-editor.component.html +++ b/src/app/tabs/droptables/droptables-editor/droptables-editor.component.html @@ -11,10 +11,6 @@
-
- -
-
- Chance to Drop (1/X) - -
-
- -
-
- -
-
-
- +
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ + @for(drop of editingData.drops; track $index) { +
+
+
+ {{ drop.result }} +
+
+ +
+
+ Max Chance (1/X) + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ }
{{ editingData | json }} - + \ No newline at end of file diff --git a/src/app/tabs/droptables/droptables-editor/droptables-editor.component.ts b/src/app/tabs/droptables/droptables-editor/droptables-editor.component.ts index f00d3ba..71ac08c 100644 --- a/src/app/tabs/droptables/droptables-editor/droptables-editor.component.ts +++ b/src/app/tabs/droptables/droptables-editor/droptables-editor.component.ts @@ -1,5 +1,5 @@ import { Component, computed, signal } from '@angular/core'; -import { IDroptable, IItemDefinition } from '../../../../interfaces'; +import { Holiday, IDroptable, IItemDefinition } from '../../../../interfaces'; import { EditorBaseComponent } from '../../../shared/components/editor-base/editor-base.component'; @Component({ @@ -13,9 +13,39 @@ export class DroptablesEditorComponent extends EditorBaseComponent { public canSave = computed(() => { const data = this.editing(); return ( - (data.mapName || data.regionName || data.isGlobal) && - data.maxChance > 0 && - data.result + (data.isGlobal || data.mapName || data.regionName) && + data.drops.length > 0 ); }); + + public addItem(item: IItemDefinition | undefined) { + if (!item) return; + + this.editing.update((droptable) => ({ + ...droptable, + drops: [ + ...droptable.drops, + { + chance: 1, + maxChance: 100, + result: item.name, + noLuckBonus: true, + requireHoliday: undefined as unknown as Holiday, + }, + ], + })); + } + + public removeItem(item: string) { + this.editing.update((npc) => { + const newNpc = { ...npc }; + newNpc.drops = newNpc.drops.filter((d) => d.result !== item); + return newNpc; + }); + } + + public hasItem(item: IItemDefinition | undefined) { + if (!item) return false; + return this.editing().drops.some((d) => d.result === item.name); + } } diff --git a/src/app/tabs/droptables/droptables.component.ts b/src/app/tabs/droptables/droptables.component.ts index de6fb4a..a411204 100644 --- a/src/app/tabs/droptables/droptables.component.ts +++ b/src/app/tabs/droptables/droptables.component.ts @@ -4,7 +4,6 @@ import { ColDef } from 'ag-grid-community'; import { IDroptable, IModKit } from '../../../interfaces'; import { defaultDroptable } from '../../helpers'; import { CellButtonsComponent } from '../../shared/components/cell-buttons/cell-buttons.component'; -import { CellSpriteComponent } from '../../shared/components/cell-sprite/cell-sprite.component'; import { EditorBaseTableComponent } from '../../shared/components/editor-base-table/editor-base-table.component'; import { HeaderButtonsComponent } from '../../shared/components/header-buttons/header-buttons.component'; @@ -27,29 +26,6 @@ export class DroptablesComponent extends EditorBaseTableComponent { ); public tableItems = computed(() => this.modService.mod().drops); public tableColumns: ColDef[] = [ - { - field: 'sprite', - headerName: '', - resizable: false, - sortable: false, - width: 100, - cellRenderer: CellSpriteComponent, - cellRendererParams: { type: 'items', fromResult: true }, - }, - { - field: 'result', - headerName: 'Item', - flex: 1, - cellDataType: 'text', - filter: 'agTextColumnFilter', - }, - { - field: 'maxChance', - flex: 1, - cellDataType: 'number', - filter: 'agNumberColumnFilter', - valueFormatter: (v) => `1/${v.value}`, - }, { field: 'mapName', flex: 1, diff --git a/src/interfaces/droptable.ts b/src/interfaces/droptable.ts index fc91570..08ccea2 100644 --- a/src/interfaces/droptable.ts +++ b/src/interfaces/droptable.ts @@ -1,21 +1,10 @@ +import { Rollable } from './building-blocks'; import { HasIdentification } from './identified'; export interface IDroptable extends HasIdentification { - result: string; - maxChance: number; - noLuckBonus: boolean; - mapName: string; - regionName: string; - requireHoliday: string; - isGlobal: boolean; -} - -export interface IDroptableMap { - mapName: string; - drops: IDroptable[]; -} + mapName?: string; + regionName?: string; + isGlobal?: boolean; -export interface IDroptableRegion { - regionName: string; - drops: IDroptable[]; + drops: Rollable[]; } diff --git a/src/interfaces/modkit.ts b/src/interfaces/modkit.ts index e856dc0..b15bdec 100644 --- a/src/interfaces/modkit.ts +++ b/src/interfaces/modkit.ts @@ -1,4 +1,4 @@ -import { IDroptable, IDroptableMap, IDroptableRegion } from './droptable'; +import { IDroptable } from './droptable'; import { IItemDefinition } from './item'; import { IEditorMap } from './map'; import { INPCDefinition } from './npc'; @@ -25,22 +25,3 @@ export interface IModKit { quests: IQuest[]; dialogs: INPCScript[]; } - -export interface IExportedModKit { - meta: { - name: string; - author: string; - version: number; - savedAt: number; - _backup: any; - }; - - npcs: INPCDefinition[]; - items: IItemDefinition[]; - drops: { maps: IDroptableMap[]; regions: IDroptableRegion[] }; - spawners: ISpawnerData[]; - recipes: IRecipe[]; - maps: IEditorMap[]; - quests: IQuest[]; - dialogs: INPCScript[]; -}