Skip to content

Commit

Permalink
Shared package for projects (#67)
Browse files Browse the repository at this point in the history
* Pull projects out into shared code

* Require node >= 18.20 for cross package linking

* Remove libram from projects

* Share projects with web version

* Missing full stop

* Do not prettify build output for web

* Split up long function for monster parts project

* Formatting

* Fix bug in monster parts
  • Loading branch information
gausie authored Apr 9, 2024
1 parent 7b6f279 commit b8193c4
Show file tree
Hide file tree
Showing 32 changed files with 933 additions and 815 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@
"build": "yarn workspace excavator-script run build",
"format": "yarn workspaces run format && yarn prettier --write .github",
"lint": "yarn workspaces run lint && yarn prettier --check .github"
},
"engines": {
"node": ">= 18.20"
}
}
32 changes: 32 additions & 0 deletions packages/excavator-projects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { AUTUMNATON } from "./projects/autumnaton";
import { BIRD_A_DAY } from "./projects/birdADay";
import { COAT_OF_PAINT } from "./projects/coatOfPaint";
import { DROP_CON_SNOWGLOBE } from "./projects/dropConSnowglobe";
import { DROP_MIXED_EVERYTHING } from "./projects/dropMixedEverything";
import { DROP_MR_CHEENGS } from "./projects/dropMrCheengs";
import { DROP_MR_SCREEGES } from "./projects/dropMrScreeges";
import { GENIE } from "./projects/genie";
import { HOOKAH } from "./projects/hookah";
import { JUICE_BAR } from "./projects/juiceBar";
import { MONSTER_PARTS } from "./projects/monsterParts";
import { MUMMING_TRUNK } from "./projects/mummingTrunk";
import { OUT_OF_ORDER } from "./projects/outOfOrder";
import type { ExcavatorProject } from "./type";

export { ExcavatorProject };

export const projects: ExcavatorProject[] = [
AUTUMNATON,
BIRD_A_DAY,
COAT_OF_PAINT,
GENIE,
HOOKAH,
JUICE_BAR,
DROP_CON_SNOWGLOBE,
DROP_MIXED_EVERYTHING,
DROP_MR_CHEENGS,
DROP_MR_SCREEGES,
MONSTER_PARTS,
MUMMING_TRUNK,
OUT_OF_ORDER,
];
20 changes: 20 additions & 0 deletions packages/excavator-projects/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "excavator-projects",
"version": "0.0.0",
"main": "index.js",
"license": "ISC",
"author": "Sam Gaus <sam@gaus.co.uk>",
"scripts": {
"format": "prettier --write .",
"lint": "prettier --check ."
},
"devDependencies": {
"excavator-prettier-config": "^0.0.0",
"prettier": "^3.1.1",
"typescript": "^5.4.3"
},
"prettier": "excavator-prettier-config",
"dependencies": {
"kolmafia": "^5.27896.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
/**
* @author midgleyc
* Determine difficulty level of zones autumnaton is sent to.
*/
import { itemAmount, Location, sessionStorage, toLocation } from "kolmafia";
import { $items, get } from "libram";
import {
getProperty,
Item,
itemAmount,
Location,
sessionStorage,
toLocation,
} from "kolmafia";

import { ExcavatorProject } from "../type";

export const AUTUMNATON: ExcavatorProject = {
name: "Autumnaton",
description: "Determine difficulty level of zones autumnaton is sent to.",
author: "midleyc",
hooks: {
COMBAT_ROUND: (meta: string, page: string) => {
const location = getProperty("autumnatonQuestLocation");
if (location) {
sessionStorage.setItem("lastQuestLocation", location);
}

// If the quest is done, the autumn-aton returns
if (!page.includes("You acquire an item: <b>autumn-aton")) return null;

const lastQuestLocation = sessionStorage.getItem("lastQuestLocation");

// Exit if we don't know where the autumn-aton was sent
if (!lastQuestLocation) {
return null;
}

sessionStorage.removeItem("lastQuestLocation");

return endQuest(lastQuestLocation, page);
},
},
};

const UPGRADE_TO_LOCATION_DETAILS = {
"energy-absorptive hat": "low outdoor",
"high performance right arm": "mid outdoor",
Expand Down Expand Up @@ -75,7 +105,11 @@ function checkItem(location: Location, page: string) {

// If user has meltables, can't be sure as some Mafia envs are wrong
if (
$items`autumn debris shield, autumn leaf pendant, autumn sweater-weather sweater`
Item.get([
"autumn debris shield",
"autumn leaf pendant",
"autumn sweater-weather sweater",
])
.map((i) => itemAmount(i))
.some((q) => q > 0)
)
Expand All @@ -89,7 +123,7 @@ function checkItem(location: Location, page: string) {
if (!acquired) return null;

// If we have a collection prow installed random items can drop, so this work is less useful.
if (get("autumnatonUpgrades").includes("cowcatcher")) return null;
if (getProperty("autumnatonUpgrades").includes("cowcatcher")) return null;

const actual = ITEM_TO_LOCATION_DETAILS[acquired];

Expand All @@ -106,29 +140,3 @@ function endQuest(locationName: string, page: string) {
const location = toLocation(locationName);
return checkUpgrade(location, page) || checkItem(location, page);
}

export const AUTUMNATON: ExcavatorProject = {
name: "Autumnaton",
hooks: {
COMBAT_ROUND: (meta: string, page: string) => {
const location = get("autumnatonQuestLocation");
if (location) {
sessionStorage.setItem("lastQuestLocation", location.toString());
}

// If the quest is done, the autumn-aton returns
if (!page.includes("You acquire an item: <b>autumn-aton")) return null;

const lastQuestLocation = sessionStorage.getItem("lastQuestLocation");

// Exit if we don't know where the autumn-aton was sent
if (!lastQuestLocation) {
return null;
}

sessionStorage.removeItem("lastQuestLocation");

return endQuest(lastQuestLocation, page);
},
},
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
/* @author gausie
* Determine the relationship between Blessing of the Bird modifiers and the day seed
*/
import { numericModifier } from "kolmafia";
import { $effect } from "libram";
import { Effect, numericModifier } from "kolmafia";

import { ExcavatorProject } from "../type";
import { getDaySeed } from "../utils/game";
import { getDaySeed } from "../utils";

export const BIRD_A_DAY: ExcavatorProject = {
name: "Bird-a-Day",
slug: "bird-a-day",
description:
"Determine the relationship between Blessing of the Bird modifiers and the day seed.",
author: "gausie",
hooks: {
CONSUME_REUSABLE: (itemName: string, page: string) => {
if (itemName !== "Bird-a-Day calendar") return null;
if (page.includes("You already read about today's bird.")) return null;

return {
...getBlessingModifiers(),
...getDaySeed(),
};
},
},
};

const BIRD_A_DAY_MODIFIERS = {
stat: ["Muscle Percent", "Mysticaliy Percent", "Moxie Percent"],
Expand All @@ -27,33 +42,18 @@ const BIRD_A_DAY_MODIFIERS = {
bonus: ["HP Regen Min", "Weapon Damage", "Damage Absorption", "MP Regen Min"],
};

const BLESSING = $effect`Blessing of the Bird`;

function getBlessingModifiers() {
const blessing = Effect.get("Blessing of the Bird");

return Object.entries(BIRD_A_DAY_MODIFIERS).reduce(
(data, [type, mods]) => {
const mod = mods.find((m) => numericModifier(BLESSING, m) !== 0);
const mod = mods.find((m) => numericModifier(blessing, m) !== 0);
return {
...data,
[type]: mod || "",
[`${type}_value`]: mod ? String(numericModifier(BLESSING, mod)) : "",
[`${type}_value`]: mod ? String(numericModifier(blessing, mod)) : "",
};
},
{} as Record<string, string>,
);
}

export const BIRD_A_DAY: ExcavatorProject = {
name: "Bird-a-Day",
hooks: {
CONSUME_REUSABLE: (itemName: string, page: string) => {
if (itemName !== "Bird-a-Day calendar") return null;
if (page.includes("You already read about today's bird.")) return null;

return {
...getBlessingModifiers(),
...getDaySeed(),
};
},
},
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
/**
* @author Phillammon
* Determine the relationship between Fresh Coat of Paint modifiers and the day seed
*/
import { numericModifier, sessionStorage } from "kolmafia";
import { $item, get } from "libram";
import { Item, getProperty, numericModifier, sessionStorage } from "kolmafia";

import { ExcavatorProject } from "../type";
import { getDaySeed, getDifficultySeed } from "../utils/game";
import { getDaySeed, getDifficultySeed } from "../utils";

export const COAT_OF_PAINT: ExcavatorProject = {
name: "Fresh Coat of Paint",
description:
"Determine the relationship between Fresh Coat of Paint modifiers and the day seed.",
author: "Phillammon",
hooks: {
DESC_ITEM: (itemName: string, page: string) => {
if (itemName !== Item.get("fresh coat of paint").name) return null;
const mod = getProperty("_coatOfPaintModifier");
if (mod === "") return null;

// Avoid sending the same data multiple times per session
if (sessionStorage.getItem("reportedCoatOfPaintMod") === mod) return null;
sessionStorage.setItem("reportedCoatOfPaintMod", mod);

return {
...getPaintModifiers(page),
...getDaySeed(),
...getDifficultySeed(),
};
},
},
};

const COAT_OF_PAINT_MODIFIERS = {
stat_experience: [
Expand Down Expand Up @@ -37,13 +56,13 @@ function getPaintModifiers(page: string) {
const paintMods = Object.entries(COAT_OF_PAINT_MODIFIERS).reduce(
(data, [type, mods]) => {
const mod = mods.find(
(m) => numericModifier($item`fresh coat of paint`, m) !== 0,
(m) => numericModifier(Item.get("fresh coat of paint"), m) !== 0,
);
return {
...data,
[type]: mod || "",
[`${type}_value`]: mod
? String(numericModifier($item`fresh coat of paint`, mod))
? String(numericModifier(Item.get("fresh coat of paint"), mod))
: "",
};
},
Expand All @@ -56,24 +75,3 @@ function getPaintModifiers(page: string) {

return paintMods;
}

export const COAT_OF_PAINT: ExcavatorProject = {
name: "Fresh Coat of Paint",
hooks: {
DESC_ITEM: (itemName: string, page: string) => {
if (itemName !== $item`fresh coat of paint`.name) return null;
const mod = get("_coatOfPaintModifier");
if (mod === "") return null;

// Avoid sending the same data multiple times per session
if (sessionStorage.getItem("reportedCoatOfPaintMod") === mod) return null;
sessionStorage.setItem("reportedCoatOfPaintMod", mod);

return {
...getPaintModifiers(page),
...getDaySeed(),
...getDifficultySeed(),
};
},
},
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
/**
* @author rinn
* Track drops from the KoL Con 13 snowglobe
*/
import "core-js/modules/es.string.match-all";
import { currentRound, equippedAmount, Item } from "kolmafia";
import { $item } from "libram";

import { ExcavatorProject } from "../type";
import { toNormalisedString } from "../utils/game";
import { toNormalisedString } from "../utils";

export const DROP_CON_SNOWGLOBE: ExcavatorProject = {
name: "KoL Con 13 Snowglobe",
slug: "snowglobe",
description: "Track drops from the KoL Con 13 snowglobe.",
author: "Rinn",
hooks: {
COMBAT_ROUND: spadeSnowglobe,
},
};

type Indicator = { type: "substat" | "item"; pattern: RegExp };

Expand Down Expand Up @@ -69,7 +75,7 @@ function spadeSnowglobe(
// Must be end of battle
if (currentRound() !== 0) return null;
// Must be wearing KoL Con 13 snowglobe
if (equippedAmount($item`KoL Con 13 snowglobe`) < 1) return null;
if (equippedAmount(Item.get("KoL Con 13 snowglobe")) < 1) return null;

const data = [];

Expand All @@ -79,7 +85,7 @@ function spadeSnowglobe(
let str = "";
if (indicator.type === "item") {
const item = Item.get(match[1]);
str = item !== $item`none` ? toNormalisedString(item) : match[1];
str = item !== Item.none ? toNormalisedString(item) : match[1];
}
data.push({
type: indicator.type,
Expand All @@ -90,10 +96,3 @@ function spadeSnowglobe(

return data;
}

export const DROP_CON_SNOWGLOBE: ExcavatorProject = {
name: "KoL Con 13 Snowglobe",
hooks: {
COMBAT_ROUND: spadeSnowglobe,
},
};
Loading

0 comments on commit b8193c4

Please sign in to comment.