afnm-types 0.6.29 → 0.6.32

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 +1 @@
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' | 'lifeScreen';
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';
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { Tutorial } from './tutorial';
2
3
  import { TriggeredEvent, GameEvent } from './event';
3
4
  import { ItemDesc } from './item';
@@ -19,16 +20,15 @@ export interface AlternativeStart {
19
20
  /**
20
21
  * Description shown in the selection UI explaining this start option
21
22
  */
22
- description: string;
23
+ description: Translatable;
23
24
  /**
24
25
  * The root event that plays when starting the game.
25
26
  * This replaces the default newGameEvent.
26
27
  */
27
28
  rootEvent: GameEvent;
28
29
  /**
29
- * The starting location name. This becomes the root for location discovery
30
- * (used by discoverUnlockedLocations). All location searches will branch
31
- * from this location.
30
+ * The starting location name. This location will be registered as a root
31
+ * for discovery (if not already) and the player will start here.
32
32
  */
33
33
  startLocation: string;
34
34
  /**
package/dist/auction.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { Item, ItemDesc } from './item';
2
3
  export interface Auction {
3
4
  characters: AuctionCharacterData[];
@@ -46,7 +47,7 @@ export interface AuctionCharacterData {
46
47
  speech?: Speech;
47
48
  }
48
49
  export interface Speech {
49
- text: string;
50
+ text: Translatable;
50
51
  id: number;
51
52
  persistent: boolean;
52
53
  }
@@ -59,7 +60,7 @@ export interface AuctionAbility {
59
60
  name: string;
60
61
  amount: number;
61
62
  };
62
- tooltip: string;
63
+ tooltip: Translatable;
63
64
  effects: AuctionAbilityEffect[];
64
65
  }
65
66
  export type AuctionAbilityEffect = DesireAbilityEffect | BuildResourceAbilityEffect | EliminateAbilityEffect;
@@ -82,7 +83,7 @@ export interface AuctionResource {
82
83
  name: string;
83
84
  icon: string;
84
85
  colour: string;
85
- tooltip: string;
86
+ tooltip: Translatable;
86
87
  bidMult?: number;
87
88
  degeneration?: 'bid' | 'item';
88
89
  }
@@ -1,9 +1,10 @@
1
+ import { Translatable } from './translatable';
1
2
  import { Destiny } from './destiny';
2
3
  import { Item } from './item';
3
4
  import { CombatStatistic, CraftingStatistic, PhysicalStatistic, Scaling, SocialStatistic } from './stat';
4
5
  export interface Background {
5
6
  name: string;
6
- description: string;
7
+ description: Translatable;
7
8
  physicalStats?: Partial<Record<PhysicalStatistic, number>>;
8
9
  socialStats?: Partial<Record<SocialStatistic, number>>;
9
10
  rawStats?: Partial<Record<CombatStatistic | CraftingStatistic, Scaling>>;
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { ReactNode } from 'react';
2
3
  import { CombatEntity, CraftingEntity, PlayerEntity, StoredStance, StoredStyle } from './entity';
3
4
  import { ItemDesc } from './item';
@@ -12,6 +13,34 @@ export interface Position {
12
13
  export interface PositionAndRotation extends Position {
13
14
  rotation: number;
14
15
  }
16
+ /** Tracks which of the 6 core essences have been placed in the gate */
17
+ export interface EssenceGate {
18
+ breath: boolean;
19
+ pulse: boolean;
20
+ echo: boolean;
21
+ growth: boolean;
22
+ marrow: boolean;
23
+ scar: boolean;
24
+ }
25
+ /** A lifeform stored in the player's soul realm */
26
+ export interface StoredLifeform {
27
+ id: string;
28
+ baseForm: string;
29
+ currentForm: string;
30
+ slottedEssences: string[];
31
+ stances: StoredStance[];
32
+ currentStyle?: StoredStyle;
33
+ storedStyles?: StoredStyle[];
34
+ evolutionPath: string[];
35
+ }
36
+ /** State for the Life Flourishing breakthrough system */
37
+ export interface LifeFlourishingState {
38
+ essenceGate: EssenceGate;
39
+ storedLifeforms: StoredLifeform[];
40
+ manifestedLifeformId?: string;
41
+ fightsInstead?: boolean;
42
+ creatingNewLifeform?: boolean;
43
+ }
15
44
  export interface BreakthroughState {
16
45
  mundane?: {
17
46
  pill?: string;
@@ -45,16 +74,7 @@ export interface BreakthroughState {
45
74
  }[];
46
75
  tilePool?: number;
47
76
  };
48
- lifeFlourishing?: {
49
- slottedEssences: string[];
50
- selectedLifeform?: string;
51
- fightsInstead?: boolean;
52
- lifeformEntity?: {
53
- stances: StoredStance[];
54
- currentStyle?: StoredStyle;
55
- storedStyles?: StoredStyle[];
56
- };
57
- };
77
+ lifeFlourishing?: LifeFlourishingState;
58
78
  previous: Partial<{
59
79
  [key in Realm]: BreakthroughBase;
60
80
  }>;
@@ -66,7 +86,7 @@ export interface BreakthroughState {
66
86
  }
67
87
  export interface BreakthroughBase {
68
88
  name: string;
69
- description: string;
89
+ description: Translatable;
70
90
  physicalStats: Partial<{
71
91
  [key in PhysicalStatistic]: number;
72
92
  }>;
package/dist/buff.d.ts CHANGED
@@ -1,6 +1,8 @@
1
+ import { Translatable } from './translatable';
1
2
  import { TechniqueElement } from './element';
2
3
  import { CombatStatistic, Scaling } from './stat';
3
4
  import { DamageType } from './DamageType';
5
+ import type { CombatEntity } from './entity';
4
6
  export type TechniqueCondition = ChanceTechniqueCondition | BuffTechniqueCondition | HpTechniqueCondition | ConditionTechniqueCondition;
5
7
  export type DamageModifier = MultiplyDamageModifier | ReduceDamageModifier | ExpressionDamageModifier;
6
8
  interface MultiplyDamageModifier {
@@ -42,23 +44,22 @@ export interface Buff {
42
44
  colour?: string;
43
45
  canStack: boolean;
44
46
  effectHint?: string;
45
- tooltip?: string;
46
- additionalTooltip?: string;
47
+ tooltip?: Translatable;
48
+ additionalTooltip?: Translatable;
47
49
  flag?: string;
48
50
  condition?: TechniqueCondition;
49
51
  removeOnConditionFailed?: boolean;
50
- statsTooltip?: string;
52
+ statsTooltip?: Translatable;
51
53
  stats: Partial<{
52
54
  [key in CombatStatistic]: Scaling;
53
55
  }> | undefined;
54
56
  charisma?: number;
55
57
  masteryPoints?: number;
56
58
  speed?: number;
57
- applicationStats?: Record<CombatStatistic, number>;
58
- applicationVariables?: Record<string, number>;
59
- appliedByOpponent?: boolean;
59
+ applicationEntity?: CombatEntity;
60
60
  allowMultipleInstances?: boolean;
61
61
  storedVariables?: Record<string, string>;
62
+ storedValues?: Record<string, number>;
62
63
  uniqueId?: string;
63
64
  internalState?: Record<string, number>;
64
65
  initialState?: Record<string, string>;
@@ -92,6 +93,27 @@ export interface Buff {
92
93
  damageModifier: DamageModifier;
93
94
  effects?: BuffEffect[];
94
95
  }[];
96
+ /** Amplifies outgoing damage/barrier/heal effects. Runs before the effect is applied. */
97
+ techniqueAmplifierEffects?: {
98
+ trigger?: TechniqueCondition;
99
+ amplifier: {
100
+ kind: 'multiply';
101
+ value: number;
102
+ };
103
+ effects?: BuffEffect[];
104
+ appliesTo: ('damage' | 'barrier' | 'heal')[];
105
+ }[];
106
+ /** Amplifies buff creation. Modifies stack count when matching buffs are created on self. */
107
+ buffAmplifierEffects?: {
108
+ trigger?: TechniqueCondition;
109
+ /** Matches buffs by name, buffType, or flag */
110
+ target: string;
111
+ modifier: {
112
+ kind: 'add' | 'multiply';
113
+ value: number;
114
+ };
115
+ effects?: BuffEffect[];
116
+ }[];
95
117
  priority?: number;
96
118
  afterTechnique?: boolean;
97
119
  combatImage?: BuffCombatImage;
@@ -173,7 +195,7 @@ export interface FormationCombatImage extends BaseCombatImage {
173
195
  scale?: number;
174
196
  showSingleInstance?: boolean;
175
197
  }
176
- export type BuffEffect = DamageEffect | DamageSelfEffect | HealEffect | BarrierEffect | CreateBuffSelfEffect | ConsumeBuffSelfEffect | CreateBuffTargetEffect | ConsumeBuffTargetEffect | NegateEffect | AddEffect | MultiplyEffect | MergeEffect | TriggerEffect | ModifyBuffGroupEffect | CleanseToxicityEffect | SetStateEffect;
198
+ export type BuffEffect = DamageEffect | DamageSelfEffect | HealEffect | BarrierEffect | CreateBuffSelfEffect | ConsumeBuffSelfEffect | CreateBuffTargetEffect | ConsumeBuffTargetEffect | NegateEffect | AddEffect | MultiplyEffect | MergeEffect | TriggerEffect | ModifyBuffGroupEffect | CleanseToxicityEffect | SetStateEffect | ConvertSelfEffect;
177
199
  interface BaseBuff {
178
200
  condition?: TechniqueCondition;
179
201
  triggerKey?: string;
@@ -268,4 +290,10 @@ interface SetStateEffect extends BaseBuff {
268
290
  value: Scaling;
269
291
  mode?: 'set' | 'add';
270
292
  }
293
+ interface ConvertSelfEffect extends BaseBuff {
294
+ kind: 'convertSelf';
295
+ source: Buff;
296
+ target: Buff;
297
+ amount: Scaling;
298
+ }
271
299
  export {};
@@ -9,4 +9,6 @@ export interface CalendarEvent {
9
9
  location?: string;
10
10
  recurrenceYears: number;
11
11
  realm?: Realm;
12
+ /** If true, event can be re-entered multiple times during its active month */
13
+ reentrant?: boolean;
12
14
  }
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { SvgIconTypeMap } from '@mui/material';
2
3
  import { OverridableComponent } from '@mui/material/OverridableComponent';
3
4
  import { Buff } from './buff';
@@ -189,7 +190,7 @@ export interface AidBreakthroughCharacterInteraction extends BaseCharacterIntera
189
190
  export interface CustomCharacterInteractionBlock {
190
191
  condition: string;
191
192
  name: string;
192
- tooltip: string;
193
+ tooltip: Translatable;
193
194
  icon: OverridableComponent<SvgIconTypeMap<{}, 'svg'>>;
194
195
  interaction: CustomCharacterInteraction;
195
196
  cooldown?: number;
@@ -254,17 +255,17 @@ export interface CharacterRelationshipDefinition {
254
255
  requiredApproval: number;
255
256
  relationshipCategory: CharacterRelationship;
256
257
  name: string;
257
- tooltip: string;
258
+ tooltip: Translatable;
258
259
  followCharacter?: FollowCharacterDefinition;
259
260
  dualCultivation?: DualCultivationDefinition;
260
261
  progressionEvent: {
261
262
  name: string;
262
- tooltip: string;
263
+ tooltip: Translatable;
263
264
  event: EventStep[];
264
265
  locationOverride?: string;
265
266
  requirement?: {
266
267
  condition: string;
267
- tooltip: string;
268
+ tooltip: Translatable;
268
269
  };
269
270
  };
270
271
  }
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { ReactNode } from 'react';
2
3
  import { SvgIconTypeMap } from '@mui/material';
3
4
  import { OverridableComponent } from '@mui/material/OverridableComponent';
@@ -18,14 +19,14 @@ export interface RecipeConditionEffect {
18
19
  name: string;
19
20
  colour: string;
20
21
  conditionEffects: Record<CraftingCondition, {
21
- tooltip: string;
22
+ tooltip: Translatable;
22
23
  effects: CraftingConditionEffect[];
23
24
  }>;
24
25
  }
25
26
  export type RecipeHarmonyType = 'forge' | 'alchemical' | 'inscription' | 'resonance';
26
27
  export interface HarmonyTypeConfig {
27
28
  name: string;
28
- description: string;
29
+ description: Translatable;
29
30
  processEffect: (harmonyData: HarmonyData, technique: CraftingTechnique, progressState: ProgressState, entity: CraftingEntity, state: CraftingState) => void;
30
31
  initEffect: (harmonyData: HarmonyData, entity: CraftingEntity) => void;
31
32
  renderComponent: (harmonyData: HarmonyData) => ReactNode;
@@ -69,6 +69,12 @@ export interface SuccessCraftingResult {
69
69
  refund: ItemDesc[];
70
70
  }
71
71
  export type CraftingResult = FailedCraftingResult | SuccessCraftingResult;
72
+ export interface CraftingTrainingMode {
73
+ flagKey: string;
74
+ tier: number;
75
+ recipeTypeId: string;
76
+ conditionName?: string;
77
+ }
72
78
  export interface CraftingState {
73
79
  player?: CraftingEntity;
74
80
  recipe?: RecipeItem;
@@ -77,4 +83,5 @@ export interface CraftingState {
77
83
  consumedPills: number;
78
84
  craftingLog: string[];
79
85
  craftResult?: CraftingResult;
86
+ trainingMode?: CraftingTrainingMode;
80
87
  }
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { CraftingBuff, CraftingTechniqueCondition } from './craftingBuff';
2
3
  import { Rarity } from './rarity';
3
4
  import { Realm } from './realm';
@@ -61,6 +62,7 @@ export interface CraftingTechnique {
61
62
  currentCooldown: number;
62
63
  justClicked?: true;
63
64
  mastery?: CraftingTechniqueMastery[];
65
+ masteryKindPools?: CraftingTechniqueEffectKind[];
64
66
  upgradeMasteries?: {
65
67
  [key: string]: CraftingTechniqueMasteryRarityMap;
66
68
  };
@@ -116,7 +118,7 @@ export interface CraftingRecipeStats {
116
118
  export type CraftingTechniqueMastery = ControlMastery | IntensityMastery | CritChanceTechniqueMastery | CritMultiplierTechniqueMastery | EffectTechniqueMastery | UpgradeCraftingTechniqueMastery | PoolCostMastery | StabilityCostMastery | SuccessChanceMastery;
117
119
  interface BaseCraftingTechniqueMastery {
118
120
  condition?: CraftingTechniqueCondition;
119
- tooltip?: string;
121
+ tooltip?: Translatable;
120
122
  rarity?: Rarity;
121
123
  }
122
124
  interface ControlMastery extends BaseCraftingTechniqueMastery {
@@ -153,7 +155,7 @@ export interface SuccessChanceMastery extends BaseCraftingTechniqueMastery {
153
155
  }
154
156
  export interface UpgradeCraftingTechniqueMastery extends BaseCraftingTechniqueMastery {
155
157
  kind: 'upgrade';
156
- tooltip: string;
158
+ tooltip: Translatable;
157
159
  upgradeKey: string;
158
160
  change: number;
159
161
  shouldMultiply?: boolean;
package/dist/destiny.d.ts CHANGED
@@ -1,7 +1,8 @@
1
+ import { Translatable } from './translatable';
1
2
  import { CombatStatistic, CraftingStatistic, Scaling } from './stat';
2
3
  export interface Destiny {
3
4
  name: string;
4
- description: string;
5
+ description: Translatable;
5
6
  combatStats?: Partial<{
6
7
  [key in CombatStatistic]: Scaling;
7
8
  }>;
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  declare const intimateStats: readonly ["satisfaction", "energy", "painThreshold"];
2
3
  export type IntimateStat = (typeof intimateStats)[number];
3
4
  declare const intimateResources: readonly ["pain", "harmony", "excitement", "rhythm"];
@@ -6,7 +7,7 @@ declare const intimateTechniqueTypes: string[];
6
7
  export type IntimateTechniqueType = (typeof intimateTechniqueTypes)[number];
7
8
  export type IntimateTrait = {
8
9
  name: string;
9
- description: string;
10
+ description: Translatable;
10
11
  stats: Partial<Record<IntimateStat, number>>;
11
12
  typeMultiplier: Partial<Record<IntimateTechniqueType, number>>;
12
13
  };
@@ -34,7 +35,7 @@ interface ResourceEffect {
34
35
  }
35
36
  export interface DualCultivationMessage {
36
37
  id: number;
37
- text: string;
38
+ text: Translatable;
38
39
  bindPoint: 'energy' | 'satisfaction' | 'resource' | 'player' | 'partner';
39
40
  color: string;
40
41
  position?: {
package/dist/entity.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { SoundEffectName } from './audio';
2
3
  import { Buff } from './buff';
3
4
  import { CraftingBuff } from './craftingBuff';
@@ -13,6 +14,7 @@ export interface CombatEffectTracking {
13
14
  damage: number;
14
15
  healing: number;
15
16
  barrier: number;
17
+ damageTaken: number;
16
18
  }
17
19
  export declare const entityTypes: readonly ["Player", "Lifeform", "Enemy"];
18
20
  export type EntityType = (typeof entityTypes)[number];
@@ -20,6 +22,7 @@ export declare const sexes: readonly ["male", "female"];
20
22
  export type Sex = (typeof sexes)[number];
21
23
  export interface PlayerEntity {
22
24
  imageIndex: number;
25
+ originalImageIndex?: number;
23
26
  customImagePath?: string;
24
27
  customImages?: {
25
28
  idle?: string;
@@ -70,6 +73,7 @@ export interface PlayerEntity {
70
73
  background: string[];
71
74
  monthBuffs?: Buff[];
72
75
  injured?: boolean;
76
+ party?: PartyMemberConfig[];
73
77
  }
74
78
  export type EnemyDifficulty = 'veryeasy' | 'easy' | 'mediumEasy' | 'medium' | 'medium+' | 'mediumhard' | 'hard' | 'hard+' | 'veryhard' | 'veryhard+' | 'veryhard++' | 'veryhard+++' | 'veryhard++++';
75
79
  export type BattleLength = 'halfround' | '1round' | 'veryshort' | 'short' | 'medium' | 'long' | 'verylong' | 'verylong+' | 'verylong++' | 'verylong+++' | 'verylong++++';
@@ -168,10 +172,13 @@ export interface EnemyEntity {
168
172
  };
169
173
  preconfiguredCombatEntity?: CombatEntity;
170
174
  phases?: EnemyEntity[];
175
+ party?: PartyMemberConfig[];
176
+ preservePartyMembers?: boolean;
171
177
  }
178
+ export type PartyMemberConfig = EnemyEntity;
172
179
  export interface CombatMessage {
173
180
  id: number;
174
- text: string;
181
+ text: Translatable;
175
182
  bindPoint: 'hp' | 'buff' | 'technique';
176
183
  color: string;
177
184
  position?: {
@@ -204,7 +211,7 @@ export interface CraftingEntity {
204
211
  }
205
212
  export interface CraftingMessage {
206
213
  id: number;
207
- text: string;
214
+ text: Translatable;
208
215
  bindPoint: 'pool' | 'stability' | 'perfection' | 'completion' | 'buff' | 'technique';
209
216
  color: string;
210
217
  position?: {
@@ -219,6 +226,7 @@ export interface CombatArtefact extends ArtefactItem {
219
226
  }
220
227
  export interface CombatEntity {
221
228
  entityType: EntityType;
229
+ name?: string;
222
230
  image: string;
223
231
  supportImage?: {
224
232
  image: string;
@@ -269,9 +277,13 @@ export interface CombatEntity {
269
277
  };
270
278
  };
271
279
  realm: Realm;
280
+ realmProgress: RealmProgress;
272
281
  stats: CombatStatsMap;
273
282
  stance: Stance;
283
+ stances?: Stance[];
274
284
  stanceRotationIndex: number;
285
+ stanceRotation: StanceRule[];
286
+ rotationOverrides?: StanceRule[];
275
287
  usedOverrides: boolean[];
276
288
  usedPills: boolean[];
277
289
  defenseFactor: number;
@@ -288,6 +300,9 @@ export interface CombatEntity {
288
300
  };
289
301
  disableBreathing?: boolean;
290
302
  effectTracking: Record<string, CombatEffectTracking>;
303
+ party?: CombatEntity[];
304
+ isPartyMember?: boolean;
305
+ partyMemberIndex?: number;
291
306
  }
292
307
  export type StanceRule = SingleStance | RandomStance;
293
308
  export interface SingleStance {
package/dist/event.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { GameScreen } from './GameScreen';
2
3
  import { MusicName, SoundEffectName } from './audio';
3
4
  import { Buff } from './buff';
@@ -34,14 +35,14 @@ export type EventStep = TextStep | SpeechStep | CombatStep | CraftingStep | Choi
34
35
  export interface TextStep {
35
36
  kind: 'text';
36
37
  condition?: string;
37
- text: string;
38
+ text: Translatable;
38
39
  sfx?: SoundEffectName;
39
40
  }
40
41
  export interface SpeechStep {
41
42
  kind: 'speech';
42
43
  condition?: string;
43
44
  character: string;
44
- text: string;
45
+ text: Translatable;
45
46
  }
46
47
  export interface CombatStep {
47
48
  kind: 'combat';
@@ -75,7 +76,7 @@ export interface ChoiceStep {
75
76
  choices: ChoiceStepChoice[];
76
77
  }
77
78
  export interface ChoiceStepChoice {
78
- text: string;
79
+ text: Translatable;
79
80
  showCondition?: string;
80
81
  condition?: EventChoiceCondition;
81
82
  hideIfDisabled?: boolean;
@@ -483,7 +484,7 @@ export interface StoneCuttingStep {
483
484
  export interface GiveItemStep {
484
485
  kind: 'giveItem';
485
486
  condition?: string;
486
- description: string;
487
+ description: Translatable;
487
488
  itemNames: string[];
488
489
  branches: {
489
490
  item: string;
package/dist/guild.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { SvgIconTypeMap } from '@mui/material';
2
3
  import { OverridableComponent } from '@mui/material/OverridableComponent';
3
4
  import { EventStep } from './event';
@@ -9,7 +10,7 @@ export interface GuildMission {
9
10
  }
10
11
  export interface Guild {
11
12
  name: string;
12
- description: string;
13
+ description: Translatable;
13
14
  icon: string;
14
15
  image: string;
15
16
  backgroundLocation: string;
package/dist/house.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { SvgIconTypeMap } from '@mui/material';
2
3
  import { OverridableComponent } from '@mui/material/OverridableComponent';
3
4
  import { ScreenEffectType } from './ScreenEffectType';
@@ -8,7 +9,7 @@ import { Rarity } from './rarity';
8
9
  import { Realm } from './realm';
9
10
  export interface House {
10
11
  name: string;
11
- description: string;
12
+ description: Translatable;
12
13
  background: string;
13
14
  screenEffect: ScreenEffectType;
14
15
  transportSeal: TransportSealItem;
@@ -27,7 +28,7 @@ export interface RoomDef {
27
28
  export type Room = BuffRoom | CultivationRoom | CraftingRoom | CompendiumRoom | HealerRoom | TeleportRoom;
28
29
  interface RoomBase {
29
30
  name: string;
30
- description: string;
31
+ description: Translatable;
31
32
  realm: Realm | 'any';
32
33
  rarity: Rarity;
33
34
  icon: OverridableComponent<SvgIconTypeMap<{}, 'svg'>>;
package/dist/item.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { Buff } from './buff';
2
3
  import { CraftingBuff } from './craftingBuff';
3
4
  import { CraftingTechniqueEffect } from './craftingTechnique';
@@ -22,7 +23,7 @@ export type Item = TechniqueItem | TechniqueCrystalItem | TechniqueShardItem | T
22
23
  interface ItemBase {
23
24
  kind: ItemKind;
24
25
  name: string;
25
- description: string;
26
+ description: Translatable;
26
27
  icon: string;
27
28
  stacks: number;
28
29
  rarity: Rarity;
@@ -156,16 +157,20 @@ export interface ArtefactTechnique {
156
157
  effects: TechniqueEffect[];
157
158
  i?: number;
158
159
  }
159
- export type PillKind = 'combat' | 'crafting' | 'advancement' | 'consumable';
160
+ export type PillKind = 'combat' | 'crafting' | 'advancement' | 'consumable' | 'appearance_change';
160
161
  interface BasePillItem extends ItemBase {
161
162
  kind: 'pill';
162
163
  pillKind: PillKind;
163
164
  }
164
- export type PillItem = CombatPillItem | CraftingPillItem | MiscPillItem | ConsumablePillItem;
165
+ export type PillItem = CombatPillItem | CraftingPillItem | MiscPillItem | ConsumablePillItem | AppearanceChangePillItem;
165
166
  export interface MiscPillItem extends BasePillItem {
166
167
  pillKind: 'advancement';
167
168
  toxicity?: undefined;
168
169
  }
170
+ export interface AppearanceChangePillItem extends BasePillItem {
171
+ pillKind: 'appearance_change';
172
+ toxicity?: undefined;
173
+ }
169
174
  export interface CombatPillItem extends BasePillItem {
170
175
  pillKind: 'combat';
171
176
  toxicity: number;
@@ -248,6 +253,11 @@ export interface MountItem extends ItemBase {
248
253
  masteryPoints?: number;
249
254
  qiAbsorption?: number;
250
255
  customTransform?: string;
256
+ explorationBonus?: number;
257
+ buffs?: {
258
+ buff: Buff;
259
+ buffStacks: Scaling;
260
+ }[];
251
261
  }
252
262
  export interface ElixirItem extends ItemBase {
253
263
  kind: 'elixir';
@@ -318,6 +328,11 @@ export interface MountEnchantment extends Enchantment {
318
328
  speed?: number;
319
329
  masteryPoints?: number;
320
330
  qiAbsorption?: number;
331
+ explorationBonus?: number;
332
+ buffs?: {
333
+ buff: Buff;
334
+ buffStacks: Scaling;
335
+ }[];
321
336
  }
322
337
  export interface RegionMonsters {
323
338
  mob: EnemyEntity[];
@@ -379,6 +394,7 @@ export interface CondensationArtEnchantment extends Enchantment {
379
394
  masteryPoints?: number;
380
395
  speed?: number;
381
396
  restoredDroplets?: number;
397
+ combatStats?: Partial<CombatStatsMap>;
382
398
  }
383
399
  export type FormationKind = 'qiDensity';
384
400
  export type FormationItem = QiDensityFormationItem;
@@ -410,7 +426,7 @@ export interface PillarShardVariant {
410
426
  }
411
427
  export interface PillarShardItem extends ItemBase {
412
428
  kind: 'pillar_shard';
413
- tooltip: string;
429
+ tooltip: Translatable;
414
430
  maxInstances?: number;
415
431
  variants?: PillarShardVariant[];
416
432
  stability?: number;
@@ -28,7 +28,7 @@ export const keybindingDefinitions = [
28
28
  {
29
29
  action: 'pause',
30
30
  category: 'general',
31
- displayName: 'Pause/Menu',
31
+ displayName: 'Pause / Menu',
32
32
  description: 'Open pause menu or settings (not rebindable)',
33
33
  defaultKey: 'Escape',
34
34
  allowRebind: false,
package/dist/life.d.ts CHANGED
@@ -1,14 +1,11 @@
1
1
  import { Buff } from './buff';
2
2
  import { StoredStance, StoredStyle } from './entity';
3
3
  import { Realm } from './realm';
4
- import { PhysicalStatistic } from './stat';
5
4
  import { Technique } from './technique';
6
5
  export interface LifeForm {
7
6
  name: string;
8
- description: string;
9
7
  image: string;
10
8
  realm: Realm;
11
- baseStats: Record<PhysicalStatistic, number>;
12
9
  buffs: Buff[];
13
10
  techniques: Technique[];
14
11
  }
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { ScreenEffectType } from './ScreenEffectType';
2
3
  import { EventStep } from './event';
3
4
  import { Rarity } from './rarity';
@@ -11,7 +12,7 @@ import { AmbienceName, MusicName } from './audio';
11
12
  export interface GameLocation {
12
13
  name: string;
13
14
  displayName?: string;
14
- description: string;
15
+ description: Translatable;
15
16
  image: string;
16
17
  icon: string;
17
18
  screenEffect: ScreenEffectType;
@@ -35,6 +36,27 @@ export interface GameLocation {
35
36
  realmProgress?: RealmProgress;
36
37
  reputationName?: string;
37
38
  }
39
+ /**
40
+ * A root location that serves as an entry point for location discovery.
41
+ * The map system discovers all locations reachable from root locations whose
42
+ * conditions are met.
43
+ *
44
+ * Root locations that are not connected to other roots by paths can only be
45
+ * traveled to via transport seals or event steps (useful for secret/hidden areas).
46
+ *
47
+ * The main game root (Nine Mountain Sect) uses condition '1' to always be visible.
48
+ * Mod roots can use conditions to only appear after certain events/flags.
49
+ */
50
+ export interface RootLocation {
51
+ /** The name of the location to use as a discovery root (must exist in locationMap) */
52
+ locationName: string;
53
+ /**
54
+ * Condition expression that determines when this root becomes active.
55
+ * Uses the same expression syntax as other conditions (e.g., "questFlag == 1").
56
+ * Use '1' for roots that should always be discovered.
57
+ */
58
+ condition: string;
59
+ }
38
60
  interface LinkBase {
39
61
  location: GameLocation;
40
62
  distance: number;
@@ -85,8 +107,8 @@ export interface CraftingMission {
85
107
  condition: string;
86
108
  }
87
109
  export declare const exploresPerUnlock = 3;
88
- export type BuildingType = 'cultivation' | 'manual' | 'crafting' | 'mission' | 'craftingHall' | 'healer' | 'market' | 'favourExchange' | 'vault' | 'custom' | 'herbField' | 'mine' | 'recipe' | 'requestBoard' | 'compendium' | 'mysticalRegion' | 'trainingGround' | 'library' | 'house' | 'altar' | 'research' | 'reforge' | 'guild' | 'modBuilding';
89
- export type LocationBuilding = CultivationBuilding | ManualBuilding | CraftingBuilding | MissionBuilding | CraftingHallBuilding | HealerBuilding | MarketBuilding | VaultBuilding | FavourExchangeBuilding | CustomBuilding | HerbFieldBuilding | MineBuilding | RecipeLibraryBuilding | RequestBoardBuilding | CompendiumBuilding | MysticalRegionBuilding | TrainingGroundBuilding | LibraryBuilding | HouseBuilding | CompressionAltarBuilding | ResearchBuilding | ReforgeBuilding | GuildBuilding | ModBuilding;
110
+ export type BuildingType = 'cultivation' | 'manual' | 'crafting' | 'mission' | 'craftingHall' | 'healer' | 'market' | 'favourExchange' | 'vault' | 'custom' | 'herbField' | 'mine' | 'recipe' | 'requestBoard' | 'compendium' | 'mysticalRegion' | 'trainingGround' | 'library' | 'house' | 'altar' | 'research' | 'reforge' | 'guild' | 'tenThousandFlames' | 'modBuilding';
111
+ export type LocationBuilding = CultivationBuilding | ManualBuilding | CraftingBuilding | MissionBuilding | CraftingHallBuilding | HealerBuilding | MarketBuilding | VaultBuilding | FavourExchangeBuilding | CustomBuilding | HerbFieldBuilding | MineBuilding | RecipeLibraryBuilding | RequestBoardBuilding | CompendiumBuilding | MysticalRegionBuilding | TrainingGroundBuilding | LibraryBuilding | HouseBuilding | CompressionAltarBuilding | ResearchBuilding | ReforgeBuilding | GuildBuilding | TenThousandFlamesBuilding | ModBuilding;
90
112
  export type LocationBuildingState = MissionBuildingState | CraftingHallBuildingState | ShopBuildingState | RequestBoardBuildingState | HouseBuildingState | CompressionAltarBuildingState;
91
113
  interface BuildingBase {
92
114
  kind: BuildingType;
@@ -208,6 +230,9 @@ export interface MysticalRegionBuilding extends BuildingBase {
208
230
  export interface TrainingGroundBuilding extends BuildingBase {
209
231
  kind: 'trainingGround';
210
232
  }
233
+ export interface TenThousandFlamesBuilding extends BuildingBase {
234
+ kind: 'tenThousandFlames';
235
+ }
211
236
  export type CustomBuildingPosition = 'top' | 'topleft' | 'topright' | 'belowtop' | 'belowtopleft' | 'belowtopright' | 'middleleft' | 'middle' | 'middleright' | 'bottom' | 'bottomleft' | 'bottomright';
212
237
  export interface CustomBuilding extends BuildingBase {
213
238
  kind: 'custom';
package/dist/location.js CHANGED
@@ -23,5 +23,6 @@ export const buildingTypeToName = {
23
23
  research: 'Vault of Infinite Reflections',
24
24
  reforge: `Infusion Workshop`,
25
25
  guild: '',
26
+ tenThousandFlames: 'Furnace of Ten Thousand Flames',
26
27
  modBuilding: '',
27
28
  };
package/dist/mine.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { EventStep } from './event';
2
3
  import { ItemDesc } from './item';
3
4
  import { Rarity } from './rarity';
@@ -40,7 +41,7 @@ export type MineChamber = OreChamber | EventChamber | RandomDropChamber | Releas
40
41
  interface BaseChamber {
41
42
  icon: string;
42
43
  name: string;
43
- description: string;
44
+ description: Translatable;
44
45
  rarity: Rarity;
45
46
  condition: string;
46
47
  isUnique?: boolean;
package/dist/mod.d.ts CHANGED
@@ -36,6 +36,40 @@ import { PuppetType } from './trainingGround';
36
36
  import { TechniqueElement } from './element';
37
37
  import { AlternativeStart } from './alternativeStart';
38
38
  import { Tutorial } from './tutorial';
39
+ import { Sex } from './entity';
40
+ /**
41
+ * Sprite images for a custom player character.
42
+ * All images should be strings (either mod:// URLs for mod assets, or data: URLs).
43
+ */
44
+ export interface PlayerSpriteImages {
45
+ /** Base/idle image shown in most UI contexts */
46
+ base: string;
47
+ /** Image shown when using aggressive stance techniques */
48
+ aggressive: string;
49
+ /** Image shown when using defensive stance techniques */
50
+ defensive: string;
51
+ /** Image shown when the player is hit */
52
+ hit: string;
53
+ /** Image shown when using offensive stance techniques */
54
+ offensive: string;
55
+ /** Image shown when using support stance techniques */
56
+ support: string;
57
+ /** Image shown when using utility stance techniques */
58
+ utility: string;
59
+ }
60
+ /**
61
+ * A custom player sprite that can be selected during character creation.
62
+ */
63
+ export interface PlayerSprite {
64
+ /** Unique identifier for this sprite */
65
+ id: string;
66
+ /** Display name shown in character creation */
67
+ name: string;
68
+ /** Which gender this sprite is available for: 'male', 'female', or 'both' */
69
+ gender: Sex | 'both';
70
+ /** The sprite images for different poses/situations */
71
+ sprites: PlayerSpriteImages;
72
+ }
39
73
  export interface ModMetadata {
40
74
  name: string;
41
75
  version: string;
@@ -483,6 +517,25 @@ export interface ModAPI {
483
517
  * linkLocations('Liang Tiao Village', { location: myLocation, distance: 5, condition: "my_unlock_flag" });
484
518
  */
485
519
  linkLocations: (existing: string, link: ConditionalLink | ExplorationLink) => void;
520
+ /**
521
+ * Register a location as a root for discovery.
522
+ * Root locations are entry points for the map discovery system - all locations
523
+ * reachable from a root will be discovered when its condition is met.
524
+ *
525
+ * Use this for secret areas or alternative starting points that aren't
526
+ * connected to the main map by paths. Players can only travel to unconnected
527
+ * roots via transport seals or event teleportation.
528
+ *
529
+ * @param locationName - Name of the location to mark as root (must already exist)
530
+ * @param condition - Condition expression for when this root is active (use '1' for always)
531
+ * @example
532
+ * // Always-active root for an alternative start area
533
+ * registerRootLocation('Hidden Valley', '1');
534
+ *
535
+ * // Conditional root that unlocks after finding a secret
536
+ * registerRootLocation('Ancient Ruins', 'foundAncientMap == 1');
537
+ */
538
+ registerRootLocation: (locationName: string, condition: string) => void;
486
539
  /**
487
540
  * Add buildings to an existing location.
488
541
  * @param location - Location key
@@ -654,6 +707,28 @@ export interface ModAPI {
654
707
  * });
655
708
  */
656
709
  addAlternativeStart: (start: AlternativeStart) => void;
710
+ /**
711
+ * Register a custom player sprite for character creation.
712
+ * Custom sprites will appear in the character creation screen alongside
713
+ * the default sprites for the specified gender.
714
+ * @param sprite - Player sprite configuration with id, name, gender, and all required images
715
+ * @example
716
+ * addPlayerSprite({
717
+ * id: 'myCustomCharacter',
718
+ * name: 'Custom Cultivator',
719
+ * gender: 'male',
720
+ * sprites: {
721
+ * base: baseImage,
722
+ * aggressive: aggressiveImage,
723
+ * defensive: defensiveImage,
724
+ * hit: hitImage,
725
+ * offensive: offensiveImage,
726
+ * support: supportImage,
727
+ * utility: utilityImage,
728
+ * }
729
+ * });
730
+ */
731
+ addPlayerSprite: (sprite: PlayerSprite) => void;
657
732
  };
658
733
  utils: {
659
734
  /**
package/dist/quest.d.ts CHANGED
@@ -1,8 +1,9 @@
1
+ import { Translatable } from './translatable';
1
2
  import { EventStep, GameEvent } from './event';
2
3
  import { ItemDesc } from './item';
3
4
  export interface Quest {
4
5
  name: string;
5
- description: string;
6
+ description: Translatable;
6
7
  category: 'main' | 'side' | 'missionHall' | 'craftingHall' | 'requestBoard' | 'guild';
7
8
  guild?: string;
8
9
  steps: QuestStep[];
@@ -45,7 +46,7 @@ interface GuildApprovalQuestReward {
45
46
  }
46
47
  export type QuestStep = EventQuestStep | ConditionQuestStep | CollectQuestStep | MissionHallQuestStep | FlagValueQuestStep | SpeakToCharacterQuestStep | KillQuestStep | WaitQuestStep | RaidQuestStep;
47
48
  interface QuestStepBase {
48
- hint: string;
49
+ hint: Translatable;
49
50
  }
50
51
  interface EventQuestStep extends QuestStepBase {
51
52
  kind: 'event';
@@ -319,12 +319,6 @@ export interface NewGameState {
319
319
  export interface GameDataState {
320
320
  flags: Record<string, number>;
321
321
  mapExploration: Record<string, number>;
322
- /**
323
- * The root location name for location discovery.
324
- * Defaults to "Nine Mountain Sect" if not set.
325
- * Can be changed by alternative starts.
326
- */
327
- discoveryRoot?: string;
328
322
  }
329
323
  export interface HistoryItem {
330
324
  text: string;
@@ -366,6 +360,11 @@ export interface GameEventState {
366
360
  [key: string]: StoredEventState;
367
361
  };
368
362
  analyticsToReport: ReportAnalyticsStep[];
363
+ /**
364
+ * Hash of the event content for "skip seen dialogue" feature.
365
+ * Generated when event starts using hashEventContent().
366
+ */
367
+ eventHash?: string;
369
368
  }
370
369
  export interface RecipeFilters {
371
370
  hideCompleted: boolean;
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  export interface SimpleGameEvent {
2
3
  location: string;
3
4
  steps: SimpleEventStep[];
@@ -5,19 +6,19 @@ export interface SimpleGameEvent {
5
6
  export type SimpleEventStep = TextStep | SpeechStep | ChoiceStep;
6
7
  interface TextStep {
7
8
  kind: 'text';
8
- text: string;
9
+ text: Translatable;
9
10
  }
10
11
  interface SpeechStep {
11
12
  kind: 'speech';
12
13
  character: string;
13
- text: string;
14
+ text: Translatable;
14
15
  }
15
16
  interface ChoiceStep {
16
17
  kind: `choice`;
17
18
  choices: ChoiceStepChoice[];
18
19
  }
19
20
  export interface ChoiceStepChoice {
20
- text: string;
21
+ text: Translatable;
21
22
  children: SimpleEventStep[];
22
23
  }
23
24
  export {};
package/dist/stat.d.ts CHANGED
@@ -3,7 +3,7 @@ import { TechniqueElement } from './element';
3
3
  export declare const physicalStatistics: readonly ["eyes", "meridians", "dantian", "muscles", "digestion", "flesh"];
4
4
  export declare const socialStatistics: readonly ["age", "lifespan", "charisma", "battlesense", "craftskill", "artefactslots", "talismanslots", "condenseEfficiency", "pillsPerRound"];
5
5
  export declare const craftingStatistics: readonly ["maxpool", "pool", "maxtoxicity", "toxicity", "resistance", "itemEffectiveness", "control", "intensity", "critchance", "critmultiplier", "pillsPerRound", "poolCostPercentage", "stabilityCostPercentage", "successChanceBonus"];
6
- export declare const combatStatistics: readonly ["maxhp", "hp", "maxbarrier", "barrier", "maxtoxicity", "toxicity", "resistance", "pillsPerRound", "itemEffectiveness", "power", "artefactpower", "critchance", "defense", "dr", "barrierMitigation", "lifesteal", "critmultiplier", "vulnerability", "weakness", "fistBoost", "blossomBoost", "weaponBoost", "cloudBoost", "bloodBoost", "celestialBoost", "fistAffinity", "blossomAffinity", "weaponAffinity", "cloudAffinity", "bloodAffinity", "celestialAffinity", "noneAffinity", "qiDroplets", "fistDisabled", "bloodDisabled", "blossomDisabled", "cloudDisabled", "celestialDisabled", "weaponDisabled", "fistResistance", "blossomResistance", "weaponResistance", "cloudResistance", "bloodResistance", "celestialResistance", "damageBoost", "healingBoost", "barrierBoost", "overheal"];
6
+ export declare const combatStatistics: readonly ["maxhp", "hp", "maxbarrier", "barrier", "maxtoxicity", "toxicity", "resistance", "pillsPerRound", "itemEffectiveness", "power", "artefactpower", "critchance", "defense", "protection", "dr", "barrierMitigation", "lifesteal", "critmultiplier", "vulnerability", "weakness", "fistBoost", "blossomBoost", "weaponBoost", "cloudBoost", "bloodBoost", "celestialBoost", "fistAffinity", "blossomAffinity", "weaponAffinity", "cloudAffinity", "bloodAffinity", "celestialAffinity", "noneAffinity", "qiDroplets", "fistDisabled", "bloodDisabled", "blossomDisabled", "cloudDisabled", "celestialDisabled", "weaponDisabled", "fistResistance", "blossomResistance", "weaponResistance", "cloudResistance", "bloodResistance", "celestialResistance", "damageBoost", "healingBoost", "barrierBoost", "overheal", "barrierBleed", "formationPartRecovery"];
7
7
  export type PhysicalStatistic = (typeof physicalStatistics)[number];
8
8
  export type SocialStatistic = (typeof socialStatistics)[number];
9
9
  export type CraftingStatistic = (typeof craftingStatistics)[number];
package/dist/stat.js CHANGED
@@ -47,6 +47,7 @@ export const combatStatistics = [
47
47
  'artefactpower',
48
48
  'critchance',
49
49
  'defense',
50
+ 'protection',
50
51
  'dr',
51
52
  'barrierMitigation',
52
53
  'lifesteal',
@@ -83,6 +84,8 @@ export const combatStatistics = [
83
84
  'healingBoost',
84
85
  'barrierBoost',
85
86
  'overheal',
87
+ 'barrierBleed',
88
+ 'formationPartRecovery',
86
89
  ];
87
90
  export const baseStatNumber = 10;
88
91
  export const expectedHpPerFlesh = 1000;
@@ -108,6 +111,7 @@ export const combatStatToName = {
108
111
  artefactpower: 'Artefact Power',
109
112
  critchance: 'Crit Chance',
110
113
  defense: 'Defense',
114
+ protection: 'Protection',
111
115
  dr: 'Damage Resistance',
112
116
  barrierMitigation: 'Barrier Effectiveness',
113
117
  lifesteal: 'Life Steal',
@@ -146,6 +150,8 @@ export const combatStatToName = {
146
150
  healingBoost: 'Healing Boost',
147
151
  barrierBoost: 'Barrier Boost',
148
152
  overheal: 'Overheal',
153
+ barrierBleed: 'Barrier Bleed',
154
+ formationPartRecovery: 'Formation Part Recovery',
149
155
  };
150
156
  export const combatStatToDescription = {
151
157
  maxhp: 'The amount of damage you can take before you are unable to continue.',
@@ -156,7 +162,8 @@ export const combatStatToDescription = {
156
162
  resistance: 'Your resistance to the effects of pill toxicity, increasing the number of pills you can digest.',
157
163
  toxicity: '',
158
164
  power: 'The strength of your techniques. This affects damage dealt, healing, barrier gained, and the strength of your buffs and debuffs.',
159
- defense: 'Your resistance to damage.',
165
+ defense: 'Your base resistance to damage.',
166
+ protection: '',
160
167
  dr: '',
161
168
  lifesteal: '',
162
169
  critchance: 'Your chance to get a critical effect on damage, healing, and barrier. Crit chance over 100% converts to bonus crit damage at a 1:3 ratio.',
@@ -197,6 +204,8 @@ export const combatStatToDescription = {
197
204
  healingBoost: '',
198
205
  barrierBoost: '',
199
206
  overheal: '',
207
+ barrierBleed: '',
208
+ formationPartRecovery: '',
200
209
  };
201
210
  // Uncommon stats that need auxiliary tooltips when they appear on buffs
202
211
  // These descriptions only show as aux tooltips in buff tooltips, not in the stats dialog
@@ -205,6 +214,11 @@ export const uncommonStatTooltips = {
205
214
  healingBoost: '<n>Healing Boost</n> increases all healing received by a percentage.',
206
215
  barrierBoost: '<n>Barrier Boost</n> increases all barrier gained by a percentage.',
207
216
  overheal: '<n>Overheal</n> converts a percentage of healing beyond your maximum health into barrier.',
217
+ protection: '<n>Protection</n> reduces damage taken to your health. Does not affect damage taken to your barrier.',
218
+ weakness: '<n>Weakness</n> reduces your power.',
219
+ vulnerability: '<n>Vulnerability</n> increases damage taken to your <n>health</n>. Does not affect damage taken to your barrier.',
220
+ barrierBleed: '<n>Barrier Bleed</n> causes a percentage of your damage to bypass the enemy barrier and strike their health directly.',
221
+ formationPartRecovery: 'Each point of <n>Formation Part Recovery</n> returns a <n>Formation Part</n> used in combat back to your Spatial Ring after battle.',
208
222
  };
209
223
  export const craftingStatToName = {
210
224
  maxpool: 'Max Qi Pool',
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  import { Buff, TechniqueCondition } from './buff';
2
3
  import { DamageType } from './DamageType';
3
4
  import { TechniqueElement } from './element';
@@ -143,7 +144,7 @@ interface TriggerEffect extends BaseTechniqueEffect {
143
144
  export type TechniqueMastery = PowerTechniqueMastery | EffectTechniqueMastery | CritChanceTechniqueMastery | CritMultiplierTechniqueMastery | UpgradeTechniqueMastery;
144
145
  interface BaseTechniqueMastery {
145
146
  condition?: TechniqueCondition;
146
- tooltip?: string;
147
+ tooltip?: Translatable;
147
148
  rarity?: Rarity;
148
149
  }
149
150
  interface PowerTechniqueMastery extends BaseTechniqueMastery {
@@ -164,7 +165,7 @@ interface EffectTechniqueMastery extends BaseTechniqueMastery {
164
165
  }
165
166
  export interface UpgradeTechniqueMastery extends BaseTechniqueMastery {
166
167
  kind: 'upgrade';
167
- tooltip: string;
168
+ tooltip: Translatable;
168
169
  upgradeKey: string;
169
170
  change: number;
170
171
  shouldMultiply?: boolean;
@@ -1,8 +1,9 @@
1
+ import { Translatable } from './translatable';
1
2
  import { EnemyEntity, Realm, RealmProgress } from '.';
2
3
  export interface PuppetType {
3
4
  id: string;
4
5
  name: string;
5
- description: string;
6
+ description: Translatable;
6
7
  image: string;
7
8
  baseMultiplier: number;
8
9
  multiplierGrowth: number;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A deferred translation object. Instead of calling t() immediately,
3
+ * store the key and variables to be resolved at render time.
4
+ * This ensures language changes take effect without reload.
5
+ */
6
+ export interface TranslatableString {
7
+ readonly _translatable: true;
8
+ readonly key: string;
9
+ readonly variables?: Record<string, string | number>;
10
+ }
11
+ /**
12
+ * A deferred plural translation object. Stores both singular and plural keys
13
+ * to be resolved at render time based on a count value.
14
+ */
15
+ export interface TranslatablePlural {
16
+ readonly _translatable: true;
17
+ readonly _plural: true;
18
+ readonly countVar: string;
19
+ readonly one: string;
20
+ readonly other: string;
21
+ readonly variables?: Record<string, string | number>;
22
+ }
23
+ /**
24
+ * A value that can be either a plain string or a deferred translation object.
25
+ * Plain strings are translated as-is. TranslatableString objects are resolved
26
+ * at render time with their stored variables.
27
+ */
28
+ export type Translatable = string | TranslatableString | TranslatablePlural;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import { Translatable } from './translatable';
1
2
  export interface Tutorial {
2
3
  name: string;
3
4
  steps: TutorialStep[];
@@ -12,11 +13,11 @@ export interface ClickTutorialStep {
12
13
  export interface DescribeTutorialStep {
13
14
  kind: 'describe';
14
15
  elementId: string;
15
- description: string;
16
+ description: Translatable;
16
17
  }
17
18
  export interface GeneralTutorialStep {
18
19
  kind: 'general';
19
- description: string;
20
+ description: Translatable;
20
21
  elementId?: undefined;
21
22
  }
22
23
  export interface SuspendContStep {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "afnm-types",
3
- "version": "0.6.29",
3
+ "version": "0.6.32",
4
4
  "description": "Type definitions for Ascend From Nine Mountains",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",