libram 0.8.17 → 0.8.19
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/Kmail.js +42 -10
- package/dist/actions/Banish.d.ts +16 -0
- package/dist/actions/Banish.js +121 -0
- package/dist/actions/FreeRun.js +23 -89
- package/dist/ascend.js +2 -1
- package/dist/challengePaths/2015/CommunityService.js +5 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lib.d.ts +42 -0
- package/dist/lib.js +53 -1
- package/dist/property.d.ts +5 -2
- package/dist/property.js +15 -4
- package/dist/propertyTypes.d.ts +4 -4
- package/dist/propertyTypes.js +4 -4
- package/dist/resources/2023/BurningLeaves.js +1 -0
- package/dist/url.d.ts +35 -0
- package/dist/url.js +67 -0
- package/package.json +1 -1
- package/dist/Path.d.ts +0 -72
- package/dist/Path.js +0 -84
package/dist/Kmail.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { extractItems, extractMeat, isGiftable, Item, visitUrl, } from "kolmafia";
|
|
2
|
+
import { combineQuery, EMPTY_VALUE, fetchUrl } from "./url";
|
|
2
3
|
import { arrayToCountedMap, chunk } from "./utils";
|
|
3
4
|
export default class Kmail {
|
|
4
5
|
id;
|
|
@@ -32,9 +33,12 @@ export default class Kmail {
|
|
|
32
33
|
* @returns Number of kmails deleted
|
|
33
34
|
*/
|
|
34
35
|
static delete(kmails) {
|
|
35
|
-
const results =
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const results = fetchUrl("messages.php", [
|
|
37
|
+
["the_action", "delete"],
|
|
38
|
+
["box", "Inbox"],
|
|
39
|
+
["pwd", EMPTY_VALUE],
|
|
40
|
+
...kmails.map((k) => [`sel${k.id}`, "on"]),
|
|
41
|
+
]);
|
|
38
42
|
return Number(results.match(/<td>(\d) messages? deleted.<\/td>/)?.[1] ?? 0);
|
|
39
43
|
}
|
|
40
44
|
static _genericSend(to, message, items, meat, chunkSize, constructUrl, successString) {
|
|
@@ -44,10 +48,18 @@ export default class Kmail {
|
|
|
44
48
|
const chunks = chunk(sendableItems, chunkSize);
|
|
45
49
|
// Split the items to be sent into chunks of max 11 item types
|
|
46
50
|
for (const c of chunks.length > 0 ? chunks : [null]) {
|
|
47
|
-
const itemsQuery =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
const itemsQuery = {};
|
|
52
|
+
if (c !== null) {
|
|
53
|
+
c.forEach(([item, quantity], i) => {
|
|
54
|
+
itemsQuery[`whichitem${i + 1}`] = item.id;
|
|
55
|
+
itemsQuery[`howmany${i + 1}`] = quantity;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const { path, query } = constructUrl({
|
|
59
|
+
meat: m,
|
|
60
|
+
chunkSize: c?.length ?? 0,
|
|
61
|
+
});
|
|
62
|
+
const r = fetchUrl(path, combineQuery(query, itemsQuery));
|
|
51
63
|
if (r.includes("That player cannot receive Meat or items")) {
|
|
52
64
|
return Kmail.gift(to, message, items, meat);
|
|
53
65
|
}
|
|
@@ -71,7 +83,16 @@ export default class Kmail {
|
|
|
71
83
|
* @returns True if the kmail was successfully sent
|
|
72
84
|
*/
|
|
73
85
|
static send(to, message = "", items = [], meat = 0) {
|
|
74
|
-
return Kmail._genericSend(to, message, items, meat, 11, (meat
|
|
86
|
+
return Kmail._genericSend(to, message, items, meat, 11, ({ meat }) => ({
|
|
87
|
+
path: "sendmessage.php",
|
|
88
|
+
query: {
|
|
89
|
+
action: "send",
|
|
90
|
+
pwd: EMPTY_VALUE,
|
|
91
|
+
towho: to,
|
|
92
|
+
message,
|
|
93
|
+
sendmeat: meat,
|
|
94
|
+
},
|
|
95
|
+
}), ">Message sent.</");
|
|
75
96
|
}
|
|
76
97
|
/**
|
|
77
98
|
* Sends a gift to a player
|
|
@@ -87,8 +108,19 @@ export default class Kmail {
|
|
|
87
108
|
* @returns True if the gift was successfully sent
|
|
88
109
|
*/
|
|
89
110
|
static gift(to, message = "", items = [], meat = 0, insideNote = "") {
|
|
90
|
-
|
|
91
|
-
|
|
111
|
+
return Kmail._genericSend(to, message, items, meat, 3, ({ meat, chunkSize }) => ({
|
|
112
|
+
path: `town_sendgift.php`,
|
|
113
|
+
query: {
|
|
114
|
+
action: "Yep.",
|
|
115
|
+
pwd: EMPTY_VALUE,
|
|
116
|
+
fromwhere: 0,
|
|
117
|
+
note: message,
|
|
118
|
+
insidenote: insideNote,
|
|
119
|
+
towho: to,
|
|
120
|
+
whichpackage: chunkSize,
|
|
121
|
+
sendmeat: meat,
|
|
122
|
+
},
|
|
123
|
+
}), ">Package sent.</");
|
|
92
124
|
}
|
|
93
125
|
constructor(rawKmail) {
|
|
94
126
|
const date = new Date(rawKmail.localtime);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ActionSource, FindActionSourceConstraints } from "./ActionSource";
|
|
2
|
+
/**
|
|
3
|
+
* Find an available banish source subject to constraints.
|
|
4
|
+
*
|
|
5
|
+
* @param constraints Preexisting constraints that restrict possible sources.
|
|
6
|
+
* @returns Banish source satisfying constraints, or null.
|
|
7
|
+
*/
|
|
8
|
+
export declare function tryFindBanish(constraints?: FindActionSourceConstraints): ActionSource | null;
|
|
9
|
+
/**
|
|
10
|
+
* Ensure an available banish source subject to constraints.
|
|
11
|
+
* Throws an error if no source can be found.
|
|
12
|
+
*
|
|
13
|
+
* @param constraints Preexisting constraints that restrict possible sources.
|
|
14
|
+
* @returns Banish source satisfying constraints.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ensureBanish(constraints?: FindActionSourceConstraints): ActionSource;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { canEquip, cliExecute, myTurncount, restoreMp, retrieveItem, visitUrl, } from "kolmafia";
|
|
2
|
+
import { Macro } from "../combat";
|
|
3
|
+
import { getFoldGroup, have } from "../lib";
|
|
4
|
+
import { Requirement } from "../maximize";
|
|
5
|
+
import { get } from "../property";
|
|
6
|
+
import * as AsdonMartin from "../resources/2017/AsdonMartin";
|
|
7
|
+
import { $item, $items, $skill } from "../template-string";
|
|
8
|
+
import { ActionSource, findActionSource, } from "./ActionSource";
|
|
9
|
+
// Value of _lastCombatStarted the last time we updated scrapbook charges.
|
|
10
|
+
let scrapbookChargesLastUpdated = get("_lastCombatStarted");
|
|
11
|
+
// Free unlimited source every 30 turns.
|
|
12
|
+
// Does not work on special monsters so needs a backup, see tryFindFreeRun.
|
|
13
|
+
// banishedMonsters isn't updated if the banish succeeds on an unbanishable monster
|
|
14
|
+
const asdonMartinSource = new ActionSource($skill `Asdon Martin: Spring-Loaded Front Bumper`, () => {
|
|
15
|
+
if (!AsdonMartin.installed())
|
|
16
|
+
return 0;
|
|
17
|
+
const banishes = get("banishedMonsters").split(":");
|
|
18
|
+
const bumperIndex = banishes
|
|
19
|
+
.map((string) => string.toLowerCase())
|
|
20
|
+
.indexOf("spring-loaded front bumper");
|
|
21
|
+
if (bumperIndex === -1)
|
|
22
|
+
return 1;
|
|
23
|
+
return myTurncount() - parseInt(banishes[bumperIndex + 1]) > 30 ? 1 : 0;
|
|
24
|
+
}, Macro.trySkill($skill `Asdon Martin: Spring-Loaded Front Bumper`), {
|
|
25
|
+
preparation: () => AsdonMartin.fillTo(50),
|
|
26
|
+
});
|
|
27
|
+
const banishSources = [
|
|
28
|
+
// Free limited sources
|
|
29
|
+
new ActionSource($skill `Snokebomb`, () => (have($skill `Snokebomb`) ? 3 - get("_snokebombUsed") : 0), Macro.skill($skill `Snokebomb`), {
|
|
30
|
+
preparation: () => restoreMp(50),
|
|
31
|
+
}),
|
|
32
|
+
new ActionSource($skill `Emotionally Chipped`, () => (have($skill `Emotionally Chipped`) ? 3 - get("_feelHatredUsed") : 0), Macro.skill($skill `Feel Hatred`)),
|
|
33
|
+
new ActionSource($item `Kremlin's Greatest Briefcase`, () => have($item `Kremlin's Greatest Briefcase`)
|
|
34
|
+
? 3 - get("_kgbTranquilizerDartUses")
|
|
35
|
+
: 0, Macro.skill($skill `KGB tranquilizer dart`), {
|
|
36
|
+
equipmentRequirements: () => new Requirement([], {
|
|
37
|
+
forceEquip: $items `Kremlin's Greatest Briefcase`,
|
|
38
|
+
}),
|
|
39
|
+
}),
|
|
40
|
+
new ActionSource($item `latte lovers member's mug`, () => have($item `latte lovers member's mug`) && !get("_latteBanishUsed")
|
|
41
|
+
? 1
|
|
42
|
+
: 0, Macro.skill($skill `Throw Latte on Opponent`), {
|
|
43
|
+
equipmentRequirements: () => new Requirement([], { forceEquip: $items `latte lovers member's mug` }),
|
|
44
|
+
}),
|
|
45
|
+
new ActionSource($item `Lil' Doctor™ bag`, () => (have($item `Lil' Doctor™ bag`) ? 3 - get("_reflexHammerUsed") : 0), Macro.skill($skill `Reflex Hammer`), {
|
|
46
|
+
equipmentRequirements: () => new Requirement([], { forceEquip: $items `Lil' Doctor™ bag` }),
|
|
47
|
+
}),
|
|
48
|
+
new ActionSource($item `mafia middle finger ring`, () => have($item `mafia middle finger ring`) &&
|
|
49
|
+
canEquip($item `mafia middle finger ring`) &&
|
|
50
|
+
!get("_mafiaMiddleFingerRingUsed")
|
|
51
|
+
? 1
|
|
52
|
+
: 0, Macro.skill($skill `Show them your ring`), {
|
|
53
|
+
equipmentRequirements: () => new Requirement([], { forceEquip: $items `mafia middle finger ring` }),
|
|
54
|
+
}),
|
|
55
|
+
new ActionSource($item `V for Vivala mask`, () => have($item `V for Vivala mask`) && !get("_vmaskBanisherUsed") ? 1 : 0, Macro.skill($skill `Creepy Grin`), {
|
|
56
|
+
equipmentRequirements: () => new Requirement([], { forceEquip: $items `V for Vivala mask` }),
|
|
57
|
+
preparation: () => restoreMp(30),
|
|
58
|
+
}),
|
|
59
|
+
new ActionSource($item `stinky cheese eye`, () => getFoldGroup($item `stinky cheese eye`).some((item) => have(item)) &&
|
|
60
|
+
!get("_stinkyCheeseBanisherUsed")
|
|
61
|
+
? 1
|
|
62
|
+
: 0, Macro.skill($skill `Give Your Opponent the Stinkeye`), {
|
|
63
|
+
equipmentRequirements: () => new Requirement([], { forceEquip: $items `stinky cheese eye` }),
|
|
64
|
+
preparation: () => {
|
|
65
|
+
if (!have($item `stinky cheese eye`)) {
|
|
66
|
+
cliExecute(`fold stinky cheese eye`);
|
|
67
|
+
}
|
|
68
|
+
return have($item `stinky cheese eye`);
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
71
|
+
new ActionSource($skill `Show your boring familiar pictures`, () => {
|
|
72
|
+
if (have($item `familiar scrapbook`)) {
|
|
73
|
+
if (scrapbookChargesLastUpdated !== get("_lastCombatStarted")) {
|
|
74
|
+
visitUrl("desc_item.php?whichitem=463063785");
|
|
75
|
+
scrapbookChargesLastUpdated = get("_lastCombatStarted");
|
|
76
|
+
}
|
|
77
|
+
return Math.floor(get("scrapbookCharges") / 100);
|
|
78
|
+
}
|
|
79
|
+
return 0;
|
|
80
|
+
}, Macro.skill($skill `Show your boring familiar pictures`), {
|
|
81
|
+
equipmentRequirements: () => new Requirement([], { forceEquip: $items `familiar scrapbook` }),
|
|
82
|
+
}),
|
|
83
|
+
new ActionSource($item `human musk`, () => Math.max(0, 3 - get("_humanMuskUses")), Macro.item($item `human musk`), {
|
|
84
|
+
preparation: () => retrieveItem($item `human musk`),
|
|
85
|
+
cost: () => ActionSource.defaultPriceFunction($item `human musk`),
|
|
86
|
+
}),
|
|
87
|
+
// Expensive unlimited sources
|
|
88
|
+
...$items `Louder Than Bomb, divine champagne popper, tennis ball`.map((item) => new ActionSource(item, () => Infinity, Macro.item(item), {
|
|
89
|
+
preparation: () => retrieveItem(item),
|
|
90
|
+
cost: () => ActionSource.defaultPriceFunction(item),
|
|
91
|
+
})),
|
|
92
|
+
];
|
|
93
|
+
/**
|
|
94
|
+
* Find an available banish source subject to constraints.
|
|
95
|
+
*
|
|
96
|
+
* @param constraints Preexisting constraints that restrict possible sources.
|
|
97
|
+
* @returns Banish source satisfying constraints, or null.
|
|
98
|
+
*/
|
|
99
|
+
export function tryFindBanish(constraints) {
|
|
100
|
+
let source = findActionSource(banishSources, constraints);
|
|
101
|
+
// Always try to use Asdon Martin: Spring-Loaded Front Bumper first,
|
|
102
|
+
// but only if another source has been found.
|
|
103
|
+
if (source && asdonMartinSource.available()) {
|
|
104
|
+
source = asdonMartinSource.merge(source);
|
|
105
|
+
}
|
|
106
|
+
return source;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ensure an available banish source subject to constraints.
|
|
110
|
+
* Throws an error if no source can be found.
|
|
111
|
+
*
|
|
112
|
+
* @param constraints Preexisting constraints that restrict possible sources.
|
|
113
|
+
* @returns Banish source satisfying constraints.
|
|
114
|
+
*/
|
|
115
|
+
export function ensureBanish(constraints) {
|
|
116
|
+
const source = tryFindBanish(constraints);
|
|
117
|
+
if (!source) {
|
|
118
|
+
throw new Error("Failed to ensure Banish source");
|
|
119
|
+
}
|
|
120
|
+
return source;
|
|
121
|
+
}
|
package/dist/actions/FreeRun.js
CHANGED
|
@@ -1,31 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { retrieveItem } from "kolmafia";
|
|
2
2
|
import { Macro } from "../combat";
|
|
3
|
-
import { ensureEffect,
|
|
3
|
+
import { ensureEffect, getSongCount, getSongLimit, have } from "../lib";
|
|
4
4
|
import { Requirement } from "../maximize";
|
|
5
5
|
import { get } from "../property";
|
|
6
6
|
import * as Bandersnatch from "../resources/2009/Bandersnatch";
|
|
7
7
|
import * as StompingBoots from "../resources/2011/StompingBoots";
|
|
8
|
-
import
|
|
9
|
-
import { $effect, $familiar, $item, $items, $skill } from "../template-string";
|
|
8
|
+
import { $effect, $familiar, $item, $items } from "../template-string";
|
|
10
9
|
import { ActionSource, findActionSource, } from "./ActionSource";
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
// Free unlimited source every 30 turns.
|
|
14
|
-
// Does not work on special monsters so needs a backup, see tryFindFreeRun.
|
|
15
|
-
// banishedMonsters isn't updated if the free run succeeds on an unbanishable monster
|
|
16
|
-
const asdonMartinSource = new ActionSource($skill `Asdon Martin: Spring-Loaded Front Bumper`, () => {
|
|
17
|
-
if (!AsdonMartin.installed())
|
|
18
|
-
return 0;
|
|
19
|
-
const banishes = get("banishedMonsters").split(":");
|
|
20
|
-
const bumperIndex = banishes
|
|
21
|
-
.map((string) => string.toLowerCase())
|
|
22
|
-
.indexOf("spring-loaded front bumper");
|
|
23
|
-
if (bumperIndex === -1)
|
|
24
|
-
return 1;
|
|
25
|
-
return myTurncount() - parseInt(banishes[bumperIndex + 1]) > 30 ? 1 : 0;
|
|
26
|
-
}, Macro.trySkill($skill `Asdon Martin: Spring-Loaded Front Bumper`), {
|
|
27
|
-
preparation: () => AsdonMartin.fillTo(50),
|
|
28
|
-
});
|
|
10
|
+
// eslint-disable-next-line libram/verify-constants
|
|
11
|
+
const EVERYTHING_LOOKS_GREEN = $effect `Everything Looks Green`;
|
|
29
12
|
const freeRunSources = [
|
|
30
13
|
// Free limited sources
|
|
31
14
|
new ActionSource($familiar `Frumious Bandersnatch`, () => (have($effect `Ode to Booze`) || getSongCount() < getSongLimit()) &&
|
|
@@ -43,48 +26,6 @@ const freeRunSources = [
|
|
|
43
26
|
equipmentRequirements: () => new Requirement(["Familiar Weight"], {}),
|
|
44
27
|
familiar: () => $familiar `Pair of Stomping Boots`,
|
|
45
28
|
}),
|
|
46
|
-
new ActionSource($skill `Snokebomb`, () => (have($skill `Snokebomb`) ? 3 - get("_snokebombUsed") : 0), Macro.skill($skill `Snokebomb`), {
|
|
47
|
-
preparation: () => restoreMp(50),
|
|
48
|
-
}),
|
|
49
|
-
new ActionSource($skill `Emotionally Chipped`, () => (have($skill `Emotionally Chipped`) ? 3 - get("_feelHatredUsed") : 0), Macro.skill($skill `Feel Hatred`)),
|
|
50
|
-
new ActionSource($item `Kremlin's Greatest Briefcase`, () => have($item `Kremlin's Greatest Briefcase`)
|
|
51
|
-
? 3 - get("_kgbTranquilizerDartUses")
|
|
52
|
-
: 0, Macro.skill($skill `KGB tranquilizer dart`), {
|
|
53
|
-
equipmentRequirements: () => new Requirement([], {
|
|
54
|
-
forceEquip: $items `Kremlin's Greatest Briefcase`,
|
|
55
|
-
}),
|
|
56
|
-
}),
|
|
57
|
-
new ActionSource($item `latte lovers member's mug`, () => have($item `latte lovers member's mug`) && !get("_latteBanishUsed")
|
|
58
|
-
? 1
|
|
59
|
-
: 0, Macro.skill($skill `Throw Latte on Opponent`), {
|
|
60
|
-
equipmentRequirements: () => new Requirement([], { forceEquip: $items `latte lovers member's mug` }),
|
|
61
|
-
}),
|
|
62
|
-
new ActionSource($item `Lil' Doctor™ bag`, () => (have($item `Lil' Doctor™ bag`) ? 3 - get("_reflexHammerUsed") : 0), Macro.skill($skill `Reflex Hammer`), {
|
|
63
|
-
equipmentRequirements: () => new Requirement([], { forceEquip: $items `Lil' Doctor™ bag` }),
|
|
64
|
-
}),
|
|
65
|
-
new ActionSource($item `mafia middle finger ring`, () => have($item `mafia middle finger ring`) &&
|
|
66
|
-
canEquip($item `mafia middle finger ring`) &&
|
|
67
|
-
!get("_mafiaMiddleFingerRingUsed")
|
|
68
|
-
? 1
|
|
69
|
-
: 0, Macro.skill($skill `Show them your ring`), {
|
|
70
|
-
equipmentRequirements: () => new Requirement([], { forceEquip: $items `mafia middle finger ring` }),
|
|
71
|
-
}),
|
|
72
|
-
new ActionSource($item `V for Vivala mask`, () => have($item `V for Vivala mask`) && !get("_vmaskBanisherUsed") ? 1 : 0, Macro.skill($skill `Creepy Grin`), {
|
|
73
|
-
equipmentRequirements: () => new Requirement([], { forceEquip: $items `V for Vivala mask` }),
|
|
74
|
-
preparation: () => restoreMp(30),
|
|
75
|
-
}),
|
|
76
|
-
new ActionSource($item `stinky cheese eye`, () => getFoldGroup($item `stinky cheese eye`).some((item) => have(item)) &&
|
|
77
|
-
!get("_stinkyCheeseBanisherUsed")
|
|
78
|
-
? 1
|
|
79
|
-
: 0, Macro.skill($skill `Give Your Opponent the Stinkeye`), {
|
|
80
|
-
equipmentRequirements: () => new Requirement([], { forceEquip: $items `stinky cheese eye` }),
|
|
81
|
-
preparation: () => {
|
|
82
|
-
if (!have($item `stinky cheese eye`)) {
|
|
83
|
-
cliExecute(`fold stinky cheese eye`);
|
|
84
|
-
}
|
|
85
|
-
return have($item `stinky cheese eye`);
|
|
86
|
-
},
|
|
87
|
-
}),
|
|
88
29
|
new ActionSource($item `navel ring of navel gazing`, () => have($item `navel ring of navel gazing`)
|
|
89
30
|
? Math.max(0, 3 - get("_navelRunaways"))
|
|
90
31
|
: 0, Macro.step("runaway"), {
|
|
@@ -95,30 +36,28 @@ const freeRunSources = [
|
|
|
95
36
|
: 0, Macro.step("runaway"), {
|
|
96
37
|
equipmentRequirements: () => new Requirement([], { forceEquip: $items `Greatest American Pants` }),
|
|
97
38
|
}),
|
|
98
|
-
new ActionSource($skill `Show your boring familiar pictures`, () => {
|
|
99
|
-
if (have($item `familiar scrapbook`)) {
|
|
100
|
-
if (scrapbookChargesLastUpdated !== get("_lastCombatStarted")) {
|
|
101
|
-
visitUrl("desc_item.php?whichitem=463063785");
|
|
102
|
-
scrapbookChargesLastUpdated = get("_lastCombatStarted");
|
|
103
|
-
}
|
|
104
|
-
return Math.floor(get("scrapbookCharges") / 100);
|
|
105
|
-
}
|
|
106
|
-
return 0;
|
|
107
|
-
}, Macro.skill($skill `Show your boring familiar pictures`), {
|
|
108
|
-
equipmentRequirements: () => new Requirement([], { forceEquip: $items `familiar scrapbook` }),
|
|
109
|
-
}),
|
|
110
39
|
new ActionSource($item `peppermint parasol`, () => Math.max(0, 3 - get("_navelRunaways")), Macro.item($item `peppermint parasol`), {
|
|
111
40
|
preparation: () => retrieveItem($item `peppermint parasol`),
|
|
112
41
|
cost: () => Math.min(ActionSource.defaultPriceFunction($item `peppermint sprout`) * 5, ActionSource.defaultPriceFunction($item `peppermint parasol`)) / 10, // Breaks after 10 successful runaways.
|
|
113
42
|
}),
|
|
114
|
-
new ActionSource($item `
|
|
115
|
-
preparation: () => retrieveItem($item `
|
|
116
|
-
cost: () => ActionSource.defaultPriceFunction($item `
|
|
43
|
+
new ActionSource($item `green smoke bomb`, () => (have(EVERYTHING_LOOKS_GREEN) ? 0 : 1), Macro.item($item `green smoke bomb`), {
|
|
44
|
+
preparation: () => retrieveItem($item `green smoke bomb`),
|
|
45
|
+
cost: () => ActionSource.defaultPriceFunction($item `green smoke bomb`),
|
|
117
46
|
}),
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
preparation: () => retrieveItem(item),
|
|
121
|
-
cost: () => ActionSource.defaultPriceFunction(item),
|
|
47
|
+
// 50% chance, get 5 to be safe
|
|
48
|
+
new ActionSource($item `tattered scrap of paper`, () => (have(EVERYTHING_LOOKS_GREEN) ? 0 : 1), Macro.item($item `tattered scrap of paper`).repeat(), {
|
|
49
|
+
preparation: () => retrieveItem($item `tattered scrap of paper`, 5),
|
|
50
|
+
cost: () => ActionSource.defaultPriceFunction($item `tattered scrap of paper`) * 5,
|
|
51
|
+
}),
|
|
52
|
+
// 30% chance, get 10 to be safe
|
|
53
|
+
new ActionSource($item `GOTO`, () => (have(EVERYTHING_LOOKS_GREEN) ? 0 : 1), Macro.item($item `GOTO`).repeat(), {
|
|
54
|
+
preparation: () => retrieveItem($item `GOTO`, 10),
|
|
55
|
+
cost: () => ActionSource.defaultPriceFunction($item `GOTO`) * 10,
|
|
56
|
+
}),
|
|
57
|
+
// limited quest items
|
|
58
|
+
...$items `fish-oil smoke bomb, giant eraser`.map((item) => new ActionSource(item, () => (have(EVERYTHING_LOOKS_GREEN) ? 0 : 1), Macro.item(item), {
|
|
59
|
+
preparation: () => have(item),
|
|
60
|
+
cost: () => 0,
|
|
122
61
|
})),
|
|
123
62
|
];
|
|
124
63
|
/**
|
|
@@ -128,12 +67,7 @@ const freeRunSources = [
|
|
|
128
67
|
* @returns Free run source satisfying constraints, or null.
|
|
129
68
|
*/
|
|
130
69
|
export function tryFindFreeRun(constraints) {
|
|
131
|
-
|
|
132
|
-
// Always try to use Asdon Martin: Spring-Loaded Front Bumper first,
|
|
133
|
-
// but only if another source has been found.
|
|
134
|
-
if (source && asdonMartinSource.available()) {
|
|
135
|
-
source = asdonMartinSource.merge(source);
|
|
136
|
-
}
|
|
70
|
+
const source = findActionSource(freeRunSources, constraints);
|
|
137
71
|
return source;
|
|
138
72
|
}
|
|
139
73
|
/**
|
package/dist/ascend.js
CHANGED
|
@@ -182,7 +182,8 @@ export function ascend(options) {
|
|
|
182
182
|
consumable: $item `astral six-pack`,
|
|
183
183
|
pet: $item `none`,
|
|
184
184
|
};
|
|
185
|
-
const
|
|
185
|
+
const prunedOptions = Object.fromEntries(Object.entries(options).filter(([, value]) => value));
|
|
186
|
+
const { path, playerClass, lifestyle, kolGender, moon, consumable, pet, permOptions, } = { ...DEFAULT_OPTIONS, ...prunedOptions };
|
|
186
187
|
if (playerClass.path !== (path.avatar ? path : Path.none)) {
|
|
187
188
|
throw new AscendError(playerClass);
|
|
188
189
|
}
|
|
@@ -277,13 +277,15 @@ export default class CommunityService {
|
|
|
277
277
|
}, new Requirement(["Spell Damage", "Spell Damage Percent"], {}));
|
|
278
278
|
static Noncombat = new CommunityService(8, "Non-Combat", "Be a Living Statue", (...effects) => {
|
|
279
279
|
const noncombatRate = -1 * hypotheticalModifier("Combat Rate", ...effects);
|
|
280
|
-
const unsoftcappedRate =
|
|
280
|
+
const unsoftcappedRate = (rate) => rate > 25 ? 25 + (rate - 25) * 5 : rate;
|
|
281
281
|
const currentFamiliarModifier = -1 *
|
|
282
282
|
numericModifier(myFamiliar(), "Combat Rate", familiarWeight(myFamiliar()) + numericModifier("Familiar Weight"), equippedItem($slot `familiar`));
|
|
283
283
|
const newFamiliarModifier = -1 *
|
|
284
284
|
numericModifier(myFamiliar(), "Combat Rate", familiarWeight(myFamiliar()) +
|
|
285
|
-
hypotheticalModifier("
|
|
286
|
-
const adjustedRate = unsoftcappedRate -
|
|
285
|
+
hypotheticalModifier("Familiar Weight", ...effects), equippedItem($slot `familiar`));
|
|
286
|
+
const adjustedRate = unsoftcappedRate(noncombatRate) -
|
|
287
|
+
unsoftcappedRate(currentFamiliarModifier) +
|
|
288
|
+
unsoftcappedRate(newFamiliarModifier);
|
|
287
289
|
return 60 - 3 * Math.floor(adjustedRate / 5);
|
|
288
290
|
}, new Requirement(["-combat"], {}));
|
|
289
291
|
static BoozeDrop = new CommunityService(9, "Item Drop", "Make Margaritas", (...effects) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ export * from "./resources";
|
|
|
16
16
|
export * from "./since";
|
|
17
17
|
export * from "./template-string";
|
|
18
18
|
export { default as Kmail } from "./Kmail";
|
|
19
|
-
export * from "./Path";
|
|
20
19
|
export { default as logger } from "./logger";
|
|
21
20
|
export * as console from "./console";
|
|
22
21
|
export * as property from "./property";
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,6 @@ export * from "./resources";
|
|
|
16
16
|
export * from "./since";
|
|
17
17
|
export * from "./template-string";
|
|
18
18
|
export { default as Kmail } from "./Kmail";
|
|
19
|
-
export * from "./Path";
|
|
20
19
|
export { default as logger } from "./logger";
|
|
21
20
|
export * as console from "./console";
|
|
22
21
|
export * as property from "./property";
|
package/dist/lib.d.ts
CHANGED
|
@@ -408,3 +408,45 @@ export declare function realmCurrency(realm: RealmType): Item | undefined;
|
|
|
408
408
|
* @returns a list of currently available currencies
|
|
409
409
|
*/
|
|
410
410
|
export declare function lgrCurrencies(): Item[];
|
|
411
|
+
declare const ACCOUNT_COMBAT_FLAGS: readonly ["aabosses", "wowbar", "bothcombatinterf", "compactmanuel", "eternalmrj", "disablelovebugs"];
|
|
412
|
+
/**
|
|
413
|
+
* Different flags you can set on your account for how to handle combat:
|
|
414
|
+
* aabosses refers to the flag that lets autoattack trigger against special monsters
|
|
415
|
+
* wowbar refers to the flag to use the Combat Action Bar
|
|
416
|
+
* bothcombatinterf refers to the flag to use both the CAB
|
|
417
|
+
* compactmanuel refers to the flag to display monster manuel data horizontally
|
|
418
|
+
* eternalmrg refers to the flag to enable endless factoid delight
|
|
419
|
+
* disablelovebugs disables love bugs
|
|
420
|
+
*/
|
|
421
|
+
export declare type AccountCombatFlag = typeof ACCOUNT_COMBAT_FLAGS[number];
|
|
422
|
+
/**
|
|
423
|
+
* Get the current value of all of your account's combat setting flags
|
|
424
|
+
* @param flags An array of the flags you want to get, defaults to all of them
|
|
425
|
+
* @returns An array of objects that contain the flags and their values as booleans
|
|
426
|
+
*/
|
|
427
|
+
export declare function getCombatFlags(flags?: AccountCombatFlag[]): {
|
|
428
|
+
flag: AccountCombatFlag;
|
|
429
|
+
value: boolean;
|
|
430
|
+
}[];
|
|
431
|
+
/**
|
|
432
|
+
* Sets the given combat setting flags on your account
|
|
433
|
+
*
|
|
434
|
+
* @param flags A spread array of objects that contain a flag and its desired value; these look like the return value of `getCombatFlags`
|
|
435
|
+
* @returns the result of the associated `visitUrl` call
|
|
436
|
+
*/
|
|
437
|
+
export declare function setCombatFlags(...flags: {
|
|
438
|
+
flag: AccountCombatFlag;
|
|
439
|
+
value: boolean;
|
|
440
|
+
}[]): string;
|
|
441
|
+
/**
|
|
442
|
+
* Perform a given action with certain combat setting flags set, returning them to their initial values if possible
|
|
443
|
+
*
|
|
444
|
+
* @param action The action you want to do with the given combat setting flags
|
|
445
|
+
* @param flags A spread array of objects that contain a combat setting flag and its desired value; these look like the return value of `getCombatFlags`
|
|
446
|
+
* @returns The result of the action
|
|
447
|
+
*/
|
|
448
|
+
export declare function withCombatFlags<T>(action: () => T, ...flags: {
|
|
449
|
+
flag: AccountCombatFlag;
|
|
450
|
+
value: boolean;
|
|
451
|
+
}[]): T;
|
|
452
|
+
export {};
|
package/dist/lib.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @module GeneralLibrary */
|
|
2
|
-
import { appearanceRates, autosellPrice, availableAmount, booleanModifier, choiceFollowsFight, cliExecute, currentRound, Effect, elementalResistance, equip, equippedItem, Familiar, fullnessLimit, getCampground, getCounters, getPlayerId, getPlayerName, getRelated, handlingChoice, haveEffect, haveFamiliar, haveServant, haveSkill, holiday, inebrietyLimit, inMultiFight, Item, Location, mallPrice, Monster, myClass, myEffects, myFamiliar, myFullness, myInebriety, myPath, myPrimestat, mySpleenUse, myThrall, myTurncount, numericModifier, Path, Servant, Skill, Slot, spleenLimit, Thrall, todayToString, toItem, toSkill, totalTurnsPlayed, visitUrl, } from "kolmafia";
|
|
2
|
+
import { appearanceRates, autosellPrice, availableAmount, booleanModifier, choiceFollowsFight, cliExecute, currentRound, Effect, elementalResistance, equip, equippedItem, Familiar, fullnessLimit, getCampground, getCounters, getPlayerId, getPlayerName, getRelated, handlingChoice, haveEffect, haveFamiliar, haveServant, haveSkill, holiday, inebrietyLimit, inMultiFight, Item, Location, mallPrice, Monster, myClass, myEffects, myFamiliar, myFullness, myInebriety, myPath, myPrimestat, mySpleenUse, myThrall, myTurncount, numericModifier, Path, Servant, Skill, Slot, spleenLimit, Thrall, todayToString, toItem, toSkill, totalTurnsPlayed, visitUrl, xpath, } from "kolmafia";
|
|
3
3
|
import logger from "./logger";
|
|
4
4
|
import { get } from "./property";
|
|
5
5
|
import { $class, $effect, $element, $familiar, $item, $items, $monsters, $skill, $stat, } from "./template-string";
|
|
@@ -847,3 +847,55 @@ export function lgrCurrencies() {
|
|
|
847
847
|
.map(realmCurrency)
|
|
848
848
|
.filter((i) => !!i);
|
|
849
849
|
}
|
|
850
|
+
const ACCOUNT_COMBAT_FLAGS = [
|
|
851
|
+
"aabosses",
|
|
852
|
+
"wowbar",
|
|
853
|
+
"bothcombatinterf",
|
|
854
|
+
"compactmanuel",
|
|
855
|
+
"eternalmrj",
|
|
856
|
+
"disablelovebugs",
|
|
857
|
+
];
|
|
858
|
+
/**
|
|
859
|
+
* Get the current value of all of your account's combat setting flags
|
|
860
|
+
* @param flags An array of the flags you want to get, defaults to all of them
|
|
861
|
+
* @returns An array of objects that contain the flags and their values as booleans
|
|
862
|
+
*/
|
|
863
|
+
export function getCombatFlags(flags = [...ACCOUNT_COMBAT_FLAGS]) {
|
|
864
|
+
const accountPage = visitUrl("account.php?tab=combat");
|
|
865
|
+
return flags.map((flag) => ({
|
|
866
|
+
flag,
|
|
867
|
+
value: xpath(accountPage, `//*[@id="opt_flag_${flag}"]/label/input[@type='checkbox']@checked`)[0] === "checked",
|
|
868
|
+
}));
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Sets the given combat setting flags on your account
|
|
872
|
+
*
|
|
873
|
+
* @param flags A spread array of objects that contain a flag and its desired value; these look like the return value of `getCombatFlags`
|
|
874
|
+
* @returns the result of the associated `visitUrl` call
|
|
875
|
+
*/
|
|
876
|
+
export function setCombatFlags(...flags) {
|
|
877
|
+
return visitUrl(`account.php?${([
|
|
878
|
+
...flat(flags.map(({ flag, value }) => [
|
|
879
|
+
`actions[]=flag_${flag}`,
|
|
880
|
+
`flag_${flag}=${Number(value)}`,
|
|
881
|
+
])),
|
|
882
|
+
"action=Update",
|
|
883
|
+
].join("&"),
|
|
884
|
+
true)}`);
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Perform a given action with certain combat setting flags set, returning them to their initial values if possible
|
|
888
|
+
*
|
|
889
|
+
* @param action The action you want to do with the given combat setting flags
|
|
890
|
+
* @param flags A spread array of objects that contain a combat setting flag and its desired value; these look like the return value of `getCombatFlags`
|
|
891
|
+
* @returns The result of the action
|
|
892
|
+
*/
|
|
893
|
+
export function withCombatFlags(action, ...flags) {
|
|
894
|
+
const initialValues = getCombatFlags(flags.map(({ flag }) => flag));
|
|
895
|
+
try {
|
|
896
|
+
return action();
|
|
897
|
+
}
|
|
898
|
+
finally {
|
|
899
|
+
setCombatFlags(...initialValues);
|
|
900
|
+
}
|
|
901
|
+
}
|
package/dist/property.d.ts
CHANGED
|
@@ -76,7 +76,9 @@ export declare function increment(property: NumericProperty, delta?: number, max
|
|
|
76
76
|
export declare function decrement(property: NumericProperty, delta?: number, min?: number): number;
|
|
77
77
|
declare type Properties = Partial<{
|
|
78
78
|
[P in KnownProperty]: unknown;
|
|
79
|
-
}
|
|
79
|
+
}> & {
|
|
80
|
+
[x in string]: unknown;
|
|
81
|
+
};
|
|
80
82
|
/**
|
|
81
83
|
* Sets the value of a set of mafia properties
|
|
82
84
|
*
|
|
@@ -120,6 +122,7 @@ export declare function withChoices<T>(choices: {
|
|
|
120
122
|
*/
|
|
121
123
|
export declare function withChoice<T>(choice: number, value: number | string, callback: () => T): T;
|
|
122
124
|
export declare class PropertiesManager {
|
|
125
|
+
private static EMPTY_PREFERENCE;
|
|
123
126
|
private properties;
|
|
124
127
|
get storedValues(): Properties;
|
|
125
128
|
/**
|
|
@@ -158,7 +161,7 @@ export declare class PropertiesManager {
|
|
|
158
161
|
*
|
|
159
162
|
* @param properties Properties for the manager to forget.
|
|
160
163
|
*/
|
|
161
|
-
clear(...properties: KnownProperty[]): void;
|
|
164
|
+
clear(...properties: (KnownProperty | string)[]): void;
|
|
162
165
|
/**
|
|
163
166
|
* Clears all properties.
|
|
164
167
|
*/
|
package/dist/property.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bounty, Class, Coinmaster, Effect, Element, Familiar, getProperty, Item, Location, Monster, Phylum, Servant, setProperty, Skill, Slot, Stat, Thrall, toBounty, toClass, toCoinmaster, toEffect, toElement, toFamiliar, toItem, toLocation, toMonster, toPhylum, toServant, toSkill, toSlot, toStat, toThrall, } from "kolmafia";
|
|
1
|
+
import { Bounty, Class, Coinmaster, Effect, Element, Familiar, getProperty, Item, Location, Monster, Phylum, propertyExists, removeProperty, Servant, setProperty, Skill, Slot, Stat, Thrall, toBounty, toClass, toCoinmaster, toEffect, toElement, toFamiliar, toItem, toLocation, toMonster, toPhylum, toServant, toSkill, toSlot, toStat, toThrall, } from "kolmafia";
|
|
2
2
|
import { isBooleanProperty, isFamiliarProperty, isLocationProperty, isMonsterProperty, isNumericOrStringProperty, isNumericProperty, isPhylumProperty, isStatProperty, isStringProperty, } from "./propertyTyping";
|
|
3
3
|
const createPropertyGetter = (transform) => (property, default_) => {
|
|
4
4
|
const value = getProperty(property);
|
|
@@ -204,6 +204,7 @@ export function withChoice(choice, value, callback) {
|
|
|
204
204
|
return withChoices({ [choice]: value }, callback);
|
|
205
205
|
}
|
|
206
206
|
export class PropertiesManager {
|
|
207
|
+
static EMPTY_PREFERENCE = Symbol("empty preference");
|
|
207
208
|
properties = {};
|
|
208
209
|
get storedValues() {
|
|
209
210
|
return this.properties;
|
|
@@ -215,8 +216,10 @@ export class PropertiesManager {
|
|
|
215
216
|
*/
|
|
216
217
|
set(propertiesToSet) {
|
|
217
218
|
for (const [propertyName, propertyValue] of Object.entries(propertiesToSet)) {
|
|
218
|
-
if (this.properties
|
|
219
|
-
this.properties[propertyName] =
|
|
219
|
+
if (!(propertyName in this.properties)) {
|
|
220
|
+
this.properties[propertyName] = propertyExists(propertyName)
|
|
221
|
+
? get(propertyName)
|
|
222
|
+
: PropertiesManager.EMPTY_PREFERENCE;
|
|
220
223
|
}
|
|
221
224
|
set(propertyName, propertyValue);
|
|
222
225
|
}
|
|
@@ -248,10 +251,18 @@ export class PropertiesManager {
|
|
|
248
251
|
*/
|
|
249
252
|
reset(...properties) {
|
|
250
253
|
for (const property of properties) {
|
|
254
|
+
if (!(property in this.properties))
|
|
255
|
+
continue;
|
|
251
256
|
const value = this.properties[property];
|
|
252
|
-
if (value) {
|
|
257
|
+
if (value === PropertiesManager.EMPTY_PREFERENCE) {
|
|
258
|
+
removeProperty(property);
|
|
259
|
+
}
|
|
260
|
+
else if (value) {
|
|
253
261
|
set(property, value);
|
|
254
262
|
}
|
|
263
|
+
else {
|
|
264
|
+
set(property, "");
|
|
265
|
+
}
|
|
255
266
|
}
|
|
256
267
|
}
|
|
257
268
|
/**
|