@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.
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Condition Helpers for Lorcana Abilities
3
+ *
4
+ * Provides a fluent API for building condition definitions.
5
+ * These helpers make it easy to construct common condition patterns.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const condition = Conditions.HasAnotherCharacter();
10
+ * const condition = Conditions.HasCharacterNamed("Elsa");
11
+ * const condition = Conditions.WhileDamaged();
12
+ * ```
13
+ */
14
+
15
+ import type { Condition } from "../condition-types";
16
+
17
+ export const Conditions = {
18
+ /**
19
+ * "If you have another character in play"
20
+ */
21
+ HasAnotherCharacter: (): Condition => ({
22
+ type: "has-another-character",
23
+ }),
24
+
25
+ /**
26
+ * "If you have a character named X"
27
+ */
28
+ HasCharacterNamed: (name: string): Condition => ({
29
+ type: "has-named-character",
30
+ name,
31
+ controller: "you",
32
+ }),
33
+
34
+ /**
35
+ * "If you have a character with classification X"
36
+ */
37
+ HasCharacterWithClassification: (classification: string): Condition => ({
38
+ type: "has-character-with-classification",
39
+ classification,
40
+ controller: "you",
41
+ }),
42
+
43
+ /**
44
+ * "If you have a character with keyword X"
45
+ */
46
+ HasCharacterWithKeyword: (keyword: string): Condition => ({
47
+ type: "has-character-with-keyword",
48
+ keyword,
49
+ controller: "you",
50
+ }),
51
+
52
+ /**
53
+ * "While this character has damage"
54
+ */
55
+ WhileDamaged: (): Condition => ({
56
+ type: "has-any-damage",
57
+ }),
58
+
59
+ /**
60
+ * "While this character has no damage"
61
+ */
62
+ WhileNoDamage: (): Condition => ({
63
+ type: "has-no-damage",
64
+ }),
65
+
66
+ /**
67
+ * "While this character is exerted"
68
+ */
69
+ WhileExerted: (): Condition => ({
70
+ type: "is-exerted",
71
+ }),
72
+
73
+ /**
74
+ * "While this character is ready"
75
+ */
76
+ WhileReady: (): Condition => ({
77
+ type: "is-ready",
78
+ }),
79
+
80
+ /**
81
+ * "While in a challenge"
82
+ */
83
+ InChallenge: (): Condition => ({
84
+ type: "in-challenge",
85
+ }),
86
+
87
+ /**
88
+ * "If you have X or more cards in hand"
89
+ */
90
+ HandSizeAtLeast: (amount: number): Condition => ({
91
+ type: "resource-count",
92
+ what: "cards-in-hand",
93
+ controller: "you",
94
+ comparison: "greater-or-equal",
95
+ value: amount,
96
+ }),
97
+
98
+ /**
99
+ * "If you have X or fewer cards in hand"
100
+ */
101
+ HandSizeAtMost: (amount: number): Condition => ({
102
+ type: "resource-count",
103
+ what: "cards-in-hand",
104
+ controller: "you",
105
+ comparison: "less-or-equal",
106
+ value: amount,
107
+ }),
108
+
109
+ /**
110
+ * "If you have no cards in hand"
111
+ */
112
+ HandIsEmpty: (): Condition => ({
113
+ type: "resource-count",
114
+ what: "cards-in-hand",
115
+ controller: "you",
116
+ comparison: "equal",
117
+ value: 0,
118
+ }),
119
+
120
+ /**
121
+ * "If you have X or more lore"
122
+ */
123
+ LoreAtLeast: (amount: number): Condition => ({
124
+ type: "lore-comparison",
125
+ comparison: "greater-or-equal",
126
+ value: amount,
127
+ }),
128
+
129
+ /**
130
+ * "If you have X or fewer lore"
131
+ */
132
+ LoreAtMost: (amount: number): Condition => ({
133
+ type: "lore-comparison",
134
+ comparison: "less-or-equal",
135
+ value: amount,
136
+ }),
137
+
138
+ /**
139
+ * "If you have a card under this character"
140
+ */
141
+ HasCardUnder: (): Condition => ({
142
+ type: "has-card-under",
143
+ }),
144
+
145
+ /**
146
+ * "If this is the first time this turn"
147
+ */
148
+ FirstTimeThisTurn: (): Condition => ({
149
+ type: "first-this-turn",
150
+ event: "action",
151
+ }),
152
+
153
+ /**
154
+ * "If you used Shift this turn"
155
+ */
156
+ UsedShiftThisTurn: (): Condition => ({
157
+ type: "used-shift",
158
+ }),
159
+
160
+ /**
161
+ * "If you have a character in play"
162
+ */
163
+ HaveCharacterInPlay: (): Condition => ({
164
+ type: "has-named-character",
165
+ controller: "you",
166
+ }),
167
+
168
+ /**
169
+ * "If you have an item in play"
170
+ */
171
+ HaveItemInPlay: (): Condition => ({
172
+ type: "has-named-item",
173
+ name: "",
174
+ controller: "you",
175
+ }),
176
+
177
+ /**
178
+ * "If you have a location in play"
179
+ */
180
+ HaveLocationInPlay: (): Condition => ({
181
+ type: "has-named-location",
182
+ name: "",
183
+ controller: "you",
184
+ }),
185
+
186
+ /**
187
+ * "If you have a card with classification X in play"
188
+ */
189
+ HaveClassificationInPlay: (classification: string): Condition => ({
190
+ type: "has-character-with-classification",
191
+ classification,
192
+ controller: "you",
193
+ }),
194
+
195
+ /**
196
+ * "If you have a card with keyword X in play"
197
+ */
198
+ HaveKeywordInPlay: (keyword: string): Condition => ({
199
+ type: "has-character-with-keyword",
200
+ keyword,
201
+ controller: "you",
202
+ }),
203
+
204
+ /**
205
+ * "If you have a card named X in play"
206
+ */
207
+ HaveNamedInPlay: (name: string): Condition => ({
208
+ type: "has-named-character",
209
+ name,
210
+ controller: "you",
211
+ }),
212
+
213
+ /**
214
+ * "If you have X or more characters in play"
215
+ */
216
+ CharacterCountAtLeast: (amount: number): Condition => ({
217
+ type: "has-character-count",
218
+ controller: "you",
219
+ comparison: "greater-or-equal",
220
+ count: amount,
221
+ }),
222
+
223
+ /**
224
+ * "If you have X or fewer characters in play"
225
+ */
226
+ CharacterCountAtMost: (amount: number): Condition => ({
227
+ type: "has-character-count",
228
+ controller: "you",
229
+ comparison: "less-or-equal",
230
+ count: amount,
231
+ }),
232
+
233
+ /**
234
+ * "If you have exactly X characters in play"
235
+ */
236
+ CharacterCountExactly: (amount: number): Condition => ({
237
+ type: "has-character-count",
238
+ controller: "you",
239
+ comparison: "equal",
240
+ count: amount,
241
+ }),
242
+
243
+ /**
244
+ * Logical AND - all conditions must be true
245
+ */
246
+ And: (...conditions: Condition[]): Condition => ({
247
+ type: "and",
248
+ conditions,
249
+ }),
250
+
251
+ /**
252
+ * Logical OR - any condition must be true
253
+ */
254
+ Or: (...conditions: Condition[]): Condition => ({
255
+ type: "or",
256
+ conditions,
257
+ }),
258
+
259
+ /**
260
+ * Logical NOT - negate a condition
261
+ */
262
+ Not: (condition: Condition): Condition => ({
263
+ type: "not",
264
+ condition,
265
+ }),
266
+ };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Cost Helpers for Lorcana Abilities
3
+ *
4
+ * Provides a fluent API for building cost definitions.
5
+ * These helpers make it easy to construct common cost patterns.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const cost = Costs.Ink(2);
10
+ * const cost = Costs.Exert();
11
+ * const cost = Costs.Combined(Costs.Ink(1), Costs.Exert());
12
+ * ```
13
+ */
14
+
15
+ import type { AbilityCost } from "../cost-types";
16
+
17
+ export const Costs = {
18
+ /**
19
+ * "X ink cost"
20
+ */
21
+ Ink: (amount: number): AbilityCost => ({ ink: amount }),
22
+
23
+ /**
24
+ * "Exert this character"
25
+ */
26
+ Exert: (): AbilityCost => ({ exert: true }),
27
+
28
+ /**
29
+ * "Banish this character"
30
+ */
31
+ BanishSelf: (): AbilityCost => ({ banishSelf: true }),
32
+
33
+ /**
34
+ * "Discard a card"
35
+ */
36
+ Discard: (amount = 1): AbilityCost => ({
37
+ discardCards: amount,
38
+ }),
39
+
40
+ /**
41
+ * "Return this card to hand"
42
+ */
43
+ ReturnToHand: (): AbilityCost => ({ returnSelfToHand: true }),
44
+
45
+ /**
46
+ * "Damage this character X"
47
+ */
48
+ DamageSelf: (amount: number): AbilityCost => ({
49
+ damageSelf: amount,
50
+ }),
51
+
52
+ /**
53
+ * "X ink and exert"
54
+ */
55
+ InkAndExert: (amount: number): AbilityCost => ({
56
+ ink: amount,
57
+ exert: true,
58
+ }),
59
+
60
+ /**
61
+ * "X ink and banish"
62
+ */
63
+ InkAndBanish: (amount: number): AbilityCost => ({
64
+ ink: amount,
65
+ banishSelf: true,
66
+ }),
67
+
68
+ /**
69
+ * "X ink and discard"
70
+ */
71
+ InkAndDiscard: (amount: number, discardAmount = 1): AbilityCost => ({
72
+ ink: amount,
73
+ discardCards: discardAmount,
74
+ }),
75
+
76
+ /**
77
+ * "Exert and banish"
78
+ */
79
+ ExertAndBanish: (): AbilityCost => ({
80
+ exert: true,
81
+ banishSelf: true,
82
+ }),
83
+ };
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Effect Helpers for Lorcana Abilities
3
+ *
4
+ * Provides a fluent API for building effect definitions.
5
+ * These helpers make it easy to construct common effect patterns.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const effect = Effects.Draw({ amount: 2 });
10
+ * const effect = Effects.Banish({ target: Targets.ChallengedCharacter(), optional: true });
11
+ * const effect = Effects.RemoveDamage({ amount: 2, target: Targets.Self() });
12
+ * ```
13
+ */
14
+
15
+ import type { Effect, OptionalEffect } from "../effect-types";
16
+ import type {
17
+ CardTarget,
18
+ CharacterTarget,
19
+ PlayerTarget,
20
+ } from "../target-types";
21
+
22
+ export const Effects = {
23
+ /**
24
+ * "Draw X cards"
25
+ */
26
+ Draw: (params: { amount: number }): Effect => ({
27
+ type: "draw",
28
+ amount: params.amount,
29
+ }),
30
+
31
+ /**
32
+ * "Banish chosen character" or "You may banish chosen character"
33
+ */
34
+ Banish: (params: { target: CharacterTarget; optional?: boolean }): Effect => {
35
+ const banishEffect: Effect = {
36
+ type: "banish",
37
+ target: params.target,
38
+ };
39
+
40
+ return params.optional
41
+ ? { type: "optional", effect: banishEffect }
42
+ : banishEffect;
43
+ },
44
+
45
+ /**
46
+ * "Remove up to X damage from target"
47
+ */
48
+ RemoveDamage: (params: {
49
+ amount: number;
50
+ target: CharacterTarget;
51
+ upTo?: boolean;
52
+ }): Effect => ({
53
+ type: "remove-damage",
54
+ amount: params.amount,
55
+ target: params.target,
56
+ upTo: params.upTo,
57
+ }),
58
+
59
+ /**
60
+ * "Target gains keyword"
61
+ */
62
+ GainKeyword: (params: {
63
+ keyword: string;
64
+ target?: CharacterTarget;
65
+ }): Effect => ({
66
+ type: "gain-keyword",
67
+ keyword: params.keyword,
68
+ target: params.target ?? "SELF",
69
+ }),
70
+
71
+ /**
72
+ * "Sequence of effects"
73
+ */
74
+ Sequence: (effects: Effect[]): Effect => ({
75
+ type: "sequence",
76
+ effects,
77
+ }),
78
+
79
+ /**
80
+ * "You may [effect]"
81
+ */
82
+ Optional: (effect: Effect): OptionalEffect => ({
83
+ type: "optional",
84
+ effect,
85
+ }),
86
+
87
+ /**
88
+ * "Deal X damage to target"
89
+ */
90
+ DealDamage: (params: {
91
+ amount: number;
92
+ target: CharacterTarget;
93
+ }): Effect => ({
94
+ type: "deal-damage",
95
+ amount: params.amount,
96
+ target: params.target,
97
+ }),
98
+
99
+ /**
100
+ * "Gain X lore"
101
+ */
102
+ GainLore: (params: { amount: number }): Effect => ({
103
+ type: "gain-lore",
104
+ amount: params.amount,
105
+ }),
106
+
107
+ /**
108
+ * "Lose X lore"
109
+ */
110
+ LoseLore: (params: { amount: number }): Effect => ({
111
+ type: "lose-lore",
112
+ amount: params.amount,
113
+ }),
114
+
115
+ /**
116
+ * "Exert target"
117
+ */
118
+ Exert: (params?: { target?: CharacterTarget }): Effect => ({
119
+ type: "exert",
120
+ target: params?.target ?? "SELF",
121
+ }),
122
+
123
+ /**
124
+ * "Ready target"
125
+ */
126
+ Ready: (params?: { target?: CharacterTarget }): Effect => ({
127
+ type: "ready",
128
+ target: params?.target ?? "SELF",
129
+ }),
130
+
131
+ /**
132
+ * "Return target to hand"
133
+ */
134
+ ReturnToHand: (params: { target: CharacterTarget }): Effect => ({
135
+ type: "return-to-hand",
136
+ target: params.target,
137
+ }),
138
+
139
+ /**
140
+ * "Discard target"
141
+ */
142
+ Discard: (params?: { target?: CharacterTarget }): Effect => ({
143
+ type: "discard",
144
+ }),
145
+
146
+ /**
147
+ * "Put target into inkwell"
148
+ */
149
+ PutIntoInkwell: (params?: { target?: CharacterTarget }): Effect => ({
150
+ type: "put-into-inkwell",
151
+ }),
152
+
153
+ /**
154
+ * "Search deck for card and put into hand"
155
+ */
156
+ SearchDeck: (): Effect => ({
157
+ type: "search-deck",
158
+ }),
159
+
160
+ /**
161
+ * "Shuffle target into deck"
162
+ */
163
+ ShuffleIntoDeck: (params: { target: CharacterTarget }): Effect => ({
164
+ type: "shuffle-into-deck",
165
+ target: params.target,
166
+ }),
167
+
168
+ /**
169
+ * "Put target on top of deck"
170
+ */
171
+ PutOnTop: (params: { target: CharacterTarget }): Effect => ({
172
+ type: "put-on-top",
173
+ }),
174
+
175
+ /**
176
+ * "Put target on bottom of deck"
177
+ */
178
+ PutOnBottom: (params: { target: CharacterTarget }): Effect => ({
179
+ type: "put-on-bottom",
180
+ target: params.target,
181
+ }),
182
+ };
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Target Helpers for Lorcana Abilities
3
+ *
4
+ * Provides a fluent API for building target definitions.
5
+ * These helpers make it easy to construct common target patterns.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const target = Targets.Self();
10
+ * const target = Targets.ChallengedCharacter();
11
+ * const target = Targets.YourCharacters();
12
+ * ```
13
+ */
14
+
15
+ import type {
16
+ CardTarget,
17
+ CharacterTarget,
18
+ PlayerTarget,
19
+ } from "../target-types";
20
+
21
+ export const Targets = {
22
+ // ========================================================================
23
+ // Self/Controller Targets
24
+ // ========================================================================
25
+
26
+ /**
27
+ * "This character" or "this card"
28
+ */
29
+ Self: (): CardTarget => "SELF",
30
+
31
+ /**
32
+ * "You" (for player-targeted effects)
33
+ */
34
+ Controller: (): PlayerTarget => "CONTROLLER",
35
+
36
+ /**
37
+ * "Your opponent"
38
+ */
39
+ Opponent: (): PlayerTarget => "OPPONENT",
40
+
41
+ // ========================================================================
42
+ // Character Targets
43
+ // ========================================================================
44
+
45
+ /**
46
+ * "Chosen character"
47
+ */
48
+ ChosenCharacter: (): CharacterTarget => "CHOSEN_CHARACTER",
49
+
50
+ /**
51
+ * "Challenged character"
52
+ */
53
+ ChallengedCharacter: (): CharacterTarget => "CHALLENGED_CHARACTER",
54
+
55
+ /**
56
+ * "Challenging character"
57
+ */
58
+ ChallengingCharacter: (): CharacterTarget => "CHALLENGING_CHARACTER",
59
+
60
+ // ========================================================================
61
+ // Your Characters
62
+ // ========================================================================
63
+
64
+ /**
65
+ * "Your characters"
66
+ */
67
+ YourCharacters: (): CharacterTarget => "YOUR_CHARACTERS",
68
+
69
+ /**
70
+ * "Your other characters"
71
+ */
72
+ YourOtherCharacters: (): CharacterTarget => "YOUR_OTHER_CHARACTERS",
73
+
74
+ // ========================================================================
75
+ // Opponent Characters
76
+ // ========================================================================
77
+
78
+ /**
79
+ * "Opponent's characters"
80
+ */
81
+ OpponentCharacters: (): CharacterTarget => "ALL_OPPOSING_CHARACTERS",
82
+
83
+ /**
84
+ * "Opposing characters"
85
+ */
86
+ OpposingCharacters: (): CharacterTarget => "OPPOSING_CHARACTERS",
87
+
88
+ // ========================================================================
89
+ // Classification-based Targets
90
+ // ========================================================================
91
+
92
+ /**
93
+ * "Your Musketeer characters"
94
+ */
95
+ YourMusketeers: (): CharacterTarget => "YOUR_MUSKETEER_CHARACTERS",
96
+
97
+ /**
98
+ * "Your Villain characters"
99
+ */
100
+ YourVillains: (): CharacterTarget => "YOUR_VILLAIN_CHARACTERS",
101
+
102
+ /**
103
+ * "Your Broom characters"
104
+ */
105
+ YourBrooms: (): CharacterTarget => "YOUR_BROOM_CHARACTERS",
106
+
107
+ /**
108
+ * "Your other Steel characters"
109
+ */
110
+ YourOtherSteelCharacters: (): CharacterTarget =>
111
+ "YOUR_OTHER_STEEL_CHARACTERS",
112
+
113
+ /**
114
+ * "Your other Amethyst characters"
115
+ */
116
+ YourOtherAmethystCharacters: (): CharacterTarget =>
117
+ "YOUR_OTHER_AMETHYST_CHARACTERS",
118
+
119
+ // ========================================================================
120
+ // Zone-based Targets
121
+ // ========================================================================
122
+
123
+ /**
124
+ * "Character from discard"
125
+ */
126
+ CharacterFromDiscard: (): CharacterTarget => "CHOSEN_CHARACTER_IN_DISCARD",
127
+
128
+ /**
129
+ * "Characters at this location"
130
+ */
131
+ CharactersHere: (): CharacterTarget => "CHARACTERS_HERE",
132
+
133
+ // ========================================================================
134
+ // All/Each Targets
135
+ // ========================================================================
136
+
137
+ /**
138
+ * "All characters"
139
+ */
140
+ AllCharacters: (): CharacterTarget => "ALL_CHARACTERS",
141
+
142
+ /**
143
+ * "All your characters"
144
+ */
145
+ AllYourCharacters: (): CharacterTarget => "YOUR_CHARACTERS",
146
+
147
+ /**
148
+ * "All opponent characters"
149
+ */
150
+ AllOpponentCharacters: (): CharacterTarget => "ALL_OPPOSING_CHARACTERS",
151
+
152
+ // ========================================================================
153
+ // Item Targets
154
+ // ========================================================================
155
+
156
+ /**
157
+ * "Your items"
158
+ */
159
+ YourItems: (): CardTarget => "YOUR_ITEMS",
160
+
161
+ /**
162
+ * "Chosen item"
163
+ */
164
+ ChosenItem: (): CardTarget => "CHOSEN_ITEM",
165
+
166
+ // ========================================================================
167
+ // Location Targets
168
+ // ========================================================================
169
+
170
+ /**
171
+ * "Your locations"
172
+ */
173
+ YourLocations: (): CardTarget => "YOUR_LOCATIONS",
174
+
175
+ /**
176
+ * "Chosen location"
177
+ */
178
+ ChosenLocation: (): CardTarget => "CHOSEN_LOCATION",
179
+
180
+ // ========================================================================
181
+ // Generic Targets
182
+ // ========================================================================
183
+
184
+ /**
185
+ * "Any character"
186
+ */
187
+ AnyCharacter: (): CharacterTarget => "ALL_CHARACTERS",
188
+
189
+ /**
190
+ * "All characters"
191
+ */
192
+ AllCharactersTarget: (): CharacterTarget => "ALL_CHARACTERS",
193
+ };