Skip to content

Commit

Permalink
Integrate 0.8 Combat and Combatant classes into system
Browse files Browse the repository at this point in the history
  • Loading branch information
stwlam committed May 22, 2021
1 parent 0bfd1fe commit 5689244
Show file tree
Hide file tree
Showing 80 changed files with 822 additions and 804 deletions.
51 changes: 35 additions & 16 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import { WorldClock } from '@system/world-clock';
import { EffectPanel } from '@system/effect-panel';
import { EffectTracker } from '@system/effect-tracker';
import { rollActionMacro, rollItemMacro } from '@scripts/macros/hotbar';
import { calculateXP } from '@scripts/macros/xp';
import { launchTravelSheet } from '@scripts/macros/travel/travel-speed-sheet';
import { ActorPF2e } from '@actor/base';
import { ItemPF2e } from '@item/base';
import { ConfigPF2e, StatusEffectIconType } from '@scripts/config';
import { CombatPF2e } from './module/combat';
import { ItemType } from '@item/data/types';
import { ActiveEffectPF2e } from '@module/active-effect';
import { CompendiumDirectoryPF2e } from '@module/apps/ui/compendium-directory';
import { ChatMessagePF2e } from '@module/chat-message';
import { MacroPF2e } from '@module/macro';
import { RuleElements } from '@module/rules/rules';
import { HomebrewSettingsKey, HomebrewTag } from '@module/settings/homebrew';
import { CombatTrackerPF2e } from '@module/system/combat-tracker';
import { StatusEffects } from '@scripts/actor/status-effects';
import { PF2ECONFIG, StatusEffectIconType } from '@scripts/config';
import { DicePF2e } from '@scripts/dice';
import { rollActionMacro, rollItemMacro } from '@scripts/macros/hotbar';
import { launchTravelSheet } from '@scripts/macros/travel/travel-speed-sheet';
import { calculateXP } from '@scripts/macros/xp';
import { EffectPanel } from '@system/effect-panel';
import { EffectTracker } from '@system/effect-tracker';
import { CheckPF2e } from '@system/rolls';
import { WorldClock } from '@system/world-clock';
import { CombatPF2e } from './module/combat';
import { ConditionManager } from './module/conditions';
import {
AbilityModifier,
CheckModifier,
ModifierPF2e,
MODIFIER_TYPE,
StatisticModifier,
ProficiencyModifier,
StatisticModifier,
} from './module/modifiers';
import { ConditionManager } from './module/conditions';
import { StatusEffects } from '@scripts/actor/status-effects';
import { DicePF2e } from '@scripts/dice';
import { ItemType } from '@item/data/types';
import { RuleElements } from '@module/rules/rules';
import { HomebrewSettingsKey, HomebrewTag } from '@module/settings/homebrew';
import { MacroPF2e } from '@module/macro';

type ItemTypeMap = {
[K in ItemType]: Owned<InstanceType<ConfigPF2e['PF2E']['Item']['entityClasses'][K]>>[];
Expand Down Expand Up @@ -60,6 +64,21 @@ declare global {
itemTypes: ItemTypeMap;
}

interface ConfigPF2e extends Config<ActorPF2e, CombatPF2e, ItemPF2e, ActiveEffectPF2e, ChatMessagePF2e, MacroPF2e> {
debug: Config['debug'] & {
ruleElement: boolean;
};

PF2E: typeof PF2ECONFIG;
time: {
roundTime: number;
};
ui: Config<ActorPF2e, CombatPF2e, ItemPF2e, ActiveEffectPF2e, ChatMessagePF2e, MacroPF2e>['ui'] & {
combat: typeof CombatTrackerPF2e;
compendium: typeof CompendiumDirectoryPF2e;
};
}

const CONFIG: ConfigPF2e;
const canvas: Canvas<ActorPF2e>;
namespace globalThis {
Expand Down
14 changes: 7 additions & 7 deletions src/module/actor/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export class ActorPF2e extends Actor<ItemPF2e, ActiveEffectPF2e> {
ui.notifications.error(`No combatant found for ${this.name} in the Combat Tracker.`);
return;
}
game.combat.setInitiative(combatant._id, roll.total);
game.combat.setInitiative(combatant.id, roll.total);
} else {
console.log(
'PF2e System | _applyInitiativeRollToCombatTracker | invalid roll object or roll.value mising: ',
Expand Down Expand Up @@ -563,14 +563,14 @@ export class ActorPF2e extends Actor<ItemPF2e, ActiveEffectPF2e> {
const skillRolled = roll.find('.flavor-text').text();
const valueRolled = parseFloat(roll.find('.dice-total').text());
const promises: Promise<void>[] = [];
for (const t of canvas.tokens.controlled) {
for (const token of canvas.tokens.controlled) {
if (!game.combat) {
ui.notifications.error('No active encounters in the Combat Tracker.');
return;
}

const combatant = game.combat.getCombatantByToken(t.id);
if (combatant === undefined) {
const combatant = game.combat.getCombatantByToken(token.id);
if (!combatant) {
ui.notifications.error("You haven't added this token to the Combat Tracker.");
return;
}
Expand All @@ -596,13 +596,13 @@ export class ActorPF2e extends Actor<ItemPF2e, ActiveEffectPF2e> {
`;
ChatMessage.create({
user: game.user.id,
speaker: { alias: t.name },
speaker: { alias: token.name },
content: message,
whisper: ChatMessage.getWhisperRecipients('GM'),
type: CONST.CHAT_MESSAGE_TYPES.OTHER,
});

promises.push(game.combat.setInitiative(combatant._id, value));
promises.push(game.combat.setInitiative(combatant.id, value));
}

await Promise.all(promises);
Expand Down Expand Up @@ -1168,5 +1168,5 @@ export interface HazardPF2e {
data: HazardData;
}

export type TokenPF2e = Token<ActorPF2e>;
export type TokenPF2e = Token<ActorPF2e> & { statusEffectChanged?: boolean };
export type UserPF2e = User<ActorPF2e>;
1 change: 0 additions & 1 deletion src/module/actor/character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import { BackgroundPF2e } from '@item/background';
import { ClassPF2e } from '@item/class';
import { CreaturePF2e } from './creature';
import { LocalizePF2e } from '@module/system/localize';
import { ConfigPF2e } from '@scripts/config';
import { FeatPF2e } from '@item/feat';
import { AutomaticBonusProgression } from '@module/rules/automatic-bonus';

Expand Down
1 change: 0 additions & 1 deletion src/module/actor/data-definitions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { BaseWeaponType, ConsumableData, ItemDataPF2e, Rarity, Size, WeaponGroup } from '@item/data/types';
import { StatisticModifier, CheckModifier, ModifierPF2e, DamageDicePF2e, MODIFIER_TYPE } from '../modifiers';
import { RollParameters } from '@system/rolls';
import { ConfigPF2e } from '@scripts/config';
import { DamageType } from '@module/damage-calculation';

export type ZeroToThree = 0 | 1 | 2 | 3;
Expand Down
2 changes: 1 addition & 1 deletion src/module/actor/npc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ export class NPCPF2e extends CreaturePF2e {
});
}

updateNPCAttitudeFromDisposition(disposition: number) {
updateAttitudeFromDisposition(disposition: number) {
this.data.data.traits.attitude.value = NPCPF2e.mapTokenDispositionToNPCAttitude(disposition);
}
}
Expand Down
1 change: 0 additions & 1 deletion src/module/actor/sheet/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import {
TraitSelectorSpeeds,
TraitSelectorWeaknesses,
} from '@module/system/trait-selector';
import { ConfigPF2e } from '@scripts/config';
import { NPCPF2e } from '@actor/npc';
import { CharacterPF2e } from '@actor/character';

Expand Down
1 change: 0 additions & 1 deletion src/module/actor/sheet/simple-npc-sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import {
WeaponData,
} from '@item/data/types';
import { ErrorPF2e, getActionGlyph, objectHasKey } from '@module/utils';
import { ConfigPF2e } from '@scripts/config';
import { InventoryItem, SheetInventory } from './data-types';

interface NPCSheetLabeledValue extends LabeledString {
Expand Down
92 changes: 40 additions & 52 deletions src/module/combat.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
import { ActorPF2e } from '@actor/base';
import { ActorDataPF2e } from '@actor/data-definitions';

type CombatantDataPF2e = CombatantData<ActorPF2e>;
export class CombatPF2e extends Combat {
get active(): boolean {
return this.data.active;
}

export class CombatPF2e extends Combat<ActorPF2e> {
/** Exclude orphaned and loot-actor tokens from combat */
async createEmbeddedDocuments(
embeddedName: 'Combatant',
data: CombatantDataPF2e[],
options?: EntityCreateOptions,
): Promise<CombatantDataPF2e[]>;
async createEmbeddedDocuments(
embeddedName: 'Combatant',
data: CombatantDataPF2e[],
options?: EntityCreateOptions,
): Promise<CombatantDataPF2e[]>;
async createEmbeddedDocuments(
embeddedName: 'Combatant',
data: CombatantDataPF2e[],
options?: EntityCreateOptions,
): Promise<CombatantDataPF2e[]> {
const createData = (Array.isArray(data) ? data : [data]).filter((datum) => {
data: Partial<foundry.data.CombatantSource>[],
context?: DocumentModificationContext,
): Promise<Combatant[]> {
const createData = data.filter((datum) => {
const token = canvas.tokens.placeables.find((canvasToken) => canvasToken.id === datum.tokenId);
if (token === undefined) {
return false;
}
if (token.actor === null) {
if (!token) return false;
if (!token.actor) {
ui.notifications.warn(`${token.name} has no associated actor.`);
return false;
}
Expand All @@ -35,41 +24,40 @@ export class CombatPF2e extends Combat<ActorPF2e> {
}
return true;
});
return super.createEmbeddedDocuments(embeddedName, createData, options);
return super.createEmbeddedDocuments(embeddedName, createData, context);
}
}

/** Use a Pathfinder 2e roll formula */
_getInitiativeFormula(combatant: CombatantDataPF2e): string {
const { actor } = combatant;
if (!actor) return '1d20';
const actorType = actor.data.type;
const data: Partial<ActorDataPF2e['data']> = actor ? actor.data.data : {};
let bonus: number;
const modifierEnabledInit = data.attributes?.initiative?.totalModifier;
if (actorType === 'hazard') {
bonus = data.attributes.stealth.value;
} else if (modifierEnabledInit !== undefined) {
bonus = modifierEnabledInit;
} else {
bonus = data.attributes.perception.value;
}

const parts = ['1d20', bonus || 0];
/** Use a Pathfinder 2e roll formula */
export function initiativeFormula(combatant: Combatant): string {
const { actor } = combatant;
if (!actor) return '1d20';
const actorType = actor.data.type;
const data: Partial<ActorDataPF2e['data']> = actor ? actor.data.data : {};
let bonus: number;
const modifierEnabledInit = data.attributes?.initiative?.totalModifier;
if (actorType === 'hazard') {
bonus = data.attributes.stealth.value;
} else if (modifierEnabledInit !== undefined) {
bonus = modifierEnabledInit;
} else {
bonus = data.attributes.perception.value;
}

// Only show initiative bonuses if they are there. Else it always shows "+ 0" on the roll.
if (
((data.attributes.initiative || {}).circumstance || 0) +
((data.attributes.initiative || {}).status || 0) !==
0
) {
parts.push((data.attributes.initiative?.circumstance || 0) + (data.attributes.initiative?.status || 0));
}
const parts = ['1d20', bonus || 0];

// NPC's are always first in PF2e rules
if (!actor.hasPlayerOwner) {
parts.push(0.5);
}
// Only show initiative bonuses if they are there. Else it always shows "+ 0" on the roll.
if (
((data.attributes.initiative || {}).circumstance || 0) + ((data.attributes.initiative || {}).status || 0) !==
0
) {
parts.push((data.attributes.initiative?.circumstance || 0) + (data.attributes.initiative?.status || 0));
}

return parts.join('+');
// NPC's are always first in PF2e rules
if (!actor.hasPlayerOwner) {
parts.push(0.5);
}

return parts.join('+');
}
5 changes: 3 additions & 2 deletions src/module/conditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,9 @@ export class ConditionManager {
}

// Update token effects from applied conditions.
if (token.hasActiveHUD) {
await StatusEffects._updateHUD(canvas.tokens.hud?.element, token);
const hudElement = canvas.tokens.hud?.element;
if (token.hasActiveHUD && hudElement) {
await StatusEffects._updateHUD(hudElement, token);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/module/item/data/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AbilityString, CreatureTrait, ValuesList, ZeroToFour } from '@actor/data-definitions';
import { PF2RuleElementData } from '@module/rules/rules-data-definitions';
import { RollNotePF2e } from '@module/notes';
import { ConfigPF2e } from '@scripts/config';
import { PHYSICAL_ITEM_TYPES } from './values';
import { LocalizePF2e } from '@module/system/localize';
import { DamageType } from '@module/damage-calculation';
Expand Down
2 changes: 0 additions & 2 deletions src/module/item/data/values.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { ConfigPF2e } from '@scripts/config';

declare const CONFIG: ConfigPF2e;

export class MystifiedTraits {
Expand Down
7 changes: 3 additions & 4 deletions src/module/item/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ export class EffectPF2e extends ItemPF2e {
result.expired = result.remaining <= 0;
if (
result.remaining === 0 &&
game.combats && // game.combat will throw an exception unless game.combats has been initialized
game.combat &&
game.combat.data.active &&
game.combat?.active &&
game.combat.combatant &&
game.combat.turns.length > game.combat.turn
) {
const initiative = game.combat.turns[game.combat.turn].initiative;
const initiative = game.combat.combatant.initiative ?? 0;
if (initiative === this.data.data.start.initiative) {
result.expired = this.data.data.duration.expiry !== 'turn-end';
} else {
Expand Down
1 change: 0 additions & 1 deletion src/module/item/runes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
WeaponDetailsData,
} from './data/types';
import { DiceModifierPF2e } from '../modifiers';
import { ConfigPF2e } from '@scripts/config';
import { ZeroToFour, ZeroToThree } from '@actor/data-definitions';

type WeaponPropertyRuneType = keyof ConfigPF2e['PF2E']['weaponPropertyRunes'];
Expand Down
1 change: 0 additions & 1 deletion src/module/item/sheet/data-types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/** Item sheet form types */

import { ABCFeatureEntryData, AncestryData, BackgroundData, ClassData, FeatData, SpellData } from '@item/data/types';
import { ConfigPF2e } from '@scripts/config';
import { ItemSheetDataPF2e } from './base';

export interface SheetOption {
Expand Down
1 change: 0 additions & 1 deletion src/module/item/sheet/spell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ItemSheetDataPF2e, ItemSheetPF2e } from './base';
import { SpellData, SpellDetailsData } from '@item/data/types';
import { SpellPF2e } from '@item/spell';
import { SpellSheetData } from './data-types';
import { ConfigPF2e } from '@scripts/config';

export class SpellSheetPF2e extends ItemSheetPF2e<SpellPF2e> {
getData(): SpellSheetData {
Expand Down
1 change: 0 additions & 1 deletion src/module/item/spell-consumables.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ConsumablePF2e } from './index';
import { AbilityString } from '@actor/data-definitions';
import { ConfigPF2e } from '@scripts/config';
import type { ActorPF2e } from '../actor/base';
import { calculateDC, DCOptions } from '../dc';
import { ConsumableData, SpellData, TrickMagicItemCastData } from './data/types';
Expand Down
1 change: 0 additions & 1 deletion src/module/migrations/626-update-spell-category.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ValuesList } from '@actor/data-definitions';
import { ItemDataPF2e, SpellDetailsData } from '@item/data/types';
import { ConfigPF2e } from '@scripts/config';
import { MigrationBase } from './base';

/**
Expand Down
1 change: 0 additions & 1 deletion src/module/settings/homebrew/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { MigrationRunner } from '@module/migration-runner';
import '@yaireo/tagify/src/tagify.scss';
import { CharacterPF2e } from '@actor/character';
import { MigrationBase } from '@module/migrations/base';
import { ConfigPF2e } from '@scripts/config';
import { BaseWeaponType } from '@item/data/types';

export type ConfigPF2eListName = typeof HomebrewElements.SETTINGS[number];
Expand Down
Loading

0 comments on commit 5689244

Please sign in to comment.