data-of-loathing 1.0.0

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.
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadEffects = exports.EffectQuality = void 0;
13
+ const utils_1 = require("../utils");
14
+ var EffectQuality;
15
+ (function (EffectQuality) {
16
+ EffectQuality["Good"] = "good";
17
+ EffectQuality["Neutral"] = "neutral";
18
+ EffectQuality["Bad"] = "bad";
19
+ })(EffectQuality || (exports.EffectQuality = EffectQuality = {}));
20
+ const isValidQuality = (0, utils_1.isMemberOfEnum)(EffectQuality);
21
+ const parseEffect = (parts) => ({
22
+ id: Number(parts[0]),
23
+ name: parts[1],
24
+ image: parts[2],
25
+ descid: parts[3],
26
+ quality: isValidQuality(parts[4]) ? parts[4] : EffectQuality.Neutral,
27
+ attributes: parts[5]
28
+ .split(",")
29
+ .map((p) => p.trim())
30
+ .filter((p) => p !== "none"),
31
+ actions: parts[6].split("|"),
32
+ });
33
+ const loadEffects = (lastKnownSize) => __awaiter(void 0, void 0, void 0, function* () {
34
+ const raw = yield (0, utils_1.loadMafiaData)("statuseffects", lastKnownSize);
35
+ if (raw === null)
36
+ return null;
37
+ return Object.assign(Object.assign({}, raw), { data: raw.data.filter((p) => p.length > 2).map(parseEffect) });
38
+ });
39
+ exports.loadEffects = loadEffects;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const vitest_1 = require("vitest");
13
+ const effects_1 = require("./effects");
14
+ const testUtils_1 = require("../testUtils");
15
+ global.fetch = vitest_1.vi.fn();
16
+ (0, vitest_1.test)("Can read effects", () => __awaiter(void 0, void 0, void 0, function* () {
17
+ vitest_1.vi.mocked(fetch).mockResolvedValue((0, testUtils_1.createFetchResponse)("1\n5\tFar Out\tfarout.gif\t5ad503e9df2df73bfbbb5377b622c8c4\tgood\tnone\tuse 1 patchouli incense stick"));
18
+ const effects = yield (0, effects_1.loadEffects)();
19
+ (0, testUtils_1.expectNotNull)(effects);
20
+ (0, vitest_1.expect)(effects.data.length).toBe(1);
21
+ const effect = effects.data[0];
22
+ (0, vitest_1.expect)(effect).toMatchObject({
23
+ id: 5,
24
+ name: "Far Out",
25
+ image: "farout.gif",
26
+ descid: "5ad503e9df2df73bfbbb5377b622c8c4",
27
+ attributes: [],
28
+ quality: "good",
29
+ actions: ["use 1 patchouli incense stick"],
30
+ });
31
+ }));
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadFamiliars = exports.isOwnable = exports.FamiliarType = void 0;
13
+ const utils_1 = require("../utils");
14
+ var FamiliarType;
15
+ (function (FamiliarType) {
16
+ FamiliarType["Stat0"] = "stat0";
17
+ FamiliarType["Stat1"] = "stat1";
18
+ FamiliarType["Item0"] = "item0";
19
+ FamiliarType["Item1"] = "item1";
20
+ FamiliarType["Item2"] = "item2";
21
+ FamiliarType["Item3"] = "item3";
22
+ FamiliarType["Meat0"] = "meat0";
23
+ FamiliarType["Combat0"] = "combat0";
24
+ FamiliarType["Combat1"] = "combat1";
25
+ FamiliarType["Drop"] = "drop";
26
+ FamiliarType["Block"] = "block";
27
+ FamiliarType["Delevel"] = "delevel";
28
+ FamiliarType["Hp0"] = "hp0";
29
+ FamiliarType["Mp0"] = "mp0";
30
+ FamiliarType["Meat1"] = "meat1";
31
+ FamiliarType["Stat2"] = "stat2";
32
+ FamiliarType["Other0"] = "other0";
33
+ FamiliarType["Hp1"] = "hp1";
34
+ FamiliarType["Mp1"] = "mp1";
35
+ FamiliarType["Stat3"] = "stat3";
36
+ FamiliarType["Other1"] = "other1";
37
+ FamiliarType["Passive"] = "passive";
38
+ FamiliarType["Underwater"] = "underwater";
39
+ FamiliarType["Variable"] = "variable";
40
+ })(FamiliarType || (exports.FamiliarType = FamiliarType = {}));
41
+ const isValidType = (0, utils_1.isMemberOfEnum)(FamiliarType);
42
+ const isOwnable = ({ id }) => {
43
+ // April Fools familiars
44
+ if (id >= 125 && id < 134)
45
+ return false;
46
+ // Pokefams
47
+ if (id >= 215 && id < 260)
48
+ return false;
49
+ return true;
50
+ };
51
+ exports.isOwnable = isOwnable;
52
+ const parseFamiliar = (parts) => {
53
+ var _a, _b;
54
+ return ({
55
+ id: Number(parts[0]),
56
+ name: parts[1],
57
+ image: parts[2],
58
+ types: parts[3]
59
+ .split(",")
60
+ .map((p) => p.trim())
61
+ .filter(isValidType),
62
+ larva: parts[4],
63
+ equipment: parts[5] || null,
64
+ arenaStats: {
65
+ cageMatch: Number(parts[6]),
66
+ scavengerHunt: Number(parts[7]),
67
+ obstacleCourse: Number(parts[8]),
68
+ hideAndSeek: Number(parts[9]),
69
+ },
70
+ attributes: (_b = (_a = parts[10]) === null || _a === void 0 ? void 0 : _a.split(",")) !== null && _b !== void 0 ? _b : [],
71
+ });
72
+ };
73
+ const loadFamiliars = (lastKnownSize) => __awaiter(void 0, void 0, void 0, function* () {
74
+ const raw = yield (0, utils_1.loadMafiaData)("familiars", lastKnownSize);
75
+ if (raw === null)
76
+ return null;
77
+ return Object.assign(Object.assign({}, raw), { data: raw.data.filter((p) => p.length > 2).map(parseFamiliar) });
78
+ });
79
+ exports.loadFamiliars = loadFamiliars;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const vitest_1 = require("vitest");
13
+ const testUtils_1 = require("../testUtils");
14
+ const familiars_1 = require("./familiars");
15
+ global.fetch = vitest_1.vi.fn();
16
+ (0, vitest_1.test)("Can read familiars", () => __awaiter(void 0, void 0, void 0, function* () {
17
+ vitest_1.vi.mocked(fetch).mockResolvedValue((0, testUtils_1.createFetchResponse)("1\n7\tSpooky Pirate Skeleton\tfamiliar7.gif\tcombat1,delevel\tspooky pirate skeleton\tblundarrrbus\t2\t3\t1\t0\thashands,haseyes,undead,cantalk"));
18
+ const familiars = yield (0, familiars_1.loadFamiliars)();
19
+ (0, testUtils_1.expectNotNull)(familiars);
20
+ (0, vitest_1.expect)(familiars.data.length).toBe(1);
21
+ const familiar = familiars.data[0];
22
+ (0, vitest_1.expect)(familiar).toMatchObject({
23
+ id: 7,
24
+ name: "Spooky Pirate Skeleton",
25
+ image: "familiar7.gif",
26
+ types: [familiars_1.FamiliarType.Combat1, familiars_1.FamiliarType.Delevel],
27
+ larva: "spooky pirate skeleton",
28
+ equipment: "blundarrrbus",
29
+ arenaStats: {
30
+ cageMatch: 2,
31
+ hideAndSeek: 0,
32
+ obstacleCourse: 1,
33
+ scavengerHunt: 3,
34
+ },
35
+ attributes: ["hashands", "haseyes", "undead", "cantalk"],
36
+ });
37
+ }));
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadItems = exports.ItemUse = void 0;
13
+ const utils_1 = require("../utils");
14
+ var ItemUse;
15
+ (function (ItemUse) {
16
+ // Primary
17
+ ItemUse["Food"] = "food";
18
+ ItemUse["Drink"] = "drink";
19
+ ItemUse["Spleen"] = "spleen";
20
+ ItemUse["Potion"] = "potion";
21
+ ItemUse["Avatar"] = "avatar";
22
+ ItemUse["Usable"] = "usable";
23
+ ItemUse["Multiple"] = "multiple";
24
+ ItemUse["Reusable"] = "reusable";
25
+ ItemUse["Message"] = "message";
26
+ ItemUse["Grow"] = "grow";
27
+ ItemUse["PokePill"] = "pokepill";
28
+ ItemUse["Hat"] = "hat";
29
+ ItemUse["Weapon"] = "weapon";
30
+ ItemUse["Sixgun"] = "sixgun";
31
+ ItemUse["Offhand"] = "offhand";
32
+ ItemUse["Container"] = "container";
33
+ ItemUse["Shirt"] = "shirt";
34
+ ItemUse["Pants"] = "pants";
35
+ ItemUse["Accessory"] = "accessory";
36
+ ItemUse["Familiar"] = "familiar";
37
+ ItemUse["Sticker"] = "sticker";
38
+ ItemUse["Card"] = "card";
39
+ ItemUse["Folder"] = "folder";
40
+ ItemUse["Bootspur"] = "bootspur";
41
+ ItemUse["Bootskin"] = "bootskin";
42
+ ItemUse["FoodHelper"] = "food helper";
43
+ ItemUse["DrinkHelper"] = "drink helper";
44
+ ItemUse["Zap"] = "zap";
45
+ ItemUse["Sphere"] = "sphere";
46
+ ItemUse["Guardian"] = "guardian";
47
+ // Secondary
48
+ ItemUse["Combat"] = "combat";
49
+ ItemUse["CombatReusable"] = "combat reusable";
50
+ ItemUse["Single"] = "single";
51
+ ItemUse["Solo"] = "solo";
52
+ ItemUse["Curse"] = "curse";
53
+ ItemUse["Bounty"] = "bounty";
54
+ ItemUse["Package"] = "package";
55
+ ItemUse["Candy"] = "candy";
56
+ ItemUse["Candy1"] = "candy1";
57
+ ItemUse["Candy2"] = "candy2";
58
+ ItemUse["Chocolate"] = "chocolate";
59
+ ItemUse["Fancy"] = "fancy";
60
+ ItemUse["Paste"] = "paste";
61
+ ItemUse["Smith"] = "smith";
62
+ ItemUse["Cook"] = "cook";
63
+ ItemUse["Mix"] = "mix";
64
+ ItemUse["Matchable"] = "matchable";
65
+ })(ItemUse || (exports.ItemUse = ItemUse = {}));
66
+ const isValidItemUse = (0, utils_1.isMemberOfEnum)(ItemUse);
67
+ const parseAccess = (accessString) => {
68
+ const access = accessString.split(",").map((p) => p.trim());
69
+ return {
70
+ quest: access.includes("q"),
71
+ gift: access.includes("g"),
72
+ tradeable: access.includes("t"),
73
+ discardable: access.includes("d"),
74
+ };
75
+ };
76
+ const parseItem = (parts) => (Object.assign(Object.assign({ id: Number(parts[0]), name: parts[1], descid: parts[2], image: parts[3], uses: parts[4].split(", ").filter(isValidItemUse) }, parseAccess(parts[5])), { autosell: Number(parts[6]), plural: parts[7] }));
77
+ const loadItems = (lastKnownSize) => __awaiter(void 0, void 0, void 0, function* () {
78
+ const raw = yield (0, utils_1.loadMafiaData)("items", lastKnownSize);
79
+ if (raw === null)
80
+ return null;
81
+ return Object.assign(Object.assign({}, raw), { data: raw.data.filter((p) => p.length > 2).map(parseItem) });
82
+ });
83
+ exports.loadItems = loadItems;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const vitest_1 = require("vitest");
13
+ const testUtils_1 = require("../testUtils");
14
+ const items_1 = require("./items");
15
+ global.fetch = vitest_1.vi.fn();
16
+ (0, vitest_1.test)("Can read items", () => __awaiter(void 0, void 0, void 0, function* () {
17
+ vitest_1.vi.mocked(fetch).mockResolvedValue((0, testUtils_1.createFetchResponse)("1\n87\tmeat from yesterday\t653772183\tmeat.gif\tnone, paste\tt,d\t5\tmeats from yesterday"));
18
+ const items = yield (0, items_1.loadItems)();
19
+ (0, testUtils_1.expectNotNull)(items);
20
+ (0, vitest_1.expect)(items.data.length).toBe(1);
21
+ const item = items.data[0];
22
+ (0, vitest_1.expect)(item).toMatchObject({
23
+ id: 87,
24
+ name: "meat from yesterday",
25
+ descid: "653772183",
26
+ image: "meat.gif",
27
+ uses: [items_1.ItemUse.Paste],
28
+ quest: false,
29
+ gift: false,
30
+ tradeable: true,
31
+ discardable: true,
32
+ autosell: 5,
33
+ plural: "meats from yesterday",
34
+ });
35
+ }));
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadOutfits = void 0;
13
+ const utils_1 = require("../utils");
14
+ const parseEquipment = (equipmentList = "") => equipmentList.trim().split(", ");
15
+ const parseTreats = (treatList = "") => treatList
16
+ .trim()
17
+ .split(", ")
18
+ .filter((t) => t !== "none")
19
+ .map((treat) => {
20
+ const m = treat.match(/^(.*?) \((\d*\.?\d+)\)$/);
21
+ if (!m)
22
+ return { item: treat, chance: 1 };
23
+ return { item: m[1], chance: Number(m[2]) };
24
+ });
25
+ const parseOutfit = (parts) => {
26
+ var _a, _b;
27
+ return ({
28
+ id: Number(parts[0]),
29
+ name: parts[1],
30
+ image: parts[2],
31
+ equipment: parseEquipment((_a = parts[3]) !== null && _a !== void 0 ? _a : ""),
32
+ treats: parseTreats(parts[0] === "80" ? "double-ice gum" : (_b = parts[4]) !== null && _b !== void 0 ? _b : ""),
33
+ });
34
+ };
35
+ const loadOutfits = (lastKnownSize) => __awaiter(void 0, void 0, void 0, function* () {
36
+ const raw = yield (0, utils_1.loadMafiaData)("outfits", lastKnownSize);
37
+ if (raw === null)
38
+ return null;
39
+ return Object.assign(Object.assign({}, raw), { data: raw.data.filter((p) => p.length > 2).map(parseOutfit) });
40
+ });
41
+ exports.loadOutfits = loadOutfits;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const vitest_1 = require("vitest");
13
+ const testUtils_1 = require("../testUtils");
14
+ const outfits_1 = require("./outfits");
15
+ global.fetch = vitest_1.vi.fn();
16
+ (0, vitest_1.test)("Can read items", () => __awaiter(void 0, void 0, void 0, function* () {
17
+ vitest_1.vi.mocked(fetch).mockResolvedValue((0, testUtils_1.createFetchResponse)("1\n35\tBlack Armaments\tblacktat.gif\tblack helmet, black sword, black shield, black greaves\tblack pudding (0.16), Blackfly Chardonnay (0.16), black & tan (0.16), black pepper (0.16), black forest cake (0.16), black forest ham (0.16)"));
18
+ const outfits = yield (0, outfits_1.loadOutfits)();
19
+ (0, testUtils_1.expectNotNull)(outfits);
20
+ (0, vitest_1.expect)(outfits.data.length).toBe(1);
21
+ const outfit = outfits.data[0];
22
+ (0, vitest_1.expect)(outfit).toMatchObject({
23
+ id: 35,
24
+ name: "Black Armaments",
25
+ image: "blacktat.gif",
26
+ equipment: ["black helmet", "black sword", "black shield", "black greaves"],
27
+ treats: [
28
+ { item: "black pudding", chance: 0.16 },
29
+ { item: "Blackfly Chardonnay", chance: 0.16 },
30
+ { item: "black & tan", chance: 0.16 },
31
+ { item: "black pepper", chance: 0.16 },
32
+ { item: "black forest cake", chance: 0.16 },
33
+ { item: "black forest ham", chance: 0.16 },
34
+ ],
35
+ });
36
+ }));
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadSkills = exports.isPermable = exports.getMaxLevel = exports.SkillType = void 0;
13
+ const utils_1 = require("../utils");
14
+ var SkillType;
15
+ (function (SkillType) {
16
+ SkillType[SkillType["Passive"] = 0] = "Passive";
17
+ SkillType[SkillType["NoncombatItemSummon"] = 1] = "NoncombatItemSummon";
18
+ SkillType[SkillType["NoncombatHealing"] = 2] = "NoncombatHealing";
19
+ SkillType[SkillType["NoncombatNonShruggableEffect"] = 3] = "NoncombatNonShruggableEffect";
20
+ SkillType[SkillType["NoncombatShruggableEffect"] = 4] = "NoncombatShruggableEffect";
21
+ SkillType[SkillType["Combat"] = 5] = "Combat";
22
+ SkillType[SkillType["OneAtATimeNoncombatSong"] = 6] = "OneAtATimeNoncombatSong";
23
+ SkillType[SkillType["CombatNoncombatHealing"] = 7] = "CombatNoncombatHealing";
24
+ SkillType[SkillType["CombatPassive"] = 8] = "CombatPassive";
25
+ SkillType[SkillType["OneAtATimeNoncombatExpression"] = 9] = "OneAtATimeNoncombatExpression";
26
+ SkillType[SkillType["OneAtATimeNoncombatWalk"] = 10] = "OneAtATimeNoncombatWalk";
27
+ SkillType[SkillType["NoncombatHealingPassive"] = 11] = "NoncombatHealingPassive";
28
+ })(SkillType || (exports.SkillType = SkillType = {}));
29
+ const isValidType = (0, utils_1.isMemberOfEnum)(SkillType);
30
+ const getMaxLevel = ({ id }) => {
31
+ switch (id) {
32
+ // Will probably be this way forever
33
+ // Slimy Sinews
34
+ case 46:
35
+ return 10;
36
+ // Slimy Synapes
37
+ case 47:
38
+ return 10;
39
+ // Slimy Shoulders
40
+ case 48:
41
+ return 10;
42
+ // Summon Annoyance
43
+ case 107:
44
+ return 9;
45
+ // Belch The Rainbow
46
+ case 117:
47
+ return 11;
48
+ // Implode Universe
49
+ case 188:
50
+ return 13;
51
+ // Will change in future
52
+ // Pirate Bellow
53
+ case 118:
54
+ return 7;
55
+ // Summon Holiday Fun
56
+ case 121:
57
+ return 6;
58
+ // Summon Carrot
59
+ case 128:
60
+ return 6;
61
+ // Bear Essence
62
+ case 134:
63
+ return 6;
64
+ // Summon Kokomo Resort Pass
65
+ case 135:
66
+ return 2;
67
+ // Calculate the Universe
68
+ case 144:
69
+ return 5;
70
+ // Experience Safari
71
+ case 180:
72
+ return 4;
73
+ // Toggle Optimality
74
+ case 7254:
75
+ return 3;
76
+ default:
77
+ return 0;
78
+ }
79
+ };
80
+ exports.getMaxLevel = getMaxLevel;
81
+ const isPermable = ({ id }) => {
82
+ // Random old skills
83
+ if (id < 10)
84
+ return false;
85
+ // Bad Moon
86
+ if (id > 20 && id <= 27)
87
+ return false;
88
+ // Way of the Surprising Fist skills
89
+ if (id > 63 && id <= 73)
90
+ return false;
91
+ // Spirit derived skills
92
+ if (id > 7175 && id < 7181)
93
+ return false;
94
+ switch (id) {
95
+ // VIP lounge skills
96
+ case 91: // Dog Tired
97
+ case 116: // Hollow Leg
98
+ return false;
99
+ // Nemesis skills
100
+ case 49: // Gothy Handwave
101
+ case 50: // Break It On Down
102
+ case 51: // Pop and Lock
103
+ case 52: // Run Like the Wind
104
+ case 3024: // Carboloading
105
+ return false;
106
+ case 6019: // Gemlli's March of Testery
107
+ return false;
108
+ // Other skills from this class are not permable
109
+ case 17047: // Mild Curs
110
+ return true;
111
+ // Avatar of West of Loathing skills
112
+ case 156: // Shoot
113
+ return false;
114
+ // Not permable but granted every ascension
115
+ case 174: // Incrdible Self-Estem
116
+ return false;
117
+ // S.I.T. Course certificate skills
118
+ case 218: // Cryptobotanist
119
+ case 219: // Insectologist
120
+ case 220: // Psychogeologist
121
+ return false;
122
+ // Replica skills
123
+ case 222: // Replica Emotionally Chipped
124
+ return false;
125
+ // Permable from PvP
126
+ case 7254: // Toggle Optimality
127
+ return true;
128
+ }
129
+ switch (Math.floor(id / 1000)) {
130
+ case 7: // Skills granted by items
131
+ case 8: // Mystical Bookshelf Skills
132
+ case 11: // Avatar of Boris skills
133
+ case 12: // Zombie Slayer skills
134
+ case 14: // Avatar of Jarlsberg skills
135
+ case 15: // Avatar of Sneaky Pete skills
136
+ case 16: // Heavy Rains skills
137
+ case 17: // Ed skills
138
+ case 18: // Cow Puncher skills
139
+ case 19: // Bean Slinger skills
140
+ case 20: // Snake Oiler skills
141
+ case 21: // The Source skills
142
+ case 22: // Nuclear Autumn skills
143
+ case 23: // Gelatinous Noob skills
144
+ case 24: // Vampyre skills
145
+ case 25: // Plumber skills
146
+ case 27: // Grey Goo skills
147
+ case 28: // AoSOL; Pig Skinner skills
148
+ case 29: // AoSOL; Cheese Wizard skills
149
+ case 30: // AoSOL; Jazz Agent skills
150
+ return false;
151
+ }
152
+ return true;
153
+ };
154
+ exports.isPermable = isPermable;
155
+ const parseSkill = (parts) => ({
156
+ id: Number(parts[0]),
157
+ name: parts[1],
158
+ image: parts[2],
159
+ type: isValidType(Number(parts[3])) ? Number(parts[3]) : SkillType.Passive,
160
+ mpCost: Number(parts[4]),
161
+ duration: Number(parts[5]),
162
+ level: parts[6] ? Number(parts[6]) : 0,
163
+ });
164
+ const loadSkills = (lastKnownSize) => __awaiter(void 0, void 0, void 0, function* () {
165
+ const raw = yield (0, utils_1.loadMafiaData)("classskills", lastKnownSize);
166
+ if (raw === null)
167
+ return null;
168
+ return Object.assign(Object.assign({}, raw), { data: raw.data.filter((p) => p.length > 2).map(parseSkill) });
169
+ });
170
+ exports.loadSkills = loadSkills;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const vitest_1 = require("vitest");
13
+ const testUtils_1 = require("../testUtils");
14
+ const skills_1 = require("./skills");
15
+ global.fetch = vitest_1.vi.fn();
16
+ (0, vitest_1.test)("Can read items", () => __awaiter(void 0, void 0, void 0, function* () {
17
+ vitest_1.vi.mocked(fetch).mockResolvedValue((0, testUtils_1.createFetchResponse)("1\n3035\tBind Penne Dreadful\tt_dreadful.gif\t3\t150\t0\t11"));
18
+ const skills = yield (0, skills_1.loadSkills)();
19
+ (0, testUtils_1.expectNotNull)(skills);
20
+ (0, vitest_1.expect)(skills.data.length).toBe(1);
21
+ const skill = skills.data[0];
22
+ (0, vitest_1.expect)(skill).toMatchObject({
23
+ id: 3035,
24
+ name: "Bind Penne Dreadful",
25
+ image: "t_dreadful.gif",
26
+ type: skills_1.SkillType.NoncombatNonShruggableEffect,
27
+ mpCost: 150,
28
+ duration: 0,
29
+ level: 11,
30
+ });
31
+ }));
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Skill = exports.Outfit = exports.Item = exports.Familiar = exports.Effect = void 0;
27
+ exports.Effect = __importStar(require("./entityTypes/effects"));
28
+ exports.Familiar = __importStar(require("./entityTypes/familiars"));
29
+ exports.Item = __importStar(require("./entityTypes/items"));
30
+ exports.Outfit = __importStar(require("./entityTypes/outfits"));
31
+ exports.Skill = __importStar(require("./entityTypes/skills"));
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.expectNotNull = exports.createFetchResponse = void 0;
4
+ const vitest_1 = require("vitest");
5
+ function createFetchResponse(data) {
6
+ return {
7
+ json: () => new Promise((resolve) => resolve(JSON.parse(data))),
8
+ text: () => new Promise((resolve) => resolve(data)),
9
+ headers: new Headers({ "Content-Length": String(data.length) }),
10
+ };
11
+ }
12
+ exports.createFetchResponse = createFetchResponse;
13
+ function expectNotNull(val) {
14
+ (0, vitest_1.expect)(val).toBeDefined();
15
+ }
16
+ exports.expectNotNull = expectNotNull;
package/dist/utils.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.isMemberOfEnum = exports.arrayOf = exports.tuple = exports.loadMafiaData = void 0;
13
+ const MAFIA_DATA_BASE = "https://raw.githubusercontent.com/kolmafia/kolmafia/main/src/data";
14
+ function loadMafiaData(fileName, lastKnownSize = 0) {
15
+ var _a;
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ const url = `${MAFIA_DATA_BASE}/${fileName}.txt`;
18
+ if (lastKnownSize > 0) {
19
+ const sizeCheck = yield fetch(url, { method: "HEAD" });
20
+ const newSize = Number((_a = sizeCheck.headers.get("Content-Length")) !== null && _a !== void 0 ? _a : 1);
21
+ if (newSize === lastKnownSize)
22
+ return null;
23
+ }
24
+ const request = yield fetch(url);
25
+ const raw = yield request.text();
26
+ return {
27
+ data: raw
28
+ .split("\n")
29
+ .slice(1)
30
+ .filter((r) => r !== "" && !r.startsWith("#"))
31
+ .map((r) => r.split("\t")),
32
+ size: Number(request.headers.get("Content-Length")),
33
+ };
34
+ });
35
+ }
36
+ exports.loadMafiaData = loadMafiaData;
37
+ const tuple = (args) => args;
38
+ exports.tuple = tuple;
39
+ const arrayOf = (items) => Array.isArray(items) ? items : [items];
40
+ exports.arrayOf = arrayOf;
41
+ const isMemberOfEnum = (e) => (token) => Object.values(e).includes(token);
42
+ exports.isMemberOfEnum = isMemberOfEnum;
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "data-of-loathing",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "author": "Sam Gaus <sam@gaus.co.uk>",
9
+ "license": "MIT",
10
+ "devDependencies": {
11
+ "@types/node": "^20.8.7",
12
+ "@typescript-eslint/eslint-plugin": "^6.8.0",
13
+ "@typescript-eslint/parser": "^6.8.0",
14
+ "eslint": "^8.52.0",
15
+ "eslint-config-prettier": "^9.0.0",
16
+ "prettier": "^3.0.3",
17
+ "typescript": "^5.2.2",
18
+ "vitest": "^0.34.6"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "format": "prettier --write .",
23
+ "prepack": "yarn run build",
24
+ "test": "vitest"
25
+ },
26
+ "packageManager": "yarn@4.0.0"
27
+ }