libram 0.6.21 → 0.6.24

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/Path.d.ts CHANGED
@@ -3,6 +3,7 @@ export declare class Path {
3
3
  name: string;
4
4
  id: number;
5
5
  hasAllPerms: boolean;
6
+ canUseSkillbooks: boolean;
6
7
  hasCampground: boolean;
7
8
  hasTerrarium: boolean;
8
9
  stomachSize: number;
@@ -14,6 +15,7 @@ export declare class Path {
14
15
  * @param name Name of path
15
16
  * @param id Path ID
16
17
  * @param hasAllPerms Does the player have immediate access to all permed skills>
18
+ * @param canUseSkillbooks Does the player have ability to learn skills from skillbooks>
17
19
  * @param hasCampground Does the player have access to the campground?
18
20
  * @param hasTerrarium Does the player have access to terrarium.php
19
21
  * @param stomachSize Maximum fullness achievable at turn 0
@@ -21,7 +23,7 @@ export declare class Path {
21
23
  * @param spleenSize Maximum spleen achievable at turn 0
22
24
  * @param classes Classes available in this path
23
25
  */
24
- constructor(name: string, id: number, hasAllPerms?: boolean, hasCampground?: boolean, hasTerrarium?: boolean, stomachSize?: number, liverSize?: number, spleenSize?: number, classes?: Class[]);
26
+ constructor(name: string, id: number, hasAllPerms?: boolean, canUseSkillbooks?: boolean, hasCampground?: boolean, hasTerrarium?: boolean, stomachSize?: number, liverSize?: number, spleenSize?: number, classes?: Class[]);
25
27
  }
26
28
  export declare const Paths: {
27
29
  readonly Unrestricted: Path;
@@ -66,4 +68,5 @@ export declare const Paths: {
66
68
  readonly QuantumTerrarium: Path;
67
69
  readonly Wildfire: Path;
68
70
  readonly GreyYou: Path;
71
+ readonly Journeyman: Path;
69
72
  };
package/dist/Path.js CHANGED
@@ -3,6 +3,7 @@ export class Path {
3
3
  name;
4
4
  id;
5
5
  hasAllPerms; //here, we define avatar-ness around being its own class
6
+ canUseSkillbooks;
6
7
  hasCampground;
7
8
  hasTerrarium;
8
9
  stomachSize;
@@ -14,6 +15,7 @@ export class Path {
14
15
  * @param name Name of path
15
16
  * @param id Path ID
16
17
  * @param hasAllPerms Does the player have immediate access to all permed skills>
18
+ * @param canUseSkillbooks Does the player have ability to learn skills from skillbooks>
17
19
  * @param hasCampground Does the player have access to the campground?
18
20
  * @param hasTerrarium Does the player have access to terrarium.php
19
21
  * @param stomachSize Maximum fullness achievable at turn 0
@@ -21,10 +23,11 @@ export class Path {
21
23
  * @param spleenSize Maximum spleen achievable at turn 0
22
24
  * @param classes Classes available in this path
23
25
  */
24
- constructor(name, id, hasAllPerms = true, hasCampground = true, hasTerrarium = true, stomachSize = 15, liverSize = 15, spleenSize = 15, classes = $classes `Seal Clubber, Turtle Tamer, Sauceror, Pastamancer, Disco Bandit, Accordion Thief`) {
26
+ constructor(name, id, hasAllPerms = true, canUseSkillbooks = true, hasCampground = true, hasTerrarium = true, stomachSize = 15, liverSize = 15, spleenSize = 15, classes = $classes `Seal Clubber, Turtle Tamer, Sauceror, Pastamancer, Disco Bandit, Accordion Thief`) {
25
27
  this.name = name;
26
28
  this.id = id;
27
29
  this.hasAllPerms = hasAllPerms;
30
+ this.canUseSkillbooks = canUseSkillbooks;
28
31
  this.hasCampground = hasCampground;
29
32
  this.hasTerrarium = hasTerrarium;
30
33
  this.stomachSize = stomachSize;
@@ -35,46 +38,47 @@ export class Path {
35
38
  }
36
39
  export const Paths = {
37
40
  Unrestricted: new Path("Unrestricted", 0),
38
- Boozetafarian: new Path("Boozetafarian", 1, false, true, true, 0),
39
- Teetotaler: new Path("Teetotaler", 2, false, true, true, 15, 0),
40
- Oxygenarian: new Path("Oxygenarian", 3, false, true, true, 0, 0),
41
+ Boozetafarian: new Path("Boozetafarian", 1, true, true, true, true, 0),
42
+ Teetotaler: new Path("Teetotaler", 2, true, true, true, true, 15, 0),
43
+ Oxygenarian: new Path("Oxygenarian", 3, true, true, true, true, 0, 0),
41
44
  BeesHateYou: new Path("Bees Hate You", 4),
42
45
  WayOfTheSurprisingFist: new Path("Way of the Surprising Fist", 6),
43
- Trendy: new Path("Trendy", 6),
44
- AvatarOfBoris: new Path("Avatar of Boris", 8, false, true, false, 20, 5, 15, $classes `Avatar of Boris`),
46
+ Trendy: new Path("Trendy", 7),
47
+ AvatarOfBoris: new Path("Avatar of Boris", 8, false, false, true, false, 20, 5, 15, $classes `Avatar of Boris`),
45
48
  BugbearInvasion: new Path("Bugbear Invasion", 9),
46
- ZombieSlayer: new Path("Zombie Slayer", 10, false, true, true, 15, 5, 15, $classes `Zombie Master`),
47
- ClassAct: new Path("Class Act", 11, false),
48
- AvatarofJarlsberg: new Path("Avatar of Jarlsberg", 12, false, true, false, 10, 10, 15, $classes `Avatar of Jarlsberg`),
49
+ ZombieSlayer: new Path("Zombie Slayer", 10, false, false, true, true, 15, 5, 15, $classes `Zombie Master`),
50
+ ClassAct: new Path("Class Act", 11, false, false),
51
+ AvatarofJarlsberg: new Path("Avatar of Jarlsberg", 12, false, false, true, false, 10, 10, 15, $classes `Avatar of Jarlsberg`),
49
52
  Big: new Path("BIG!", 14),
50
53
  KolHs: new Path("KOLHS", 15),
51
54
  ClassAct2: new Path("Class Act II: A Class For Pigs", 16, false),
52
- AvatarofSneakyPete: new Path("Avatar of Sneaky Pete", 17, false, true, false, 5, 20, 15, $classes `Avatar of Sneaky Pete`),
55
+ AvatarofSneakyPete: new Path("Avatar of Sneaky Pete", 17, false, false, true, false, 5, 20, 15, $classes `Avatar of Sneaky Pete`),
53
56
  SlowAndSteady: new Path("Slow and Steady", 18),
54
57
  HeavyRains: new Path("Heavy Rains", 19),
55
- Picky: new Path("Picky", 21, false),
58
+ Picky: new Path("Picky", 21, false, false),
56
59
  Standard: new Path("Standard", 22),
57
- ActuallyEdTheUndying: new Path("Actually Ed the Undying", 23, false, false, false, 0, 0, 5, $classes `Ed`),
60
+ ActuallyEdTheUndying: new Path("Actually Ed the Undying", 23, false, false, false, false, 0, 0, 5, $classes `Ed`),
58
61
  OneCrazyRandomSummer: new Path("One Crazy Random Summer", 24),
59
62
  CommunityService: new Path("Community Service", 25),
60
- AvatarOfWestOfLoathing: new Path("Avatar of West of Loathing", 26, false, true, true, 10, 10, 10, $classes `Cow Puncher, Snake Oiler, Beanslinger`),
63
+ AvatarOfWestOfLoathing: new Path("Avatar of West of Loathing", 26, false, false, true, true, 10, 10, 10, $classes `Cow Puncher, Snake Oiler, Beanslinger`),
61
64
  TheSource: new Path("The Source", 27),
62
- NuclearAutumn: new Path("Nuclear Autumn", 28, false, false, true, 3, 3, 3),
63
- GelatinousNoob: new Path("Gelatinous Noob", 29, false, true, true, 0, 0, 0, $classes `Gelatinous Noob`),
64
- LicenseToAdventure: new Path("License to Adventure", 30, true, true, false, 0, 2, 15),
65
+ NuclearAutumn: new Path("Nuclear Autumn", 28, false, false, false, true, 3, 3, 3),
66
+ GelatinousNoob: new Path("Gelatinous Noob", 29, false, false, true, true, 0, 0, 0, $classes `Gelatinous Noob`),
67
+ LicenseToAdventure: new Path("License to Adventure", 30, true, true, true, false, 0, 2, 15),
65
68
  LiveAscendRepeat: new Path("Live. Ascend. Repeat.", 31),
66
- PocketFamiliars: new Path("Pocket Familiars", 32, false, true, false),
69
+ PocketFamiliars: new Path("Pocket Familiars", 32, false, false, true, false),
67
70
  GLover: new Path("G-Lover", 33),
68
71
  DisguisesDelimit: new Path("Disguises Delimit", 34),
69
- DarkGyffte: new Path("Dark Gyffte", 35, false, true, false, 5, 5, 15, $classes `Vampyre`),
72
+ DarkGyffte: new Path("Dark Gyffte", 35, false, false, true, false, 5, 5, 15, $classes `Vampyre`),
70
73
  TwoCrazyRandomSummer: new Path("Two Crazy Random Summer", 36),
71
74
  KingdomOfExploathing: new Path("Kingdom of Exploathing", 37),
72
- PathOfThePlumber: new Path("Path of the Plumber", 38, false, true, true, 20, 0, 5, $classes `Plumber`),
73
- LowKeySummer: new Path("Low Key Summer", 40),
75
+ PathOfThePlumber: new Path("Path of the Plumber", 38, false, false, true, true, 20, 0, 5, $classes `Plumber`),
76
+ LowKeySummer: new Path("Low Key Summer", 39),
74
77
  GreyGoo: new Path("Grey Goo", 40),
75
- YouRobot: new Path("You, Robot", 41, false, false, true, 0, 0, 0),
76
- QuantumTerrarium: new Path("Quantum Terrarium", 42, true, true, false),
78
+ YouRobot: new Path("You, Robot", 41, false, false, false, true, 0, 0, 0),
79
+ QuantumTerrarium: new Path("Quantum Terrarium", 42, true, true, true, false),
77
80
  Wildfire: new Path("Wildfire", 43),
78
- GreyYou: new Path("Grey You", 44, false, true, true, 0, 0, 0, // eslint-disable-next-line libram/verify-constants
81
+ GreyYou: new Path("Grey You", 44, false, false, true, true, 0, 0, 0, // eslint-disable-next-line libram/verify-constants
79
82
  $classes `Grey Goo`),
83
+ Journeyman: new Path("Journeyman", 45, false, false),
80
84
  };
@@ -216,7 +216,7 @@ export default class CommunityService {
216
216
  }, new Requirement(["Weapon Damage", "Weapon Damage Percent"], {}));
217
217
  static SpellDamage = new CommunityService(7, "Spell Damage", "Make Sausage", () => {
218
218
  const dragonfishDamage = myFamiliar() === $familiar `Magic Dragonfish`
219
- ? numericModifier($familiar `Magic Dragonfish`, "Spell Damage Percent", familiarWeight($familiar `Magic Dragonfish`) + weightAdjustment(), $item `none`)
219
+ ? numericModifier($familiar `Magic Dragonfish`, "Spell Damage Percent", familiarWeight($familiar `Magic Dragonfish`) + weightAdjustment(), $item.none)
220
220
  : 0;
221
221
  // We add 0.001 because the floor function sometimes introduces weird rounding errors
222
222
  return (60 -
package/dist/combat.js CHANGED
@@ -78,7 +78,7 @@ export class Macro {
78
78
  * Convert macro to string.
79
79
  */
80
80
  toString() {
81
- return this.components.join(";");
81
+ return (this.components.join(";") + ";").replace(/;;+/g, ";");
82
82
  }
83
83
  /**
84
84
  * Gives your macro a new name to be used when saving an autoattack.
@@ -115,10 +115,7 @@ export class Macro {
115
115
  */
116
116
  step(...nextSteps) {
117
117
  const nextStepsStrings = [].concat(...nextSteps.map((x) => (x instanceof Macro ? x.components : [x])));
118
- this.components = [
119
- ...this.components,
120
- ...nextStepsStrings.filter((s) => s.length > 0),
121
- ];
118
+ this.components.push(...nextStepsStrings.filter((s) => s.length > 0));
122
119
  return this;
123
120
  }
124
121
  /**
@@ -225,7 +225,7 @@ class DietPlanner {
225
225
  const helpers = [];
226
226
  if (this.seasoning &&
227
227
  itemType(menuItem.item) === "food" &&
228
- this.mpa > mallPrice($item `Special Seasoning`)) {
228
+ this.mpa * 0.5 > mallPrice($item `Special Seasoning`)) {
229
229
  helpers.push(this.seasoning);
230
230
  }
231
231
  if (itemType(menuItem.item) === "food" && this.mayoLookup.size) {
package/dist/lib.js CHANGED
@@ -178,7 +178,8 @@ export function haveWandererCounter(wanderer) {
178
178
  * @category Wanderers
179
179
  */
180
180
  export function isVoteWandererNow() {
181
- return totalTurnsPlayed() % 11 == 1;
181
+ return (totalTurnsPlayed() % 11 === 1 &&
182
+ get("lastVoteMonsterTurn") < totalTurnsPlayed());
182
183
  }
183
184
  /**
184
185
  * Tells us whether we can expect a given wanderer now. Behaves differently
@@ -200,7 +201,7 @@ export function isWandererNow(wanderer) {
200
201
  if (deterministicWanderers.includes(wanderer)) {
201
202
  return haveCounter(wanderer, 0, 0);
202
203
  }
203
- if (wanderer == Wanderer.Kramco) {
204
+ if (wanderer === Wanderer.Kramco) {
204
205
  return true;
205
206
  }
206
207
  if (wanderer === Wanderer.Vote) {
@@ -327,12 +328,12 @@ export function getBanishedMonsters() {
327
328
  result.set($skill `Use the Force`, Monster.get(foe));
328
329
  }
329
330
  else if ([
330
- Item.get("none"),
331
+ Item.none,
331
332
  Item.get(`training scroll: Snokebomb`),
332
333
  Item.get(`tomayohawk-style reflex hammer`),
333
334
  null,
334
335
  ].includes(banisherItem)) {
335
- if (Skill.get(banisher) === $skill `none`) {
336
+ if (Skill.get(banisher) === $skill.none) {
336
337
  break;
337
338
  }
338
339
  else {
@@ -376,13 +377,13 @@ export function canUse(item) {
376
377
  */
377
378
  export function noneToNull(thing) {
378
379
  if (thing instanceof Effect) {
379
- return thing === Effect.get("none") ? null : thing;
380
+ return thing === Effect.none ? null : thing;
380
381
  }
381
382
  if (thing instanceof Familiar) {
382
- return thing === Familiar.get("none") ? null : thing;
383
+ return thing === Familiar.none ? null : thing;
383
384
  }
384
385
  if (thing instanceof Item) {
385
- return thing === Item.get("none") ? null : thing;
386
+ return thing === Item.none ? null : thing;
386
387
  }
387
388
  return thing;
388
389
  }
@@ -513,11 +514,11 @@ export const Environment = {
513
514
  */
514
515
  export function findLeprechaunMultiplier(familiar) {
515
516
  if (familiar === $familiar `Mutant Cactus Bud`) {
516
- return numericModifier(familiar, "Leprechaun Effectiveness", 1, $item `none`);
517
+ return numericModifier(familiar, "Leprechaun Effectiveness", 1, $item.none);
517
518
  }
518
519
  if (familiar === $familiar `Reanimated Reanimator`)
519
520
  return 0;
520
- const meatBonus = numericModifier(familiar, "Meat Drop", 1, $item `none`);
521
+ const meatBonus = numericModifier(familiar, "Meat Drop", 1, $item.none);
521
522
  if (meatBonus === 0)
522
523
  return 0;
523
524
  return Math.pow(Math.sqrt(meatBonus / 2 + 55 / 4 + 3) - Math.sqrt(55) / 2, 2);
@@ -530,11 +531,11 @@ export function findLeprechaunMultiplier(familiar) {
530
531
  */
531
532
  export function findFairyMultiplier(familiar) {
532
533
  if (familiar === $familiar `Mutant Fire Ant`) {
533
- return numericModifier(familiar, "Fairy Effectiveness", 1, $item `none`);
534
+ return numericModifier(familiar, "Fairy Effectiveness", 1, $item.none);
534
535
  }
535
536
  if (familiar === $familiar `Reanimated Reanimator`)
536
537
  return 0;
537
- const itemBonus = numericModifier(familiar, "Item Drop", 1, $item `none`);
538
+ const itemBonus = numericModifier(familiar, "Item Drop", 1, $item.none);
538
539
  if (itemBonus === 0)
539
540
  return 0;
540
541
  return Math.pow(Math.sqrt(itemBonus + 55 / 4 + 3) - Math.sqrt(55) / 2, 2);
package/dist/maximize.js CHANGED
@@ -195,11 +195,11 @@ function applyCached(entry, options) {
195
195
  }
196
196
  if (equippedAmount($item `Crown of Thrones`) > 0 &&
197
197
  entry.rider.get($item `Crown of Thrones`)) {
198
- enthroneFamiliar(entry.rider.get($item `Crown of Thrones`) || $familiar `none`);
198
+ enthroneFamiliar(entry.rider.get($item `Crown of Thrones`) || $familiar.none);
199
199
  }
200
200
  if (equippedAmount($item `Buddy Bjorn`) > 0 &&
201
201
  entry.rider.get($item `Buddy Bjorn`)) {
202
- bjornifyFamiliar(entry.rider.get($item `Buddy Bjorn`) || $familiar `none`);
202
+ bjornifyFamiliar(entry.rider.get($item `Buddy Bjorn`) || $familiar.none);
203
203
  }
204
204
  }
205
205
  const slotStructure = [
@@ -312,28 +312,39 @@ export function maximizeCached(objectives, options = {}) {
312
312
  const { forceEquip, preventEquip, bonusEquip, onlySlot, preventSlot, forceUpdate, } = fullOptions;
313
313
  // Sort each group in objective to ensure consistent ordering in string
314
314
  const objective = [
315
- ...objectives.sort(),
316
- ...forceEquip.map((item) => `equip ${item}`).sort(),
317
- ...preventEquip.map((item) => `-equip ${item}`).sort(),
318
- ...onlySlot.map((slot) => `${slot}`).sort(),
319
- ...preventSlot.map((slot) => `-${slot}`).sort(),
320
- ...Array.from(bonusEquip.entries())
321
- .filter(([, bonus]) => bonus !== 0)
322
- .map(([item, bonus]) => `${Math.round(bonus * 100) / 100} bonus ${item}`)
323
- .sort(),
315
+ ...new Set([
316
+ ...objectives.sort(),
317
+ ...forceEquip.map((item) => `equip ${item}`).sort(),
318
+ ...preventEquip.map((item) => `-equip ${item}`).sort(),
319
+ ...onlySlot.map((slot) => `${slot}`).sort(),
320
+ ...preventSlot.map((slot) => `-${slot}`).sort(),
321
+ ...Array.from(bonusEquip.entries())
322
+ .filter(([, bonus]) => bonus !== 0)
323
+ .map(([item, bonus]) => `${Math.round(bonus * 100) / 100} bonus ${item}`)
324
+ .sort(),
325
+ ]),
324
326
  ].join(", ");
325
- const cacheEntry = checkCache(objective, fullOptions);
327
+ // Items equipped in slots not touched by the maximizer must be in the cache key
328
+ const untouchedSlots = cachedSlots.filter((slot) => preventSlot.includes(slot) ||
329
+ (onlySlot.length > 0 && !onlySlot.includes(slot)));
330
+ const cacheKey = [
331
+ objective,
332
+ ...untouchedSlots
333
+ .map((slot) => `${slot}:${equippedItem(slot)}`)
334
+ .sort(),
335
+ ].join("; ");
336
+ const cacheEntry = checkCache(cacheKey, fullOptions);
326
337
  if (cacheEntry && !forceUpdate) {
327
338
  logger.info("Equipment found in maximize cache, equipping...");
328
339
  applyCached(cacheEntry, fullOptions);
329
340
  if (verifyCached(cacheEntry)) {
330
- logger.info(`Equipped cached ${objective}`);
341
+ logger.info(`Equipped cached ${cacheKey}`);
331
342
  return true;
332
343
  }
333
344
  logger.warning("Maximize cache application failed, maximizing...");
334
345
  }
335
346
  const result = maximize(objective, false);
336
- saveCached(objective, fullOptions);
347
+ saveCached(cacheKey, fullOptions);
337
348
  return result;
338
349
  }
339
350
  export class Requirement {
@@ -369,11 +380,11 @@ export class Requirement {
369
380
  forceEquip: [
370
381
  ...(optionsA.forceEquip ?? []),
371
382
  ...(other.maximizeOptions.forceEquip ?? []),
372
- ],
383
+ ].filter((x) => !other.maximizeOptions.preventEquip?.includes(x)),
373
384
  preventEquip: [
374
385
  ...(optionsA.preventEquip ?? []),
375
386
  ...(other.maximizeOptions.preventEquip ?? []),
376
- ],
387
+ ].filter((x) => !other.maximizeOptions.forceEquip?.includes(x)),
377
388
  bonusEquip: new Map([
378
389
  ...(optionsA.bonusEquip?.entries() ?? []),
379
390
  ...(optionsB.bonusEquip?.entries() ?? []),
package/dist/mood.js CHANGED
@@ -104,7 +104,7 @@ class SkillMoodElement extends MoodElement {
104
104
  let maxCasts;
105
105
  if (hpCost(this.skill) > 0) {
106
106
  // FIXME: restore HP
107
- maxCasts = Math.floor(myHp() / hpCost(this.skill));
107
+ maxCasts = Math.max(0, Math.floor((myHp() - 1) / hpCost(this.skill))); // Do not allow ourselves to hit 0 hp
108
108
  }
109
109
  else {
110
110
  const cost = mpCost(this.skill);
@@ -274,7 +274,7 @@ export class Mood {
274
274
  */
275
275
  effect(effect, gainEffect) {
276
276
  const skill = toSkill(effect);
277
- if (!gainEffect && skill !== $skill `none`) {
277
+ if (!gainEffect && skill !== $skill.none) {
278
278
  this.skill(skill);
279
279
  }
280
280
  else {
package/dist/property.js CHANGED
@@ -13,7 +13,7 @@ const createMafiaClassPropertyGetter = (Type, toType) => createPropertyGetter((v
13
13
  if (value === "")
14
14
  return null;
15
15
  const v = toType(value);
16
- return v === Type.get("none") ? null : v;
16
+ return v === Type.none ? null : v;
17
17
  });
18
18
  export const getString = createPropertyGetter((value) => value);
19
19
  export const getCommaSeparated = createPropertyGetter((value) => value.split(/, ?/));