afnm-types 0.6.57 → 0.6.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- export type GameScreen = 'location' | 'recipe' | 'mission' | 'craftingHall' | 'manual' | 'cultivation' | 'map' | 'healer' | 'market' | 'favour' | 'herbField' | 'mine' | 'recipeLibrary' | 'requestBoard' | 'compendium' | 'library' | 'altar' | 'research' | 'reforge' | 'pillarGrid' | 'fallenStar' | 'trainingGround' | 'tenThousandFlames' | 'lifeScreen' | 'soulShardDelve' | 'enchantmentShop' | 'challengeBoard';
2
- export type ScreenType = GameScreen | 'newgame' | 'combat' | 'crafting' | 'dualCultivation' | 'event' | 'auction' | 'mysticalRegion' | 'tournament' | 'house' | 'guild' | 'stoneCutting' | 'fallenStar' | 'soulShardDelve';
1
+ export type GameScreen = 'location' | 'recipe' | 'mission' | 'craftingHall' | 'manual' | 'cultivation' | 'map' | 'healer' | 'market' | 'favour' | 'herbField' | 'mine' | 'recipeLibrary' | 'requestBoard' | 'compendium' | 'library' | 'altar' | 'research' | 'reforge' | 'expedition' | 'pillarGrid' | 'fallenStar' | 'trainingGround' | 'tenThousandFlames' | 'lifeScreen' | 'soulShardDelve' | 'enchantmentShop' | 'challengeBoard' | 'formationPuzzle' | 'rumours';
2
+ export type ScreenType = GameScreen | 'newgame' | 'combat' | 'crafting' | 'dualCultivation' | 'event' | 'auction' | 'mysticalRegion' | 'tournament' | 'house' | 'guild' | 'stoneCutting' | 'fallenStar' | 'soulShardDelve' | 'expedition';
package/dist/audio.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export declare const ambienceNames: readonly ["HerbField", "Market", "Forge", "SectHall", "Wind", "Crypt", "Forest", "Rain", "BoilingLake", "BoilingLakeSurface", "Field", "Space", "CultivationChamber"];
2
2
  export type AmbienceName = (typeof ambienceNames)[number];
3
- export declare const musicNames: readonly ["Ascending", "Crafting", "Crypt", "Forest", "Herb", "Lake", "Liangtiao", "Mine", "Observatory", "Reststop", "Sect", "Settingoff", "Shenhenda", "Tomb", "Valley", "Combat", "Xidian", "North", "Wastes", "DualCultivation", "ProgenitorRuGong", "ProgenitorDongTiang", "ProgenitorYingMeihua", "ProgenitorDiaoGian", "ProgenitorTeJinshu", "ProgenitorLuBuLin"];
3
+ export declare const musicNames: readonly ["Ascending", "Crafting", "Crypt", "Forest", "Herb", "Lake", "Liangtiao", "Mine", "Observatory", "Reststop", "Sect", "Settingoff", "Shenhenda", "Tomb", "Valley", "Combat", "Xidian", "North", "Wastes", "DualCultivation", "ProgenitorRuGong", "ProgenitorDongTiang", "ProgenitorYingMeihua", "ProgenitorDiaoGian", "ProgenitorTeJinshu", "ProgenitorLuBuLin", "YuMaiMine", "JadeForest", "Expedition", "SoulShard"];
4
4
  export type MusicName = (typeof musicNames)[number];
5
5
  export declare const soundEffectNames: readonly ["Hit", "Buff", "Debuff", "Heal", "Death", "Fuse", "Refine", "Stabilize", "Equip", "Drink", "Learn", "Crystal", "Eat", "BuySell", "Select", "Confirm", "Hover", "Cancel", "OpenEquip", "PlayerDialogOpen", "CrystalCrack", "CrystalCrackOpen", "CrystalCrackBg", "ChangeTab", "Failed", "MasteryUnveil", "BuildingEnter", "Talk", "Healer", "DialogClose", "BuildingLeave", "SelectItem", "RemoveItem", "BottleneckBreakthrough", "BreakthroughLightning", "Pool", "CraftingBuff", "CraftFail", "CraftSuccess", "PerfectCraft", "TakeItem", "Text", "Speech", "Destiny", "Money", "Favour", "Reputation", "Qi", "Location", "BreakthroughItemSet", "BreakthroughItemRemove", "Footstep", "Fly", "SpawnImpact", "SelectStance", "Plant", "Unplant", "Collect", "Dig", "GrowlBark", "GrowlChirp", "GrowlDeep", "GrowlDrone", "GrowlFrog", "GrowlGrind", "GrowlHigh", "GrowlLoud", "GrowlMinotaur", "GrowlRumble", "GrowlScreech", "GrowlSlow", "GrowlSnuffle", "Satisfaction", "CloudAttack", "BlossomAttack", "FistAttack", "WeaponAttack", "BloodAttack", "CelestialAttack"];
6
6
  export type SoundEffectName = (typeof soundEffectNames)[number];
package/dist/audio.js CHANGED
@@ -40,6 +40,10 @@ export const musicNames = [
40
40
  'ProgenitorDiaoGian',
41
41
  'ProgenitorTeJinshu',
42
42
  'ProgenitorLuBuLin',
43
+ 'YuMaiMine',
44
+ 'JadeForest',
45
+ 'Expedition',
46
+ 'SoulShard',
43
47
  ];
44
48
  export const soundEffectNames = [
45
49
  'Hit',
@@ -3,9 +3,17 @@ import type { ReactNode } from 'react';
3
3
  import type { CombatEntity, CraftingEntity, PlayerEntity, StoredStance, StoredStyle } from './entity';
4
4
  import type { ItemDesc } from './item';
5
5
  import type { Realm, RealmProgress } from './realm';
6
- import type { PhysicalStatistic, SocialStatistic, Scaling } from './stat';
6
+ import type { CombatStatistic, CraftingStatistic, PhysicalStatistic, Scaling, SocialStatistic } from './stat';
7
7
  import type { Buff } from './buff';
8
8
  import type { CraftingBuff } from './craftingBuff';
9
+ /**
10
+ * Discriminator for manifestation events queued and replayed during the
11
+ * lifeFlourishing breakthrough. Runtime constants matching each member live
12
+ * in src/store/slices/manifestation/manifestationFlags.ts and are typed
13
+ * against this union, so adding a new event there only compiles after the
14
+ * member is added here.
15
+ */
16
+ export type ManifestationEventId = 'manifestation_birth' | 'manifestation_aspect_filled_creativity' | 'manifestation_aspect_filled_empathy' | 'manifestation_aspect_filled_agency' | 'manifestation_focus_selector';
9
17
  export interface Position {
10
18
  x: number;
11
19
  y: number;
@@ -23,12 +31,177 @@ export interface StoredFigment {
23
31
  stances: StoredStance[];
24
32
  currentStyle?: StoredStyle;
25
33
  storedStyles?: StoredStyle[];
34
+ assignedTiers?: Record<string, number>;
35
+ }
36
+ /** Variant of an incursion fight. Drives the enemy roster and the reward
37
+ * amount the player gets when they win. */
38
+ export type IncursionKind = 'normal' | 'horde' | 'boss';
39
+ /** An active firmament incursion targeting the player's inner world */
40
+ export interface ActiveIncursion {
41
+ id: string;
42
+ spawnedYear: number;
43
+ spawnedMonth: number;
44
+ /** Variant of fight when the player engages this incursion. Defaults to
45
+ * 'normal' for backward compatibility with saves spawned before kinds
46
+ * existed. */
47
+ kind?: IncursionKind;
48
+ /** Frozen difficulty proxy used to scale the enemies on engagement.
49
+ * Sampled at spawn time from the live firmament progress plus a small
50
+ * random jitter and a -5% offset per active incursion. Falling back to
51
+ * the live progress is fine for legacy incursions. */
52
+ effectiveProgress?: number;
53
+ /** Amount of +N applied per chosen figment-upgrade pick after a win.
54
+ * 1 for normal, larger for harder variants. */
55
+ upgradeAmount?: number;
56
+ }
57
+ /** Generated but uncollected essence accumulating in the inner world */
58
+ export interface PendingEssence {
59
+ essenceItemName: string;
60
+ count: number;
61
+ progress: number;
62
+ }
63
+ /** Three life aspects that grow as the manifestation lives in the world. */
64
+ export type ManifestationAspect = 'creativity' | 'empathy' | 'agency';
65
+ /** A single entry in the manifestation's activity diary. */
66
+ export interface ManifestationLogEntry {
67
+ year: number;
68
+ month: number;
69
+ day: number;
70
+ /** Localisable log line built from real game-data nouns. */
71
+ text: Translatable;
72
+ /** Which aspect this entry advanced, if any. */
73
+ aspect?: ManifestationAspect;
74
+ /** Aspect delta from this entry (typically 0 on failure, +1 on success). */
75
+ delta?: number;
76
+ }
77
+ /** Tracks one recently-consumed item for the creativity gift bonus. */
78
+ export interface ManifestationConsumptionEntry {
79
+ item: string;
80
+ count: number;
81
+ day: number;
82
+ }
83
+ /** Capstone of the Life Flourishing realm: an autonomous lifeform walking the world. */
84
+ export interface ManifestationState {
85
+ /** Player-visible name. Generated at first manifest, editable. */
86
+ name: string;
87
+ /** Linked StoredFigment id that provides visuals, species, and stances. */
88
+ figmentId: string;
89
+ /** Calendar year of first manifestation. */
90
+ birthYear: number;
91
+ /** Calendar month of first manifestation. */
92
+ birthMonth: number;
93
+ /** Aspect values, 0..100 integer. */
94
+ creativity: number;
95
+ empathy: number;
96
+ agency: number;
97
+ /** Biases the monthly move decision and which aspect category actions prefer. */
98
+ focus: ManifestationAspect;
99
+ /** Current location (GameLocation.name) the manifestation is wandering at. */
100
+ locationName: string;
101
+ /** Months spent at the current location; forces a move if it stagnates. */
102
+ monthsAtLocation: number;
103
+ /**
104
+ * Destination the manifestation is travelling toward. Movement is
105
+ * resolved one node per month along the shortest path; once
106
+ * `locationName === destinationLocationName` the field is cleared.
107
+ * Undefined means "no current journey, idle at locationName."
108
+ */
109
+ destinationLocationName?: string;
110
+ /** Ring buffer of diary entries, newest last. Capped at MANIFESTATION_LOG_CAP. */
111
+ log: ManifestationLogEntry[];
112
+ /** Accumulator so day-batches still emit one entry per 3 days. */
113
+ daysSinceLastLog: number;
114
+ /** Manifestation events that have already played. */
115
+ seenEvents: ManifestationEventId[];
116
+ /** Manifestation event queued to play on next player co-located interaction. */
117
+ pendingEvent?: ManifestationEventId;
118
+ /** Months until a random-encounter milestone is eligible again. */
119
+ randomEventCooldown: number;
120
+ /** Creativity gift cooldown in months. <=0 means eligible to gift. */
121
+ creativityGiftCooldown: number;
122
+ /** Empathy companion cooldown in months. <=0 means eligible to join. */
123
+ empathyCompanionCooldown: number;
124
+ /** Items the player has recently consumed; bounded ring of size MANIFESTATION_CONSUMPTION_CAP. */
125
+ recentConsumption: ManifestationConsumptionEntry[];
26
126
  }
27
127
  /** State for the Life Flourishing breakthrough system */
28
128
  export interface LifeFlourishingState {
29
129
  unlockedSpecies: string[];
30
130
  storedFigments: StoredFigment[];
31
- manifestedFigmentId?: string;
131
+ evokedFigmentId?: string;
132
+ worldAspectId?: string;
133
+ firmamentProgress?: number;
134
+ activeIncursions?: ActiveIncursion[];
135
+ pendingEssences?: PendingEssence[];
136
+ essenceTiersUnlocked?: Record<string, number>;
137
+ /** The single manifested lifeform, if any. */
138
+ manifestation?: ManifestationState;
139
+ /**
140
+ * Lifeform realm used for inner-world combat (incursions + expand) ONLY.
141
+ * Independent of the player's realm. Defaults to bodyForging / Early when
142
+ * unset. When the lifeform is manifested in the outer world, the
143
+ * manifestation companion stats still read player realm.
144
+ */
145
+ lifeformRealm?: Realm;
146
+ /** Step within the lifeform realm: 0 = Early, 1 = Middle, 2 = Late. */
147
+ lifeformRealmStep?: LifeformRealmStep;
148
+ /**
149
+ * Calendar stamp of when the player first created any figment. Drives the
150
+ * time component of the incursion spawn rate. Undefined => no incursions
151
+ * can spawn yet.
152
+ */
153
+ firstFigmentYear?: number;
154
+ firstFigmentMonth?: number;
155
+ /** Global figment upgrade pool earned from incursion victories. */
156
+ figmentUpgrades?: FigmentUpgrades;
157
+ /**
158
+ * Present while an unspent incursion-victory upgrade is owed to the player.
159
+ * The Life screen renders a blocking picker until the player picks one.
160
+ * `upgradeAmount` is the +N applied when an upgrade is chosen; carried over
161
+ * from the resolved incursion so harder variants pay out more.
162
+ * `baseExpansion` is the firmament-expansion gain already auto-applied on
163
+ * victory (1-3%), surfaced in the picker so the player can see it.
164
+ */
165
+ pendingFigmentUpgrade?: {
166
+ upgradeAmount: number;
167
+ baseExpansion: number;
168
+ };
169
+ /** Ids of minor world aspects the player has unlocked. */
170
+ unlockedMinorAspectIds?: string[];
171
+ /**
172
+ * Three slots arranged in an arc below the main aspect; each entry is the
173
+ * world aspect id placed in that slot (major or minor) or undefined.
174
+ * Length grows as the player unlocks slots (cap 3).
175
+ */
176
+ slottedAspectIds?: (string | undefined)[];
177
+ /**
178
+ * Months remaining of firmament-suppression from a consumed Calming item.
179
+ * While positive, the monthly incursion-chance accumulation is halved.
180
+ * Refreshing the buff (consuming another item) re-sets it to the full
181
+ * duration rather than stacking.
182
+ */
183
+ firmamentReductionMonths?: number;
184
+ /**
185
+ * Accumulated incursion-spawn chance, 0..100. Each month the spawn formula
186
+ * adds its computed value to this counter (instead of rolling against it).
187
+ * When it crosses 100 an incursion spawns and the counter resets to 0.
188
+ */
189
+ incursionChance?: number;
190
+ }
191
+ /** Step within a lifeform realm: 0 = Early, 1 = Middle, 2 = Late. */
192
+ export type LifeformRealmStep = 0 | 1 | 2;
193
+ /**
194
+ * Global figment combat upgrades. The five percent fields are capped at 30
195
+ * (each point = +1%). Enhancement is uncapped and applies as a flat +N
196
+ * enhancement to every figment technique used in inner-world combat.
197
+ */
198
+ export interface FigmentUpgrades {
199
+ hp: number;
200
+ power: number;
201
+ protection: number;
202
+ barrierMit: number;
203
+ critMult: number;
204
+ enhancement: number;
32
205
  }
33
206
  export interface BreakthroughState {
34
207
  mundane?: {
@@ -48,6 +221,10 @@ export interface BreakthroughState {
48
221
  };
49
222
  coreFormation?: {
50
223
  compressions?: number;
224
+ /** Location names of altars the player has successfully compressed at
225
+ * at least once. Used to gate past-9 over-compressions to new altars,
226
+ * and to grant per-altar stat bonuses on breakthrough. */
227
+ beatenAltars?: string[];
51
228
  };
52
229
  pillarCreation?: {
53
230
  grid: string[];
@@ -82,6 +259,16 @@ export interface BreakthroughBase {
82
259
  socialStats: Partial<{
83
260
  [key in SocialStatistic]: number;
84
261
  }>;
262
+ /** Permanent additive combat-stat bonuses granted by the breakthrough.
263
+ * Values are `Scaling` so the dialog can render multipliers as "+10%
264
+ * Power" instead of the evaluated flat amount. */
265
+ combatStats?: Partial<{
266
+ [key in CombatStatistic]: Scaling;
267
+ }>;
268
+ /** Permanent additive crafting-stat bonuses granted by the breakthrough. */
269
+ craftingStats?: Partial<{
270
+ [key in CraftingStatistic]: Scaling;
271
+ }>;
85
272
  combatBuffs?: {
86
273
  buff: Buff;
87
274
  buffStacks: Scaling;
@@ -141,6 +328,12 @@ export interface Breakthrough extends BreakthroughBase {
141
328
  socialStats: Partial<{
142
329
  [key in SocialStatistic]: number;
143
330
  }>;
331
+ combatStats?: Partial<{
332
+ [key in CombatStatistic]: Scaling;
333
+ }>;
334
+ craftingStats?: Partial<{
335
+ [key in CraftingStatistic]: Scaling;
336
+ }>;
144
337
  combatBuffs?: {
145
338
  buff: Buff;
146
339
  buffStacks: Scaling;
package/dist/buff.d.ts CHANGED
@@ -101,6 +101,14 @@ export interface Buff {
101
101
  type?: TechniqueElement;
102
102
  noneType?: string;
103
103
  secondaryType?: TechniqueElement | 'origin';
104
+ /** Marks this buff as droplet-flavoured. Its outgoing damage / heal / barrier
105
+ * / temp HP effects gain the entity's <n>dropletBoost</n>, exactly as if the
106
+ * effects came from a technique with a droplet cost. */
107
+ isDroplet?: boolean;
108
+ /** Marks this buff as an opener for boost purposes. Effects gain <n>openerBoost</n>. */
109
+ isOpener?: boolean;
110
+ /** Marks this buff as a finisher for boost purposes. Effects gain <n>finisherBoost</n>. */
111
+ isFinisher?: boolean;
104
112
  enhancement?: number;
105
113
  beforeTechniqueEffects?: BuffEffect[];
106
114
  afterTechniqueEffects?: BuffEffect[];
@@ -188,6 +196,11 @@ export interface Buff {
188
196
  guardianHp?: number;
189
197
  /** Runtime guardian max HP — set automatically from guardianIntercept.maxHp at buff creation */
190
198
  guardianMaxHp?: number;
199
+ /** Cached hash of the static portion of this buff (name, flag, buffType,
200
+ * stats keys and values, condition). Populated lazily by cloneCombatEntity
201
+ * and createBuff so subsequent clones carry it forward via object spread,
202
+ * saving the per-call string-hashing work in calculateCombatEntityHash. */
203
+ _staticHash?: number;
191
204
  }
192
205
  type BuffCombatImage = ScatterCombatImage | ArcCombatImage | FloatingCombatImage | OverlayCombatImage | CompanionCombatImage | GuardianCombatImage | GroundCombatImage | FormationCombatImage | ForegroundCombatImage | BackgroundCombatImage | TransformationCombatImage | AvatarEffectCombatImage;
193
206
  interface BaseCombatImage {
@@ -0,0 +1,21 @@
1
+ import type { Buff } from './buff';
2
+ /**
3
+ * Per-entity indexes built by walking entity.buffs once, then read repeatedly
4
+ * during combat to avoid filtering the full buff list per category lookup.
5
+ *
6
+ * Invariant: indexes hold direct references into entity.buffs. They are valid
7
+ * only while that array's contents are unchanged. cloneCombatEntity does not
8
+ * carry the cache forward; invalidateEntityHash clears it after any mutation
9
+ * routed through mutateCombatEntity.
10
+ */
11
+ export interface BuffIndexes {
12
+ beforeTechnique: Buff[];
13
+ afterTechnique: Buff[];
14
+ onRound: Buff[];
15
+ onRoundStart: Buff[];
16
+ damageIntercept: Buff[];
17
+ guardian: Buff[];
18
+ buffAmplifier: Buff[];
19
+ techniqueAmplifier: Buff[];
20
+ byStat: Record<string, Buff[]>;
21
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -109,5 +109,7 @@ export interface NormalizedBuildSubmission {
109
109
  name?: string;
110
110
  stances: StoredStance[];
111
111
  currentStyle?: StoredStyle;
112
+ /** Per-essence tier assignments for this figment. */
113
+ assignedTiers?: Record<string, number>;
112
114
  };
113
115
  }
@@ -111,7 +111,7 @@ export interface Character {
111
111
  condition: string;
112
112
  }[];
113
113
  }
114
- export declare const characterRelationships: readonly ["Hostile", "Neutral", "Friendly", "Intimate"];
114
+ export declare const characterRelationships: readonly ["Hostile", "Neutral", "Friendly", "Intimate", "Special"];
115
115
  export type CharacterRelationship = (typeof characterRelationships)[number];
116
116
  export declare const relationshipTextColour: Record<CharacterRelationship, string>;
117
117
  export declare const relationshipBorderColour: Record<CharacterRelationship, string>;
@@ -196,6 +196,7 @@ export interface ShopCharacterInteraction extends BaseCharacterInteraction {
196
196
  tokenStock: Array<{
197
197
  item: Item;
198
198
  tokenCost: number;
199
+ buyAsStack?: boolean;
199
200
  }>;
200
201
  };
201
202
  }
package/dist/character.js CHANGED
@@ -1,19 +1,28 @@
1
- export const characterRelationships = ['Hostile', 'Neutral', 'Friendly', 'Intimate'];
1
+ export const characterRelationships = [
2
+ 'Hostile',
3
+ 'Neutral',
4
+ 'Friendly',
5
+ 'Intimate',
6
+ 'Special',
7
+ ];
2
8
  export const relationshipTextColour = {
3
9
  Hostile: 'red',
4
10
  Neutral: 'white',
5
11
  Friendly: 'palegreen',
6
12
  Intimate: 'pink',
13
+ Special: 'gold',
7
14
  };
8
15
  export const relationshipBorderColour = {
9
16
  Hostile: '#780000',
10
17
  Neutral: 'rgb(75,75,75)',
11
18
  Friendly: '#19521e',
12
19
  Intimate: '#9e007c',
20
+ Special: '#7a5900',
13
21
  };
14
22
  export const relationshipTooltip = {
15
23
  Hostile: 'You can attack a hostile character, or threaten them to steal their possessions.',
16
24
  Neutral: 'Willing to talk and maybe trade with you, but little else.',
17
25
  Friendly: '',
18
26
  Intimate: '',
27
+ Special: '',
19
28
  };
@@ -46,6 +46,7 @@ exports.NON_TRANSLATABLE_PROPERTIES = [
46
46
  'shard',
47
47
  'ability',
48
48
  'guild',
49
+ 'relationship',
49
50
  'eventName',
50
51
  'achievementID',
51
52
  'apiSecret',
@@ -327,6 +328,10 @@ exports.EXCLUDE_PATTERNS = [
327
328
  /^[a-z]+-[a-z]+,\s*[a-z]+-[a-z]+$/,
328
329
  // shaders
329
330
  /.*vec2.*/,
331
+ // CSS anywhere in the string
332
+ /@keyframes/,
333
+ /box-shadow/,
334
+ /rgb/i,
330
335
  ];
331
336
  /** Patterns to exclude from code-changes report */
332
337
  exports.CODE_CHANGE_EXCLUDE_PATTERNS = [
package/dist/combat.d.ts CHANGED
@@ -97,7 +97,7 @@ export interface CurrentCombatState {
97
97
  enemyEffectTracking: Record<string, CombatEffectTracking>;
98
98
  stanceTracking: Record<string, StanceTracking>;
99
99
  partyStanceTracking: Record<number, Record<string, StanceTracking>>;
100
- pillTracking: Record<string, number>;
100
+ pillTracking: Record<string, InventoryItemState>;
101
101
  autoUseRowTracking: Record<number, number>;
102
102
  inventoryItems?: InventoryItemState[];
103
103
  loot: Item[];
@@ -3,7 +3,7 @@ import type { ReactNode, PropsWithChildren, ReactElement } from 'react';
3
3
  import type { SoundEffectName } from './audio';
4
4
  import type { ScreenEffectType } from './ScreenEffectType';
5
5
  import type React from 'react';
6
- export type BorderType = 'wood' | 'mystic';
6
+ export type BorderType = 'wood' | 'mystic' | 'expedition' | 'expeditionSmall';
7
7
  interface GameDialogProps {
8
8
  id: string;
9
9
  onClose?: () => void;
@@ -33,6 +33,7 @@ export type GameIconButtonFC = React.ForwardRefRenderFunction<HTMLButtonElement,
33
33
  hoverSfx?: SoundEffectName;
34
34
  clickSfx?: SoundEffectName;
35
35
  tooltip?: ReactNode;
36
+ fancyBorder?: boolean;
36
37
  }>;
37
38
  export type GameCloseButtonFC = React.ForwardRefRenderFunction<HTMLButtonElement, Omit<IconButtonProps & {
38
39
  hoverSfx?: SoundEffectName;
package/dist/entity.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Translatable } from './translatable';
2
2
  import type { SoundEffectName } from './audio';
3
3
  import type { Buff } from './buff';
4
+ import type { BuffIndexes } from './buffIndexes';
4
5
  import type { CraftingBuff } from './craftingBuff';
5
6
  import type { CraftingTechnique, KnownCraftingTechnique } from './craftingTechnique';
6
7
  import type { TechniqueElement } from './element';
@@ -337,6 +338,12 @@ export interface CombatEntity {
337
338
  maxqiDroplets?: number;
338
339
  /** Cached hash for getVariablesFromEntity. Cleared whenever stats or buffs mutate. */
339
340
  _cachedHash?: string;
341
+ /** Cached buff indexes (by effect category and by stat). Cleared whenever buffs mutate.
342
+ * See src/util/buffIndexes.ts. */
343
+ _buffIndexes?: BuffIndexes;
344
+ /** Cached pre-trigger buff-count snapshot. Cleared whenever buffs mutate.
345
+ * See src/combat/effects/preTriggerSnapshot.ts. */
346
+ _preTriggerSnapshot?: Record<string, number>;
340
347
  }
341
348
  export type StanceRule = SingleStance | RandomStance;
342
349
  export interface SingleStance {
package/dist/event.d.ts CHANGED
@@ -7,6 +7,7 @@ import type { CraftingBuff } from './craftingBuff';
7
7
  import type { IntimateTrait } from './dualCultivation';
8
8
  import type { TechniqueElement } from './element';
9
9
  import type { EnemyEntity } from './entity';
10
+ import type { FormationGlyphId, FormationNodeId, FormationWinCondition } from './formation';
10
11
  import type { ItemDesc } from './item';
11
12
  import type { Realm, RealmProgress } from './realm';
12
13
  import type { PhysicalStatistic, ReputationTier, SocialStatistic } from './stat';
@@ -33,13 +34,13 @@ export interface GameEvent {
33
34
  value: number;
34
35
  }[];
35
36
  }
36
- export declare const EVENT_STEP_KINDS: readonly ["text", "speech", "combat", "crafting", "choice", "conditional", "flag", "exit", "createBuff", "consumeBuff", "addItem", "addMultipleItem", "dropItem", "removeItem", "replaceItem", "location", "quest", "money", "favour", "destiny", "reputation", "qi", "unlockLocation", "unlockAltar", "setCharacter", "clearCharacter", "label", "gotoLabel", "unlockCraftingTechnique", "unlockTechnique", "unlockAuctionTechnique", "addRecipe", "addManual", "learnNpcStances", "talkToCharacter", "tradeWithCharacter", "craftWithCharacter", "fightCharacter", "markBeatCharacter", "markDidEncounter", "changeHp", "passTime", "analytics", "approval", "progressRelationship", "selectRelationshipPath", "updateCharacterDefinition", "markGifted", "auction", "markCalendarEventComplete", "advanceMysticalRegion", "craftSkill", "tournament", "dualCultivation", "teamUp", "craftingTeamUp", "addFollower", "breakParty", "clearTeamUp", "setAltarCooldown", "setTradeCooldown", "compressCore", "changeScreen", "changeBGM", "clearChangeBGM", "addGuildApproval", "advanceGuildRank", "overridePlayerRealm", "setContentRealmOverride", "setAidBreakthroughCooldown", "stoneCutting", "giveItem", "changePhysicalStat", "changeSocialStat", "status", "clearStatus"];
37
+ export declare const EVENT_STEP_KINDS: readonly ["text", "speech", "combat", "crafting", "choice", "conditional", "flag", "exit", "createBuff", "consumeBuff", "addItem", "addMultipleItem", "dropItem", "removeItem", "replaceItem", "location", "quest", "money", "favour", "destiny", "reputation", "qi", "unlockLocation", "unlockAltar", "setCharacter", "clearCharacter", "label", "gotoLabel", "unlockCraftingTechnique", "unlockTechnique", "unlockAuctionTechnique", "addRecipe", "addManual", "learnNpcStances", "talkToCharacter", "tradeWithCharacter", "craftWithCharacter", "fightCharacter", "markBeatCharacter", "markDidEncounter", "changeHp", "passTime", "analytics", "approval", "progressRelationship", "selectRelationshipPath", "updateCharacterDefinition", "markGifted", "auction", "markCalendarEventComplete", "advanceMysticalRegion", "craftSkill", "tournament", "dualCultivation", "teamUp", "craftingTeamUp", "addFollower", "breakParty", "clearTeamUp", "setAltarCooldown", "setTradeCooldown", "compressCore", "changeScreen", "changeBGM", "clearChangeBGM", "addGuildApproval", "advanceGuildRank", "overridePlayerRealm", "setContentRealmOverride", "setAidBreakthroughCooldown", "stoneCutting", "formationPuzzle", "giveItem", "changePhysicalStat", "changeSocialStat", "status", "clearStatus"];
37
38
  export type EventStepKind = (typeof EVENT_STEP_KINDS)[number];
38
39
  export interface BaseEventStep {
39
40
  kind: EventStepKind;
40
41
  condition?: string;
41
42
  }
42
- export type EventStep = TextStep | SpeechStep | CombatStep | CraftingStep | ChoiceStep | ConditionalStep | SetFlagStep | ExitStep | CreateBuffStep | ConsumeBuffStep | ChangeLocationStep | AddItemStep | RemoveItemStep | AddQuestStep | ChangeMoneyStep | ChangeFavourStep | AddDestinyStep | ChangeReputationStep | QiStep | UnlockLocationStep | ClearCharacterStep | SetCharacterStep | LabelStep | GotoLabelStep | UnlockCraftingTechniqueStep | TalkToCharacterStep | TradeWithCharacterStep | CraftWithCharacterStep | FightCharacterStep | MarkBeatCharacterStep | MarkDidEncounterStep | ChangeHpStep | PassTimeStep | ReportAnalyticsStep | ApprovalStep | ProgressRelationshipStep | MarkGiftedStep | UpdateCharacterDefinitionStep | AuctionStep | MarkCalendarEventCompleteStep | AddMultipleItemStep | AdvanceMysticalRegionStep | CraftSkillStep | TournamentStep | TeamUpStep | CraftingTeamUpStep | AddFollowerStep | BreakPartyStep | ClearTeamUpStep | UnlockAltarStep | DropItemStep | SetAltarCooldownStep | CompressCoreStep | ChangeScreenStep | UnlockTechniqueStep | UnlockAuctionTechniqueStep | AddRecipeStep | AddManualStep | LearnNpcStancesStep | ReplaceItemStep | DualCultivationStep | ChangeBGMStep | ClearChangeBGMStep | AddGuildApprovalStep | AdvanceGuildRankStep | OverridePlayerRealmStep | SetContentRealmOverrideStep | SetAidBreakthroughCooldownStep | StoneCuttingStep | GiveItemStep | ChangePhysicalStatStep | ChangeSocialStatStep | SelectRelationshipPathStep | SetTradeCooldownStep | StatusStep | ClearStatusStep;
43
+ export type EventStep = TextStep | SpeechStep | CombatStep | CraftingStep | ChoiceStep | ConditionalStep | SetFlagStep | ExitStep | CreateBuffStep | ConsumeBuffStep | ChangeLocationStep | AddItemStep | RemoveItemStep | AddQuestStep | ChangeMoneyStep | ChangeFavourStep | AddDestinyStep | ChangeReputationStep | QiStep | UnlockLocationStep | ClearCharacterStep | SetCharacterStep | LabelStep | GotoLabelStep | UnlockCraftingTechniqueStep | TalkToCharacterStep | TradeWithCharacterStep | CraftWithCharacterStep | FightCharacterStep | MarkBeatCharacterStep | MarkDidEncounterStep | ChangeHpStep | PassTimeStep | ReportAnalyticsStep | ApprovalStep | ProgressRelationshipStep | MarkGiftedStep | UpdateCharacterDefinitionStep | AuctionStep | MarkCalendarEventCompleteStep | AddMultipleItemStep | AdvanceMysticalRegionStep | CraftSkillStep | TournamentStep | TeamUpStep | CraftingTeamUpStep | AddFollowerStep | BreakPartyStep | ClearTeamUpStep | UnlockAltarStep | DropItemStep | SetAltarCooldownStep | CompressCoreStep | ChangeScreenStep | UnlockTechniqueStep | UnlockAuctionTechniqueStep | AddRecipeStep | AddManualStep | LearnNpcStancesStep | ReplaceItemStep | DualCultivationStep | ChangeBGMStep | ClearChangeBGMStep | AddGuildApprovalStep | AdvanceGuildRankStep | OverridePlayerRealmStep | SetContentRealmOverrideStep | SetAidBreakthroughCooldownStep | StoneCuttingStep | FormationPuzzleStep | GiveItemStep | ChangePhysicalStatStep | ChangeSocialStatStep | SelectRelationshipPathStep | SetTradeCooldownStep | StatusStep | ClearStatusStep | IncreaseInstabilityStep | EndExpeditionStep | AddItemsToFoundStep | AddItemsToExtractedStep;
43
44
  export interface TextStep extends BaseEventStep {
44
45
  kind: 'text';
45
46
  text: Translatable;
@@ -125,6 +126,7 @@ interface ItemCondition {
125
126
  item: ItemDesc;
126
127
  alternates?: ItemDesc[];
127
128
  amount: number;
129
+ displayName?: Translatable;
128
130
  }
129
131
  interface MoneyCondition {
130
132
  kind: 'money';
@@ -174,6 +176,7 @@ export interface CreateBuffStep extends BaseEventStep {
174
176
  buff: Buff;
175
177
  amount: string;
176
178
  persistBeyondEvent?: boolean;
179
+ debuff?: boolean;
177
180
  }
178
181
  export interface ConsumeBuffStep extends BaseEventStep {
179
182
  kind: 'consumeBuff';
@@ -469,6 +472,39 @@ export interface StoneCuttingStep extends BaseEventStep {
469
472
  /** Number of stones the player can cut for free, evaluated as expression */
470
473
  freeCount?: string;
471
474
  }
475
+ export interface FormationPuzzleStep extends BaseEventStep {
476
+ kind: 'formationPuzzle';
477
+ isTutorial?: boolean;
478
+ /** Shown in the activity history when the puzzle starts. */
479
+ displayName?: string;
480
+ /** Prefix for the per-glyph completion flags. For each glyph type with at
481
+ * least one activated placement, two flags are written, keyed by the
482
+ * glyph's single-character `gridSymbol` (the same symbol used in `layout`).
483
+ * `{flagPrefix}_{gridSymbol}` holds the total power absorbed across
484
+ * activated placements of that glyph type, and
485
+ * `{flagPrefix}_{gridSymbol}_count` holds the number of activated (fully
486
+ * powered) placements of that glyph type. */
487
+ flagPrefix: string;
488
+ /** ASCII grid layout. Each non-empty line is one row (top = y=0).
489
+ * Tokens: `.` empty cell, `_` off-grid, node gridSymbol for pre-placed
490
+ * (locked) nodes, `SYM:>` for a rotated pre-placed node. */
491
+ layout: string;
492
+ pool: {
493
+ nodes: {
494
+ nodeId: FormationNodeId;
495
+ count: number;
496
+ }[];
497
+ glyphs: {
498
+ nodeId: FormationGlyphId;
499
+ count: number;
500
+ }[];
501
+ };
502
+ winCondition: FormationWinCondition[];
503
+ /** Followed when the player presses Seal with the win condition met. */
504
+ success: EventStep[];
505
+ /** Followed when the player presses Give Up. */
506
+ failure: EventStep[];
507
+ }
472
508
  export interface GiveItemStep extends BaseEventStep {
473
509
  kind: 'giveItem';
474
510
  description: Translatable;
@@ -513,4 +549,26 @@ export interface EventStatusThreshold {
513
549
  colour: string;
514
550
  label?: Translatable;
515
551
  }
552
+ export interface IncreaseInstabilityStep {
553
+ kind: 'instability';
554
+ condition?: string;
555
+ }
556
+ export interface EndExpeditionStep {
557
+ kind: 'endExpedition';
558
+ failed: boolean;
559
+ condition?: string;
560
+ }
561
+ export interface AddItemsToFoundStep {
562
+ kind: 'addToFound';
563
+ items: {
564
+ item: ItemDesc;
565
+ count: number;
566
+ }[];
567
+ condition?: string;
568
+ }
569
+ export interface AddItemsToExtractedStep {
570
+ kind: 'addToExtracted';
571
+ extractSlots: number;
572
+ condition?: string;
573
+ }
516
574
  export {};
package/dist/event.js CHANGED
@@ -70,6 +70,7 @@ export const EVENT_STEP_KINDS = [
70
70
  'setContentRealmOverride',
71
71
  'setAidBreakthroughCooldown',
72
72
  'stoneCutting',
73
+ 'formationPuzzle',
73
74
  'giveItem',
74
75
  'changePhysicalStat',
75
76
  'changeSocialStat',