From 7035ca40b1b0dd07465801a0aceb2454cf93d345 Mon Sep 17 00:00:00 2001 From: Kyle Kemp Date: Mon, 12 Aug 2024 10:52:30 -0500 Subject: [PATCH] closes #8 --- src/app/app.icons.ts | 6 + src/app/helpers/npc.ts | 20 +- .../input-itemslot.component.html | 6 + .../input-itemslot.component.scss | 0 .../input-itemslot.component.ts | 14 + .../input-sfx/input-sfx.component.html | 6 + .../input-sfx/input-sfx.component.scss | 0 .../input-sfx/input-sfx.component.ts | 52 ++ .../input-skill/input-skill.component.ts | 2 +- .../input-stat/input-stat.component.html | 2 +- .../input-stat/input-stat.component.ts | 1 + src/app/shared/shared.module.ts | 6 + .../items-editor/items-editor.component.html | 6 +- .../npcs-editor/npcs-editor.component.html | 466 +++++++++++++++++- .../npcs-editor/npcs-editor.component.scss | 20 + .../npcs/npcs-editor/npcs-editor.component.ts | 262 +++++++++- src/interfaces/building-blocks.ts | 11 +- src/interfaces/npc.ts | 44 +- src/styles.scss | 9 +- 19 files changed, 858 insertions(+), 75 deletions(-) create mode 100644 src/app/shared/components/input-itemslot/input-itemslot.component.html create mode 100644 src/app/shared/components/input-itemslot/input-itemslot.component.scss create mode 100644 src/app/shared/components/input-itemslot/input-itemslot.component.ts create mode 100644 src/app/shared/components/input-sfx/input-sfx.component.html create mode 100644 src/app/shared/components/input-sfx/input-sfx.component.scss create mode 100644 src/app/shared/components/input-sfx/input-sfx.component.ts diff --git a/src/app/app.icons.ts b/src/app/app.icons.ts index 2a8b2b7..9d8cf07 100644 --- a/src/app/app.icons.ts +++ b/src/app/app.icons.ts @@ -1,8 +1,11 @@ import { heroArrowDownOnSquare, + heroArrowPathRoundedSquare, heroArrowsRightLeft, heroDocumentDuplicate, heroDocumentText, + heroFaceFrown, + heroFaceSmile, heroMinus, heroPencil, heroPlus, @@ -18,4 +21,7 @@ export const appIcons = { heroMinus, heroTrash, heroArrowsRightLeft, + heroFaceFrown, + heroFaceSmile, + heroArrowPathRoundedSquare, }; diff --git a/src/app/helpers/npc.ts b/src/app/helpers/npc.ts index 88bcc1a..b5541da 100644 --- a/src/app/helpers/npc.ts +++ b/src/app/helpers/npc.ts @@ -69,12 +69,16 @@ export const defaultNPC: () => INPCDefinition = () => ({ spawn: { messages: [''], sfx: { - name: '', + name: undefined as unknown as string, maxChance: 0, }, }, combat: { messages: [], + sfx: { + name: undefined as unknown as string, + maxChance: 0, + }, }, }, items: { @@ -100,6 +104,20 @@ export const defaultNPC: () => INPCDefinition = () => ({ ammo: [], }, }, + allegianceReputation: { + Adventurers: 0, + Enemy: 0, + GM: 0, + NaturalResource: 0, + None: 0, + Pirates: 0, + Royalty: 0, + Townsfolk: 0, + Underground: 0, + Wilderness: 0, + }, repMod: [], skills: {}, + summonSkillModifiers: {}, + summonStatModifiers: {}, }); diff --git a/src/app/shared/components/input-itemslot/input-itemslot.component.html b/src/app/shared/components/input-itemslot/input-itemslot.component.html new file mode 100644 index 0000000..ef0ac83 --- /dev/null +++ b/src/app/shared/components/input-itemslot/input-itemslot.component.html @@ -0,0 +1,6 @@ +
+ + + Item Slot +
diff --git a/src/app/shared/components/input-itemslot/input-itemslot.component.scss b/src/app/shared/components/input-itemslot/input-itemslot.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/components/input-itemslot/input-itemslot.component.ts b/src/app/shared/components/input-itemslot/input-itemslot.component.ts new file mode 100644 index 0000000..46c90f0 --- /dev/null +++ b/src/app/shared/components/input-itemslot/input-itemslot.component.ts @@ -0,0 +1,14 @@ +import { Component, model, output } from '@angular/core'; +import { ItemSlot, ItemSlotType } from '../../../../interfaces'; + +@Component({ + selector: 'app-input-itemslot', + templateUrl: './input-itemslot.component.html', + styleUrl: './input-itemslot.component.scss', +}) +export class InputItemslotComponent { + public itemSlot = model.required(); + public change = output(); + + public values = [...Object.values(ItemSlot).sort()]; +} diff --git a/src/app/shared/components/input-sfx/input-sfx.component.html b/src/app/shared/components/input-sfx/input-sfx.component.html new file mode 100644 index 0000000..f003d42 --- /dev/null +++ b/src/app/shared/components/input-sfx/input-sfx.component.html @@ -0,0 +1,6 @@ +
+ + + {{ label() }} +
diff --git a/src/app/shared/components/input-sfx/input-sfx.component.scss b/src/app/shared/components/input-sfx/input-sfx.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/components/input-sfx/input-sfx.component.ts b/src/app/shared/components/input-sfx/input-sfx.component.ts new file mode 100644 index 0000000..e4d36e5 --- /dev/null +++ b/src/app/shared/components/input-sfx/input-sfx.component.ts @@ -0,0 +1,52 @@ +import { Component, input, model, output } from '@angular/core'; + +@Component({ + selector: 'app-input-sfx', + templateUrl: './input-sfx.component.html', + styleUrl: './input-sfx.component.scss', +}) +export class InputSfxComponent { + public sfx = model.required(); + public change = output(); + + public label = input('SFX'); + + public values = [ + 'combat-block-armor', + 'combat-block-weapon', + 'combat-die', + 'combat-hit-melee', + 'combat-hit-spell', + 'combat-kill', + 'combat-miss', + 'combat-special-blunderbuss', + + 'env-door-close', + 'env-door-open', + 'env-stairs', + + 'monster-bear', + 'monster-bird', + 'monster-dragon', + 'monster-ghost', + 'monster-goblin', + 'monster-rocks', + 'monster-skeleton', + 'monster-turkey', + 'monster-wolf', + + 'spell-aoe-fire', + 'spell-aoe-frost', + 'spell-buff-magical', + 'spell-buff', + 'spell-buff-physical', + 'spell-buff-protection', + 'spell-conjure', + 'spell-debuff-give', + 'spell-debuff-receive', + 'spell-heal', + 'spell-sight-effect', + 'spell-special-revive', + 'spell-special-teleport', + ]; +} diff --git a/src/app/shared/components/input-skill/input-skill.component.ts b/src/app/shared/components/input-skill/input-skill.component.ts index 1761a7b..8c5ed60 100644 --- a/src/app/shared/components/input-skill/input-skill.component.ts +++ b/src/app/shared/components/input-skill/input-skill.component.ts @@ -7,7 +7,7 @@ import { Skill } from '../../../../interfaces'; styleUrl: './input-skill.component.scss', }) export class InputSkillComponent { - public skill = model.required(); + public skill = model.required(); public label = input('Skill'); public change = output(); diff --git a/src/app/shared/components/input-stat/input-stat.component.html b/src/app/shared/components/input-stat/input-stat.component.html index 22b614d..5b8c482 100644 --- a/src/app/shared/components/input-stat/input-stat.component.html +++ b/src/app/shared/components/input-stat/input-stat.component.html @@ -2,5 +2,5 @@ - Stat + {{ label() }} diff --git a/src/app/shared/components/input-stat/input-stat.component.ts b/src/app/shared/components/input-stat/input-stat.component.ts index e7562e9..6492ec9 100644 --- a/src/app/shared/components/input-stat/input-stat.component.ts +++ b/src/app/shared/components/input-stat/input-stat.component.ts @@ -9,6 +9,7 @@ import { coreStats, extraStats } from '../../../helpers'; }) export class InputStatComponent { public stat = model.required(); + public label = input('Stat'); public change = output(); public allowCore = input(true); public allowExtra = input(true); diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index f41613f..7f9ee64 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -37,6 +37,8 @@ import { InputHostilityComponent } from './components/input-hostility/input-host import { InputAllegianceComponent } from './components/input-allegiance/input-allegiance.component'; import { InputCategoryComponent } from './components/input-category/input-category.component'; import { InputChallengeratingComponent } from './components/input-challengerating/input-challengerating.component'; +import { InputItemslotComponent } from './components/input-itemslot/input-itemslot.component'; +import { InputSfxComponent } from './components/input-sfx/input-sfx.component'; @NgModule({ declarations: [ @@ -70,6 +72,8 @@ import { InputChallengeratingComponent } from './components/input-challengeratin InputAllegianceComponent, InputCategoryComponent, InputChallengeratingComponent, + InputItemslotComponent, + InputSfxComponent, ], imports: [ CommonModule, @@ -111,6 +115,8 @@ import { InputChallengeratingComponent } from './components/input-challengeratin InputAllegianceComponent, InputCategoryComponent, InputChallengeratingComponent, + InputItemslotComponent, + InputSfxComponent, ], }) export class SharedModule {} diff --git a/src/app/tabs/items/items-editor/items-editor.component.html b/src/app/tabs/items/items-editor/items-editor.component.html index fb2dbb9..975040c 100644 --- a/src/app/tabs/items/items-editor/items-editor.component.html +++ b/src/app/tabs/items/items-editor/items-editor.component.html @@ -160,7 +160,7 @@ -
+
-
+
-
+
-
+
@if($index === 0) {
-
+
-
+
-
+
-
+
-
- - @for(spell of editingData.usableSkills; track $index) { -
-
-
- -
+ @for(spell of editingData.usableSkills; track $index) { +
+
+
+
+
-
-
- Use Chance (Weight) - -
+
+
+ Use Chance (Weight) +
+
-
-
- -
+
+
+
- }
+ }
@@ -365,7 +362,7 @@
-
+
+
+ + @for(item of editingData.items.sack; track item) { +
+
+
+ +
+
+ +
+
+ Chance (-1 = always) + +
+
+ +
+
+ Max Chance (1/X) + +
+
+ +
+
+ +
+
+
+ } +
+ + @for(col of equipmentColumns; track $index) { +
+ @for(slot of col; track $index) { +
+ +
+ + @for(item of editingData.items.equipment[slot]; track item; let eqSlot = $index) { +
+
+
+ +
+
+ +
+
+ Weight + +
+
+ +
+
+ +
+
+
+ } + } +
+ } +
} @case (3) { +
+
+
+ +
+
+ Tan Skill Required + +
+ +
+ +
+
+ +
+ +
+ Drop Pool Min Items + +
+ +
+ Drop Pool Max Items + +
+
+
+ +
+
+ +
+ + @for(item of editingData.drops; track item; let eqSlot = $index) { +
+
+
+ +
+
+ +
+
+ Chance (-1 = always) + +
+
+ +
+
+ Max Chance (1/X) + +
+
+ +
+
+ +
+
+
+ } +
+ +
+
+ +
+ + @for(item of editingData.dropPool.items; track item; let eqSlot = $index) { +
+
+
+ +
+
+ +
+
+ +
+
+
+ } +
+ +
+
+ +
+ + @for(item of editingData.copyDrops; track item; let eqSlot = $index) { +
+
+
+ +
+
+ +
+
+ +
+
+
+ } +
+
} @case (4) { +
+ +
+
+ +
+ + @for(message of editingData.triggers.combat.messages; track $index) { +
+
+
+ Combat Message + +
+
+ +
+
+ +
+
+
+ } +
+ +
+
+ Spawn Message + +
+ +
+ +
+ +
+ Spawn SFX % + +
+
+ +
+
+ Leash Message + +
+ +
+ +
+ +
+ Leash SFX % + +
+
+ +
+} + +@case (5) { +
+ +
+ @for(allegiance of allegiances; track $index) { +
+
+
+ {{ allegiance }} Outlook + +
+
+ +
+
+ + + + + +
+
+ +
+ } +
+ + +
+ @for(repMod of editingData.repMod; track $index) { +
+ {{ repMod.allegiance }} Delta On Kill + +
+ + } +
+ + +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ + @for(stat of summonStatsInOrder(); track $index) { +
+
+
+ Summon {{ stat }} Owner Multiplier + +
+
+ +
+
+ +
+
+
+ } +
+ + +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ + @for(skill of summonSkillsInOrder(); track $index) { +
+
+
+ Summon {{ skill }} Owner Multiplier + +
+
+ +
+
+ +
+
+
+ } +
+ +
} } diff --git a/src/app/tabs/npcs/npcs-editor/npcs-editor.component.scss b/src/app/tabs/npcs/npcs-editor/npcs-editor.component.scss index f717bdb..a84d48d 100644 --- a/src/app/tabs/npcs/npcs-editor/npcs-editor.component.scss +++ b/src/app/tabs/npcs/npcs-editor/npcs-editor.component.scss @@ -9,3 +9,23 @@ flex: 1 1 30%; } } + +.equipment-pickers { + & > .form-column:first-child { + flex: 3; + } + + & > .form-column:not(:first-child) { + flex: 2; + } +} + +.drop-pickers { + & > .form-column:first-child { + flex: 1; + } + + & > .form-column:not(:first-child) { + flex: 2; + } +} diff --git a/src/app/tabs/npcs/npcs-editor/npcs-editor.component.ts b/src/app/tabs/npcs/npcs-editor/npcs-editor.component.ts index 8c5924b..4f58a37 100644 --- a/src/app/tabs/npcs/npcs-editor/npcs-editor.component.ts +++ b/src/app/tabs/npcs/npcs-editor/npcs-editor.component.ts @@ -7,7 +7,15 @@ import { signal, } from '@angular/core'; import { isNumber, sortBy } from 'lodash'; -import { INPCDefinition, StatType } from '../../../../interfaces'; +import { + Allegiance, + AllegianceType, + IItemDefinition, + INPCDefinition, + ItemSlotType, + SkillType, + StatType, +} from '../../../../interfaces'; import { ElectronService } from '../../../services/electron.service'; import { EditorBaseComponent } from '../../../shared/components/editor-base/editor-base.component'; @@ -29,6 +37,7 @@ export class NpcsEditorComponent { name: 'Gear' }, { name: 'Drops' }, { name: 'Triggers' }, + { name: 'Faction Reputation & Summonability' }, ]; public readonly coreProps: Array<{ @@ -53,14 +62,35 @@ export class NpcsEditorComponent 'luk', ]; + public equipmentColumns: Array> = [ + ['rightHand', 'leftHand', 'armor', 'robe1', 'robe2'], + ['head', 'neck', 'waist', 'wrists', 'hands', 'feet'], + ['ear', 'ring1', 'ring2', 'trinket', 'potion', 'ammo'], + ]; + + public allegiances = Object.values(Allegiance).sort(); + public currentStat = signal(undefined); + public currentSummonStat = signal(undefined); + public currentSummonSkill = signal(undefined); public currentTrait = signal(undefined); + public tansFor = signal(undefined); public statsInOrder = computed(() => { const npc = this.editing(); return sortBy(Object.keys(npc.otherStats)) as StatType[]; }); + public summonStatsInOrder = computed(() => { + const npc = this.editing(); + return sortBy(Object.keys(npc.summonStatModifiers)) as StatType[]; + }); + + public summonSkillsInOrder = computed(() => { + const npc = this.editing(); + return sortBy(Object.keys(npc.summonSkillModifiers)) as SkillType[]; + }); + public traitsInOrder = computed(() => { const npc = this.editing(); return sortBy(Object.keys(npc.traitLevels)); @@ -88,18 +118,48 @@ export class NpcsEditorComponent }); } + ngOnInit(): void { + this.checkLinkedStats(); + const npc = this.editing(); + npc.items.sack.forEach((i) => (i._itemRef = signal(undefined))); + + (this.equipmentColumns.flat(Infinity) as ItemSlotType[]).forEach( + (slot: ItemSlotType) => { + npc.items.equipment[slot].forEach( + (i) => (i._itemRef = signal(undefined)) + ); + } + ); + + npc.drops.forEach((d) => (d._itemRef = signal(undefined))); + npc.dropPool.items.forEach((d) => (d._itemRef = signal(undefined))); + + const reps = npc.repMod ?? []; + npc.repMod = this.allegiances.map((allegiance) => ({ + allegiance, + delta: reps.find((r) => r.allegiance === allegiance)?.delta ?? 0, + })); + + this.editing.set(npc); + + super.ngOnInit(); + } + public addTrait(trait: string | undefined, value = 0) { if (!trait) return; - const npc = structuredClone(this.editing()); - npc.traitLevels[trait] = value; - this.editing.set(npc); + this.editing.update((npc) => ({ + ...npc, + traitLevels: { ...npc.traitLevels, [trait]: value }, + })); } public removeTrait(trait: string) { - const npc = structuredClone(this.editing()); - delete npc.traitLevels[trait]; - this.editing.set(npc); + this.editing.update((npc) => { + const newNpc = { ...npc }; + delete npc.traitLevels[trait]; + return newNpc; + }); } public hasTrait(trait: string | undefined) { @@ -110,15 +170,18 @@ export class NpcsEditorComponent public addStat(stat: StatType | undefined, value = 0) { if (!stat) return; - const npc = structuredClone(this.editing()); - npc.otherStats[stat] = value; - this.editing.set(npc); + this.editing.update((npc) => ({ + ...npc, + otherStats: { ...npc.otherStats, [stat]: value }, + })); } public removeStat(stat: StatType) { - const npc = structuredClone(this.editing()); - delete npc.otherStats[stat]; - this.editing.set(npc); + this.editing.update((npc) => { + const newNpc = { ...npc }; + delete npc.otherStats[stat]; + return newNpc; + }); } public hasStat(stat: StatType | undefined) { @@ -126,6 +189,50 @@ export class NpcsEditorComponent return isNumber(this.editing().otherStats[stat]); } + public addSummonStat(stat: StatType | undefined, value = 0) { + if (!stat) return; + + this.editing.update((npc) => ({ + ...npc, + summonStatModifiers: { ...npc.summonStatModifiers, [stat]: value }, + })); + } + + public removeSummonStat(stat: StatType) { + this.editing.update((npc) => { + const newNpc = { ...npc }; + delete npc.summonStatModifiers[stat]; + return newNpc; + }); + } + + public hasSummonStat(stat: StatType | undefined) { + if (!stat) return false; + return isNumber(this.editing().summonStatModifiers[stat]); + } + + public addSummonSkill(skill: SkillType | undefined, value = 0) { + if (!skill) return; + + this.editing.update((npc) => ({ + ...npc, + summonSkillModifiers: { ...npc.summonSkillModifiers, [skill]: value }, + })); + } + + public removeSummonSkill(skill: SkillType) { + this.editing.update((npc) => { + const newNpc = { ...npc }; + delete npc.summonSkillModifiers[skill]; + return newNpc; + }); + } + + public hasSummonSkill(skill: SkillType | undefined) { + if (!skill) return false; + return isNumber(this.editing().summonSkillModifiers[skill]); + } + public addSprite() { this.update('sprite', [...this.editing().sprite, 0]); } @@ -205,15 +312,138 @@ export class NpcsEditorComponent this.linkStats.set(isLinked); } - ngOnInit(): void { - this.checkLinkedStats(); - super.ngOnInit(); + public addSackItem() { + const npc = this.editing(); + npc.items.sack.push({ + chance: -1, + maxChance: 100, + result: undefined as unknown as string, + _itemRef: signal(undefined), + }); + + this.editing.set(npc); + } + + public removeSackItem(index: number) { + const npc = this.editing(); + npc.items.sack.splice(index, 1); + this.editing.set(npc); + } + + public addEquipmentItem(slot: ItemSlotType) { + const npc = this.editing(); + npc.items.equipment[slot].push({ + chance: 1, + result: undefined as unknown as string, + _itemRef: signal(undefined), + }); + + this.editing.set(npc); + } + + public removeEquipmentItem(slot: ItemSlotType, index: number) { + const npc = this.editing(); + npc.items.equipment[slot].splice(index, 1); + this.editing.set(npc); + } + + public addDrop() { + const npc = this.editing(); + npc.drops.push({ + chance: 1, + result: undefined as unknown as string, + _itemRef: signal(undefined), + }); + this.editing.set(npc); + } + + public removeDrop(index: number) { + const npc = this.editing(); + npc.drops.splice(index, 1); + this.editing.set(npc); + } + + public addCopyDrop() { + const npc = this.editing(); + npc.copyDrops.push({ + chance: -1, + result: undefined as unknown as string, + }); + this.editing.set(npc); + } + + public removeCopyDrop(index: number) { + const npc = this.editing(); + npc.copyDrops.splice(index, 1); + this.editing.set(npc); + } + + public addDropPoolItem() { + const npc = this.editing(); + npc.dropPool.items.push({ + chance: 1, + result: undefined as unknown as string, + _itemRef: signal(undefined), + }); + this.editing.set(npc); + } + + public removeDropPoolItem(index: number) { + const npc = this.editing(); + npc.dropPool.items.splice(index, 1); + this.editing.set(npc); + } + + public addCombatMessage() { + const npc = this.editing(); + npc.triggers.combat.messages.push(''); + this.editing.set(npc); + } + + public removeCombatMessage(index: number) { + const npc = this.editing(); + npc.triggers.combat.messages.splice(index, 1); + this.editing.set(npc); + } + + public setReputation(allegiance: AllegianceType, number = 0) { + const npc = this.editing(); + npc.allegianceReputation[allegiance] = number; + this.editing.set(npc); } doSave() { const npc = this.editing(); npc.usableSkills = npc.usableSkills.filter((f) => f.result); npc.baseEffects = npc.baseEffects.filter((f) => f.name); + npc.items.sack = npc.items.sack.filter((f) => f.result); + npc.items.sack.forEach((item) => { + delete item._itemRef; + }); + + (this.equipmentColumns.flat(Infinity) as ItemSlotType[]).forEach( + (slot: ItemSlotType) => { + npc.items.equipment[slot] = npc.items.equipment[slot].filter( + (f) => f.result + ); + + npc.items.equipment[slot].forEach((item) => { + delete item._itemRef; + }); + } + ); + + npc.drops.forEach((d) => delete d._itemRef); + npc.dropPool.items.forEach((d) => delete d._itemRef); + + npc.drops = npc.drops.filter((d) => d.result); + npc.copyDrops = npc.copyDrops.filter((d) => d.result); + npc.dropPool.items = npc.dropPool.items.filter((d) => d.result); + + npc.triggers.combat.messages = npc.triggers.combat.messages.filter(Boolean); + + npc.repMod = npc.repMod.filter((r) => r.delta); + this.editing.set(npc); super.doSave(); diff --git a/src/interfaces/building-blocks.ts b/src/interfaces/building-blocks.ts index 0d2505c..ebd7be1 100644 --- a/src/interfaces/building-blocks.ts +++ b/src/interfaces/building-blocks.ts @@ -1,3 +1,6 @@ +import { WritableSignal } from '@angular/core'; +import { IItemDefinition } from './item'; + export enum Allegiance { // for things that do not have an allegiance None = 'None', @@ -72,13 +75,11 @@ export enum ItemSlot { Ear = 'ear', Waist = 'waist', Wrists = 'wrists', - Ring = 'ring', // internal type, not to be used as an actual slot Ring1 = 'ring1', Ring2 = 'ring2', Hands = 'hands', Feet = 'feet', Armor = 'armor', - Robe = 'robe', // internal type, not to be used as an actual slot Robe1 = 'robe1', Robe2 = 'robe2', RightHand = 'rightHand', @@ -88,6 +89,8 @@ export enum ItemSlot { Ammo = 'ammo', } +export type ItemSlotType = `${ItemSlot}`; + export enum Stat { // core STR = 'str', @@ -198,6 +201,8 @@ export enum Skill { Wand = 'wand', } +export type SkillType = `${Skill}`; + export enum Tradeskill { Alchemy = 'alchemy', Spellforging = 'spellforging', @@ -312,6 +317,8 @@ export interface Rollable { maxChance?: number; requireHoliday?: Holiday; noLuckBonus?: boolean; + + _itemRef?: WritableSignal; } export interface RandomNumber { diff --git a/src/interfaces/npc.ts b/src/interfaces/npc.ts index c356256..2d37c20 100644 --- a/src/interfaces/npc.ts +++ b/src/interfaces/npc.ts @@ -1,4 +1,3 @@ -import { IBehavior, IDialogTree } from './behavior'; import { AlignmentType, AllegianceType, @@ -42,7 +41,7 @@ export interface INPCDefinition extends HasIdentification { allegiance: AllegianceType; // the current reputation (how it views other allegiances) - allegianceReputation?: Partial>; + allegianceReputation: Record; // whether the npc can only use water aquaticOnly?: boolean; @@ -63,17 +62,11 @@ export interface INPCDefinition extends HasIdentification { }; }>; - // the behaviors for the npc - behaviors?: IBehavior[]; - // the drop chance for copying items that are already equipped - copyDrops?: Rollable[]; - - // the dialog tree for the npc, if applicable - dialog?: IDialogTree; + copyDrops: Rollable[]; // the drop pool for lairs that can drop X of Y items - dropPool?: { + dropPool: { replace?: boolean; choose: { min: number; @@ -83,7 +76,7 @@ export interface INPCDefinition extends HasIdentification { }; // stuff that can be put in the loot table for normal drops - drops?: Rollable[]; + drops: Rollable[]; // the hp multiplier for the npc hpMult: number; @@ -95,27 +88,21 @@ export interface INPCDefinition extends HasIdentification { forceAI?: string; // gear items that can spawn on the creature - items?: { - equipment?: Partial>; - sack?: Rollable[]; - belt?: Rollable[]; + items: { + equipment: Record; + sack: Rollable[]; + belt: Rollable[]; }; // the creatures level level: number; - // how far the NPC can wander, in tiles - maxWanderRandomlyDistance?: number; - // the creature class (used for rippers, etc) monsterClass?: MonsterClassType; // the monster grouping, so Hostility.Always dont infight with themselves monsterGroup?: string; - // the owner of the creature (used for summons) - owner?: string; - // the "other stats" for this npc, inherited from NPC definition otherStats: Partial>; @@ -149,10 +136,10 @@ export interface INPCDefinition extends HasIdentification { stats: StatBlock; // the modifiers (based on potency) for each stat to modify this character by - summonStatModifiers?: Record; + summonStatModifiers: Partial>; // the modifiers (based on potency) for each skill to modify this character by - summonSkillModifiers?: Record; + summonSkillModifiers: Partial>; // the skill required to tan this creature tanSkillRequired?: number; @@ -164,7 +151,16 @@ export interface INPCDefinition extends HasIdentification { traitLevels: Record; // npc triggers - triggers?: Partial>; + triggers: Record< + NPCTriggerType, + { + messages: string[]; + sfx: { + name: string; + maxChance: number; + }; + } + >; // npc usable skills usableSkills: Rollable[]; diff --git a/src/styles.scss b/src/styles.scss index 188cf3f..1b9d079 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -63,7 +63,14 @@ ag-grid-angular { .form-column { @apply flex; @apply flex-col; - @apply flex-1; + + &:not(.button-column) { + @apply flex-1; + } + + &.button-column { + @apply w-12; + } } .form-row {