@bct-app/game-engine 0.1.6-beta.3 → 0.1.6

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/dist/index.d.mts CHANGED
@@ -10,6 +10,21 @@ type TApplyOperationToPlayersArgs = {
10
10
  };
11
11
  declare const applyOperationToPlayers: ({ players, operations, allAbilities, characters, timelines, timelineIndexAtNow, }: TApplyOperationToPlayersArgs) => TPlayer[];
12
12
 
13
+ type TCanInvokeAbilityArgs = {
14
+ ability: TAbility;
15
+ effector: TPlayer | undefined;
16
+ currentTimelineIdx: number;
17
+ timelines: TTimeline[];
18
+ priorOperations?: TOperation[];
19
+ };
20
+ type TCanInvokeAbilityResult = {
21
+ allowed: true;
22
+ } | {
23
+ allowed: false;
24
+ reason: string;
25
+ };
26
+ declare const canInvokeAbility: ({ ability, effector, currentTimelineIdx, timelines, priorOperations, }: TCanInvokeAbilityArgs) => TCanInvokeAbilityResult;
27
+
13
28
  declare const transformEmptyArray: <T>(arr: T[]) => T[];
14
29
  declare const copyPlayers: (players: TPlayer[]) => TPlayer[];
15
30
  declare const buildPlayerSeatMap: (players: TPlayer[]) => Map<number, TPlayer>;
@@ -42,4 +57,4 @@ declare const isReminder: (value: unknown) => value is TReminder;
42
57
  */
43
58
  declare const isPlayerReminderArray: (value: unknown) => value is TPlayerReminder[];
44
59
 
45
- export { adjustValueAsNumber, adjustValueAsNumberArray, applyOperationToPlayers, buildPlayerSeatMap, copyPlayers, getSourceValue, getValueFromPayloads, isNumberOrNumberArray, isPlayerReminderArray, isReminder, resolveSourceValue, transformEmptyArray };
60
+ export { type TCanInvokeAbilityArgs, type TCanInvokeAbilityResult, adjustValueAsNumber, adjustValueAsNumberArray, applyOperationToPlayers, buildPlayerSeatMap, canInvokeAbility, copyPlayers, getSourceValue, getValueFromPayloads, isNumberOrNumberArray, isPlayerReminderArray, isReminder, resolveSourceValue, transformEmptyArray };
package/dist/index.d.ts CHANGED
@@ -10,6 +10,21 @@ type TApplyOperationToPlayersArgs = {
10
10
  };
11
11
  declare const applyOperationToPlayers: ({ players, operations, allAbilities, characters, timelines, timelineIndexAtNow, }: TApplyOperationToPlayersArgs) => TPlayer[];
12
12
 
13
+ type TCanInvokeAbilityArgs = {
14
+ ability: TAbility;
15
+ effector: TPlayer | undefined;
16
+ currentTimelineIdx: number;
17
+ timelines: TTimeline[];
18
+ priorOperations?: TOperation[];
19
+ };
20
+ type TCanInvokeAbilityResult = {
21
+ allowed: true;
22
+ } | {
23
+ allowed: false;
24
+ reason: string;
25
+ };
26
+ declare const canInvokeAbility: ({ ability, effector, currentTimelineIdx, timelines, priorOperations, }: TCanInvokeAbilityArgs) => TCanInvokeAbilityResult;
27
+
13
28
  declare const transformEmptyArray: <T>(arr: T[]) => T[];
14
29
  declare const copyPlayers: (players: TPlayer[]) => TPlayer[];
15
30
  declare const buildPlayerSeatMap: (players: TPlayer[]) => Map<number, TPlayer>;
@@ -42,4 +57,4 @@ declare const isReminder: (value: unknown) => value is TReminder;
42
57
  */
43
58
  declare const isPlayerReminderArray: (value: unknown) => value is TPlayerReminder[];
44
59
 
45
- export { adjustValueAsNumber, adjustValueAsNumberArray, applyOperationToPlayers, buildPlayerSeatMap, copyPlayers, getSourceValue, getValueFromPayloads, isNumberOrNumberArray, isPlayerReminderArray, isReminder, resolveSourceValue, transformEmptyArray };
60
+ export { type TCanInvokeAbilityArgs, type TCanInvokeAbilityResult, adjustValueAsNumber, adjustValueAsNumberArray, applyOperationToPlayers, buildPlayerSeatMap, canInvokeAbility, copyPlayers, getSourceValue, getValueFromPayloads, isNumberOrNumberArray, isPlayerReminderArray, isReminder, resolveSourceValue, transformEmptyArray };
package/dist/index.js CHANGED
@@ -193,7 +193,7 @@ var createEffectHandler = (type, handler) => {
193
193
  };
194
194
 
195
195
  // src/effects/handlers/ability-change.ts
196
- var toAbilityIdList = (value) => {
196
+ var toIdList = (value) => {
197
197
  if (typeof value === "string") {
198
198
  return value.length > 0 ? [value] : void 0;
199
199
  }
@@ -205,14 +205,13 @@ var toAbilityIdList = (value) => {
205
205
  };
206
206
  var applyAbilityChange = createEffectHandler("ABILITY_CHANGE", ({
207
207
  effect,
208
- operation,
209
208
  payloads,
210
209
  effector,
211
210
  writableInputs,
212
211
  getSnapshotSeatMap,
213
212
  abilityMap,
214
- makePlayersEffect,
215
- characterMap
213
+ characterMap,
214
+ makePlayersEffect
216
215
  }) => {
217
216
  const resolvedRaw = resolveSourceValue(
218
217
  effect.source,
@@ -220,45 +219,46 @@ var applyAbilityChange = createEffectHandler("ABILITY_CHANGE", ({
220
219
  payloads,
221
220
  effector,
222
221
  getSnapshotSeatMap(),
223
- (player) => player.abilities,
222
+ (player) => player.characterId,
224
223
  (value) => typeof value === "string" && value.length > 0 || Array.isArray(value) && value.every((item) => typeof item === "string"),
225
- (characterId) => {
226
- const character = characterMap.get(characterId);
227
- if (!character) {
228
- console.warn("Character not found for ABILITY_CHANGE effect source:", characterId);
229
- return [];
230
- }
231
- return character.abilities.map((a) => a.id);
232
- }
224
+ (characterId) => characterId
233
225
  );
234
- const resolvedAbilityIds = toAbilityIdList(resolvedRaw);
235
- if (!resolvedAbilityIds) {
236
- console.warn("Ability ID not found for ABILITY_CHANGE effect:", effect.source);
226
+ const resolvedCharacterIds = toIdList(resolvedRaw);
227
+ if (!resolvedCharacterIds) {
228
+ console.warn("Character ID not found for ABILITY_CHANGE effect:", effect.source);
237
229
  return;
238
230
  }
231
+ const mode = effect.mode ?? "REPLACE";
239
232
  makePlayersEffect.forEach((player) => {
240
- const overrideRaw = operation.abilityChangeOverrides?.[String(player.seat)];
241
- const overrideIds = toAbilityIdList(overrideRaw);
242
- const finalAbilityIds = overrideIds ?? resolvedAbilityIds;
243
- finalAbilityIds.forEach((finalAbilityId) => {
244
- const newAbility = abilityMap.get(finalAbilityId);
245
- if (!newAbility) {
246
- console.warn("Ability not found for ABILITY_CHANGE effect:", finalAbilityId);
247
- return;
248
- }
249
- const replaceAtSameStage = (abilities) => {
250
- const idx = abilities.findIndex((aid) => abilityMap.get(aid)?.stage === newAbility.stage);
251
- if (idx >= 0) {
252
- abilities[idx] = finalAbilityId;
253
- } else {
254
- abilities.push(finalAbilityId);
233
+ if (!player.gainCharactersAbility) {
234
+ player.gainCharactersAbility = [];
235
+ }
236
+ if (mode === "REPLACE") {
237
+ player.gainCharactersAbility = [...resolvedCharacterIds];
238
+ } else {
239
+ for (const characterId of resolvedCharacterIds) {
240
+ if (!player.gainCharactersAbility.includes(characterId)) {
241
+ player.gainCharactersAbility.push(characterId);
255
242
  }
256
- };
257
- replaceAtSameStage(player.abilities);
258
- if (player.perceivedCharacter?.asCharacter) {
259
- replaceAtSameStage(player.perceivedCharacter.abilities);
260
243
  }
261
- });
244
+ }
245
+ if (player.perceivedCharacter?.asCharacter) {
246
+ const perceived = player.perceivedCharacter;
247
+ resolvedCharacterIds.forEach((characterId) => {
248
+ const character = characterMap.get(characterId);
249
+ if (!character) return;
250
+ character.abilities.forEach((newAbility) => {
251
+ const idx = perceived.abilities.findIndex(
252
+ (aid) => abilityMap.get(aid)?.stage === newAbility.stage
253
+ );
254
+ if (idx >= 0) {
255
+ perceived.abilities[idx] = newAbility.id;
256
+ } else {
257
+ perceived.abilities.push(newAbility.id);
258
+ }
259
+ });
260
+ });
261
+ }
262
262
  });
263
263
  });
264
264
 
package/dist/index.mjs CHANGED
@@ -155,7 +155,7 @@ var createEffectHandler = (type, handler) => {
155
155
  };
156
156
 
157
157
  // src/effects/handlers/ability-change.ts
158
- var toAbilityIdList = (value) => {
158
+ var toIdList = (value) => {
159
159
  if (typeof value === "string") {
160
160
  return value.length > 0 ? [value] : void 0;
161
161
  }
@@ -167,14 +167,13 @@ var toAbilityIdList = (value) => {
167
167
  };
168
168
  var applyAbilityChange = createEffectHandler("ABILITY_CHANGE", ({
169
169
  effect,
170
- operation,
171
170
  payloads,
172
171
  effector,
173
172
  writableInputs,
174
173
  getSnapshotSeatMap,
175
174
  abilityMap,
176
- makePlayersEffect,
177
- characterMap
175
+ characterMap,
176
+ makePlayersEffect
178
177
  }) => {
179
178
  const resolvedRaw = resolveSourceValue(
180
179
  effect.source,
@@ -182,45 +181,46 @@ var applyAbilityChange = createEffectHandler("ABILITY_CHANGE", ({
182
181
  payloads,
183
182
  effector,
184
183
  getSnapshotSeatMap(),
185
- (player) => player.abilities,
184
+ (player) => player.characterId,
186
185
  (value) => typeof value === "string" && value.length > 0 || Array.isArray(value) && value.every((item) => typeof item === "string"),
187
- (characterId) => {
188
- const character = characterMap.get(characterId);
189
- if (!character) {
190
- console.warn("Character not found for ABILITY_CHANGE effect source:", characterId);
191
- return [];
192
- }
193
- return character.abilities.map((a) => a.id);
194
- }
186
+ (characterId) => characterId
195
187
  );
196
- const resolvedAbilityIds = toAbilityIdList(resolvedRaw);
197
- if (!resolvedAbilityIds) {
198
- console.warn("Ability ID not found for ABILITY_CHANGE effect:", effect.source);
188
+ const resolvedCharacterIds = toIdList(resolvedRaw);
189
+ if (!resolvedCharacterIds) {
190
+ console.warn("Character ID not found for ABILITY_CHANGE effect:", effect.source);
199
191
  return;
200
192
  }
193
+ const mode = effect.mode ?? "REPLACE";
201
194
  makePlayersEffect.forEach((player) => {
202
- const overrideRaw = operation.abilityChangeOverrides?.[String(player.seat)];
203
- const overrideIds = toAbilityIdList(overrideRaw);
204
- const finalAbilityIds = overrideIds ?? resolvedAbilityIds;
205
- finalAbilityIds.forEach((finalAbilityId) => {
206
- const newAbility = abilityMap.get(finalAbilityId);
207
- if (!newAbility) {
208
- console.warn("Ability not found for ABILITY_CHANGE effect:", finalAbilityId);
209
- return;
210
- }
211
- const replaceAtSameStage = (abilities) => {
212
- const idx = abilities.findIndex((aid) => abilityMap.get(aid)?.stage === newAbility.stage);
213
- if (idx >= 0) {
214
- abilities[idx] = finalAbilityId;
215
- } else {
216
- abilities.push(finalAbilityId);
195
+ if (!player.gainCharactersAbility) {
196
+ player.gainCharactersAbility = [];
197
+ }
198
+ if (mode === "REPLACE") {
199
+ player.gainCharactersAbility = [...resolvedCharacterIds];
200
+ } else {
201
+ for (const characterId of resolvedCharacterIds) {
202
+ if (!player.gainCharactersAbility.includes(characterId)) {
203
+ player.gainCharactersAbility.push(characterId);
217
204
  }
218
- };
219
- replaceAtSameStage(player.abilities);
220
- if (player.perceivedCharacter?.asCharacter) {
221
- replaceAtSameStage(player.perceivedCharacter.abilities);
222
205
  }
223
- });
206
+ }
207
+ if (player.perceivedCharacter?.asCharacter) {
208
+ const perceived = player.perceivedCharacter;
209
+ resolvedCharacterIds.forEach((characterId) => {
210
+ const character = characterMap.get(characterId);
211
+ if (!character) return;
212
+ character.abilities.forEach((newAbility) => {
213
+ const idx = perceived.abilities.findIndex(
214
+ (aid) => abilityMap.get(aid)?.stage === newAbility.stage
215
+ );
216
+ if (idx >= 0) {
217
+ perceived.abilities[idx] = newAbility.id;
218
+ } else {
219
+ perceived.abilities.push(newAbility.id);
220
+ }
221
+ });
222
+ });
223
+ }
224
224
  });
225
225
  });
226
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bct-app/game-engine",
3
- "version": "0.1.6-beta.3",
3
+ "version": "0.1.6",
4
4
  "description": "Game engine utilities for BCT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,13 +15,6 @@
15
15
  "dist",
16
16
  "README.md"
17
17
  ],
18
- "scripts": {
19
- "clean": "rm -rf dist",
20
- "build": "tsup src/index.ts --dts --format cjs,esm",
21
- "dev": "tsup src/index.ts --dts --format cjs,esm --watch",
22
- "test": "vitest",
23
- "test:run": "vitest run"
24
- },
25
18
  "keywords": [
26
19
  "game-engine",
27
20
  "bct"
@@ -37,12 +30,19 @@
37
30
  "access": "public"
38
31
  },
39
32
  "dependencies": {
40
- "@bct-app/game-model": "0.1.3-beta.0"
33
+ "@bct-app/game-model": "0.1.3"
41
34
  },
42
35
  "devDependencies": {
43
36
  "@vitest/ui": "^4.1.3",
44
37
  "tsup": "^8.0.2",
45
38
  "typescript": "^5.9.3",
46
39
  "vitest": "^4.1.3"
40
+ },
41
+ "scripts": {
42
+ "clean": "rm -rf dist",
43
+ "build": "tsup src/index.ts --dts --format cjs,esm",
44
+ "dev": "tsup src/index.ts --dts --format cjs,esm --watch",
45
+ "test": "vitest",
46
+ "test:run": "vitest run"
47
47
  }
48
- }
48
+ }