libram 0.4.4 → 0.4.8

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/Clan.js CHANGED
@@ -9,6 +9,7 @@ import { getFoldGroup } from "./lib";
9
9
  import logger from "./logger";
10
10
  import { arrayToCountedMap, countedMapToArray, countedMapToString, notNull, parseNumber, } from "./utils";
11
11
  export class ClanError extends Error {
12
+ reason;
12
13
  constructor(message, reason) {
13
14
  super(message);
14
15
  this.reason = reason;
@@ -38,10 +39,8 @@ const toPlayerId = (player) => typeof player === "string" ? getPlayerId(player)
38
39
  const LOG_FAX_PATTERN = /(\d{2}\/\d{2}\/\d{2}, \d{2}:\d{2}(?:AM|PM): )<a [^>]+>([^<]+)<\/a>(?: faxed in a (?<monster>.*?))<br>/;
39
40
  const WHITELIST_DEGREE_PATTERN = /(?<name>.*?) \(°(?<degree>\d+)\)/;
40
41
  export class Clan {
41
- constructor(id, name) {
42
- this.id = id;
43
- this.name = name;
44
- }
42
+ id;
43
+ name;
45
44
  static _join(id) {
46
45
  const result = visitUrl(`showclan.php?recruiter=1&whichclan=${id}&pwd&whichclan=${id}&action=joinclan&apply=Apply+to+this+Clan&confirm=on`);
47
46
  if (!result.includes("clanhalltop.gif")) {
@@ -143,6 +142,10 @@ export class Clan {
143
142
  return new Clan(id, name);
144
143
  });
145
144
  }
145
+ constructor(id, name) {
146
+ this.id = id;
147
+ this.name = name;
148
+ }
146
149
  /**
147
150
  * Join clan
148
151
  */
package/dist/Copier.js CHANGED
@@ -1,6 +1,10 @@
1
1
  export class Copier {
2
+ couldCopy;
3
+ prepare;
4
+ canCopy;
5
+ copiedMonster;
6
+ fightCopy = null;
2
7
  constructor(couldCopy, prepare, canCopy, copiedMonster, fightCopy) {
3
- this.fightCopy = null;
4
8
  this.couldCopy = couldCopy;
5
9
  this.prepare = prepare;
6
10
  this.canCopy = canCopy;
package/dist/Kmail.js CHANGED
@@ -2,18 +2,12 @@ import "core-js/modules/es.object.entries";
2
2
  import { extractItems, extractMeat, isGiftable, toInt, visitUrl, } from "kolmafia";
3
3
  import { arrayToCountedMap, chunk } from "./utils";
4
4
  export default class Kmail {
5
- constructor(rawKmail) {
6
- const date = new Date(rawKmail.localtime);
7
- // Date come from KoL formatted with YY and so will be parsed 19YY, which is wrong.
8
- // We can safely add 100 because if 19YY was a leap year, 20YY will be too!
9
- date.setFullYear(date.getFullYear() + 100);
10
- this.id = Number(rawKmail.id);
11
- this.date = date;
12
- this.type = rawKmail.type;
13
- this.senderId = Number(rawKmail.fromid);
14
- this.senderName = rawKmail.fromname;
15
- this.rawMessage = rawKmail.message;
16
- }
5
+ id;
6
+ date;
7
+ type;
8
+ senderId;
9
+ senderName;
10
+ rawMessage;
17
11
  /**
18
12
  * Parses a kmail from KoL's native format
19
13
  *
@@ -99,6 +93,18 @@ export default class Kmail {
99
93
  const baseUrl = `town_sendgift.php?action=Yep.&pwd&fromwhere=0&note=${message}&insidenote=${insideNote}&towho=${to}`;
100
94
  return Kmail._genericSend(to, message, items, meat, 3, (m, itemsQuery, chunkSize) => `${baseUrl}&whichpackage=${chunkSize}${itemsQuery ? `&${itemsQuery}` : ""}&sendmeat=${m}`, ">Package sent.</");
101
95
  }
96
+ constructor(rawKmail) {
97
+ const date = new Date(rawKmail.localtime);
98
+ // Date come from KoL formatted with YY and so will be parsed 19YY, which is wrong.
99
+ // We can safely add 100 because if 19YY was a leap year, 20YY will be too!
100
+ date.setFullYear(date.getFullYear() + 100);
101
+ this.id = Number(rawKmail.id);
102
+ this.date = date;
103
+ this.type = rawKmail.type;
104
+ this.senderId = Number(rawKmail.fromid);
105
+ this.senderName = rawKmail.fromname;
106
+ this.rawMessage = rawKmail.message;
107
+ }
102
108
  /**
103
109
  * Delete the kmail
104
110
  *
package/dist/Path.js CHANGED
@@ -1,5 +1,14 @@
1
1
  import { $classes } from "./template-string";
2
2
  export class Path {
3
+ name;
4
+ id;
5
+ hasAllPerms; //here, we define avatar-ness around being its own class
6
+ hasCampground;
7
+ hasTerrarium;
8
+ stomachSize;
9
+ liverSize; //Defined as the lowest inebriety that makes you unable to drink more, just to make it fifteens across the board
10
+ spleenSize;
11
+ classes;
3
12
  /**
4
13
  *
5
14
  * @param name Name of path
package/dist/combat.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * @category Combat
5
5
  * @returns {number} The macro ID.
6
6
  */
7
- export declare function getMacroId(): number;
7
+ export declare function getMacroId(name?: string): number;
8
8
  declare type ItemOrName = Item | string;
9
9
  declare type SkillOrName = Skill | string;
10
10
  declare type Constructor<T> = {
@@ -21,13 +21,20 @@ export declare class InvalidMacroError extends Error {
21
21
  */
22
22
  export declare class Macro {
23
23
  static SAVED_MACRO_PROPERTY: string;
24
- static cachedMacroId: number | null;
25
- static cachedAutoAttack: string | null;
24
+ static cachedMacroIds: Map<string, number>;
25
+ static cachedAutoAttacks: Map<string, string>;
26
26
  components: string[];
27
+ name: string;
27
28
  /**
28
29
  * Convert macro to string.
29
30
  */
30
31
  toString(): string;
32
+ /**
33
+ * Gives your macro a new name to be used when saving an autoattack.
34
+ * @param name The name to be used when saving as an autoattack.
35
+ * @returns The previous name assigned to this macro.
36
+ */
37
+ rename(name: string): string;
31
38
  /**
32
39
  * Save a macro to a Mafia property for use in a consult script.
33
40
  */
@@ -60,6 +67,15 @@ export declare class Macro {
60
67
  * Set this macro as a KoL native autoattack.
61
68
  */
62
69
  setAutoAttack(): void;
70
+ /**
71
+ * Renames the macro, then sets it as an autoattack.
72
+ * @param name The name to save the macro under as an autoattack.
73
+ */
74
+ setAutoAttackAs(name: string): void;
75
+ /**
76
+ * Clear all cached autoattacks, and delete all stored macros server-side.
77
+ */
78
+ static clearAutoAttackMacros(): void;
63
79
  /**
64
80
  * Add an "abort" step to this macro.
65
81
  * @returns {Macro} This object itself.
package/dist/combat.js CHANGED
@@ -9,11 +9,11 @@ const MACRO_NAME = "Script Autoattack Macro";
9
9
  * @category Combat
10
10
  * @returns {number} The macro ID.
11
11
  */
12
- export function getMacroId() {
13
- const macroMatches = xpath(visitUrl("account_combatmacros.php"), `//select[@name="macroid"]/option[text()="${MACRO_NAME}"]/@value`);
12
+ export function getMacroId(name = MACRO_NAME) {
13
+ const macroMatches = xpath(visitUrl("account_combatmacros.php"), `//select[@name="macroid"]/option[text()="${name}"]/@value`);
14
14
  if (macroMatches.length === 0) {
15
15
  visitUrl("account_combatmacros.php?action=new");
16
- const newMacroText = visitUrl(`account_combatmacros.php?macroid=0&name=${MACRO_NAME}&macrotext=abort&action=save`);
16
+ const newMacroText = visitUrl(`account_combatmacros.php?macroid=0&name=${name}&macrotext=abort&action=save`);
17
17
  return parseInt(xpath(newMacroText, "//input[@name=macroid]/@value")[0], 10);
18
18
  }
19
19
  else {
@@ -69,15 +69,27 @@ export class InvalidMacroError extends Error {
69
69
  * For example, you can do `Macro.skill('Saucestorm').attack()`.
70
70
  */
71
71
  export class Macro {
72
- constructor() {
73
- this.components = [];
74
- }
72
+ static SAVED_MACRO_PROPERTY = "libram_savedMacro";
73
+ static cachedMacroIds = new Map();
74
+ static cachedAutoAttacks = new Map();
75
+ components = [];
76
+ name = MACRO_NAME;
75
77
  /**
76
78
  * Convert macro to string.
77
79
  */
78
80
  toString() {
79
81
  return this.components.join(";");
80
82
  }
83
+ /**
84
+ * Gives your macro a new name to be used when saving an autoattack.
85
+ * @param name The name to be used when saving as an autoattack.
86
+ * @returns The previous name assigned to this macro.
87
+ */
88
+ rename(name) {
89
+ const returnValue = this.name;
90
+ this.name = name;
91
+ return returnValue;
92
+ }
81
93
  /**
82
94
  * Save a macro to a Mafia property for use in a consult script.
83
95
  */
@@ -128,16 +140,36 @@ export class Macro {
128
140
  * Set this macro as a KoL native autoattack.
129
141
  */
130
142
  setAutoAttack() {
131
- if (Macro.cachedMacroId === null)
132
- Macro.cachedMacroId = getMacroId();
133
- if (getAutoAttack() === 99000000 + Macro.cachedMacroId &&
134
- this.toString() === Macro.cachedAutoAttack) {
143
+ let id = Macro.cachedMacroIds.get(this.name);
144
+ if (id === undefined)
145
+ Macro.cachedMacroIds.set(this.name, getMacroId(this.name));
146
+ id = getMacroId(this.name);
147
+ if (getAutoAttack() === 99000000 + id &&
148
+ this.toString() === Macro.cachedAutoAttacks.get(this.name)) {
135
149
  // This macro is already set. Don"t make the server request.
136
150
  return;
137
151
  }
138
- visitUrl(`account_combatmacros.php?macroid=${Macro.cachedMacroId}&name=${urlEncode(MACRO_NAME)}&macrotext=${urlEncode(this.toString())}&action=save`, true, true);
139
- visitUrl(`account.php?am=1&action=autoattack&value=${99000000 + Macro.cachedMacroId}&ajax=1`);
140
- Macro.cachedAutoAttack = this.toString();
152
+ visitUrl(`account_combatmacros.php?macroid=${id}&name=${urlEncode(this.name)}&macrotext=${urlEncode(this.toString())}&action=save`, true, true);
153
+ visitUrl(`account.php?am=1&action=autoattack&value=${99000000 + id}&ajax=1`);
154
+ Macro.cachedAutoAttacks.set(this.name, this.toString());
155
+ }
156
+ /**
157
+ * Renames the macro, then sets it as an autoattack.
158
+ * @param name The name to save the macro under as an autoattack.
159
+ */
160
+ setAutoAttackAs(name) {
161
+ this.name = name;
162
+ this.setAutoAttack();
163
+ }
164
+ /**
165
+ * Clear all cached autoattacks, and delete all stored macros server-side.
166
+ */
167
+ static clearAutoAttackMacros() {
168
+ for (const name of Macro.cachedAutoAttacks.keys()) {
169
+ const id = Macro.cachedMacroIds.get(name) ?? getMacroId(name);
170
+ visitUrl(`account_combatmacros.php?macroid=${id}&action=edit&what=Delete&confirm=1`);
171
+ Macro.cachedAutoAttacks.delete(name);
172
+ }
141
173
  }
142
174
  /**
143
175
  * Add an "abort" step to this macro.
@@ -409,9 +441,6 @@ export class Macro {
409
441
  return new this().ifNotHolidayWanderer(macro);
410
442
  }
411
443
  }
412
- Macro.SAVED_MACRO_PROPERTY = "libram_savedMacro";
413
- Macro.cachedMacroId = null;
414
- Macro.cachedAutoAttack = null;
415
444
  /**
416
445
  * Adventure in a location and handle all combats with a given macro.
417
446
  * To use this function you will need to create a consult script that runs Macro.load().submit() and a CCS that calls that consult script.
@@ -4,6 +4,7 @@ declare type MenuItemOptions = {
4
4
  maximum?: number | "auto";
5
5
  additionalValue?: number;
6
6
  wishEffect?: Effect;
7
+ priceOverride?: number;
7
8
  };
8
9
  export declare class MenuItem {
9
10
  item: Item;
@@ -12,7 +13,17 @@ export declare class MenuItem {
12
13
  maximum?: number;
13
14
  additionalValue?: number;
14
15
  wishEffect?: Effect;
16
+ priceOverride?: number;
15
17
  static defaultOptions: Map<Item, MenuItemOptions>;
18
+ /**
19
+ * Construct a new menu item, possibly with extra properties. Items in MenuItem.defaultOptions have intelligent defaults.
20
+ * @param item Item to add to menu.
21
+ * @param options.organ Designate item as belonging to a specific organ.
22
+ * @param options.size Override item organ size. Necessary for any non-food/booze/spleen item.
23
+ * @param options.maximum Maximum uses remaining today, or "auto" to check dailyusesleft Mafia property.
24
+ * @param options.additionalValue Additional value (positive) or cost (negative) to consider with item, e.g. from buffs.
25
+ * @param options.wishEffect If item is a pocket wish, effect to wish for.
26
+ */
16
27
  constructor(item: Item, options?: MenuItemOptions);
17
28
  equals(other: MenuItem): boolean;
18
29
  toString(): string;
@@ -50,8 +50,76 @@ function expectedAdventures(item, modifiers) {
50
50
  }) / interpolated.length);
51
51
  }
52
52
  export class MenuItem {
53
+ item;
54
+ organ;
55
+ size;
56
+ maximum;
57
+ additionalValue;
58
+ wishEffect;
59
+ priceOverride;
60
+ static defaultOptions = new Map([
61
+ [
62
+ $item `distention pill`,
63
+ {
64
+ organ: "food",
65
+ maximum: !have($item `distention pill`) || get("_distentionPillUsed") ? 0 : 1,
66
+ size: -1,
67
+ },
68
+ ],
69
+ [
70
+ $item `synthetic dog hair pill`,
71
+ {
72
+ organ: "booze",
73
+ maximum: !have($item `synthetic dog hair pill`) ||
74
+ get("_syntheticDogHairPillUsed")
75
+ ? 0
76
+ : 1,
77
+ size: -1,
78
+ },
79
+ ],
80
+ [
81
+ $item `cuppa Voraci tea`,
82
+ { organ: "food", maximum: get("_voraciTeaUsed") ? 0 : 1, size: -1 },
83
+ ],
84
+ [
85
+ $item `cuppa Sobrie tea`,
86
+ { organ: "booze", maximum: get("_sobrieTeaUsed") ? 0 : 1, size: -1 },
87
+ ],
88
+ [
89
+ $item `mojo filter`,
90
+ {
91
+ organ: "spleen item",
92
+ maximum: 3 - get("currentMojoFilters"),
93
+ size: -1,
94
+ },
95
+ ],
96
+ [$item `spice melange`, { maximum: get("spiceMelangeUsed") ? 0 : 1 }],
97
+ [
98
+ $item `Ultra Mega Sour Ball`,
99
+ { maximum: get("_ultraMegaSourBallUsed") ? 0 : 1 },
100
+ ],
101
+ [
102
+ $item `The Plumber's mushroom stew`,
103
+ { maximum: get("_plumbersMushroomStewEaten") ? 0 : 1 },
104
+ ],
105
+ [$item `The Mad Liquor`, { maximum: get("_madLiquorDrunk") ? 0 : 1 }],
106
+ [
107
+ $item `Doc Clock's thyme cocktail`,
108
+ { maximum: get("_docClocksThymeCocktailDrunk") ? 0 : 1 },
109
+ ],
110
+ [$item `Mr. Burnsger`, { maximum: get("_mrBurnsgerEaten") ? 0 : 1 }],
111
+ ]);
112
+ /**
113
+ * Construct a new menu item, possibly with extra properties. Items in MenuItem.defaultOptions have intelligent defaults.
114
+ * @param item Item to add to menu.
115
+ * @param options.organ Designate item as belonging to a specific organ.
116
+ * @param options.size Override item organ size. Necessary for any non-food/booze/spleen item.
117
+ * @param options.maximum Maximum uses remaining today, or "auto" to check dailyusesleft Mafia property.
118
+ * @param options.additionalValue Additional value (positive) or cost (negative) to consider with item, e.g. from buffs.
119
+ * @param options.wishEffect If item is a pocket wish, effect to wish for.
120
+ */
53
121
  constructor(item, options = {}) {
54
- const { size, organ, maximum, additionalValue, wishEffect } = {
122
+ const { size, organ, maximum, additionalValue, wishEffect, priceOverride, } = {
55
123
  ...options,
56
124
  ...(MenuItem.defaultOptions.get(item) ?? {}),
57
125
  };
@@ -59,6 +127,7 @@ export class MenuItem {
59
127
  this.maximum = maximum === "auto" ? item.dailyusesleft : maximum;
60
128
  this.additionalValue = additionalValue;
61
129
  this.wishEffect = wishEffect;
130
+ this.priceOverride = priceOverride;
62
131
  const typ = itemType(this.item);
63
132
  this.organ = organ ?? (isOrgan(typ) ? typ : undefined);
64
133
  this.size =
@@ -75,46 +144,29 @@ export class MenuItem {
75
144
  return this.item === other.item && this.wishEffect === other.wishEffect;
76
145
  }
77
146
  toString() {
147
+ if (this.wishEffect) {
148
+ return `${this.item}:${this.wishEffect}`;
149
+ }
78
150
  return this.item.toString();
79
151
  }
80
152
  price() {
81
- return npcPrice(this.item) > 0 ? npcPrice(this.item) : mallPrice(this.item);
153
+ return (this.priceOverride ??
154
+ (npcPrice(this.item) > 0 ? npcPrice(this.item) : mallPrice(this.item)));
82
155
  }
83
156
  }
84
- MenuItem.defaultOptions = new Map([
85
- [$item `Mr. Burnsger`, { maximum: "auto" }],
86
- [
87
- $item `distention pill`,
88
- {
89
- organ: "food",
90
- maximum: "auto",
91
- size: -1,
92
- },
93
- ],
94
- [
95
- $item `synthetic dog hair pill`,
96
- { organ: "booze", maximum: "auto", size: -1 },
97
- ],
98
- [$item `cuppa Voraci tea`, { organ: "food", maximum: "auto", size: -1 }],
99
- [$item `cuppa Sobrie tea`, { organ: "booze", maximum: "auto", size: -1 }],
100
- [
101
- $item `mojo filter`,
102
- {
103
- organ: "spleen item",
104
- maximum: 3 - get("currentMojoFilters"),
105
- size: -1,
106
- },
107
- ],
108
- [$item `spice melange`, { maximum: "auto" }],
109
- [$item `Ultra Mega Sour Ball`, { maximum: "auto" }],
110
- ]);
111
157
  const organs = ["food", "booze", "spleen item"];
112
158
  function isOrgan(x) {
113
159
  return organs.includes(x);
114
160
  }
115
161
  class DietPlanner {
162
+ mpa;
163
+ menu;
164
+ fork;
165
+ mug;
166
+ seasoning;
167
+ mayoflex;
168
+ spleenValue = 0;
116
169
  constructor(mpa, menu) {
117
- this.spleenValue = 0;
118
170
  this.mpa = mpa;
119
171
  this.fork = menu.find((item) => item.item === $item `Ol' Scratch's salad fork`);
120
172
  this.mug = menu.find((item) => item.item === $item `Frosty's frosty mug`);
@@ -1,5 +1,6 @@
1
1
  import { sum } from "../utils";
2
2
  class Not {
3
+ thing;
3
4
  constructor(thing) {
4
5
  this.thing = thing;
5
6
  }
package/dist/freerun.d.ts CHANGED
@@ -20,4 +20,5 @@ export declare class FreeRun {
20
20
  options?: FreeRunOptions;
21
21
  constructor(name: string, available: () => boolean, macro: Macro, options?: FreeRunOptions);
22
22
  }
23
- export declare function findFreeRun(useFamiliar?: boolean, buyStuff?: boolean): FreeRun | undefined;
23
+ export declare function tryFindFreeRun(useFamiliar?: boolean): FreeRun | null;
24
+ export declare function ensureFreeRun(useFamiliar?: boolean): FreeRun;
package/dist/freerun.js CHANGED
@@ -6,6 +6,10 @@ import { get } from "./property";
6
6
  import { Bandersnatch } from "./resources";
7
7
  import { $effect, $familiar, $item, $items, $skill } from "./template-string";
8
8
  export class FreeRun {
9
+ name;
10
+ available;
11
+ macro;
12
+ options;
9
13
  constructor(name, available, macro, options) {
10
14
  this.name = name;
11
15
  this.available = available;
@@ -83,10 +87,13 @@ function cheapestRunSource() {
83
87
  }
84
88
  function cheapestItemRun() {
85
89
  const cheapestRun = cheapestRunSource();
86
- return new FreeRun("Cheap Combat Item", () => retrieveItem(cheapestRun), Macro.trySkill($skill `Asdon Martin: Spring-Loaded Front Bumper`).item(cheapestRunSource()), {
90
+ return new FreeRun("Cheap Combat Item", () => retrieveItem(cheapestRun), Macro.trySkill($skill `Asdon Martin: Spring-Loaded Front Bumper`).item(cheapestRun), {
87
91
  preparation: () => retrieveItem(cheapestRun),
88
92
  });
89
93
  }
90
- export function findFreeRun(useFamiliar = true, buyStuff = true) {
91
- return (freeRuns.find((run) => run.available() && (useFamiliar || run?.options?.familiar)) ?? (buyStuff ? cheapestItemRun() : undefined));
94
+ export function tryFindFreeRun(useFamiliar = true) {
95
+ return (freeRuns.find((run) => run.available() && (useFamiliar || run?.options?.familiar)) ?? null);
96
+ }
97
+ export function ensureFreeRun(useFamiliar = true) {
98
+ return tryFindFreeRun(useFamiliar) ?? cheapestItemRun();
92
99
  }
package/dist/lib.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /** @module GeneralLibrary */
2
2
  import "core-js/modules/es.object.entries";
3
+ import "core-js/features/array/flat";
3
4
  /**
4
5
  * Returns the current maximum Accordion Thief songs the player can have in their head
5
6
  *
package/dist/lib.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /** @module GeneralLibrary */
2
2
  import "core-js/modules/es.object.entries";
3
+ import "core-js/features/array/flat";
3
4
  import { appearanceRates, autosellPrice, availableAmount, booleanModifier, cliExecute, fullnessLimit, getCampground, getCounters, getPlayerId, getPlayerName, getRelated, haveEffect, haveFamiliar, haveServant, haveSkill, holiday, inebrietyLimit, mallPrice, myEffects, myFamiliar, myFullness, myInebriety, myPath, mySpleenUse, myThrall, myTurncount, numericModifier, spleenLimit, toItem, toSkill, totalTurnsPlayed, } from "kolmafia";
4
5
  import { $class, $familiar, $item, $items, $monsters } from "./template-string";
5
6
  import { get } from "./property";
package/dist/logger.js CHANGED
@@ -5,9 +5,7 @@ const defaultHandlers = {
5
5
  error: (error) => printHtml(`<span style="background: red; color: white;"><b>[Libram]</b> ${error.toString()}</span>`),
6
6
  };
7
7
  class Logger {
8
- constructor() {
9
- this.handlers = defaultHandlers;
10
- }
8
+ handlers = defaultHandlers;
11
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
10
  setHandler(level, callback) {
13
11
  this.handlers[level] = callback;
package/dist/maximize.js CHANGED
@@ -27,6 +27,10 @@ export function setDefaultMaximizeOptions(options) {
27
27
  // Subset of slots that are valid for caching.
28
28
  const cachedSlots = $slots `hat, weapon, off-hand, back, shirt, pants, acc1, acc2, acc3, familiar`;
29
29
  class CacheEntry {
30
+ equipment;
31
+ rider;
32
+ familiar;
33
+ canEquipItemCount;
30
34
  constructor(equipment, rider, familiar, canEquipItemCount) {
31
35
  this.equipment = equipment;
32
36
  this.rider = rider;
@@ -35,18 +39,15 @@ class CacheEntry {
35
39
  }
36
40
  }
37
41
  class OutfitLRUCache {
38
- constructor(maxSize) {
39
- // Current outfits allocated
40
- this.#outfitSlots = [];
41
- // Array of indices into #outfitSlots in order of use. Most recent at the front.
42
- this.#useHistory = [];
43
- this.#maxSize = maxSize;
44
- }
42
+ static OUTFIT_PREFIX = "Script Outfit";
45
43
  // Current outfits allocated
46
- #outfitSlots;
44
+ #outfitSlots = [];
47
45
  // Array of indices into #outfitSlots in order of use. Most recent at the front.
48
- #useHistory;
46
+ #useHistory = [];
49
47
  #maxSize;
48
+ constructor(maxSize) {
49
+ this.#maxSize = maxSize;
50
+ }
50
51
  checkConsistent() {
51
52
  if (this.#useHistory.length !== this.#outfitSlots.length ||
52
53
  ![...this.#useHistory].sort().every((value, index) => value === index)) {
@@ -84,7 +85,6 @@ class OutfitLRUCache {
84
85
  }
85
86
  }
86
87
  }
87
- OutfitLRUCache.OUTFIT_PREFIX = "Script Outfit";
88
88
  /**
89
89
  * Save current equipment as KoL-native outfit.
90
90
  * @param name Name of new outfit.
@@ -302,6 +302,8 @@ export function maximizeCached(objectives, options = {}) {
302
302
  saveCached(objective, fullOptions);
303
303
  }
304
304
  export class Requirement {
305
+ #maximizeParameters;
306
+ #maximizeOptions;
305
307
  /**
306
308
  * A convenient way of combining maximization parameters and options
307
309
  * @param maximizeParameters Parameters you're attempting to maximize
@@ -311,8 +313,6 @@ export class Requirement {
311
313
  this.#maximizeParameters = maximizeParameters;
312
314
  this.#maximizeOptions = maximizeOptions;
313
315
  }
314
- #maximizeParameters;
315
- #maximizeOptions;
316
316
  get maximizeParameters() {
317
317
  return this.#maximizeParameters;
318
318
  }
@@ -11,3 +11,9 @@ export declare type ModifierValue<T> = T extends BooleanModifier ? boolean : T e
11
11
  export declare type Modifiers = Partial<{
12
12
  [T in BooleanModifier | ClassModifier | EffectModifier | MonsterModifier | NumericModifier | SkillModifier | StatModifier | StringModifier]: ModifierValue<T>;
13
13
  }>;
14
+ /**
15
+ * Merge arbitrarily many Modifiers objects into one, summing all numeric modifiers, and ||ing all boolean modifiers.
16
+ * @param modifierss Modifiers objects to be merged together.
17
+ * @returns A single Modifiers object obtained by merging.
18
+ */
19
+ export declare function mergeModifiers(...modifierss: Modifiers[]): Modifiers;
package/dist/modifier.js CHANGED
@@ -33,3 +33,33 @@ export function get(name, subject) {
33
33
  return statModifier(subject, name);
34
34
  }
35
35
  }
36
+ /**
37
+ * Merge two Modifiers objects into one, summing all numeric modifiers, ||ing all boolean modifiers, and otherwise letting the second object overwrite the first.
38
+ * @param modifiers1 Modifiers objects to be merged onto.
39
+ * @param modifiers2 Modifiers object to merge.
40
+ * @returns A single Modifiers object obtained by merging.
41
+ */
42
+ function pairwiseMerge(modifiers1, modifiers2) {
43
+ const returnValue = { ...modifiers1, ...modifiers2 };
44
+ for (const modifier in modifiers1) {
45
+ if (Array.from(Object.values(modifiers2)).includes(modifier)) {
46
+ if (arrayContains(modifier, numericModifiers)) {
47
+ returnValue[modifier] =
48
+ (modifiers1[modifier] ?? 0) + (modifiers2[modifier] ?? 0);
49
+ }
50
+ if (arrayContains(modifier, booleanModifiers)) {
51
+ returnValue[modifier] =
52
+ (modifiers1[modifier] ?? false) || (modifiers2[modifier] ?? false);
53
+ }
54
+ }
55
+ }
56
+ return returnValue;
57
+ }
58
+ /**
59
+ * Merge arbitrarily many Modifiers objects into one, summing all numeric modifiers, and ||ing all boolean modifiers.
60
+ * @param modifierss Modifiers objects to be merged together.
61
+ * @returns A single Modifiers object obtained by merging.
62
+ */
63
+ export function mergeModifiers(...modifierss) {
64
+ return modifierss.reduce((a, b) => pairwiseMerge(a, b), {});
65
+ }