Skip to content

Commit

Permalink
Merge pull request #977 from kgar/quick-fix-npc-dc
Browse files Browse the repository at this point in the history
fixed: Non-Classed NPCs were missing spell DC in spellbook footer, Actions tab DC missing and formatting issues
  • Loading branch information
kgar authored Feb 4, 2025
2 parents 155fce4 + a58867a commit ee0b6bf
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 20 deletions.
4 changes: 4 additions & 0 deletions src/components/item-list/item-table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
align-items: center;
justify-content: center;

&.flex-column {
flex-direction: column;
}

&:not(.no-gap) {
gap: 0.25rem;
}
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const CONSTANTS = {
DOCUMENT_NAME_ACTOR: 'Actor',
DOCUMENT_NAME_ITEM: 'Item',
DOCUMENT_NAME_ACTIVITY: 'Activity',
ACTIVITY_TYPE_SAVE: 'save',
ATTUNEMENT_OPTIONAL: 'optional',
ATTUNEMENT_REQUIRED: 'required',
FAVORITES_SECTION_TYPE_ACTIVITY: 'activity',
Expand Down
28 changes: 28 additions & 0 deletions src/features/item/ItemContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { CONSTANTS } from 'src/constants';
import type { Item5e } from 'src/types/item.types';
import type { ItemSaveContext } from 'src/types/types';

export class ItemContext {
static getItemSaveContext(item: Item5e): ItemSaveContext | undefined {
let activitySave = {
...item.system.activities?.getByType(CONSTANTS.ACTIVITY_TYPE_SAVE)[0]
?.save,
};

if (activitySave) {
return {
ability: activitySave.ability?.size
? activitySave.ability.size === 1
? CONFIG.DND5E.abilities[activitySave.ability.first()]?.abbreviation
: game.i18n.localize('DND5E.AbbreviationDC')
: null,
dc: activitySave.dc,
};
}
}

static getToHit(item: Item5e): number | null {
const toHit = parseInt(item.labels.modifier);
return item.hasAttack && !isNaN(toHit) ? toHit : null;
}
}
7 changes: 7 additions & 0 deletions src/sheets/classic/Tidy5eCharacterSheet.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import AttachedInfoCard from 'src/components/info-card/AttachedInfoCard.svelte';
import { ExpansionTracker } from 'src/features/expand-collapse/ExpansionTracker.svelte';
import { AttributePins } from 'src/features/attribute-pins/AttributePins';
import type { AttributePinFlag } from 'src/foundry/TidyFlags.types';
import { ItemContext } from 'src/features/item/ItemContext';

export class Tidy5eCharacterSheet
extends BaseSheetCustomSectionMixin(
Expand Down Expand Up @@ -1496,6 +1497,12 @@ export class Tidy5eCharacterSheet
context.canToggle = 'equipped' in item.system;
}

// Save
context.save = ItemContext.getItemSaveContext(item);

// To Hit
context.toHit = ItemContext.getToHit(item);

// Activities
context.activities = Activities.getVisibleActivities(
item,
Expand Down
3 changes: 3 additions & 0 deletions src/sheets/classic/Tidy5eGroupSheetClassic.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import AttachedInfoCard from 'src/components/info-card/AttachedInfoCard.svelte';
import { ImportSheetControl } from '../../features/sheet-header-controls/ImportSheetControl';
import { SheetSections } from 'src/features/sections/SheetSections';
import { ExpansionTracker } from 'src/features/expand-collapse/ExpansionTracker.svelte';
import { ItemContext } from 'src/features/item/ItemContext';

type MemberStats = {
currentHP: number;
Expand Down Expand Up @@ -828,6 +829,8 @@ export class Tidy5eGroupSheetClassic extends Tidy5eActorSheetBaseMixin(
containerContents: undefined,
hasUses: item.hasLimitedUses,
isStack: item.system.quantity > 1,
save: ItemContext.getItemSaveContext(item),
toHit: ItemContext.getToHit(item),
totalWeight: (await item.system.totalWeight)?.toNearest(0.1) ?? 0,
};
}
Expand Down
9 changes: 8 additions & 1 deletion src/sheets/classic/Tidy5eKgarVehicleSheet.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ import { TidyHooks } from 'src/foundry/TidyHooks';
import { InlineToggleService } from 'src/features/expand-collapse/InlineToggleService.svelte';
import { Container } from 'src/features/containers/Container';
import { Activities } from 'src/features/activities/activities';
import type { Activity5e } from 'src/foundry/dnd5e.types';
import { CoarseReactivityProvider } from 'src/features/reactivity/CoarseReactivityProvider.svelte';
import AttachedInfoCard from 'src/components/info-card/AttachedInfoCard.svelte';
import { ExpansionTracker } from 'src/features/expand-collapse/ExpansionTracker.svelte';
import { ItemContext } from 'src/features/item/ItemContext';

export class Tidy5eVehicleSheet
extends dnd5e.applications.actor.ActorSheet5eVehicle
Expand Down Expand Up @@ -579,6 +579,13 @@ export class Tidy5eVehicleSheet
const ctx: VehicleItemContext = {};
ctx.canToggle = false;
ctx.hasUses = uses && uses.max > 0;

// Save
ctx.save = ItemContext.getItemSaveContext(item);

// To Hit
ctx.toHit = ItemContext.getToHit(item);

// Activities
ctx.activities = Activities.getVisibleActivities(
item,
Expand Down
7 changes: 7 additions & 0 deletions src/sheets/classic/Tidy5eNpcSheet.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import type { Activity5e } from 'src/foundry/dnd5e.types';
import { CoarseReactivityProvider } from 'src/features/reactivity/CoarseReactivityProvider.svelte';
import AttachedInfoCard from 'src/components/info-card/AttachedInfoCard.svelte';
import { ExpansionTracker } from 'src/features/expand-collapse/ExpansionTracker.svelte';
import { ItemContext } from 'src/features/item/ItemContext';

export class Tidy5eNpcSheet
extends BaseSheetCustomSectionMixin(
Expand Down Expand Up @@ -939,6 +940,12 @@ export class Tidy5eNpcSheet
ctx.hasUses = uses && uses.max > 0;
ctx.canToggle = 'equipped' in item.system;

// Save
ctx.save = ItemContext.getItemSaveContext(item);

// To Hit
ctx.toHit = ItemContext.getToHit(item);

ctx.totalWeight = item.system.totalWeight?.toNearest(0.1);
if (item.type === CONSTANTS.ITEM_TYPE_SPELL) {
if (this._concentration.items.has(item)) {
Expand Down
44 changes: 30 additions & 14 deletions src/sheets/classic/actor/tabs/ActorActionsTab.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import ItemTableRow from 'src/components/item-list/v1/ItemTableRow.svelte';
import ItemTableCell from 'src/components/item-list/v1/ItemTableCell.svelte';
import { FoundryAdapter } from 'src/foundry/foundry-adapter';
import type { ActorSheetContextV1 } from 'src/types/types';
import type {
CharacterSheetContext,
NpcSheetContext,
VehicleSheetContext,
} from 'src/types/types';
import { getContext } from 'svelte';
import ItemName from 'src/components/item-list/ItemName.svelte';
import { CONSTANTS } from 'src/constants';
Expand Down Expand Up @@ -34,8 +38,14 @@
setSearchResultsContext,
} from 'src/features/search/search.svelte';
import { getSheetContext } from 'src/sheets/sheet-context.svelte';
import { formatAsModifier } from 'src/utils/formatting';
let context = $derived(getSheetContext<ActorSheetContextV1>());
let context =
$derived(
getSheetContext<
CharacterSheetContext | NpcSheetContext | VehicleSheetContext
>(),
);
let tabId = getContext<string>(CONSTANTS.SVELTE_CONTEXT.TAB_ID);
let inlineToggleService = getContext<InlineToggleService>(
CONSTANTS.SVELTE_CONTEXT.INLINE_TOGGLE_SERVICE,
Expand Down Expand Up @@ -127,6 +137,8 @@
{/snippet}
{#snippet body()}
{#each section.actions as actionItem (actionItem.item.id)}
{@const ctx = context.itemContext[actionItem.item.id]}

<ItemTableRow
item={actionItem.item}
onMouseDown={(event) =>
Expand Down Expand Up @@ -248,27 +260,27 @@
</ItemTableCell>
<ItemTableCell baseWidth="5rem" cssClass="flex-column no-gap">
<!-- HIT / DC -->
{#if actionItem.item.labels?.save || actionItem.item.labels?.toHit}
{#if actionItem.item.labels?.save !== '' && actionItem.item.labels?.save !== undefined}
{@const saveAbilityLabel =
FoundryAdapter.lookupAbility(
actionItem.item.system.save.ability,
)?.label ?? ''}
{@const save = ctx?.save}
{#if save?.dc || ctx?.toHit}
{#if save?.dc}
<span
title={actionItem.item.labels?.save ?? ''}
class="flex-column-truncate"
>
{localize('DND5E.AbbreviationDC')}
{actionItem.item.system.save.dc ?? ''}
{save.dc.value}
</span>
<small
title={saveAbilityLabel}
class="flex-column-truncate">{saveAbilityLabel}</small
title={save.ability}
class="flex-column-truncate dc-ability-text"
>
{save.ability}
</small>
{:else}
<span title={actionItem.item.labels?.toHit ?? ''}
>{actionItem.item.labels?.toHit ?? ''}</span
>
{@const toHit = formatAsModifier(
ctx.toHit?.toString() ?? '',
)}
<span>{toHit}</span>
{/if}
{/if}
</ItemTableCell>
Expand Down Expand Up @@ -347,4 +359,8 @@
small {
color: var(--t5e-tertiary-color);
}
.dc-ability-text {
text-transform: uppercase;
}
</style>
3 changes: 3 additions & 0 deletions src/types/group.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
ActorV2,
ContainerPanelItemContext,
InventorySection,
ItemSaveContext,
Tab,
TidySectionBase,
Utilities,
Expand Down Expand Up @@ -55,6 +56,8 @@ export interface GroupItemContext {
containerContents?: ContainerContents;
hasUses?: boolean;
isStack?: boolean;
save?: ItemSaveContext;
toHit?: number | null;
totalWeight?: number;
}

Expand Down
15 changes: 15 additions & 0 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@ export type AvailableLevel = {

export type AttunementContext = { icon: string; cls: string; title: string };

export type ItemSaveContext = {
ability: string;
dc: {
calculation: string;
formula: string;
value: number;
};
};

export type CharacterItemContext = {
activities?: ActivityItemContext[];
attunement?: AttunementContext;
Expand All @@ -226,6 +235,8 @@ export type CharacterItemContext = {
isStack?: boolean;
linkedUses?: LinkedUses;
needsSubclass?: boolean;
save?: ItemSaveContext;
toHit?: number | null;
toggleClass?: string;
toggleTitle?: string;
totalWeight?: number;
Expand Down Expand Up @@ -423,6 +434,8 @@ export type NpcItemContext = {
linkedUses?: LinkedUses;
needsSubclass?: boolean;
parent?: Item5e;
save?: ItemSaveContext;
toHit?: number | null;
toggleTitle?: string;
totalWeight?: number;
};
Expand Down Expand Up @@ -468,6 +481,8 @@ export type VehicleItemContext = {
containerContents?: ContainerContents;
cover?: string;
hasUses?: boolean;
save?: ItemSaveContext;
toHit?: number | null;
threshold?: number | string;
toggleClass?: string;
toggleTitle?: string;
Expand Down
13 changes: 8 additions & 5 deletions src/utils/formula.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,15 @@ export function calculateSpellAttackAndDc(
spellAbility as keyof typeof CONFIG.DND5E.abilities
]?.label ?? FoundryAdapter.localize('DND5E.None');

const hasSpellcastingProgression =
!isNil(spellClass?.system.spellcasting.progression) &&
spellClass?.system.spellcasting.progression !==
CONSTANTS.SPELLCASTING_PROGRESSION_NONE;

return {
dc:
spellClass?.system.spellcasting.progression !==
CONSTANTS.SPELLCASTING_PROGRESSION_NONE
? spellClass?.system.spellcasting.save
: actor.system.attributes.spelldc,
dc: hasSpellcastingProgression
? spellClass?.system.spellcasting.save
: actor.system.attributes.spelldc,
dcTooltip: getDcTooltip(actor, spellAbility),
meleeMod: msakTotal,
meleeTooltip: buildAttackModTooltip(
Expand Down

0 comments on commit ee0b6bf

Please sign in to comment.