@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,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost Types for Lorcana Abilities
|
|
3
|
+
*
|
|
4
|
+
* Defines the costs required to activate abilities in Lorcana.
|
|
5
|
+
* Activated abilities use the format: "{cost} - {effect}"
|
|
6
|
+
*
|
|
7
|
+
* Common costs:
|
|
8
|
+
* - {E} = Exert this card
|
|
9
|
+
* - {d} {I} = Pay ink (where d is a number)
|
|
10
|
+
* - Banish this card/item
|
|
11
|
+
* - Discard cards
|
|
12
|
+
*
|
|
13
|
+
* @example "{E} - Draw a card" (exert cost)
|
|
14
|
+
* @example "{E}, 2 {I} - Deal 3 damage" (exert + ink cost)
|
|
15
|
+
* @example "Banish this item - Gain 3 lore" (banish self cost)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { CardType } from "../cards/card-types";
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Individual Cost Components
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Exert cost - tap/exhaust this card
|
|
26
|
+
*/
|
|
27
|
+
export interface ExertCost {
|
|
28
|
+
type: "exert";
|
|
29
|
+
/** What to exert (defaults to self) */
|
|
30
|
+
target?: "self" | "another-character" | "item";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Ink cost - pay from inkwell
|
|
35
|
+
*/
|
|
36
|
+
export interface InkCost {
|
|
37
|
+
type: "ink";
|
|
38
|
+
amount: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Banish cost - sacrifice a card
|
|
43
|
+
*/
|
|
44
|
+
export type BanishCost =
|
|
45
|
+
| {
|
|
46
|
+
type: "banish";
|
|
47
|
+
/** Simple banish targets */
|
|
48
|
+
target: "self" | "item" | "character";
|
|
49
|
+
}
|
|
50
|
+
| {
|
|
51
|
+
type: "banish";
|
|
52
|
+
/** Banish a specific card type/name */
|
|
53
|
+
target: "specific";
|
|
54
|
+
/** For "specific" target - card type or name required */
|
|
55
|
+
cardType?: CardType;
|
|
56
|
+
/** For "specific" target - card name required */
|
|
57
|
+
cardName?: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Discard cost - discard cards from hand
|
|
62
|
+
*/
|
|
63
|
+
export interface DiscardCost {
|
|
64
|
+
type: "discard";
|
|
65
|
+
/** How many cards to discard */
|
|
66
|
+
amount: number;
|
|
67
|
+
/** Whether the player chooses which cards (vs random) */
|
|
68
|
+
chosen?: boolean;
|
|
69
|
+
/** Specific card type required */
|
|
70
|
+
cardType?: CardType | "song";
|
|
71
|
+
/** Specific card name required */
|
|
72
|
+
cardName?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Deal damage to self cost
|
|
77
|
+
*/
|
|
78
|
+
export interface DamageSelfCost {
|
|
79
|
+
type: "damage-self";
|
|
80
|
+
amount: number;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Return card to hand cost
|
|
85
|
+
*/
|
|
86
|
+
export interface ReturnToHandCost {
|
|
87
|
+
type: "return-to-hand";
|
|
88
|
+
/** What to return */
|
|
89
|
+
target:
|
|
90
|
+
| "self" // Return this card
|
|
91
|
+
| "another-character" // Return another of your characters
|
|
92
|
+
| "item"; // Return one of your items
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Put card under another card cost
|
|
97
|
+
*/
|
|
98
|
+
export interface PutUnderCost {
|
|
99
|
+
type: "put-under";
|
|
100
|
+
/** What goes under */
|
|
101
|
+
source: "card-from-hand" | "top-of-deck";
|
|
102
|
+
/** Card type requirement */
|
|
103
|
+
cardType?: CardType;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Exert another card cost (not self)
|
|
108
|
+
*/
|
|
109
|
+
export interface ExertOtherCost {
|
|
110
|
+
type: "exert-other";
|
|
111
|
+
/** What to exert */
|
|
112
|
+
target: "character" | "item";
|
|
113
|
+
/** How many to exert */
|
|
114
|
+
amount?: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ============================================================================
|
|
118
|
+
// Combined Cost
|
|
119
|
+
// ============================================================================
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Individual cost component
|
|
123
|
+
*/
|
|
124
|
+
export type CostComponent =
|
|
125
|
+
| ExertCost
|
|
126
|
+
| InkCost
|
|
127
|
+
| BanishCost
|
|
128
|
+
| DiscardCost
|
|
129
|
+
| DamageSelfCost
|
|
130
|
+
| ReturnToHandCost
|
|
131
|
+
| PutUnderCost
|
|
132
|
+
| ExertOtherCost;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Complete ability cost - can have multiple components
|
|
136
|
+
*
|
|
137
|
+
* @example "{E}" - just exert
|
|
138
|
+
* ```typescript
|
|
139
|
+
* { exert: true }
|
|
140
|
+
* ```
|
|
141
|
+
*
|
|
142
|
+
* @example "{E}, 2 {I}" - exert and pay 2 ink
|
|
143
|
+
* ```typescript
|
|
144
|
+
* { exert: true, ink: 2 }
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @example "{E}, Banish this item" - exert and banish self
|
|
148
|
+
* ```typescript
|
|
149
|
+
* { exert: true, banishSelf: true }
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @example "Choose and discard a card" - discard cost
|
|
153
|
+
* ```typescript
|
|
154
|
+
* { discardCards: 1, discardChosen: true }
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* **Valid Cost Combinations:**
|
|
159
|
+
* - `exert` can be combined with any other cost
|
|
160
|
+
* - `ink` must be a positive number (omit if no ink cost)
|
|
161
|
+
* - Banish costs (`banishSelf`, `banishItem`, `banishCharacter`) are mutually exclusive
|
|
162
|
+
* - `discardChosen` requires `discardCards` to also be set
|
|
163
|
+
* - `discardCardType`/`discardCardName` require `discardCards` to also be set
|
|
164
|
+
* - Use `components` for complex costs not covered by simple fields
|
|
165
|
+
*
|
|
166
|
+
* @todo Consider refactoring to discriminated unions for better type safety in a future major version
|
|
167
|
+
*/
|
|
168
|
+
export interface AbilityCost {
|
|
169
|
+
/** Whether to exert this card */
|
|
170
|
+
exert?: boolean;
|
|
171
|
+
|
|
172
|
+
/** Ink to pay from inkwell (must be positive if present) */
|
|
173
|
+
ink?: number;
|
|
174
|
+
|
|
175
|
+
/** Banish this card (mutually exclusive with banishItem/banishCharacter) */
|
|
176
|
+
banishSelf?: boolean;
|
|
177
|
+
|
|
178
|
+
/** Banish one of your items (mutually exclusive with banishSelf/banishCharacter) */
|
|
179
|
+
banishItem?: boolean;
|
|
180
|
+
|
|
181
|
+
/** Banish one of your characters (mutually exclusive with banishSelf/banishItem) */
|
|
182
|
+
banishCharacter?: boolean;
|
|
183
|
+
|
|
184
|
+
/** Banish another card (generic) */
|
|
185
|
+
banishOther?: boolean;
|
|
186
|
+
|
|
187
|
+
/** Number of cards to discard from hand */
|
|
188
|
+
discardCards?: number;
|
|
189
|
+
|
|
190
|
+
/** Alias for discardCards (singular form) */
|
|
191
|
+
discardCard?: number;
|
|
192
|
+
|
|
193
|
+
/** Whether discarded cards are chosen (requires discardCards) */
|
|
194
|
+
discardChosen?: boolean;
|
|
195
|
+
|
|
196
|
+
/** Specific card type required for discard (requires discardCards) */
|
|
197
|
+
discardCardType?: CardType | "song";
|
|
198
|
+
|
|
199
|
+
/** Specific card name required for discard (requires discardCards) */
|
|
200
|
+
discardCardName?: string;
|
|
201
|
+
|
|
202
|
+
/** Damage to deal to this character */
|
|
203
|
+
damageSelf?: number;
|
|
204
|
+
|
|
205
|
+
/** Return this card to hand */
|
|
206
|
+
returnSelfToHand?: boolean;
|
|
207
|
+
|
|
208
|
+
/** Return another character to hand */
|
|
209
|
+
returnCharacterToHand?: boolean;
|
|
210
|
+
|
|
211
|
+
/** Number of items to exert (other than self) */
|
|
212
|
+
exertItems?: number;
|
|
213
|
+
|
|
214
|
+
/** Number of characters to exert (other than self) */
|
|
215
|
+
exertCharacters?: number;
|
|
216
|
+
|
|
217
|
+
/** Exert a single character (singular form) */
|
|
218
|
+
exertCharacter?: boolean;
|
|
219
|
+
|
|
220
|
+
/** Exert another card (generic) */
|
|
221
|
+
exertOther?: boolean;
|
|
222
|
+
|
|
223
|
+
/** Target for cost (e.g., which character to exert) */
|
|
224
|
+
target?: string;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Discard cost as an object (alternative format)
|
|
228
|
+
* Used by parser for complex discard costs
|
|
229
|
+
*/
|
|
230
|
+
discard?: {
|
|
231
|
+
cardType?: CardType | "song" | "character";
|
|
232
|
+
amount?: number;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Complex cost components (for less common costs)
|
|
237
|
+
* Used when the simple fields above don't suffice
|
|
238
|
+
*/
|
|
239
|
+
components?: CostComponent[];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// Cost Builders (convenience)
|
|
244
|
+
// ============================================================================
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Create an exert-only cost
|
|
248
|
+
*/
|
|
249
|
+
export function exertCost(): AbilityCost {
|
|
250
|
+
return { exert: true };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Create an exert + ink cost
|
|
255
|
+
*/
|
|
256
|
+
export function exertAndInkCost(ink: number): AbilityCost {
|
|
257
|
+
return { exert: true, ink };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Create a banish-self cost
|
|
262
|
+
*/
|
|
263
|
+
export function banishSelfCost(): AbilityCost {
|
|
264
|
+
return { banishSelf: true };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Create an exert + banish item cost
|
|
269
|
+
*/
|
|
270
|
+
export function exertAndBanishItemCost(): AbilityCost {
|
|
271
|
+
return { exert: true, banishItem: true };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Create a discard cost
|
|
276
|
+
*/
|
|
277
|
+
export function discardCost(amount: number, chosen = true): AbilityCost {
|
|
278
|
+
return { discardCards: amount, discardChosen: chosen };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ============================================================================
|
|
282
|
+
// Type Guards
|
|
283
|
+
// ============================================================================
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Check if a cost requires exerting
|
|
287
|
+
*/
|
|
288
|
+
export function requiresExert(cost: AbilityCost): boolean {
|
|
289
|
+
return cost.exert === true;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if a cost requires paying ink
|
|
294
|
+
*/
|
|
295
|
+
export function requiresInk(cost: AbilityCost): boolean {
|
|
296
|
+
return (cost.ink ?? 0) > 0;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Check if a cost requires banishing something
|
|
301
|
+
*/
|
|
302
|
+
export function requiresBanish(cost: AbilityCost): boolean {
|
|
303
|
+
return (
|
|
304
|
+
cost.banishSelf === true ||
|
|
305
|
+
cost.banishItem === true ||
|
|
306
|
+
cost.banishCharacter === true
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Check if a cost requires discarding cards
|
|
312
|
+
*/
|
|
313
|
+
export function requiresDiscard(cost: AbilityCost): boolean {
|
|
314
|
+
return (cost.discardCards ?? 0) > 0;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Get total ink cost
|
|
319
|
+
*/
|
|
320
|
+
export function getInkCost(cost: AbilityCost): number {
|
|
321
|
+
return cost.ink ?? 0;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Check if cost is "free" (no cost)
|
|
326
|
+
*/
|
|
327
|
+
export function isFreeCost(cost: AbilityCost): boolean {
|
|
328
|
+
return (
|
|
329
|
+
!(
|
|
330
|
+
cost.exert ||
|
|
331
|
+
cost.ink ||
|
|
332
|
+
cost.banishSelf ||
|
|
333
|
+
cost.banishItem ||
|
|
334
|
+
cost.banishCharacter ||
|
|
335
|
+
cost.discardCards ||
|
|
336
|
+
cost.damageSelf ||
|
|
337
|
+
cost.returnSelfToHand ||
|
|
338
|
+
cost.returnCharacterToHand ||
|
|
339
|
+
cost.exertItems ||
|
|
340
|
+
cost.exertCharacters
|
|
341
|
+
) &&
|
|
342
|
+
(!cost.components || cost.components.length === 0)
|
|
343
|
+
);
|
|
344
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Types for Effects
|
|
3
|
+
*
|
|
4
|
+
* Defines primitive types used across multiple effect modules:
|
|
5
|
+
* - Amount types (fixed or variable)
|
|
6
|
+
* - Effect duration types
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { CardTarget, CharacterTarget } from "../target-types";
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Amount Types
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Amount can be a fixed number, variable based on game state, or a string reference
|
|
17
|
+
*/
|
|
18
|
+
export type Amount = number | VariableAmount | AmountString;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* String-based amount references
|
|
22
|
+
*/
|
|
23
|
+
export type AmountString =
|
|
24
|
+
| "all" // All damage, all cards, etc.
|
|
25
|
+
| "DISCARDED_COUNT" // Number of cards discarded
|
|
26
|
+
| "DISCARDED_CARD_LORE" // Lore value of discarded card
|
|
27
|
+
| "RETURNED_CARD_COST" // Cost of returned card
|
|
28
|
+
| "DAMAGE_DEALT" // Amount of damage dealt
|
|
29
|
+
| "OPPONENTS_DAMAGED_CHARACTER_COUNT" // Number of opponent's damaged characters
|
|
30
|
+
| "X" // Variable amount (determined at resolution)
|
|
31
|
+
// Extended amount references for card text coverage
|
|
32
|
+
| "DAMAGE_REMOVED" // Amount of damage removed
|
|
33
|
+
| "HAND" // Number of cards in hand
|
|
34
|
+
| "TARGET_COST" // Cost of target card
|
|
35
|
+
| "TARGET_STRENGTH" // Strength of target character
|
|
36
|
+
| "TARGET_WILLPOWER"; // Willpower of target character
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Counter types for for-each amounts
|
|
40
|
+
*/
|
|
41
|
+
export type ForEachCounterType =
|
|
42
|
+
| "characters"
|
|
43
|
+
| "damaged-characters"
|
|
44
|
+
| "items"
|
|
45
|
+
| "locations"
|
|
46
|
+
| "cards-in-hand"
|
|
47
|
+
| "cards-in-discard"
|
|
48
|
+
| "damage-on-self"
|
|
49
|
+
| "damage-on-target"
|
|
50
|
+
| "cards-under-self";
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Variable amount calculated from game state
|
|
54
|
+
*/
|
|
55
|
+
export type VariableAmount =
|
|
56
|
+
| { type: "damage-on-target" }
|
|
57
|
+
| { type: "damage-on-self" }
|
|
58
|
+
| {
|
|
59
|
+
type: "cards-in-hand";
|
|
60
|
+
controller: "you" | "opponent" | "opponents";
|
|
61
|
+
modifier?: number;
|
|
62
|
+
}
|
|
63
|
+
| { type: "characters-in-play"; controller: "you" | "opponent" | "opponents" }
|
|
64
|
+
| { type: "items-in-play"; controller: "you" | "opponent" }
|
|
65
|
+
| { type: "cards-in-discard"; controller: "you" | "opponent" }
|
|
66
|
+
| { type: "lore"; controller: "you" | "opponent" }
|
|
67
|
+
| { type: "strength-of"; target: CharacterTarget }
|
|
68
|
+
| { type: "willpower-of"; target: CharacterTarget }
|
|
69
|
+
| { type: "lore-value-of"; target: CharacterTarget }
|
|
70
|
+
| { type: "cost-of"; target: CardTarget }
|
|
71
|
+
| { type: "cards-under-self" }
|
|
72
|
+
| {
|
|
73
|
+
type: "classification-character-count";
|
|
74
|
+
classification: string;
|
|
75
|
+
controller: "you" | "opponent";
|
|
76
|
+
}
|
|
77
|
+
| { type: "locations-in-play"; controller: "you" | "opponent" }
|
|
78
|
+
// For-each based amounts
|
|
79
|
+
| {
|
|
80
|
+
type: "for-each";
|
|
81
|
+
counter: ForEachCounterType | { type: string; controller?: string };
|
|
82
|
+
count?: number | VariableAmount;
|
|
83
|
+
modifier?: number;
|
|
84
|
+
}
|
|
85
|
+
// Additional variable amounts
|
|
86
|
+
| { type: "count"; what?: string; controller?: string; of?: string }
|
|
87
|
+
| { type: "VARIABLE" } // Generic variable amount
|
|
88
|
+
| { type: "lore-lost" } // Amount of lore lost
|
|
89
|
+
| { type: "stat"; stat?: string; target?: string }; // Stat value
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Check if amount is variable (vs fixed number)
|
|
93
|
+
*/
|
|
94
|
+
export function isVariableAmount(amount: Amount): amount is VariableAmount {
|
|
95
|
+
return typeof amount === "object";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Effect Duration Types
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* How long an effect lasts
|
|
104
|
+
*/
|
|
105
|
+
export type EffectDuration =
|
|
106
|
+
| "this-turn"
|
|
107
|
+
| "until-start-of-next-turn"
|
|
108
|
+
| "until-end-of-turn"
|
|
109
|
+
| "permanent"
|
|
110
|
+
| "while-condition"
|
|
111
|
+
| "next-play-this-turn" // Used with static abilities
|
|
112
|
+
| "next-turn" // Until the start/end of their next turn
|
|
113
|
+
| "their-next-turn" // Until the opponent's next turn
|
|
114
|
+
| "while-in-play" // While the card is in play
|
|
115
|
+
| { type: string }; // Allow object-based durations for flexibility
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Effect Types
|
|
3
|
+
*
|
|
4
|
+
* Core effect types for common game actions:
|
|
5
|
+
* - Draw/Discard cards
|
|
6
|
+
* - Deal/Remove damage
|
|
7
|
+
* - Gain/Lose lore
|
|
8
|
+
* - Exert/Ready/Banish cards
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
CharacterTarget,
|
|
13
|
+
ItemTarget,
|
|
14
|
+
LocationTarget,
|
|
15
|
+
PlayerTarget,
|
|
16
|
+
TargetZone,
|
|
17
|
+
} from "../target-types";
|
|
18
|
+
import type { Amount } from "./amount-types";
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Draw/Discard Effects
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Draw cards effect
|
|
26
|
+
*
|
|
27
|
+
* @example "Draw 2 cards"
|
|
28
|
+
* @example "Each player draws a card"
|
|
29
|
+
*/
|
|
30
|
+
export interface DrawEffect {
|
|
31
|
+
type: "draw";
|
|
32
|
+
amount?: Amount;
|
|
33
|
+
target?: PlayerTarget;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Discard cards effect
|
|
38
|
+
*
|
|
39
|
+
* @example "Choose and discard a card"
|
|
40
|
+
* @example "Each opponent discards a card at random"
|
|
41
|
+
*/
|
|
42
|
+
export interface DiscardEffect {
|
|
43
|
+
type: "discard";
|
|
44
|
+
amount?: Amount;
|
|
45
|
+
target?: PlayerTarget;
|
|
46
|
+
/** Whether the affected player chooses which cards */
|
|
47
|
+
chosen?: boolean;
|
|
48
|
+
/** Who chooses (alternative to chosen) */
|
|
49
|
+
chosenBy?: "you" | "opponent" | "TARGET";
|
|
50
|
+
/** If not chosen, discard is random */
|
|
51
|
+
random?: boolean;
|
|
52
|
+
/** Discard from specific zone (default: hand) */
|
|
53
|
+
from?: TargetZone;
|
|
54
|
+
/** Filter for what can be discarded */
|
|
55
|
+
filter?: {
|
|
56
|
+
cardType?: string;
|
|
57
|
+
maxCost?: number;
|
|
58
|
+
classification?: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Damage Effects
|
|
64
|
+
// ============================================================================
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Deal damage effect
|
|
68
|
+
*
|
|
69
|
+
* @example "Deal 3 damage to chosen character"
|
|
70
|
+
* @example "Deal 2 damage to each opposing character"
|
|
71
|
+
*/
|
|
72
|
+
export interface DealDamageEffect {
|
|
73
|
+
type: "deal-damage";
|
|
74
|
+
amount?: Amount;
|
|
75
|
+
target?: CharacterTarget | LocationTarget;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Put damage counters (different from "deal" - doesn't trigger "when dealt damage")
|
|
80
|
+
*/
|
|
81
|
+
export interface PutDamageEffect {
|
|
82
|
+
type: "put-damage";
|
|
83
|
+
amount: Amount;
|
|
84
|
+
target: CharacterTarget | LocationTarget;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Remove damage effect
|
|
89
|
+
*
|
|
90
|
+
* @example "Remove up to 3 damage from chosen character"
|
|
91
|
+
*/
|
|
92
|
+
export interface RemoveDamageEffect {
|
|
93
|
+
type: "remove-damage";
|
|
94
|
+
amount?: Amount;
|
|
95
|
+
target?: CharacterTarget | LocationTarget;
|
|
96
|
+
/** "up to" allows removing less than max */
|
|
97
|
+
upTo?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Move damage counters effect
|
|
102
|
+
*
|
|
103
|
+
* @example "Move 2 damage from chosen character to another"
|
|
104
|
+
*/
|
|
105
|
+
export interface MoveDamageEffect {
|
|
106
|
+
type: "move-damage";
|
|
107
|
+
amount?: Amount;
|
|
108
|
+
from?: CharacterTarget;
|
|
109
|
+
to?: CharacterTarget;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// Lore Effects
|
|
114
|
+
// ============================================================================
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Gain lore effect
|
|
118
|
+
*
|
|
119
|
+
* @example "Gain 2 lore"
|
|
120
|
+
*/
|
|
121
|
+
export interface GainLoreEffect {
|
|
122
|
+
type: "gain-lore";
|
|
123
|
+
amount?: Amount;
|
|
124
|
+
target?: PlayerTarget;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Lose lore effect
|
|
129
|
+
*
|
|
130
|
+
* @example "Each opponent loses 1 lore"
|
|
131
|
+
*/
|
|
132
|
+
export interface LoseLoreEffect {
|
|
133
|
+
type: "lose-lore";
|
|
134
|
+
amount: Amount;
|
|
135
|
+
target?: PlayerTarget;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ============================================================================
|
|
139
|
+
// Card State Effects
|
|
140
|
+
// ============================================================================
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Exert effect
|
|
144
|
+
*
|
|
145
|
+
* @example "Exert chosen character"
|
|
146
|
+
*/
|
|
147
|
+
export interface ExertEffect {
|
|
148
|
+
type: "exert";
|
|
149
|
+
target?: CharacterTarget | ItemTarget | LocationTarget;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Ready effect
|
|
154
|
+
*
|
|
155
|
+
* @example "Ready chosen character"
|
|
156
|
+
*/
|
|
157
|
+
export interface ReadyEffect {
|
|
158
|
+
type: "ready";
|
|
159
|
+
target?: CharacterTarget | ItemTarget | LocationTarget;
|
|
160
|
+
/** Restriction after readying */
|
|
161
|
+
restriction?: "cant-quest" | "cant-challenge" | "cant-quest-or-challenge";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Banish effect
|
|
166
|
+
*
|
|
167
|
+
* @example "Banish chosen character"
|
|
168
|
+
* @example "Banish all opposing items"
|
|
169
|
+
*/
|
|
170
|
+
export interface BanishEffect {
|
|
171
|
+
type: "banish";
|
|
172
|
+
target?: CharacterTarget | ItemTarget | LocationTarget;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// Look At / Reveal Effects
|
|
177
|
+
// ============================================================================
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Look at cards effect
|
|
181
|
+
*
|
|
182
|
+
* @example "Look at the top 3 cards of your deck"
|
|
183
|
+
*/
|
|
184
|
+
export interface LookAtCardsEffect {
|
|
185
|
+
type: "look-at-cards";
|
|
186
|
+
amount: Amount;
|
|
187
|
+
source: "deck" | "hand" | "discard";
|
|
188
|
+
target: PlayerTarget;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Put card into hand effect
|
|
193
|
+
*
|
|
194
|
+
* @example "Put a card into your hand"
|
|
195
|
+
*/
|
|
196
|
+
export interface PutInHandEffect {
|
|
197
|
+
type: "put-in-hand";
|
|
198
|
+
source: "deck" | "discard" | "revealed";
|
|
199
|
+
target: PlayerTarget;
|
|
200
|
+
}
|