@xforge-dev/forge-kit 0.24.1 → 0.24.3

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/README.md CHANGED
@@ -132,7 +132,9 @@ the lowercased name without spaces, so a stored board never holds names.
132
132
  ### Legion Points (GMS v.272)
133
133
 
134
134
  v.272 removes the board. The points model sits beside it (the board stays for app versions still reading it):
135
- `legionPoints` (the automatic raid's ranks, B 1 … SSS 5, as many members as the Legion rank holds), stat levels
135
+ `legionPoints` (the automatic raid's ranks, B 1 … SSS 5, as many members as the Legion rank holds; `raidSplit` gives
136
+ those and the bonus-only rest, since every member at rank B or higher gives its effect: `effectMembers`; pass the
137
+ owned event blocks and the two equipped ones add a member's points of their rank each: `legionPointsBreakdown`), stat levels
136
138
  (`LegionStats`, one point a level, what a grid square was: same values, caps 15 inner and 40 outer),
137
139
  `allocationProblem`, `statTotals`, `suggestStats`, the two highest event blocks (`appliedEventBlocks`), 10 named
138
140
  presets (`SharedPoints`, stored under `points` in the shared row so an older board write leaves it alone) and the 5th
package/dist/legion.d.ts CHANGED
@@ -211,10 +211,31 @@ export type PointsMember = {
211
211
  * The caller works out ranks (Zero's own levels) and Legion level.
212
212
  */
213
213
  export declare function raidComposition<M extends PointsMember>(members: readonly M[], legionLevel: number): M[];
214
+ /**
215
+ * The Legion split in two: `counted`, the members the raid takes (their ranks are the Legion Points), and `bonus`, the
216
+ * other members at rank B or higher, whose effects apply too but who give no points. Members below B are in neither.
217
+ */
218
+ export declare function raidSplit<M extends PointsMember>(members: readonly M[], legionLevel: number): {
219
+ counted: M[];
220
+ bonus: M[];
221
+ };
222
+ /** Members whose effects apply: every member at rank B or higher, counted by the raid or not. */
223
+ export declare const effectMembers: <M extends PointsMember>(members: readonly M[]) => M[];
214
224
  /** The two event blocks that apply: the highest values among those owned. */
215
225
  export declare function appliedEventBlocks(owned: readonly EventBlock[]): EventBlock[];
216
- /** Legion Points to spend: the ranks of the members the raid counts. Event blocks add ATT, not points. */
217
- export declare function legionPoints(members: readonly PointsMember[], legionLevel: number): number;
226
+ /** Legion Points an equipped event block gives: a member's of its rank (B 1 … SSS 5; Ride or Die is SSS, as on the board). */
227
+ export declare const eventBlockPoints: (b: EventBlock) => number;
228
+ /** Legion Points split: the members the raid counts, and the two equipped event blocks (the two highest owned). */
229
+ export declare function legionPointsBreakdown(members: readonly PointsMember[], legionLevel: number, blocks?: readonly EventBlock[]): {
230
+ members: number;
231
+ blocks: number;
232
+ total: number;
233
+ };
234
+ /**
235
+ * Legion Points to spend: the ranks of the members the raid counts, plus the two equipped event blocks' (a member's of
236
+ * the same rank each; they don't take a member's place). Their ATT is separate.
237
+ */
238
+ export declare function legionPoints(members: readonly PointsMember[], legionLevel: number, blocks?: readonly EventBlock[]): number;
218
239
  /** Points the stat levels spend. */
219
240
  export declare const pointsSpent: (stats: LegionStats) => number;
220
241
  /** What each stat gives at its level (only stats with a level). */
package/dist/legion.js CHANGED
@@ -227,8 +227,9 @@ export function legionLevelRank(level) {
227
227
  /** Members the automatic Legion Raid takes at this Legion level (Nameless I's 9 below it). */
228
228
  export const raidMembers = (level) => (legionLevelRank(level) ?? LEGION_LEVEL_RANKS[0]).members;
229
229
  // The rules are the board's, without the board: a stat level is what a grid square was (same value per level, the
230
- // same caps: inner stats 15, outer stats 40, open from the start as every area was), and only the members the raid
231
- // counts (the top members by Legion level, as the board's slots were) give points and their effects.
230
+ // same caps: inner stats 15, outer stats 40, open from the start as every area was). Every member at rank B or higher
231
+ // gives its effect; only the members the raid counts (the top members by level, as many as the board's slots were)
232
+ // give points.
232
233
  /** What one level of each stat gives: a grid square's value. */
233
234
  export const STAT_PER_LEVEL = { ...GRID_PER_SQUARE };
234
235
  /** Each stat's highest level: its grid area's size. */
@@ -245,13 +246,35 @@ export const statUnlocked = (k, legionLevel) => statCap(k, legionLevel) > 0;
245
246
  export function raidComposition(members, legionLevel) {
246
247
  return members.filter((m) => m.rank).sort((a, b) => b.level - a.level).slice(0, raidMembers(legionLevel));
247
248
  }
249
+ /**
250
+ * The Legion split in two: `counted`, the members the raid takes (their ranks are the Legion Points), and `bonus`, the
251
+ * other members at rank B or higher, whose effects apply too but who give no points. Members below B are in neither.
252
+ */
253
+ export function raidSplit(members, legionLevel) {
254
+ const counted = raidComposition(members, legionLevel);
255
+ const taken = new Set(counted);
256
+ return { counted, bonus: members.filter((m) => m.rank && !taken.has(m)).sort((a, b) => b.level - a.level) };
257
+ }
258
+ /** Members whose effects apply: every member at rank B or higher, counted by the raid or not. */
259
+ export const effectMembers = (members) => members.filter((m) => m.rank);
248
260
  /** The two event blocks that apply: the highest values among those owned. */
249
261
  export function appliedEventBlocks(owned) {
250
262
  return [...owned].sort((a, b) => b.value - a.value).slice(0, MAX_EVENT_BLOCKS);
251
263
  }
252
- /** Legion Points to spend: the ranks of the members the raid counts. Event blocks add ATT, not points. */
253
- export function legionPoints(members, legionLevel) {
254
- return raidComposition(members, legionLevel).reduce((t, m) => t + RANK_POINTS[m.rank], 0);
264
+ /** Legion Points an equipped event block gives: a member's of its rank (B 1 … SSS 5; Ride or Die is SSS, as on the board). */
265
+ export const eventBlockPoints = (b) => eventBlockSquares(b);
266
+ /** Legion Points split: the members the raid counts, and the two equipped event blocks (the two highest owned). */
267
+ export function legionPointsBreakdown(members, legionLevel, blocks = []) {
268
+ const m = raidComposition(members, legionLevel).reduce((t, x) => t + RANK_POINTS[x.rank], 0);
269
+ const b = appliedEventBlocks(blocks).reduce((t, x) => t + eventBlockPoints(x), 0);
270
+ return { members: m, blocks: b, total: m + b };
271
+ }
272
+ /**
273
+ * Legion Points to spend: the ranks of the members the raid counts, plus the two equipped event blocks' (a member's of
274
+ * the same rank each; they don't take a member's place). Their ATT is separate.
275
+ */
276
+ export function legionPoints(members, legionLevel, blocks = []) {
277
+ return legionPointsBreakdown(members, legionLevel, blocks).total;
255
278
  }
256
279
  /** Points the stat levels spend. */
257
280
  export const pointsSpent = (stats) => Object.values(stats).reduce((t, n) => t + (n ?? 0), 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xforge-dev/forge-kit",
3
- "version": "0.24.1",
3
+ "version": "0.24.3",
4
4
  "description": "Shared auth, app registry and UI for xForge apps",
5
5
  "license": "MIT",
6
6
  "repository": {