@drmxrcy/tcg-lorcana-types 0.0.0-202602060544
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.
- package/package.json +46 -0
- package/src/abilities/ability-types.ts +766 -0
- package/src/abilities/condition-types.ts +1202 -0
- package/src/abilities/cost-types.ts +344 -0
- package/src/abilities/effect-types/amount-types.ts +115 -0
- package/src/abilities/effect-types/basic-effects.ts +200 -0
- package/src/abilities/effect-types/combined-types.ts +564 -0
- package/src/abilities/effect-types/control-flow.ts +317 -0
- package/src/abilities/effect-types/index.ts +136 -0
- package/src/abilities/effect-types/modifier-effects.ts +248 -0
- package/src/abilities/effect-types/movement-effects.ts +216 -0
- package/src/abilities/effect-types/scry-effects.ts +269 -0
- package/src/abilities/helpers/Abilities.ts +172 -0
- package/src/abilities/helpers/Conditions.ts +266 -0
- package/src/abilities/helpers/Costs.ts +83 -0
- package/src/abilities/helpers/Effects.ts +182 -0
- package/src/abilities/helpers/Targets.ts +193 -0
- package/src/abilities/helpers/Triggers.ts +167 -0
- package/src/abilities/helpers/index.ts +42 -0
- package/src/abilities/index.ts +401 -0
- package/src/abilities/target-types.ts +791 -0
- package/src/abilities/trigger-types.ts +530 -0
- package/src/cards/card-types.ts +502 -0
- package/src/cards/classifications.ts +86 -0
- package/src/cards/deck-validation.ts +71 -0
- package/src/cards/index.ts +77 -0
- package/src/cards/ink-types.ts +55 -0
- package/src/game/index.ts +14 -0
- package/src/game/state-types.ts +258 -0
- package/src/index.ts +16 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control Flow Effect Types
|
|
3
|
+
*
|
|
4
|
+
* Effects that control the flow of ability resolution:
|
|
5
|
+
* - Sequence (do A then B)
|
|
6
|
+
* - Choice (choose one of A or B)
|
|
7
|
+
* - Conditional (if X then A else B)
|
|
8
|
+
* - Optional (you may do A)
|
|
9
|
+
* - For-each (for each X, do A)
|
|
10
|
+
* - Repeat (do A X times)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { Condition } from "../condition-types";
|
|
14
|
+
import type { CharacterTarget, PlayerTarget } from "../target-types";
|
|
15
|
+
import type { Amount, EffectDuration } from "./amount-types";
|
|
16
|
+
|
|
17
|
+
// Forward reference - will be imported from combined-types at runtime
|
|
18
|
+
// This avoids circular dependency during type checking
|
|
19
|
+
import type { Effect } from "./combined-types";
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Control Flow Effects
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Sequence of effects (executed in order)
|
|
27
|
+
*
|
|
28
|
+
* @example "Draw 2 cards, then choose and discard a card"
|
|
29
|
+
*/
|
|
30
|
+
export interface SequenceEffect {
|
|
31
|
+
type: "sequence";
|
|
32
|
+
/** Array of effects to execute in order (preferred name) */
|
|
33
|
+
steps?: Effect[];
|
|
34
|
+
/** Alias for steps - both are supported for parser compatibility */
|
|
35
|
+
effects?: Effect[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Choose one of multiple effects
|
|
40
|
+
*
|
|
41
|
+
* @example "Choose one: Draw a card. Deal 2 damage to chosen character."
|
|
42
|
+
*/
|
|
43
|
+
export interface ChoiceEffect {
|
|
44
|
+
type: "choice";
|
|
45
|
+
/** Array of effect options (preferred name) */
|
|
46
|
+
options?: Effect[];
|
|
47
|
+
/** Alias for options - both are supported for parser compatibility */
|
|
48
|
+
choices?: Effect[];
|
|
49
|
+
/** Who makes the choice */
|
|
50
|
+
chooser?: PlayerTarget;
|
|
51
|
+
/** Who chooses (alternative field) */
|
|
52
|
+
chosenBy?: "you" | "opponent" | "TARGET";
|
|
53
|
+
/** Label/name for each option (for display) */
|
|
54
|
+
optionLabels?: string[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Conditional effect (if/then/else)
|
|
59
|
+
*
|
|
60
|
+
* @example "If you have a character named Elsa, draw a card"
|
|
61
|
+
*/
|
|
62
|
+
export interface ConditionalEffect {
|
|
63
|
+
type: "conditional";
|
|
64
|
+
condition?: Condition;
|
|
65
|
+
/** Effect to execute if condition is true (preferred) */
|
|
66
|
+
then?: Effect;
|
|
67
|
+
/** Alternative field for then effect */
|
|
68
|
+
effect?: Effect;
|
|
69
|
+
/** Effect to execute if condition is false */
|
|
70
|
+
else?: Effect;
|
|
71
|
+
/** Alternative fields for if-true/if-false */
|
|
72
|
+
ifTrue?: Effect;
|
|
73
|
+
ifFalse?: Effect;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Optional effect ("you may")
|
|
78
|
+
*
|
|
79
|
+
* @example "You may draw a card"
|
|
80
|
+
*/
|
|
81
|
+
export interface OptionalEffect {
|
|
82
|
+
type: "optional";
|
|
83
|
+
effect?: Effect;
|
|
84
|
+
/** Who decides */
|
|
85
|
+
chooser?: PlayerTarget;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* For-each effect (repeat for each X)
|
|
90
|
+
*
|
|
91
|
+
* @example "Gain 1 lore for each character you have in play"
|
|
92
|
+
*/
|
|
93
|
+
export interface ForEachEffect {
|
|
94
|
+
type: "for-each";
|
|
95
|
+
counter?: ForEachCounter;
|
|
96
|
+
effect?: Effect;
|
|
97
|
+
/** Maximum times to repeat (optional) */
|
|
98
|
+
maximum?: number;
|
|
99
|
+
/** Stat to modify (for static for-each effects) */
|
|
100
|
+
stat?: "strength" | "willpower" | "lore";
|
|
101
|
+
/** Modifier per count (for static for-each effects) */
|
|
102
|
+
modifier?: number;
|
|
103
|
+
/** Target for the effect */
|
|
104
|
+
target?: CharacterTarget;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* What to count for for-each effects
|
|
109
|
+
*/
|
|
110
|
+
export type ForEachCounter =
|
|
111
|
+
| { type: "characters"; controller: "you" | "opponent" | "any" }
|
|
112
|
+
| { type: "damaged-characters"; controller: "you" | "opponent" | "any" }
|
|
113
|
+
| { type: "items"; controller: "you" | "opponent" }
|
|
114
|
+
| { type: "items-in-play"; controller: "you" | "opponent" }
|
|
115
|
+
| { type: "locations"; controller: "you" | "opponent" }
|
|
116
|
+
| { type: "cards-in-hand"; controller: "you" | "opponent" }
|
|
117
|
+
| { type: "cards-in-discard"; controller: "you" | "opponent" }
|
|
118
|
+
| { type: "damage-on-self" }
|
|
119
|
+
| { type: "damage-on-target" }
|
|
120
|
+
| { type: "cards-under-self" }
|
|
121
|
+
| { type: "characters-that-sang"; thisTurn: boolean };
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Repeat effect X times
|
|
125
|
+
*/
|
|
126
|
+
export interface RepeatEffect {
|
|
127
|
+
type: "repeat";
|
|
128
|
+
times: Amount;
|
|
129
|
+
effect: Effect;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Additional Effect Types for Parser Support
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Cost-effect pattern - pay a cost to get an effect
|
|
138
|
+
*
|
|
139
|
+
* @example "Return chosen character to your hand to play another character"
|
|
140
|
+
* @example "Banish one of your items to draw 2 cards"
|
|
141
|
+
*/
|
|
142
|
+
export interface CostEffectEffect {
|
|
143
|
+
type: "cost-effect";
|
|
144
|
+
cost: Effect | { ink?: number; type?: string; target?: string };
|
|
145
|
+
effect: Effect;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Reveal and conditional effect - reveal cards and act based on what's revealed
|
|
150
|
+
*
|
|
151
|
+
* @example "Reveal the top card. If it's a character, play it for free."
|
|
152
|
+
*/
|
|
153
|
+
export interface RevealAndConditionalEffect {
|
|
154
|
+
type: "reveal-and-conditional";
|
|
155
|
+
reveal: {
|
|
156
|
+
source: "deck" | "hand" | "discard";
|
|
157
|
+
count: number;
|
|
158
|
+
position?: "top" | "bottom";
|
|
159
|
+
};
|
|
160
|
+
condition: {
|
|
161
|
+
type: "card-type" | "classification" | "name" | "cost";
|
|
162
|
+
cardType?: string;
|
|
163
|
+
classification?: string;
|
|
164
|
+
name?: string;
|
|
165
|
+
maxCost?: number;
|
|
166
|
+
};
|
|
167
|
+
ifTrue: Effect;
|
|
168
|
+
ifFalse?: Effect;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Grant keyword effect (for triggered/action effects, not static)
|
|
173
|
+
*
|
|
174
|
+
* @example "Your characters gain Evasive this turn"
|
|
175
|
+
*/
|
|
176
|
+
export interface GrantKeywordEffect {
|
|
177
|
+
type: "grant-keyword";
|
|
178
|
+
keyword: string;
|
|
179
|
+
value?: number;
|
|
180
|
+
target: CharacterTarget;
|
|
181
|
+
duration?: EffectDuration;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Grant multiple keywords at once
|
|
186
|
+
*
|
|
187
|
+
* @example "Chosen character gains Challenger +2 and Resist +2 this turn"
|
|
188
|
+
*/
|
|
189
|
+
export interface GrantKeywordsEffect {
|
|
190
|
+
type: "grant-keywords";
|
|
191
|
+
keywords: Array<{ keyword: string; value?: number }>;
|
|
192
|
+
target: CharacterTarget;
|
|
193
|
+
duration?: EffectDuration;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Delayed effect - effect that happens at a later time
|
|
198
|
+
*
|
|
199
|
+
* @example "At the end of the turn, banish them"
|
|
200
|
+
*/
|
|
201
|
+
export interface DelayedEffect {
|
|
202
|
+
type: "delayed";
|
|
203
|
+
timing: "end-of-turn" | "start-of-next-turn" | "end-of-next-turn";
|
|
204
|
+
effect: Effect;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Play for free effect
|
|
209
|
+
*
|
|
210
|
+
* @example "Play a character with cost 4 or less for free"
|
|
211
|
+
*/
|
|
212
|
+
export interface PlayForFreeEffect {
|
|
213
|
+
type: "play-for-free";
|
|
214
|
+
filter?: {
|
|
215
|
+
cardType?: string;
|
|
216
|
+
maxCost?: number | string;
|
|
217
|
+
classification?: string;
|
|
218
|
+
};
|
|
219
|
+
enterExerted?: boolean;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Put on deck effect
|
|
224
|
+
*
|
|
225
|
+
* @example "Put the rest on the bottom of your deck in any order"
|
|
226
|
+
*/
|
|
227
|
+
export interface PutOnDeckEffect {
|
|
228
|
+
type: "put-on-deck";
|
|
229
|
+
position?: "top" | "bottom" | "choice";
|
|
230
|
+
order?: "any" | "random";
|
|
231
|
+
options?: Array<{ position: "top" | "bottom" } | string>;
|
|
232
|
+
target?: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Look effect (for looking at cards)
|
|
237
|
+
*
|
|
238
|
+
* @example "Look at the top 3 cards of your deck"
|
|
239
|
+
*/
|
|
240
|
+
export interface LookEffect {
|
|
241
|
+
type: "look";
|
|
242
|
+
source?: "deck" | "hand" | "discard";
|
|
243
|
+
position?: "top" | "bottom";
|
|
244
|
+
count?: number;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Put into hand effect
|
|
249
|
+
*
|
|
250
|
+
* @example "You may put one into your hand"
|
|
251
|
+
*/
|
|
252
|
+
export interface PutIntoHandEffect {
|
|
253
|
+
type: "put-into-hand";
|
|
254
|
+
count: number;
|
|
255
|
+
source?: "revealed" | "deck" | "discard";
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Compound effect (legacy - use sequence instead)
|
|
260
|
+
* @deprecated Use SequenceEffect instead
|
|
261
|
+
*/
|
|
262
|
+
export interface CompoundEffect {
|
|
263
|
+
type: "compound";
|
|
264
|
+
effects?: Effect[];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* For each opponent effect
|
|
269
|
+
*/
|
|
270
|
+
export interface ForEachOpponentEffect {
|
|
271
|
+
type: "for-each-opponent";
|
|
272
|
+
effect: Effect;
|
|
273
|
+
condition?: Condition;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* For each player effect
|
|
278
|
+
*/
|
|
279
|
+
export interface ForEachPlayerEffect {
|
|
280
|
+
type: "for-each-player";
|
|
281
|
+
effect: Effect;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Prevent damage effect
|
|
286
|
+
*/
|
|
287
|
+
export interface PreventDamageEffect {
|
|
288
|
+
type: "prevent-damage";
|
|
289
|
+
amount?: Amount | "all";
|
|
290
|
+
target?: CharacterTarget;
|
|
291
|
+
source?: "challenges" | "abilities" | "all" | "CHALLENGE";
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Gain ability effect (for triggered effects)
|
|
296
|
+
*/
|
|
297
|
+
export interface GainAbilityEffect {
|
|
298
|
+
type: "gain-ability";
|
|
299
|
+
ability?: {
|
|
300
|
+
type: string;
|
|
301
|
+
[key: string]: unknown;
|
|
302
|
+
};
|
|
303
|
+
target?: CharacterTarget;
|
|
304
|
+
duration?: EffectDuration;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Redirect damage effect
|
|
309
|
+
*/
|
|
310
|
+
export interface RedirectDamageEffect {
|
|
311
|
+
type: "redirect-damage";
|
|
312
|
+
from?: CharacterTarget;
|
|
313
|
+
to?: CharacterTarget;
|
|
314
|
+
target?: CharacterTarget;
|
|
315
|
+
/** Amount of damage to redirect */
|
|
316
|
+
amount?: Amount | "all";
|
|
317
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect Types Index
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all effect types and type guards from sub-modules.
|
|
5
|
+
* Import from this file for all effect-related types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Shared types
|
|
9
|
+
export type {
|
|
10
|
+
Amount,
|
|
11
|
+
AmountString,
|
|
12
|
+
EffectDuration,
|
|
13
|
+
ForEachCounterType,
|
|
14
|
+
VariableAmount,
|
|
15
|
+
} from "./amount-types";
|
|
16
|
+
export { isVariableAmount } from "./amount-types";
|
|
17
|
+
|
|
18
|
+
// Basic effects
|
|
19
|
+
export type {
|
|
20
|
+
BanishEffect,
|
|
21
|
+
DealDamageEffect,
|
|
22
|
+
DiscardEffect,
|
|
23
|
+
DrawEffect,
|
|
24
|
+
ExertEffect,
|
|
25
|
+
GainLoreEffect,
|
|
26
|
+
LoseLoreEffect,
|
|
27
|
+
MoveDamageEffect,
|
|
28
|
+
PutDamageEffect,
|
|
29
|
+
ReadyEffect,
|
|
30
|
+
RemoveDamageEffect,
|
|
31
|
+
} from "./basic-effects";
|
|
32
|
+
// Combined types and guards
|
|
33
|
+
export type {
|
|
34
|
+
ChallengeReadyEffect,
|
|
35
|
+
Effect,
|
|
36
|
+
EntersPlayWithEffect,
|
|
37
|
+
GainKeywordsEffect,
|
|
38
|
+
ReplacementEffect,
|
|
39
|
+
StaticEffect,
|
|
40
|
+
} from "./combined-types";
|
|
41
|
+
export {
|
|
42
|
+
isControlFlowEffect,
|
|
43
|
+
isScryEffect,
|
|
44
|
+
targetsCharacters,
|
|
45
|
+
} from "./combined-types";
|
|
46
|
+
// Control flow effects
|
|
47
|
+
export type {
|
|
48
|
+
ChoiceEffect,
|
|
49
|
+
CompoundEffect,
|
|
50
|
+
ConditionalEffect,
|
|
51
|
+
CostEffectEffect,
|
|
52
|
+
DelayedEffect,
|
|
53
|
+
ForEachCounter,
|
|
54
|
+
ForEachEffect,
|
|
55
|
+
ForEachOpponentEffect,
|
|
56
|
+
ForEachPlayerEffect,
|
|
57
|
+
GainAbilityEffect,
|
|
58
|
+
GrantKeywordEffect,
|
|
59
|
+
GrantKeywordsEffect,
|
|
60
|
+
LookEffect,
|
|
61
|
+
OptionalEffect,
|
|
62
|
+
PlayForFreeEffect,
|
|
63
|
+
PreventDamageEffect,
|
|
64
|
+
PutIntoHandEffect,
|
|
65
|
+
PutOnDeckEffect,
|
|
66
|
+
RedirectDamageEffect,
|
|
67
|
+
RepeatEffect,
|
|
68
|
+
RevealAndConditionalEffect,
|
|
69
|
+
SequenceEffect,
|
|
70
|
+
} from "./control-flow";
|
|
71
|
+
|
|
72
|
+
// Modifier effects
|
|
73
|
+
export type {
|
|
74
|
+
CostReductionEffect,
|
|
75
|
+
DrawUntilHandSizeEffect,
|
|
76
|
+
EntersPlayEffect,
|
|
77
|
+
GainKeywordEffect,
|
|
78
|
+
GrantAbilityEffect,
|
|
79
|
+
LoseKeywordEffect,
|
|
80
|
+
ModifyStatEffect,
|
|
81
|
+
NameACardEffect,
|
|
82
|
+
PropertyModificationEffect,
|
|
83
|
+
PutOnTopEffect,
|
|
84
|
+
RestrictionEffect,
|
|
85
|
+
RevealHandEffect,
|
|
86
|
+
RevealTopCardEffect,
|
|
87
|
+
SearchDeckEffect,
|
|
88
|
+
SetStatEffect,
|
|
89
|
+
WinConditionEffect,
|
|
90
|
+
} from "./modifier-effects";
|
|
91
|
+
// Movement effects
|
|
92
|
+
export type {
|
|
93
|
+
EnablePlayFromUnderEffect,
|
|
94
|
+
GrantAbilitiesWhileHereEffect,
|
|
95
|
+
MoveCostReductionEffect,
|
|
96
|
+
MoveToLocationEffect,
|
|
97
|
+
PlayCardEffect,
|
|
98
|
+
PutIntoInkwellEffect,
|
|
99
|
+
PutOnBottomEffect,
|
|
100
|
+
PutUnderEffect,
|
|
101
|
+
ReturnFromDiscardEffect,
|
|
102
|
+
ReturnToHandEffect,
|
|
103
|
+
ShuffleIntoDeckEffect,
|
|
104
|
+
} from "./movement-effects";
|
|
105
|
+
// Scry effects
|
|
106
|
+
export type {
|
|
107
|
+
ScryAndFilter,
|
|
108
|
+
ScryCardFilter,
|
|
109
|
+
ScryCardOrdering,
|
|
110
|
+
ScryCardTypeFilter,
|
|
111
|
+
ScryClassificationFilter,
|
|
112
|
+
ScryCostComparisonFilter,
|
|
113
|
+
ScryDeckBottomDestination,
|
|
114
|
+
ScryDeckTopDestination,
|
|
115
|
+
ScryDestination,
|
|
116
|
+
ScryDiscardDestination,
|
|
117
|
+
ScryEffect,
|
|
118
|
+
ScryFloodbornFilter,
|
|
119
|
+
ScryHandDestination,
|
|
120
|
+
ScryInkwellDestination,
|
|
121
|
+
ScryKeywordFilter,
|
|
122
|
+
ScryNameFilter,
|
|
123
|
+
ScryNotFilter,
|
|
124
|
+
ScryOrFilter,
|
|
125
|
+
ScryPlayDestination,
|
|
126
|
+
ScrySongFilter,
|
|
127
|
+
} from "./scry-effects";
|
|
128
|
+
export {
|
|
129
|
+
isScryDeckBottomDestination,
|
|
130
|
+
isScryDeckTopDestination,
|
|
131
|
+
isScryDiscardDestination,
|
|
132
|
+
isScryHandDestination,
|
|
133
|
+
isScryInkwellDestination,
|
|
134
|
+
isScryPlayDestination,
|
|
135
|
+
isScryRemainderDestination,
|
|
136
|
+
} from "./scry-effects";
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modifier Effect Types
|
|
3
|
+
*
|
|
4
|
+
* Effects that modify game state or card properties:
|
|
5
|
+
* - Stat modifications (strength, willpower, lore)
|
|
6
|
+
* - Keyword granting/removal
|
|
7
|
+
* - Restrictions
|
|
8
|
+
* - Special state modifications
|
|
9
|
+
* - Reveal/Search effects
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { CardType } from "../../cards/card-types";
|
|
13
|
+
import type { Condition } from "../condition-types";
|
|
14
|
+
import type {
|
|
15
|
+
CardTarget,
|
|
16
|
+
CharacterTarget,
|
|
17
|
+
LocationTarget,
|
|
18
|
+
PlayerTarget,
|
|
19
|
+
} from "../target-types";
|
|
20
|
+
import type { Amount, EffectDuration } from "./amount-types";
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Stat Modification Effects
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Modify stat effect (for "this turn" effects)
|
|
28
|
+
*
|
|
29
|
+
* @example "Chosen character gets +2 strength this turn"
|
|
30
|
+
* @example "Your characters get +1 lore this turn"
|
|
31
|
+
*/
|
|
32
|
+
export interface ModifyStatEffect {
|
|
33
|
+
type: "modify-stat";
|
|
34
|
+
stat?: "strength" | "willpower" | "lore";
|
|
35
|
+
modifier?: Amount;
|
|
36
|
+
target?: CharacterTarget | LocationTarget;
|
|
37
|
+
duration?: EffectDuration;
|
|
38
|
+
/** Alternative field for modifier value */
|
|
39
|
+
value?: Amount;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Set stat effect (absolute value)
|
|
44
|
+
*/
|
|
45
|
+
export interface SetStatEffect {
|
|
46
|
+
type: "set-stat";
|
|
47
|
+
stat: "strength" | "willpower" | "lore";
|
|
48
|
+
value: Amount;
|
|
49
|
+
target: CharacterTarget;
|
|
50
|
+
duration?: EffectDuration;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Keyword Effects
|
|
55
|
+
// ============================================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Grant keyword effect
|
|
59
|
+
*
|
|
60
|
+
* @example "Chosen character gains Rush this turn"
|
|
61
|
+
* @example "Your characters gain Resist +2 this turn"
|
|
62
|
+
*/
|
|
63
|
+
export interface GainKeywordEffect {
|
|
64
|
+
type: "gain-keyword";
|
|
65
|
+
keyword?:
|
|
66
|
+
| "Rush"
|
|
67
|
+
| "Ward"
|
|
68
|
+
| "Evasive"
|
|
69
|
+
| "Bodyguard"
|
|
70
|
+
| "Support"
|
|
71
|
+
| "Reckless"
|
|
72
|
+
| "Alert"
|
|
73
|
+
| "Challenger"
|
|
74
|
+
| "Resist"
|
|
75
|
+
| "Singer"
|
|
76
|
+
| "Sing Together"
|
|
77
|
+
| string; // Allow any keyword string for flexibility
|
|
78
|
+
/** For Challenger +X and Resist +X */
|
|
79
|
+
value?: number;
|
|
80
|
+
target?: CharacterTarget;
|
|
81
|
+
duration?: EffectDuration;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Lose keyword effect
|
|
86
|
+
*/
|
|
87
|
+
export interface LoseKeywordEffect {
|
|
88
|
+
type: "lose-keyword";
|
|
89
|
+
keyword: string;
|
|
90
|
+
target: CharacterTarget;
|
|
91
|
+
duration?: EffectDuration;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Restriction Effects
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Apply restriction effect
|
|
100
|
+
*
|
|
101
|
+
* @example "Chosen character can't quest during their next turn"
|
|
102
|
+
* @example "Characters can't be challenged while here"
|
|
103
|
+
*/
|
|
104
|
+
export interface RestrictionEffect {
|
|
105
|
+
type: "restriction";
|
|
106
|
+
restriction?:
|
|
107
|
+
| "cant-quest"
|
|
108
|
+
| "cant-challenge"
|
|
109
|
+
| "cant-be-challenged"
|
|
110
|
+
| "cant-ready"
|
|
111
|
+
| "cant-quest-or-challenge"
|
|
112
|
+
| "cant-be-dealt-damage"
|
|
113
|
+
| "cant-sing"
|
|
114
|
+
| "cant-move"
|
|
115
|
+
| "enters-play-exerted"
|
|
116
|
+
| "skip-draw-step"
|
|
117
|
+
| "must-quest" // Forces character to quest if able
|
|
118
|
+
| "cant-play-actions" // Opponents can't play actions
|
|
119
|
+
| "cant-play-characters" // Opponents can't play characters
|
|
120
|
+
| "cant-play" // Generic can't play restriction
|
|
121
|
+
// Extended restrictions for card text coverage
|
|
122
|
+
| "doesnt-ready"; // Character doesn't ready (alias for cant-ready)
|
|
123
|
+
target?: CharacterTarget | PlayerTarget;
|
|
124
|
+
duration?: EffectDuration;
|
|
125
|
+
/** Condition for when the restriction applies */
|
|
126
|
+
condition?: Condition;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Grant ability effect (can challenge ready characters, etc.)
|
|
131
|
+
*/
|
|
132
|
+
export interface GrantAbilityEffect {
|
|
133
|
+
type: "grant-ability";
|
|
134
|
+
ability?:
|
|
135
|
+
| "can-challenge-ready"
|
|
136
|
+
| "takes-no-damage-from-challenges"
|
|
137
|
+
| "return-to-hand-when-banished"
|
|
138
|
+
| { type: string; [key: string]: unknown }; // Allow object-based abilities
|
|
139
|
+
target?: CharacterTarget;
|
|
140
|
+
duration?: EffectDuration;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Reduce cost effect
|
|
145
|
+
*
|
|
146
|
+
* @example "You pay 1 less to play this item"
|
|
147
|
+
*/
|
|
148
|
+
export interface CostReductionEffect {
|
|
149
|
+
type: "cost-reduction";
|
|
150
|
+
amount?: Amount | string;
|
|
151
|
+
/** Alternative field for reduction amount */
|
|
152
|
+
reduction?: { ink: number | string };
|
|
153
|
+
cardType?: CardType | "song";
|
|
154
|
+
target?: PlayerTarget; // Who gets the reduction (usually YOU)
|
|
155
|
+
duration?: EffectDuration;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// Misc Effects
|
|
160
|
+
// ============================================================================
|
|
161
|
+
|
|
162
|
+
export interface NameACardEffect {
|
|
163
|
+
type: "name-a-card";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface RevealTopCardEffect {
|
|
167
|
+
type: "reveal-top-card";
|
|
168
|
+
target?: PlayerTarget; // Whose deck
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface PutOnTopEffect {
|
|
172
|
+
type: "put-on-top";
|
|
173
|
+
source?: "revealed" | CardTarget;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface DrawUntilHandSizeEffect {
|
|
177
|
+
type: "draw-until-hand-size";
|
|
178
|
+
size: number;
|
|
179
|
+
target?: PlayerTarget;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// Special State Modifications
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Enters play modification effect
|
|
188
|
+
*
|
|
189
|
+
* @example "Enters play exerted"
|
|
190
|
+
* @example "Enters play with 2 damage"
|
|
191
|
+
*/
|
|
192
|
+
export interface EntersPlayEffect {
|
|
193
|
+
type: "enters-play-modification";
|
|
194
|
+
modification: "exerted" | "damaged";
|
|
195
|
+
amount?: number; // for damaged
|
|
196
|
+
target: CharacterTarget;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Win condition modification effect
|
|
201
|
+
*
|
|
202
|
+
* @example "Opponents need 25 lore to win"
|
|
203
|
+
*/
|
|
204
|
+
export interface WinConditionEffect {
|
|
205
|
+
type: "win-condition-modification";
|
|
206
|
+
loreRequired: number;
|
|
207
|
+
target: PlayerTarget;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Property modification effect
|
|
212
|
+
*
|
|
213
|
+
* @example "This character counts as being named 'Dalmatian Puppy'"
|
|
214
|
+
*/
|
|
215
|
+
export interface PropertyModificationEffect {
|
|
216
|
+
type: "property-modification";
|
|
217
|
+
property?: "name";
|
|
218
|
+
value?: string;
|
|
219
|
+
operation?: "add-alias";
|
|
220
|
+
target?: CharacterTarget;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ============================================================================
|
|
224
|
+
// Reveal/Search Effects
|
|
225
|
+
// ============================================================================
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Reveal hand effect
|
|
229
|
+
*/
|
|
230
|
+
export interface RevealHandEffect {
|
|
231
|
+
type: "reveal-hand";
|
|
232
|
+
target: PlayerTarget;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Search deck effect
|
|
237
|
+
*/
|
|
238
|
+
export interface SearchDeckEffect {
|
|
239
|
+
type: "search-deck";
|
|
240
|
+
cardType?: CardType | "song" | "floodborn";
|
|
241
|
+
cardName?: string;
|
|
242
|
+
classification?: string;
|
|
243
|
+
putInto?: "hand" | "top-of-deck" | "play";
|
|
244
|
+
/** Alias for putInto: "top-of-deck" */
|
|
245
|
+
putOnTop?: boolean;
|
|
246
|
+
reveal?: boolean;
|
|
247
|
+
shuffle?: boolean;
|
|
248
|
+
}
|