libram 0.8.28 → 0.8.29
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.d.ts +128 -0
- package/dist/Clan.js +300 -0
- package/dist/Copier.d.ts +9 -0
- package/dist/Copier.js +15 -0
- package/dist/Dungeon.d.ts +45 -0
- package/dist/Dungeon.js +115 -0
- package/dist/Kmail.d.ts +133 -0
- package/dist/Kmail.js +259 -0
- package/dist/actions/ActionSource.d.ts +131 -0
- package/dist/actions/ActionSource.js +178 -0
- package/dist/actions/Banish.d.ts +16 -0
- package/dist/actions/Banish.js +121 -0
- package/dist/actions/FreeKill.d.ts +16 -0
- package/dist/actions/FreeKill.js +94 -0
- package/dist/actions/FreeRun.d.ts +16 -0
- package/dist/actions/FreeRun.js +81 -0
- package/dist/actions/index.d.ts +4 -0
- package/dist/actions/index.js +4 -0
- package/dist/ascend.d.ts +83 -0
- package/dist/ascend.js +268 -0
- package/dist/challengePaths/2014/HeavyRains.d.ts +22 -0
- package/dist/challengePaths/2014/HeavyRains.js +75 -0
- package/dist/challengePaths/2015/CommunityService.d.ts +125 -0
- package/dist/challengePaths/2015/CommunityService.js +334 -0
- package/dist/challengePaths/2016/NuclearAutumn.d.ts +13 -0
- package/dist/challengePaths/2016/NuclearAutumn.js +21 -0
- package/dist/challengePaths/index.d.ts +4 -0
- package/dist/challengePaths/index.js +4 -0
- package/dist/combat.d.ts +414 -0
- package/dist/combat.js +711 -0
- package/dist/console.d.ts +12 -0
- package/dist/console.js +14 -0
- package/dist/counter.d.ts +22 -0
- package/dist/counter.js +37 -0
- package/dist/diet/index.d.ts +80 -0
- package/dist/diet/index.js +680 -0
- package/dist/diet/knapsack.d.ts +8 -0
- package/dist/diet/knapsack.js +128 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +26 -0
- package/dist/lib.d.ts +507 -0
- package/dist/lib.js +970 -0
- package/dist/logger.d.ts +35 -0
- package/dist/logger.js +62 -0
- package/dist/maximize.d.ts +122 -0
- package/dist/maximize.js +531 -0
- package/dist/modifier.d.ts +41 -0
- package/dist/modifier.js +160 -0
- package/dist/modifierTypes.d.ts +16 -0
- package/dist/modifierTypes.js +9 -0
- package/dist/mood.d.ts +105 -0
- package/dist/mood.js +349 -0
- package/dist/moonSign.d.ts +13 -0
- package/dist/moonSign.js +25 -0
- package/dist/overlappingNames.d.ts +3 -0
- package/dist/overlappingNames.js +42 -0
- package/dist/property.d.ts +222 -0
- package/dist/property.js +385 -0
- package/dist/propertyTypes.d.ts +19 -0
- package/dist/propertyTypes.js +10 -0
- package/dist/propertyTyping.d.ts +65 -0
- package/dist/propertyTyping.js +91 -0
- package/dist/resources/2007/CandyHearts.d.ts +9 -0
- package/dist/resources/2007/CandyHearts.js +24 -0
- package/dist/resources/2008/DivineFavors.d.ts +9 -0
- package/dist/resources/2008/DivineFavors.js +27 -0
- package/dist/resources/2008/Stickers.d.ts +49 -0
- package/dist/resources/2008/Stickers.js +84 -0
- package/dist/resources/2009/Bandersnatch.d.ts +56 -0
- package/dist/resources/2009/Bandersnatch.js +93 -0
- package/dist/resources/2009/LoveSongs.d.ts +9 -0
- package/dist/resources/2009/LoveSongs.js +24 -0
- package/dist/resources/2009/SpookyPutty.d.ts +31 -0
- package/dist/resources/2009/SpookyPutty.js +49 -0
- package/dist/resources/2010/Brickos.d.ts +9 -0
- package/dist/resources/2010/Brickos.js +21 -0
- package/dist/resources/2010/CrownOfThrones.d.ts +68 -0
- package/dist/resources/2010/CrownOfThrones.js +418 -0
- package/dist/resources/2010/LookingGlass.d.ts +29 -0
- package/dist/resources/2010/LookingGlass.js +89 -0
- package/dist/resources/2011/Gygaxian.d.ts +9 -0
- package/dist/resources/2011/Gygaxian.js +24 -0
- package/dist/resources/2011/ObtuseAngel.d.ts +33 -0
- package/dist/resources/2011/ObtuseAngel.js +51 -0
- package/dist/resources/2011/StompingBoots.d.ts +37 -0
- package/dist/resources/2011/StompingBoots.js +57 -0
- package/dist/resources/2012/RainDoh.d.ts +25 -0
- package/dist/resources/2012/RainDoh.js +37 -0
- package/dist/resources/2012/ReagnimatedGnome.d.ts +31 -0
- package/dist/resources/2012/ReagnimatedGnome.js +46 -0
- package/dist/resources/2012/Resolutions.d.ts +9 -0
- package/dist/resources/2012/Resolutions.js +28 -0
- package/dist/resources/2013/Florist.d.ts +81 -0
- package/dist/resources/2013/Florist.js +245 -0
- package/dist/resources/2013/JungMan.d.ts +33 -0
- package/dist/resources/2013/JungMan.js +69 -0
- package/dist/resources/2013/PulledTaffy.d.ts +9 -0
- package/dist/resources/2013/PulledTaffy.js +33 -0
- package/dist/resources/2014/CrimboShrub.d.ts +42 -0
- package/dist/resources/2014/CrimboShrub.js +89 -0
- package/dist/resources/2014/DNALab.d.ts +56 -0
- package/dist/resources/2014/DNALab.js +162 -0
- package/dist/resources/2014/WinterGarden.d.ts +23 -0
- package/dist/resources/2014/WinterGarden.js +35 -0
- package/dist/resources/2015/BarrelShrine.d.ts +8 -0
- package/dist/resources/2015/BarrelShrine.js +25 -0
- package/dist/resources/2015/ChateauMantegna.d.ts +52 -0
- package/dist/resources/2015/ChateauMantegna.js +99 -0
- package/dist/resources/2015/DeckOfEveryCard.d.ts +29 -0
- package/dist/resources/2015/DeckOfEveryCard.js +122 -0
- package/dist/resources/2015/Dinseylandfill.d.ts +89 -0
- package/dist/resources/2015/Dinseylandfill.js +205 -0
- package/dist/resources/2015/MayoClinic.d.ts +23 -0
- package/dist/resources/2015/MayoClinic.js +49 -0
- package/dist/resources/2016/GingerBread.d.ts +32 -0
- package/dist/resources/2016/GingerBread.js +73 -0
- package/dist/resources/2016/SourceTerminal.d.ts +181 -0
- package/dist/resources/2016/SourceTerminal.js +275 -0
- package/dist/resources/2016/Witchess.d.ts +17 -0
- package/dist/resources/2016/Witchess.js +47 -0
- package/dist/resources/2017/AsdonMartin.d.ts +59 -0
- package/dist/resources/2017/AsdonMartin.js +238 -0
- package/dist/resources/2017/Horsery.d.ts +19 -0
- package/dist/resources/2017/Horsery.js +42 -0
- package/dist/resources/2017/MummingTrunk.d.ts +8 -0
- package/dist/resources/2017/MummingTrunk.js +33 -0
- package/dist/resources/2017/Pantogram.d.ts +92 -0
- package/dist/resources/2017/Pantogram.js +174 -0
- package/dist/resources/2017/Robortender.d.ts +30 -0
- package/dist/resources/2017/Robortender.js +90 -0
- package/dist/resources/2017/Spacegate.d.ts +86 -0
- package/dist/resources/2017/Spacegate.js +178 -0
- package/dist/resources/2017/TunnelOfLove.d.ts +39 -0
- package/dist/resources/2017/TunnelOfLove.js +120 -0
- package/dist/resources/2018/LatteLoversMembersMug.d.ts +392 -0
- package/dist/resources/2018/LatteLoversMembersMug.js +303 -0
- package/dist/resources/2018/SongBoom.d.ts +33 -0
- package/dist/resources/2018/SongBoom.js +55 -0
- package/dist/resources/2019/BeachComb.d.ts +72 -0
- package/dist/resources/2019/BeachComb.js +118 -0
- package/dist/resources/2019/CampAway.d.ts +39 -0
- package/dist/resources/2019/CampAway.js +72 -0
- package/dist/resources/2019/Snapper.d.ts +33 -0
- package/dist/resources/2019/Snapper.js +73 -0
- package/dist/resources/2020/Cartography.d.ts +16 -0
- package/dist/resources/2020/Cartography.js +48 -0
- package/dist/resources/2020/Guzzlr.d.ts +160 -0
- package/dist/resources/2020/Guzzlr.js +275 -0
- package/dist/resources/2020/RetroCape.d.ts +51 -0
- package/dist/resources/2020/RetroCape.js +115 -0
- package/dist/resources/2021/CrystalBall.d.ts +14 -0
- package/dist/resources/2021/CrystalBall.js +41 -0
- package/dist/resources/2021/DaylightShavings.d.ts +40 -0
- package/dist/resources/2021/DaylightShavings.js +74 -0
- package/dist/resources/2022/AutumnAton.d.ts +78 -0
- package/dist/resources/2022/AutumnAton.js +182 -0
- package/dist/resources/2022/CombatLoversLocket.d.ts +44 -0
- package/dist/resources/2022/CombatLoversLocket.js +82 -0
- package/dist/resources/2022/GreyGoose.d.ts +59 -0
- package/dist/resources/2022/GreyGoose.js +90 -0
- package/dist/resources/2022/JuneCleaver.d.ts +47 -0
- package/dist/resources/2022/JuneCleaver.js +69 -0
- package/dist/resources/2022/TrainSet.d.ts +146 -0
- package/dist/resources/2022/TrainSet.js +228 -0
- package/dist/resources/2023/AugustScepter.d.ts +25 -0
- package/dist/resources/2023/AugustScepter.js +40 -0
- package/dist/resources/2023/BurningLeaves.d.ts +25 -0
- package/dist/resources/2023/BurningLeaves.js +74 -0
- package/dist/resources/2023/CinchoDeMayo.d.ts +25 -0
- package/dist/resources/2023/CinchoDeMayo.js +45 -0
- package/dist/resources/2023/ClosedCircuitPayphone.d.ts +80 -0
- package/dist/resources/2023/ClosedCircuitPayphone.js +129 -0
- package/dist/resources/2023/CursedMonkeyPaw.d.ts +46 -0
- package/dist/resources/2023/CursedMonkeyPaw.js +113 -0
- package/dist/resources/2024/AprilingBandHelmet.d.ts +57 -0
- package/dist/resources/2024/AprilingBandHelmet.js +118 -0
- package/dist/resources/2024/ChestMimic.d.ts +42 -0
- package/dist/resources/2024/ChestMimic.js +125 -0
- package/dist/resources/LibramSummon.d.ts +18 -0
- package/dist/resources/LibramSummon.js +74 -0
- package/dist/resources/index.d.ts +54 -0
- package/dist/resources/index.js +54 -0
- package/dist/resources/putty-likes.d.ts +21 -0
- package/dist/resources/putty-likes.js +33 -0
- package/dist/session.d.ts +169 -0
- package/dist/session.js +284 -0
- package/dist/since.d.ts +51 -0
- package/dist/since.js +108 -0
- package/dist/template-string.d.ts +324 -0
- package/dist/template-string.js +265 -0
- package/dist/url.d.ts +35 -0
- package/dist/url.js +67 -0
- package/dist/utils.d.ts +178 -0
- package/dist/utils.js +255 -0
- package/package.json +2 -2
package/dist/ascend.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { eudoraItem, getCampground, Item, Path, use, visitUrl, xpath, haveSkill, getPermedSkills, toSkill, } from "kolmafia";
|
|
2
|
+
import { signNameToId } from "./moonSign";
|
|
3
|
+
import { get } from "./property";
|
|
4
|
+
import { ChateauMantegna } from "./resources";
|
|
5
|
+
import { $item, $items, $stat } from "./template-string";
|
|
6
|
+
import { arrayContains, tc } from "./utils";
|
|
7
|
+
export var Lifestyle;
|
|
8
|
+
(function (Lifestyle) {
|
|
9
|
+
Lifestyle[Lifestyle["casual"] = 1] = "casual";
|
|
10
|
+
Lifestyle[Lifestyle["softcore"] = 2] = "softcore";
|
|
11
|
+
Lifestyle[Lifestyle["normal"] = 2] = "normal";
|
|
12
|
+
Lifestyle[Lifestyle["hardcore"] = 3] = "hardcore";
|
|
13
|
+
})(Lifestyle || (Lifestyle = {}));
|
|
14
|
+
export var KolGender;
|
|
15
|
+
(function (KolGender) {
|
|
16
|
+
KolGender[KolGender["male"] = 1] = "male";
|
|
17
|
+
KolGender[KolGender["female"] = 2] = "female";
|
|
18
|
+
})(KolGender || (KolGender = {}));
|
|
19
|
+
/**
|
|
20
|
+
* Get a mapping of permed skills to the extent to which they're permed.
|
|
21
|
+
*
|
|
22
|
+
* If a skill is not permed at all, it will not appear in the mapping.
|
|
23
|
+
*
|
|
24
|
+
* @returns Permed skills mapping
|
|
25
|
+
*/
|
|
26
|
+
export function permedSkills() {
|
|
27
|
+
return new Map(Array.from(Object.entries(getPermedSkills())).map(([skillName, isHardcore]) => [
|
|
28
|
+
toSkill(skillName),
|
|
29
|
+
isHardcore ? Lifestyle.hardcore : Lifestyle.softcore,
|
|
30
|
+
]));
|
|
31
|
+
}
|
|
32
|
+
export class AscendError extends Error {
|
|
33
|
+
}
|
|
34
|
+
const gardens = [
|
|
35
|
+
"packet of pumpkin seeds",
|
|
36
|
+
"Peppermint Pip Packet",
|
|
37
|
+
"packet of dragon's teeth",
|
|
38
|
+
"packet of beer seeds",
|
|
39
|
+
"packet of winter seeds",
|
|
40
|
+
"packet of thanksgarden seeds",
|
|
41
|
+
"packet of tall grass seeds",
|
|
42
|
+
"packet of mushroom spores",
|
|
43
|
+
"packet of rock seeds",
|
|
44
|
+
];
|
|
45
|
+
const eudorae = [
|
|
46
|
+
"My Own Pen Pal kit",
|
|
47
|
+
"GameInformPowerDailyPro subscription card",
|
|
48
|
+
"Xi Receiver Unit",
|
|
49
|
+
"New-You Club Membership Form",
|
|
50
|
+
"Our Daily Candles™ order form",
|
|
51
|
+
];
|
|
52
|
+
const isGarden = (x) => arrayContains(x, gardens);
|
|
53
|
+
const isEudora = (x) => arrayContains(x, eudorae);
|
|
54
|
+
const isDesk = (x) => arrayContains(x, ChateauMantegna.desks);
|
|
55
|
+
const isNightstand = (x) => arrayContains(x, ChateauMantegna.nightstands);
|
|
56
|
+
const isCeiling = (x) => arrayContains(x, ChateauMantegna.ceilings);
|
|
57
|
+
export class AscensionPrepError extends Error {
|
|
58
|
+
cause;
|
|
59
|
+
constructor(cause, original) {
|
|
60
|
+
if (isGarden(cause)) {
|
|
61
|
+
super(`Unable to swap garden to ${cause}; garden is currently ${original}.`);
|
|
62
|
+
}
|
|
63
|
+
else if (isEudora(cause)) {
|
|
64
|
+
super(`Unable to swap eudora to ${cause}; eudora is currently ${original}.`);
|
|
65
|
+
}
|
|
66
|
+
else if (isDesk(cause)) {
|
|
67
|
+
super(`Unable to swap chateau desk to ${cause}; desk is currently ${original}.`);
|
|
68
|
+
}
|
|
69
|
+
else if (isNightstand(cause)) {
|
|
70
|
+
super(`Unable to swap chateau nightstand to ${cause}; nightstand is currently ${original}.`);
|
|
71
|
+
}
|
|
72
|
+
else if (isCeiling(cause)) {
|
|
73
|
+
super(`Unable to swap chateau ceiling to ${cause}; ceiling is currently ${original}.`);
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
super(cause);
|
|
77
|
+
this.cause = cause;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Determine the id of the appropriate moon sign.
|
|
82
|
+
*
|
|
83
|
+
* @param moon Either a moon sign or the desired unlocked zone name
|
|
84
|
+
* @param playerClass Class, required for working out a moon sign based on the desired zone
|
|
85
|
+
* @returns Moon sign id
|
|
86
|
+
*/
|
|
87
|
+
function inputToMoonId(moon, playerClass) {
|
|
88
|
+
if (typeof moon === "number")
|
|
89
|
+
return moon;
|
|
90
|
+
const offset = () => {
|
|
91
|
+
switch (playerClass.primestat) {
|
|
92
|
+
case $stat `Muscle`:
|
|
93
|
+
return 0;
|
|
94
|
+
case $stat `Mysticality`:
|
|
95
|
+
return 1;
|
|
96
|
+
case $stat `Moxie`:
|
|
97
|
+
return 2;
|
|
98
|
+
default:
|
|
99
|
+
throw new AscendError(`unknown prime stat for ${playerClass}`);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const fromNormalInput = signNameToId(tc(moon));
|
|
103
|
+
if (fromNormalInput > 0)
|
|
104
|
+
return fromNormalInput;
|
|
105
|
+
switch (moon.toLowerCase()) {
|
|
106
|
+
case "degrassi":
|
|
107
|
+
case "degrassi knoll":
|
|
108
|
+
case "friendly degrassi knoll":
|
|
109
|
+
case "knoll":
|
|
110
|
+
return 1 + offset();
|
|
111
|
+
case "canada":
|
|
112
|
+
case "canadia":
|
|
113
|
+
case "little canadia":
|
|
114
|
+
return 4 + offset();
|
|
115
|
+
case "gnomads":
|
|
116
|
+
case "gnomish":
|
|
117
|
+
case "gnomish gnomads camp":
|
|
118
|
+
return 7 + offset();
|
|
119
|
+
default:
|
|
120
|
+
throw new AscendError("Invalid moon sign!");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Determine if player is currently in Valhalla
|
|
125
|
+
*
|
|
126
|
+
* @returns Whether player is in Valhalla
|
|
127
|
+
*/
|
|
128
|
+
function isInValhalla() {
|
|
129
|
+
const charPaneText = visitUrl("charpane.php");
|
|
130
|
+
// Match the infinity images (inf_small.gif, inf_large.gif)
|
|
131
|
+
// At time of writing, the full img tag used is:
|
|
132
|
+
// <img src="https://d2uyhvukfffg5a.cloudfront.net/otherimages/inf_small.gif">
|
|
133
|
+
const matches = charPaneText.match(/<img src="[^"]*\/otherimages\/inf_\w+\.gif">/);
|
|
134
|
+
return matches !== null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Hops the gash, perming no skills by default
|
|
138
|
+
*
|
|
139
|
+
* @param options Configuration for the ascension
|
|
140
|
+
* @param options.path Your path of choice for this ascension
|
|
141
|
+
* @param options.playerClass Your class of choice for this ascension
|
|
142
|
+
* @param options.lifestyle 1 for casual, 2 for softcore, 3 for hardcore. Alternately, use the Lifestyle enum
|
|
143
|
+
* @param options.kolGender An entry from the KolGender enum: 1 for male, 2 for female (sorry that it's limited to those). Defaults to 2 or the corresponding value for defaultGenderOverride pref (which should be 'male' or 'female')
|
|
144
|
+
* @param options.moon Your moon sign as a string, or the zone you're looking for as a string
|
|
145
|
+
* @param options.consumable From the astral deli. Pick the container item, not the product. Defaults to astral six-pack, provide $item`none` for nothing.
|
|
146
|
+
* @param options.pet From the astral pet store.
|
|
147
|
+
* @param options.permOptions Options for perming during a player's stay in Valhalla
|
|
148
|
+
* @param options.permOptions.permSkills A Map<Skill, Lifestyle> of skills you'd like to perm, ordered by priority.
|
|
149
|
+
* @param options.permOptions.neverAbort Whether the ascension should abort on failure
|
|
150
|
+
*/
|
|
151
|
+
export function ascend(options) {
|
|
152
|
+
const DEFAULT_OPTIONS = {
|
|
153
|
+
kolGender: get("defaultGenderOverride", "female") === "male"
|
|
154
|
+
? KolGender.male
|
|
155
|
+
: KolGender.female,
|
|
156
|
+
consumable: $item `astral six-pack`,
|
|
157
|
+
pet: $item `none`,
|
|
158
|
+
};
|
|
159
|
+
const prunedOptions = Object.fromEntries(Object.entries(options).filter(([, value]) => value));
|
|
160
|
+
const { path, playerClass, lifestyle, kolGender, moon, consumable, pet, permOptions, } = { ...DEFAULT_OPTIONS, ...prunedOptions };
|
|
161
|
+
if (playerClass.path !== (path.avatar ? path : Path.none)) {
|
|
162
|
+
throw new AscendError(`Invalid class ${playerClass} for this path!`);
|
|
163
|
+
}
|
|
164
|
+
if (path.id < 0)
|
|
165
|
+
throw new AscendError(`Invalid path: ${path}!`);
|
|
166
|
+
const moonId = inputToMoonId(moon, playerClass);
|
|
167
|
+
if (moonId < 1 || moonId > 9)
|
|
168
|
+
throw new Error(`Invalid moon ${moon}`);
|
|
169
|
+
if (!$items `none, astral six-pack, astral hot dog dinner, [10882]carton of astral energy drinks`.includes(consumable)) {
|
|
170
|
+
throw new AscendError(`Invalid astral consumable: ${consumable}`);
|
|
171
|
+
}
|
|
172
|
+
if (!$items `none, astral bludgeon, astral shield, astral chapeau, astral bracer, astral longbow, astral shorts, astral mace, astral trousers, astral ring, astral statuette, astral pistol, astral mask, astral pet sweater, astral shirt, astral belt`.includes(pet)) {
|
|
173
|
+
throw new AscendError(`Invalid astral pet: ${pet}`);
|
|
174
|
+
}
|
|
175
|
+
const unownedSkills = [...(permOptions?.permSkills.keys() ?? [])].filter((skill) => !haveSkill(skill));
|
|
176
|
+
if (unownedSkills.length) {
|
|
177
|
+
throw new AscendError(`You're trying to perm the following skills, but don't actually have them: ${unownedSkills.join(", ")}`);
|
|
178
|
+
}
|
|
179
|
+
const unpermableSkills = [...(permOptions?.permSkills.keys() ?? [])].filter((skill) => !skill.permable);
|
|
180
|
+
if (unpermableSkills.length) {
|
|
181
|
+
throw new AscendError(`You're trying to perm the following skills, but they're unpermable: ${unownedSkills.join(", ")}`);
|
|
182
|
+
}
|
|
183
|
+
if (!isInValhalla()) {
|
|
184
|
+
visitUrl("ascend.php?action=ascend&confirm=on&confirm2=on");
|
|
185
|
+
}
|
|
186
|
+
if (!isInValhalla()) {
|
|
187
|
+
throw new AscendError("Failed to ascend--do you have a pending trade offer?");
|
|
188
|
+
}
|
|
189
|
+
visitUrl("afterlife.php?action=pearlygates");
|
|
190
|
+
if (consumable !== $item `none`) {
|
|
191
|
+
visitUrl(`afterlife.php?action=buydeli&whichitem=${consumable.id}`);
|
|
192
|
+
}
|
|
193
|
+
if (pet !== $item `none`) {
|
|
194
|
+
visitUrl(`afterlife.php?action=buyarmory&whichitem=${pet.id}`);
|
|
195
|
+
}
|
|
196
|
+
if (permOptions) {
|
|
197
|
+
const currentPerms = permedSkills();
|
|
198
|
+
let karma = get("bankedKarma");
|
|
199
|
+
for (const [skill, prospectivePermLevel,] of permOptions.permSkills.entries()) {
|
|
200
|
+
const currentPermLevel = currentPerms.get(skill) ?? Lifestyle.casual;
|
|
201
|
+
if (prospectivePermLevel > currentPermLevel) {
|
|
202
|
+
const expectedKarma = 100 * (prospectivePermLevel - currentPermLevel);
|
|
203
|
+
if (karma < expectedKarma) {
|
|
204
|
+
if (!permOptions.neverAbort)
|
|
205
|
+
throw new AscendError(`Skill ${skill} is too karmaically expensive!`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
karma -= expectedKarma;
|
|
209
|
+
const permText = prospectivePermLevel === Lifestyle.hardcore ? "hcperm" : "scperm";
|
|
210
|
+
visitUrl(`afterlife.php?action=${permText}&whichskill=${skill.id}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
visitUrl(`afterlife.php?action=ascend&confirmascend=1&whichsign=${moonId}&gender=${kolGender}&whichclass=${playerClass.id}&whichpath=${path.id}&asctype=${lifestyle}&nopetok=1&noskillsok=1&lamepathok=1&lamesignok=1&pwd`, true);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Sets up various iotms you may want to use in the coming ascension
|
|
218
|
+
*
|
|
219
|
+
* @param ascensionPrep Configuration for various ascension prep settings. Any ommitted key will be kept as-is
|
|
220
|
+
* @param ascensionPrep.garden Garden to which to switch
|
|
221
|
+
* @param ascensionPrep.eudora Eudora to which to switch
|
|
222
|
+
* @param ascensionPrep.chateau Chateau configuration
|
|
223
|
+
* @param ascensionPrep.chateau.desk Chateau desk configuration
|
|
224
|
+
* @param ascensionPrep.chateau.ceiling Chateau ceiling configuration
|
|
225
|
+
* @param ascensionPrep.chateau.nightstand Chateau nightstand configuration
|
|
226
|
+
* @param ascensionPrep.throwOnFail If true, this will throw an error when it fails to switch something
|
|
227
|
+
*/
|
|
228
|
+
export function prepareAscension({ garden, eudora, chateau, throwOnFail, } = {}) {
|
|
229
|
+
throwOnFail = throwOnFail ?? true;
|
|
230
|
+
if (garden && !Object.getOwnPropertyNames(getCampground()).includes(garden)) {
|
|
231
|
+
use(Item.get(garden));
|
|
232
|
+
const gardenName = Object.getOwnPropertyNames(getCampground()).find(isGarden);
|
|
233
|
+
if (gardenName !== garden && throwOnFail) {
|
|
234
|
+
throw new AscensionPrepError(garden, gardenName);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (eudora && eudoraItem().name !== eudora) {
|
|
238
|
+
const eudoraNumber = 1 + eudorae.indexOf(eudora);
|
|
239
|
+
if (!xpath(visitUrl("account.php?tab=correspondence"), `//select[@name="whichpenpal"]/option/@value`).includes(eudoraNumber.toString()) &&
|
|
240
|
+
throwOnFail) {
|
|
241
|
+
throw new AscensionPrepError(`Unable to swap eudora to ${eudora} because you are not subscribed to it.`);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
visitUrl(`account.php?actions[]=whichpenpal&whichpenpal=${eudoraNumber}&action=Update`, true);
|
|
245
|
+
}
|
|
246
|
+
if (eudoraItem() !== Item.get(eudora) && throwOnFail) {
|
|
247
|
+
throw new AscensionPrepError(eudora, eudoraItem());
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (chateau && ChateauMantegna.have()) {
|
|
251
|
+
const { desk, ceiling, nightstand } = chateau;
|
|
252
|
+
if (ceiling && ChateauMantegna.getCeiling() !== ceiling) {
|
|
253
|
+
if (!ChateauMantegna.changeCeiling(ceiling) && throwOnFail) {
|
|
254
|
+
throw new AscensionPrepError(ceiling, ChateauMantegna.getCeiling() ?? "unknown");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (desk && ChateauMantegna.getDesk() !== desk) {
|
|
258
|
+
if (!ChateauMantegna.changeDesk(desk) && throwOnFail) {
|
|
259
|
+
throw new AscensionPrepError(desk, ChateauMantegna.getDesk() ?? "unknown");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (nightstand && ChateauMantegna.getNightstand() !== nightstand) {
|
|
263
|
+
if (!ChateauMantegna.changeNightstand(nightstand) && throwOnFail) {
|
|
264
|
+
throw new AscensionPrepError(nightstand, ChateauMantegna.getNightstand() ?? "unknown");
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Location, Monster } from "kolmafia";
|
|
2
|
+
/**
|
|
3
|
+
* Cast Rain Man and fight the target monster
|
|
4
|
+
* @param target the monster to fight
|
|
5
|
+
*/
|
|
6
|
+
export declare function rainMan(target: Monster): void;
|
|
7
|
+
/**
|
|
8
|
+
* Check if you can summon this monster using Rain Man
|
|
9
|
+
* @param target the monster to attempt to summon
|
|
10
|
+
* @returns true if you can summon the target monster, false otherwise
|
|
11
|
+
*/
|
|
12
|
+
export declare function canRainMan(target: Monster): boolean;
|
|
13
|
+
export declare const RAIN_MONSTER_WINDOW_BEGIN = "Rain Monster window begin";
|
|
14
|
+
export declare const RAIN_MONSTER_WINDOW_END = "Rain Monster window end";
|
|
15
|
+
export declare const wanderers: readonly Monster[];
|
|
16
|
+
/**
|
|
17
|
+
* Calculate the expected wandering monster based on current water level
|
|
18
|
+
* @param location the location to check for wanderers
|
|
19
|
+
* @returns The monster for this location given the current waterlevel
|
|
20
|
+
*/
|
|
21
|
+
export declare function expectedWanderer(location: Location): Monster;
|
|
22
|
+
export declare const path: import("kolmafia").Path;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Modifier, Monster, monsterFactoidsAvailable, myRain, numericModifier, useSkill, visitUrl, } from "kolmafia";
|
|
2
|
+
import { have } from "../../lib";
|
|
3
|
+
import { withChoice } from "../../property";
|
|
4
|
+
import { $monster, $path, $skill } from "../../template-string";
|
|
5
|
+
/**
|
|
6
|
+
* Cast Rain Man and fight the target monster
|
|
7
|
+
* @param target the monster to fight
|
|
8
|
+
*/
|
|
9
|
+
export function rainMan(target) {
|
|
10
|
+
if (canRainMan(target)) {
|
|
11
|
+
withChoice(970, `1&whichmonster=${target.id}`, () => useSkill($skill `Rain Man`));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Check if you can summon this monster using Rain Man
|
|
16
|
+
* @param target the monster to attempt to summon
|
|
17
|
+
* @returns true if you can summon the target monster, false otherwise
|
|
18
|
+
*/
|
|
19
|
+
export function canRainMan(target) {
|
|
20
|
+
if (!have($skill `Rain Man`) || // having the skill implies you are in heavy rains path
|
|
21
|
+
myRain() < 50 ||
|
|
22
|
+
!target.copyable ||
|
|
23
|
+
target.id < 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (monsterFactoidsAvailable(target, false) > 0) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const page = withChoice(970, 2, () => visitUrl(`runskillz.php?pwd&action=Skillz&whichskill=${$skill `Rain Man`.id}&quantity=1`));
|
|
30
|
+
return page.indexOf(`<option value=${target.id}>`) > 0;
|
|
31
|
+
}
|
|
32
|
+
export const RAIN_MONSTER_WINDOW_BEGIN = "Rain Monster window begin";
|
|
33
|
+
export const RAIN_MONSTER_WINDOW_END = "Rain Monster window end";
|
|
34
|
+
export const wanderers = Object.freeze(Monster.get([
|
|
35
|
+
"giant isopod",
|
|
36
|
+
"gourmet gourami",
|
|
37
|
+
"freshwater bonefish",
|
|
38
|
+
"alley catfish",
|
|
39
|
+
"piranhadon",
|
|
40
|
+
"giant tardigrade",
|
|
41
|
+
"aquaconda",
|
|
42
|
+
"storm cow",
|
|
43
|
+
]));
|
|
44
|
+
/**
|
|
45
|
+
* Calculate the expected wandering monster based on current water level
|
|
46
|
+
* @param location the location to check for wanderers
|
|
47
|
+
* @returns The monster for this location given the current waterlevel
|
|
48
|
+
*/
|
|
49
|
+
export function expectedWanderer(location) {
|
|
50
|
+
const difficultyWaterLevel = location.difficultyLevel === "low" ? 1 : 2;
|
|
51
|
+
const environmentWaterLevel = location.environment === "underground"
|
|
52
|
+
? 4
|
|
53
|
+
: location.environment === "indoor"
|
|
54
|
+
? 2
|
|
55
|
+
: 1; // location.environment === "unknown" || "outdoors"
|
|
56
|
+
const waterLevel = numericModifier(Modifier.get("Water Level")) +
|
|
57
|
+
difficultyWaterLevel +
|
|
58
|
+
environmentWaterLevel;
|
|
59
|
+
if (waterLevel > 1 && waterLevel < 6) {
|
|
60
|
+
return wanderers[waterLevel - 1];
|
|
61
|
+
}
|
|
62
|
+
else if (waterLevel === 6 && location.environment === "underground") {
|
|
63
|
+
return $monster `giant tardigrade`;
|
|
64
|
+
}
|
|
65
|
+
else if (waterLevel === 6 && location.environment === "indoor") {
|
|
66
|
+
return $monster `aquaconda`;
|
|
67
|
+
}
|
|
68
|
+
else if (waterLevel === 6 && location.environment === "outdoor") {
|
|
69
|
+
return $monster `storm cow`;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
return $monster `giant isopod`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export const path = $path `Heavy Rains`;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Effect } from "kolmafia";
|
|
2
|
+
import { Requirement } from "../../maximize";
|
|
3
|
+
export default class CommunityService {
|
|
4
|
+
private choice;
|
|
5
|
+
private stat;
|
|
6
|
+
private property;
|
|
7
|
+
private predictor;
|
|
8
|
+
private maximizeRequirements;
|
|
9
|
+
private timer;
|
|
10
|
+
/**
|
|
11
|
+
* Class to store properties of various CS tests.
|
|
12
|
+
*
|
|
13
|
+
* @param id The id the game HTML uses to identify the test; this is used primarily in runChoice.
|
|
14
|
+
* @param stat The principle stat the test measures, often used as more easily memorable shorthand for the specific tests
|
|
15
|
+
* @param property The name of the test as a string, often used as part of the string property "csServicesPerformed".
|
|
16
|
+
* @param predictor A function that returns an estimate for the number of turns that the test will take given your character's current state.
|
|
17
|
+
* @param maximizeRequirements A Requirement object, if applicable, that aligns with the things needed to maximize for this particular test.
|
|
18
|
+
*/
|
|
19
|
+
private constructor();
|
|
20
|
+
/**
|
|
21
|
+
* @returns The id number of the test, used primarily in runChoice.
|
|
22
|
+
*/
|
|
23
|
+
get id(): number;
|
|
24
|
+
/**
|
|
25
|
+
* @returns The primary stat the test measures, used primarily as memorable shorthand in place of test names.
|
|
26
|
+
*/
|
|
27
|
+
get statName(): string;
|
|
28
|
+
/**
|
|
29
|
+
* @returns The name of the test, used primarily as part of the string property "csServicesPerformed"
|
|
30
|
+
*/
|
|
31
|
+
get name(): string;
|
|
32
|
+
/**
|
|
33
|
+
* @returns The predicted number of turns this test will take given your character's current state.
|
|
34
|
+
*/
|
|
35
|
+
get prediction(): number;
|
|
36
|
+
/**
|
|
37
|
+
* @returns A Requirement object, if applicable, that aligns with the things needed to maximize for this particular test.
|
|
38
|
+
*/
|
|
39
|
+
get requirement(): Requirement | null;
|
|
40
|
+
/**
|
|
41
|
+
* Start the time & turn counter for the Test in question.
|
|
42
|
+
*/
|
|
43
|
+
startTimer(): void;
|
|
44
|
+
private static taskTimers;
|
|
45
|
+
/**
|
|
46
|
+
* Start the time & turn counter for the given task
|
|
47
|
+
*
|
|
48
|
+
* @param name The name of the task to start the counter of
|
|
49
|
+
*/
|
|
50
|
+
static startTimer(name: string): void;
|
|
51
|
+
static logTask(name: string, action: () => number | void): void;
|
|
52
|
+
/**
|
|
53
|
+
* Checks the "csServicesPerformed" property to see whether mafia currently believes this test is complete.
|
|
54
|
+
*
|
|
55
|
+
* @returns Whether mafia currently believes this test is complete.
|
|
56
|
+
*/
|
|
57
|
+
isDone(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Maximizes based on the Requirement associated with this particular test.
|
|
60
|
+
*/
|
|
61
|
+
maximize(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Attempts to turn in the test to the Council of Loathing.
|
|
64
|
+
*
|
|
65
|
+
* @returns Whether mafia believes the test is complete at the end of this function.
|
|
66
|
+
*/
|
|
67
|
+
do(): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Wrapper function that prepares for a test and then completes it, adding time and turn details to the log.
|
|
70
|
+
*
|
|
71
|
+
* @param prepare A function that does all necessary preparations for this CS test, including choosing your outfit. Optionally returns the number of turns you expect to spend preparing for the test.
|
|
72
|
+
* @param maxTurns We will run the test iff the predicted/actual turns is less than or equal to this parameter.
|
|
73
|
+
* @returns "completed", "failed", or "already completed".
|
|
74
|
+
*/
|
|
75
|
+
run(prepare: () => void | number, maxTurns?: number): "completed" | "failed" | "already completed";
|
|
76
|
+
private _verifyIsDone;
|
|
77
|
+
/**
|
|
78
|
+
* Checks council.php to verify that a test is complete; more reliable than isDone, but requires an additional pagehit.
|
|
79
|
+
*
|
|
80
|
+
* @returns Whether council.php suggests that the test is complete.
|
|
81
|
+
*/
|
|
82
|
+
verifyIsDone(): boolean;
|
|
83
|
+
private _actualCost;
|
|
84
|
+
/**
|
|
85
|
+
* Checks council.php for the number of turns this test will take; more reliable than prediction, but requires an additional pagehit.
|
|
86
|
+
*
|
|
87
|
+
* @returns The number of turns to complete this test according to council.php.
|
|
88
|
+
*/
|
|
89
|
+
actualCost(): number;
|
|
90
|
+
/**
|
|
91
|
+
* @param effects A spread array of Effects to consider
|
|
92
|
+
* @returns The number of turns we expect to save if we start using those effects
|
|
93
|
+
*/
|
|
94
|
+
turnsSavedBy(...effects: Effect[]): number;
|
|
95
|
+
/**
|
|
96
|
+
* A log of the predicted turns, actual turns, and duration of each CS test performed.
|
|
97
|
+
*/
|
|
98
|
+
static log: {
|
|
99
|
+
[index: string]: {
|
|
100
|
+
predictedTurns: number;
|
|
101
|
+
turnCost: number;
|
|
102
|
+
seconds: number;
|
|
103
|
+
type: "test" | "task";
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Prints turncount and time details of the test in question.
|
|
108
|
+
*
|
|
109
|
+
* @param colour The colour (or color) you'd like the log to be printed in.
|
|
110
|
+
*/
|
|
111
|
+
static printLog(colour?: string): void;
|
|
112
|
+
static HP: CommunityService;
|
|
113
|
+
static Muscle: CommunityService;
|
|
114
|
+
static Mysticality: CommunityService;
|
|
115
|
+
static Moxie: CommunityService;
|
|
116
|
+
static FamiliarWeight: CommunityService;
|
|
117
|
+
static WeaponDamage: CommunityService;
|
|
118
|
+
static SpellDamage: CommunityService;
|
|
119
|
+
static Noncombat: CommunityService;
|
|
120
|
+
static BoozeDrop: CommunityService;
|
|
121
|
+
static HotRes: CommunityService;
|
|
122
|
+
static CoilWire: CommunityService;
|
|
123
|
+
static donate: () => void;
|
|
124
|
+
static path: import("kolmafia").Path;
|
|
125
|
+
}
|