diff --git a/fish.test.ts b/fish.test.ts deleted file mode 100644 index 58984166d7..0000000000 --- a/fish.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Bank } from 'oldschooljs'; -import { describe, it } from 'vitest'; - -import { Gear } from '../../../src/lib/structures/Gear'; -import { fishCommand } from '../../../src/mahoji/commands/fish'; -import { testRunCmd } from '../utils'; - -describe('Fish Command', () => { - it('should handle insufficient fishing level', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'Trout/Salmon', quantity: 1 }, - result: '<:minion:778418736180494347> Your minion needs 20 Fishing to fish Trout/Salmon.' - }); - }); - - it('should handle insufficient QP', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'karambwanji', quantity: 1 }, - user: { skills_fishing: 9_999_999, QP: 0 }, - result: 'You need 15 qp to catch those!' - }); - }); - - it('should handle invalid fish', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'asdf' }, - result: 'Thats not a valid fish to catch.' - }); - }); - - it('should handle insufficient barb fishing levels', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'Barbarian fishing' }, - user: { skills_fishing: 1 }, - result: '<:minion:778418736180494347> Your minion needs 48 Fishing to fish Barbarian fishing.' - }); - }); - - it('should fish', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'Shrimps/Anchovies' }, - result: "<:minion:778418736180494347> Your minion is now fishing Shrimps/Anchovies, it'll take around 30 minutes to finish" - }); - }); - - it('should catch insufficient feathers', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'Barbarian fishing' }, - user: { - skills_fishing: 999_999, - skills_agility: 999_999, - skills_strength: 999_999, - meleeGear: new Gear({ weapon: 'Pearl barbarian rod' }) - }, - result: 'You need Feather to fish Barbarian fishing!' - }); - }); - - it('should boost', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'Barbarian fishing' }, - user: { - skills_fishing: 999_999, - skills_agility: 999_999, - skills_strength: 999_999, - bank: new Bank().add('Feather', 1000) - }, - result: `<:minion:778418736180494347> Your minion is now fishing 100x Barbarian fishing, it'll take around 6 minutes, 1 second to finish. - -**Boosts:** 5% for Pearl barbarian rod.` - }); - }); - - it('should fish barrel boost', () => { - testRunCmd({ - cmd: fishCommand, - opts: { name: 'shrimps' }, - user: { - skills_fishing: 999_999, - meleeGear: new Gear({ cape: 'Fish sack barrel' }) - }, - result: `<:minion:778418736180494347> Your minion is now fishing Shrimps/Anchovies, it'll take around 39 minutes, 1 second to finish. - - **Boosts:** +9 trip minutes and +28 inventory slots for having a Fish sack barrel.` - }); - }); -}); diff --git a/fish.ts b/fish.ts deleted file mode 100644 index 552dfa698b..0000000000 --- a/fish.ts +++ /dev/null @@ -1,398 +0,0 @@ -import { stringMatches } from '@oldschoolgg/toolkit'; -import type { CommandRunOptions } from '@oldschoolgg/toolkit'; -import { ApplicationCommandOptionType } from 'discord.js'; -import { Time } from 'e'; -import { Bank } from 'oldschooljs'; -import TzTokJad from 'oldschooljs/dist/simulation/monsters/special/TzTokJad'; -import { WildernessDiary, userhasDiaryTier } from '../../lib/diaries'; - -import Fishing from '../../lib/skilling/skills/fishing'; -import { Fish, SkillsEnum } from '../../lib/skilling/types'; -import type { FishingActivityTaskOptions } from '../../lib/types/minions'; -//import { formatDuration, itemID, itemNameFromID } from '../../lib/util'; -import { formatDuration, itemNameFromID } from '../../lib/util'; -import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask'; -import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength'; -import type { OSBMahojiCommand } from '../lib/util'; -import { MUserClass } from '../../lib/MUser'; - - - -function radasBlessing(user: MUser) { - const blessingBoosts = [ - ["Rada's blessing 4", 8], - ["Rada's blessing 3", 6], - ["Rada's blessing 2", 4], - ["Rada's blessing 1", 2] - ]; - - for (const [itemName, boostPercent] of blessingBoosts) { - if (user.hasEquipped(itemName)) { - return { blessingEquipped: true, blessingChance: boostPercent as number }; - } - } - return { blessingEquipped: false, blessingChance: 0 }; -} - - - -function rollExtraLoot( - lootAmount: number, - flakesUsed: number, - currentInv: number, - blessingChance: number, - spirit_flakes: boolean, - flakesQuantity: number -): [number, number, number] { - currentInv++; - if (Math.random() < blessingChance / 100) { - lootAmount++; - currentInv++; - } - if (spirit_flakes && flakesUsed < flakesQuantity && Math.random() < 0.5) { - lootAmount++; - flakesUsed++; - currentInv++; - } - // Return updated values - return [lootAmount, flakesUsed, currentInv]; -} - - -function determineFishingTime( - quantity: number, - tripTicks: number, - powerfish: boolean, - spirit_flakes: boolean, - fish: Fish, - user: MUserClass, - invSlots: number, - blessingChance: number, - flakesQuantity: number, - harpoonBoost: number -) { - let ticksElapsed = 0; - let catches1 = 0, catches2 = 0, catches3 = 0; - let lootAmount1 = 0, lootAmount2 = 0, lootAmount3 = 0; - let flakesUsed = 0; - let currentInv = 0; - - let fishLvl = user.skillLevel(SkillsEnum.Fishing); - let effFishLvl = fishLvl; - if (fishLvl > 68) { - if (fish.name === 'Shark' || fish.name === 'Mackerel/Cod/Bass' || fish.name === 'Lobster') { - effFishLvl += 7; // fishing guild boost - } else if (fish.name === 'Tuna/Swordfish' && !powerfish) { - effFishLvl += 7; // can't 2t in the guild - } - } - - // probabilities of catching a fish at the user's fishing lvl - let p1 = harpoonBoost * (fish.chance1Lvl99! - (99 - effFishLvl) * (fish.chance1Lvl99! - fish.chance1Lvl1!) / (99 - 1)); - let p2 = fish.id2 === undefined ? 0 : harpoonBoost * (fish.chance2Lvl99! - (99 - effFishLvl) * (fish.chance2Lvl99! - fish.chance2Lvl1!) / (99 - 1)); - let p3 = fish.id3 === undefined ? 0 : harpoonBoost * (fish.chance3Lvl99! - (99 - effFishLvl) * (fish.chance3Lvl99! - fish.chance2Lvl1!) / (99 - 1)); - - let ticksPerRoll = fish.ticksPerRoll!; - let lostTicks = fish.lostTicks!; - let bankingTime = fish.bankingTime; - - if (fish.name === 'Barbarian fishing') { - if (powerfish) { - ticksPerRoll = 3; - lostTicks = 0.02; // more focused - } - if (user.allItemsOwned.has('Fishing cape') || user.allItemsOwned.has('Fishing cape (t)') || user.allItemsOwned.has('Max cape')) { - bankingTime = 20; - } - } else if (fish.name === 'Trout/Salmon') { - if (powerfish) { - ticksPerRoll = 3; - lostTicks = 0.03; - } - } else if (fish.name === 'Tuna/Swordfish') { - if (powerfish) { - ticksPerRoll = 2; - lostTicks = 0.01; - } - } - - if (powerfish) { - while (ticksElapsed < tripTicks) { - if (p3 != 0 && Math.random() < p3) { - catches3++; // roll for the highest lvl fish first - } else if (p2 != 0 && Math.random() < p2) { - catches2++; // then the second only if first one wasn't caught - } else if (Math.random() < p1) { - catches1++; - } - ticksElapsed += ticksPerRoll! * (1 + lostTicks!); // only part of the code that's not exactly how it works in osrs approximate - - if (catches1 + catches2 + catches3 >= quantity) { - break; - } - } - } else { - while (ticksElapsed < tripTicks) { - if (p3 != 0 && Math.random() < p3) { - catches3++; - lootAmount3++; - [lootAmount3, flakesUsed, currentInv] = rollExtraLoot(lootAmount3, flakesUsed, currentInv, blessingChance, spirit_flakes, flakesQuantity); - } else if (p2 != 0 && Math.random() < p2) { - catches2++; - lootAmount2++; - [lootAmount2, flakesUsed, currentInv] = rollExtraLoot(lootAmount2, flakesUsed, currentInv, blessingChance, spirit_flakes, flakesQuantity); - } else if (Math.random() < p1) { - catches1++; - lootAmount1++; - [lootAmount1, flakesUsed, currentInv] = rollExtraLoot(lootAmount1, flakesUsed, currentInv, blessingChance, spirit_flakes, flakesQuantity); - } - - ticksElapsed += ticksPerRoll! * (1 + lostTicks!); - - if (catches1 + catches2 + catches3 >= quantity) { - break; - } - - if (currentInv >= invSlots) { - ticksElapsed += bankingTime!; - currentInv = 0; - } - - } - } - - return { catches1, catches2, catches3, lootAmount1, lootAmount2, lootAmount3, ticksElapsed, flakesUsed }; -} - - - - -export const fishCommand: OSBMahojiCommand = { - name: 'fish', - description: 'Send your minion to fish fish.', - attributes: { - requiresMinion: true, - requiresMinionNotBusy: true, - examples: ['/fish name:Shrimp'] - }, - options: [ - { - type: ApplicationCommandOptionType.String, - name: 'name', - description: 'The thing you want to fish.', - required: true, - autocomplete: async (value: string) => { - return Fishing.Fishes.filter(i => - !value ? true : i.name.toLowerCase().includes(value.toLowerCase()) - ).map(i => ({ - name: i.name, - value: i.name - })); - } - }, - { - type: ApplicationCommandOptionType.Integer, - name: 'minutes', - description: 'Trip length in minutes (optional).', - required: false, - min_value: 1 - }, - { - type: ApplicationCommandOptionType.Boolean, - name: 'powerfish', - description: 'Set this to true to powerfish. Higher xp/hour, no loot (default false, optional).', - required: false - }, - { - type: ApplicationCommandOptionType.Boolean, - name: 'spirit_flakes', - description: 'Set this to true to use spirit flakes (default false, optional).', - required: false - } - ], - run: async ({ - options, - userID, - channelID - }: CommandRunOptions<{ - name: string; - quantity?: number, - powerfish?: boolean, - spirit_flakes?: boolean - }>) => { - const user = await mUserFetch(userID); - const fish = Fishing.Fishes.find( - fish => - stringMatches(fish.id, options.name) || - stringMatches(fish.name, options.name) || - fish.alias?.some(alias => stringMatches(alias, options.name)) - ); - if (!fish) return 'Thats not a valid fish to catch.'; - - let { quantity, powerfish, spirit_flakes } = options; - - quantity = quantity ?? 3000; - powerfish = powerfish ?? false; - if (powerfish) { - spirit_flakes = false; // don't use flakes if power fishing - } - spirit_flakes = spirit_flakes ?? false; - - // requirement checks - if (user.skillLevel(SkillsEnum.Fishing) < fish.level) { - return `${user.minionName} needs ${fish.level} Fishing to fish ${fish.name}.`; - } - - if (fish.qpRequired) { - if (user.QP < fish.qpRequired) { - return `You need ${fish.qpRequired} qp to catch those!`; - } - } - - if ( - fish.name === 'Barbarian fishing' && - (user.skillLevel(SkillsEnum.Agility) < 15 || user.skillLevel(SkillsEnum.Strength) < 15) - ) { - return 'You need at least 15 Agility and Strength to do Barbarian Fishing.'; - } - - if (fish.name === 'Infernal eel') { - const jadKC = await user.getKC(TzTokJad.id); - if (jadKC === 0) { - return 'You are not worthy JalYt. Before you can fish Infernal Eels, you need to have defeated the mighty TzTok-Jad!'; - } - } - - const anglerOutfit = Object.keys(Fishing.anglerItems).map(i => itemNameFromID(Number.parseInt(i))); - if (fish.name === 'Minnow' && anglerOutfit.some(test => !user.hasEquippedOrInBank(test!))) { - return 'You need to own the Angler Outfit to fish for Minnows.'; - } - - // boosts - const boosts = []; - if (fish.name === 'Tuna/Swordfish' || fish.name === 'Shark') { - if (user.hasEquipped('Crystal harpoon')) { - boosts.push('35% for Crystal harpoon'); - } else if (user.hasEquipped('Dragon harpoon')) { - boosts.push('20% for Dragon harpoon'); - } else if (user.hasEquipped('Infernal harpoon')) { - boosts.push('20% for Infernal harpoon'); - } - } - - if (powerfish) { - boosts.push('**Powerfishing**'); - } - - if (!powerfish) { - if (user.allItemsOwned.has('Fish sack barrel') || user.allItemsOwned.has('Fish barrel')) { - if (fish.name === 'Minnow' || fish.name === 'Karambwanji' || fish.name === 'Infernal eel') { - boosts.push(`+9 trip minutes for having a ${user.allItemsOwned.has('Fish sack barrel') ? 'Fish sack barrel' : 'Fish barrel'}`); - } else { - boosts.push(`+9 trip minutes and +28 inventory slots for having a ${user.allItemsOwned.has('Fish sack barrel') ? 'Fish sack barrel' : 'Fish barrel'}`); - } - } - } - - if (fish.name === 'Dark crab') { - const [hasWildyElite] = await userhasDiaryTier(user, WildernessDiary.elite); - if (hasWildyElite) { - fish.chance1Lvl1 = 0.0961; - fish.chance1Lvl99 = 0.3439; - boosts.push('Increased dark crab catch rate from having the Elite Wilderness Diary'); - } - } - - if (spirit_flakes) { - if (!user.bank.has('Spirit flakes')) { - return 'You need to have at least one spirit flake!'; - } - - boosts.push(`\n50% more fish from using spirit flakes`); - } - - const { blessingEquipped, blessingChance } = radasBlessing(user); - if (blessingEquipped) { - boosts.push(`\nYour Rada's Blessing gives ${blessingChance}% chance of extra fish`); - } - - - let harpoonBoost = 1.0; - if (fish.name === 'Tuna/Swordfish' || fish.name === 'Shark') { - if (user.hasEquipped("Dragon harpoon") || user.hasEquipped("Infernal harpoon")) { - harpoonBoost = 1.2; - } else if (user.hasEquipped("Crystal harpoon")) { - harpoonBoost = 1.35; - } - } - - let invSlots = 26; - if (user.allItemsOwned.has('Fish sack barrel') || user.allItemsOwned.has('Fish barrel')) { - invSlots += 28; - } - - let maxTripLength = calcMaxTripLength(user, 'Fishing'); - if (!powerfish && (user.allItemsOwned.has('Fish sack barrel') || user.allItemsOwned.has('Fish barrel'))) { - maxTripLength += Time.Minute * 9; - } - let tripTicks = maxTripLength / (Time.Second * 0.6); - - let flakesQuantity = user.bank.amount('Spirit flakes'); - - if (fish.bait) { - const baseCost = new Bank().add(fish.bait); - const maxCanDo = user.bank.fits(baseCost); - if (maxCanDo === 0) { - return `You need ${itemNameFromID(fish.bait)} to fish ${fish.name}!`; - } - - if (maxCanDo < quantity) { - quantity = maxCanDo; - } - } - - // determining fish time and quantities - const { catches1: Qty1, catches2: Qty2, catches3: Qty3, lootAmount1: loot1, lootAmount2: loot2, lootAmount3: loot3, ticksElapsed: tripLength, flakesUsed: flakesToRemove } = determineFishingTime( - quantity, - tripTicks, - powerfish, - spirit_flakes, - fish, - user, - invSlots, - blessingChance, - flakesQuantity, - harpoonBoost - ); - - - let duration = Time.Second * 0.6 * tripLength; - - await addSubTaskToActivityTask({ - fishID: fish.id, - userID: user.id, - channelID: channelID.toString(), - duration: duration, - quantity: quantity, - Qty1: Qty1, - Qty2: Qty2, - Qty3: Qty3, - loot1: loot1, - loot2: loot2, - loot3: loot3, - flakesToRemove: flakesToRemove, - powerfish: powerfish, - spirit_flakes: spirit_flakes, - type: 'Fishing' - }); - - let response = `${user.minionName} is now fishing ${fish.name}, it'll take around ${formatDuration(duration)} to finish.`; - - if (boosts.length > 0) { - response += `\n\n**Boosts:** ${boosts.join(', ')}.`; - } - - return response; - } -}; - diff --git a/fishing.ts b/fishing.ts deleted file mode 100644 index 28b0d1cfbd..0000000000 --- a/fishing.ts +++ /dev/null @@ -1,368 +0,0 @@ -import { Emoji } from '../../constants'; -import itemID from '../../util/itemID'; -import type { Fish } from '../types'; -import { SkillsEnum } from '../types'; - -const fishes: Fish[] = [ - { - name: 'Shrimps/Anchovies', - level: 1, - xp: 10, - id: itemID('Raw shrimps'), - chance1Lvl1: 0.1373, // catch chance for fish 1 at lvl 1 - chance1Lvl99: 1.0000, - - level2: 15, - xp2: 40, - id2: itemID('Raw anchovies'), - chance2Lvl1: 0.0937, - chance2Lvl99: 0.5039, - - petChance: 435_165, - clueScrollChance: 870_330, - lostTicks: 0.05, // percentage of ticks spent moving/dropping, - bankingTime: 30, - ticksPerRoll: 6 - }, - { - name: 'Sardine/Herring', - level: 5, - xp: 20, - id: itemID('Raw sardine'), - chance1Lvl1: 0.1267, - chance1Lvl99: 0.7539, - - level2: 10, - xp2: 30, - id2: itemID('Raw herring'), - chance2Lvl1: 0.1273, - chance2Lvl99: 0.5039, - - bait: itemID('Fishing bait'), - petChance: 528_000, - clueScrollChance: 1_056_000, - lostTicks: 0.05, - bankingTime: 30, - ticksPerRoll: 5 - }, - { - name: 'Karambwanji', - level: 5, - xp: 20, - id: itemID('Raw karambwanji'), - chance1Lvl1: 0.3945, - chance1Lvl99: 0.9805, - - petChance: 443_697, - qpRequired: 15, - clueScrollChance: 443_697, - lostTicks: 0.01, - bankingTime: 0, - ticksPerRoll: 6 - }, - { - name: 'Mackerel/Cod/Bass', - level: 16, - xp: 20, - id: itemID('Raw mackerel'), - chance1Lvl1: 0.0645, - chance1Lvl99: 0.2897, - - level2: 23, - xp2: 45, - id2: itemID('Raw cod'), - chance2Lvl1: 0.0173, - chance2Lvl99: 0.2188, - - level3: 46, - xp3: 100, - id3: itemID('Raw bass'), - bigFish: itemID('Big bass'), - bigFishRate: 1000, - chance3Lvl1: 0.0156, - chance3Lvl99: 0.1602, - - petChance: 382_609, - clueScrollChance: 1_147_827, - lostTicks: 0.05, - bankingTime: 25, - ticksPerRoll: 6 - }, - { - name: 'Trout/Salmon', - level: 20, - xp: 50, - id: itemID('Raw trout'), - chance1Lvl1: 0.0174, - chance1Lvl99: 0.7538, - - level2: 30, - xp2: 70, - id2: itemID('Raw salmon'), - chance2Lvl1: 0.0683, - chance2Lvl99: 0.3789, - - petChance: 461_808, - bait: itemID('Feather'), - clueScrollChance: 923_616, - lostTicks: 0.05, - bankingTime: 30, - ticksPerRoll: 5 - }, - { - name: 'Pike', - level: 25, - xp: 60, - id: itemID('Raw pike'), - chance1Lvl1: 0.0685, - chance1Lvl99: 0.3789, - - petChance: 305_792, - bait: itemID('Fishing bait'), - clueScrollChance: 305_792, - lostTicks: 0.05, - bankingTime: 30, - ticksPerRoll: 5 - }, - { - name: 'Tuna/Swordfish', - alias: ['sword, sf'], - level: 35, - xp: 80, - id: itemID('Raw tuna'), - chance1Lvl1: 0.0326, - chance1Lvl99: 0.2539, - - level2: 50, - xp2: 100, - id2: itemID('Raw swordfish'), - bigFish: itemID('Big swordfish'), - bigFishRate: 2500, - chance2Lvl1: 0.0196, - chance2Lvl99: 0.1914, - - petChance: 128_885, - clueScrollChance: 257_770, - lostTicks: 0.05, - bankingTime: 25, - ticksPerRoll: 6 - }, - { - name: 'Cave eel', - level: 38, - xp: 80, - id: itemID('Raw cave eel'), - chance1Lvl1: 0.1900, - chance1Lvl99: 0.3164, - lostTicks: 0.05, - bankingTime: 40, - ticksPerRoll: 5 - }, - { - name: 'Lobster', - alias: ['lobs'], - level: 40, - xp: 90, - id: itemID('Raw lobster'), - chance1Lvl1: 0.0247, - chance1Lvl99: 0.3750, - petChance: 116_129, - clueScrollChance: 116_129, - lostTicks: 0.05, - bankingTime: 25, - ticksPerRoll: 6 - }, - { - name: 'Monkfish', - alias: ['monk'], - level: 62, - xp: 120, - id: itemID('Raw monkfish'), - chance1Lvl1: 0.1900, - chance1Lvl99: 0.3555, - petChance: 138_583, - qpRequired: 100, - clueScrollChance: 138_583, - lostTicks: 0.10, - bankingTime: 20, - ticksPerRoll: 6 - }, - { - name: 'Karambwan', - alias: ['karam'], - level: 65, - xp: 50, - id: itemID('Raw karambwan'), - chance1Lvl1: 0.0210, - chance1Lvl99: 0.6289, - petChance: 170_874, - bait: itemID('Raw karambwanji'), - clueScrollChance: 170_874, - lostTicks: 0.00, // fishing spots never moves - bankingTime: 25, - ticksPerRoll: 4 - }, - { - name: 'Shark', - alias: ['shark'], - level: 76, - xp: 110, - id: itemID('Raw shark'), - chance1Lvl1: 0.0102, - chance1Lvl99: 0.1602, - petChance: 82_243, - bigFish: itemID('Big shark'), - bigFishRate: 5000, - clueScrollChance: 82_243, - lostTicks: 0.05, - bankingTime: 25, - ticksPerRoll: 6 - }, - { - name: 'Anglerfish', - alias: ['angler'], - level: 82, - xp: 120, - id: itemID('Raw anglerfish'), - chance1Lvl1: 0.0096, - chance1Lvl99: 0.1445, - petChance: 78_649, - bait: itemID('Sandworms'), - qpRequired: 40, - clueScrollChance: 78_649, - lostTicks: 0.05, - bankingTime: 30, - ticksPerRoll: 5 - }, - { - name: 'Minnow', - alias: ['minnows'], - level: 82, - xp: 26.1, - id: itemID('Minnow'), - chance1Lvl1: 0.6666, // no info on catch chance - chance1Lvl99: 0.9259, // handpicked to match wiki rates - petChance: 977_778, - qpRequired: 1, - clueScrollChance: 977_778, - lostTicks: 0.25, - bankingTime: 0, // stackable - ticksPerRoll: 2 - }, - { - name: 'Dark crab', - alias: ['crab', 'dark'], - level: 85, - xp: 130, - id: itemID('Raw dark crab'), - chance1Lvl1: 0.0230, - chance1Lvl99: 0.1602, - petChance: 149_434, - bait: itemID('Dark fishing bait'), - clueScrollChance: 149_434, - lostTicks: 0.05, - bankingTime: 0, - ticksPerRoll: 6 - }, - { - name: 'Barbarian fishing', - alias: ['barb', 'barbarian'], - level: 48, - xp: 50, - id: itemID('Leaping trout'), - chance1Lvl1: 32 / 255, - chance1Lvl99: 192 / 255, - - level2: 58, - xp2: 70, - id2: itemID('Leaping salmon'), - chance2Lvl1: 16 / 255, - chance2Lvl99: 96 / 255, - - level3: 70, - xp3: 80, - id3: itemID('Leaping sturgeon'), - chance3Lvl1: 8 / 255, - chance3Lvl99: 64 / 255, - - petChance: 426_954, - bait: itemID('Feather'), - clueScrollChance: 1_280_862, - lostTicks: 0.05, - bankingTime: 40, - ticksPerRoll: 5 - }, - { - name: 'Infernal eel', - level: 80, - xp: 95, - id: itemID('Infernal eel'), - petChance: 160_000, - bait: itemID('Fishing bait'), - clueScrollChance: 165_000, - chance1Lvl1: 0.1253, - chance1Lvl99: 0.3672, - lostTicks: 0.10, - bankingTime: 0, - ticksPerRoll: 5 - } -]; - -// Types of fish in camdozaal -const camdozaalFishes: Fish[] = [ - { - level: 7, - xp: 8, - id: itemID('Raw guppy'), - name: 'Raw guppy', - petChance: 257_770, - timePerFish: 5.5, - clueScrollChance: 257_770 - }, - { - level: 20, - xp: 16, - id: itemID('Raw cavefish'), - name: 'Raw cavefish', - petChance: 257_770, - timePerFish: 5.5, - clueScrollChance: 257_770 - }, - { - level: 33, - xp: 24, - id: itemID('Raw tetra'), - name: 'Raw tetra', - petChance: 257_770, - timePerFish: 5.5, - clueScrollChance: 257_770 - }, - { - level: 46, - xp: 33, - id: itemID('Raw catfish'), - name: 'Raw catfish', - petChance: 257_770, - timePerFish: 5.5, - clueScrollChance: 257_770 - } -]; - -const anglerItems: { [key: number]: number } = { - [itemID('Angler hat')]: 0.4, - [itemID('Angler top')]: 0.8, - [itemID('Angler waders ')]: 0.6, - [itemID('Angler boots')]: 0.2 -}; - -const Fishing = { - aliases: ['fishing'], - Fishes: fishes, - camdozaalFishes, - id: SkillsEnum.Fishing, - emoji: Emoji.Fishing, - anglerItems, - name: 'Fishing' -}; - -export default Fishing; diff --git a/fishingActivity.ts b/fishingActivity.ts deleted file mode 100644 index 37ee34fd82..0000000000 --- a/fishingActivity.ts +++ /dev/null @@ -1,211 +0,0 @@ -//import { calcPercentOfNum, percentChance, randInt } from 'e'; -import { calcPercentOfNum } from 'e'; -import { Bank } from 'oldschooljs'; -import { z } from 'zod'; -//import { Time } from 'e'; -import { Emoji, Events } from '../../lib/constants'; -import addSkillingClueToLoot from '../../lib/minions/functions/addSkillingClueToLoot'; -import Fishing from '../../lib/skilling/skills/fishing'; -import { SkillsEnum } from '../../lib/skilling/types'; -import type { FishingActivityTaskOptions } from '../../lib/types/minions'; -import { roll, skillingPetDropRate } from '../../lib/util'; -import { handleTripFinish } from '../../lib/util/handleTripFinish'; -// itemID from '../../lib/util/itemID'; -import { anglerBoostPercent } from '../../mahoji/mahojiSettings'; - -const allFishIDs = Fishing.Fishes.flatMap(fish => [fish.id, fish.id2, fish.id3]); - -export const fishingTask: MinionTask = { - type: 'Fishing', - dataSchema: z.object({ - type: z.literal('Fishing'), - fishID: z.number().refine(fishID => allFishIDs.includes(fishID), { - message: 'Invalid fish ID' - }), - quantity: z.number().min(1) - }), - async run(data: FishingActivityTaskOptions) { - let { fishID, userID, channelID, duration, spirit_flakes, - Qty1, Qty2 = 0, Qty3 = 0, loot1 = 0, loot2 = 0, loot3 = 0, flakesToRemove } = data; - - spirit_flakes = spirit_flakes ?? false; - - const user = await mUserFetch(userID); - const fishLvl = user.skillLevel(SkillsEnum.Fishing); - - const minnowQuantity: { [key: number]: number[] } = { - 99: [10, 14], - 95: [11, 13], - 90: [10, 13], - 85: [10, 11], - 1: [10, 10] - }; - - let baseMinnow = [10, 10]; - for (const [level, quantities] of Object.entries(minnowQuantity).reverse()) { - if (fishLvl >= Number.parseInt(level)) { - baseMinnow = quantities; - break; - } - } - - const baseKarambwanji = 1 + Math.floor(fishLvl / 5); - - let xpReceived = 0; - let agilityXpReceived = 0; - let strengthXpReceived = 0; - - const fish = Fishing.Fishes.find(fish => fish.id === fishID)!; - - // adding xp and loot - - xpReceived += fish.xp * Qty1; - if (Qty2 != 0) xpReceived += fish.xp2! * Qty2; - if (Qty3 != 0) xpReceived += fish.xp3! * Qty3; - - if (fish.name === 'Barbarian fishing') { - agilityXpReceived += 7 * Qty3 + 6 * Qty2 + 5 * Qty1; - strengthXpReceived += 7 * Qty3 + 6 * Qty2 + 5 * Qty1; - } - - - // If they have the entire angler outfit, give an extra 0.5% xp bonus - let bonusXP = 0; - if ( - user.gear.skilling.hasEquipped( - Object.keys(Fishing.anglerItems).map(i => Number.parseInt(i)), - true - ) - ) { - const amountToAdd = Math.floor(xpReceived * (2.5 / 100)); - xpReceived += amountToAdd; - bonusXP += amountToAdd; - } else { - // For each angler item, check if they have it, give its' XP boost if so. - for (const [itemID, bonus] of Object.entries(Fishing.anglerItems)) { - if (user.hasEquipped(Number.parseInt(itemID))) { - const amountToAdd = Math.floor(xpReceived * (bonus / 100)); - xpReceived += amountToAdd; - bonusXP += amountToAdd; - } - } - } - - - let xpRes = await user.addXP({ - skillName: SkillsEnum.Fishing, - amount: xpReceived, - duration - }); - xpRes += - agilityXpReceived > 0 - ? await user.addXP({ - skillName: SkillsEnum.Agility, - amount: agilityXpReceived, - duration - }) - : ''; - xpRes += - strengthXpReceived > 0 - ? await user.addXP({ - skillName: SkillsEnum.Strength, - amount: strengthXpReceived, - duration - }) - : ''; - - - const loot = new Bank(); - loot.add(fish.id3!, loot3); - loot.add(fish.id2!, loot2); - - // handling stackable fish - if (fish.name === 'Minnow') { - let sum = 0; - for (let i = 0; i < loot1; i++) { - sum += Math.floor(Math.random() * (baseMinnow[1] - baseMinnow[0] + 1)) + baseMinnow[0]; - } - loot1 = sum; - } else if (fish.name === 'Karambwanji') { - loot1 *= baseKarambwanji; - } - loot.add(fish!.id, loot1); - - let str = '' - - const totalCatches = Qty1 + Qty2 + Qty3; - str = `${user}, ${user.minionName} finished fishing ${totalCatches} ${fish.name}. ${xpRes}`; - - - const cost = new Bank(); - if (spirit_flakes) { - cost.add('Spirit flakes', flakesToRemove); - } - - if (fish.bait) { - cost.add(fish.bait, totalCatches); - } - - await user.removeItemsFromBank(cost); - - // Add clue scrolls - if (fish.clueScrollChance) { - addSkillingClueToLoot(user, SkillsEnum.Fishing, totalCatches, fish.clueScrollChance, loot); - } - - const xpBonusPercent = anglerBoostPercent(user); - if (xpBonusPercent > 0) { - bonusXP += Math.ceil(calcPercentOfNum(xpBonusPercent, xpReceived)); - } - - if (bonusXP > 0) { - str += `\n\n**Bonus XP:** ${bonusXP.toLocaleString()}`; - } - - // Roll for pet - if (fish.petChance) { - const { petDropRate } = skillingPetDropRate(user, SkillsEnum.Fishing, fish.petChance); - for (let i = 0; i < totalCatches; i++) { - if (roll(petDropRate)) { - loot.add('Heron'); - str += "\nYou have a funny feeling you're being followed..."; - globalClient.emit( - Events.ServerNotification, - `${Emoji.Fishing} **${user.badgedUsername}'s** minion, ${user.minionName}, just received a Heron while fishing ${fish.name} at level ${fishLvl} Fishing!` - ); - } - } - } - - // bigFishQuantity add this - if (fish.bigFishRate && fish.bigFish) { - let bigFishQuantity = 0; - if (fish.name === 'Shark') { - bigFishQuantity = Qty1; - } - if (fish.name === 'Tuna/Swordfish') { - bigFishQuantity = Qty2; - } - if (fish.name === 'Mackerel/Cod/Bass') { - bigFishQuantity = Qty3; - } - for (let i = 0; i < bigFishQuantity!; i++) { - if (roll(fish.bigFishRate)) { - loot.add(fish.bigFish); - } - } - } - - - await transactItems({ - userID: user.id, - collectionLog: true, - itemsToAdd: loot - }); - - str += `\n\nYou received: ${loot}.`; - - handleTripFinish(user, channelID, str, undefined, data, loot); - } -} - diff --git a/minionStatus.ts b/minionStatus.ts deleted file mode 100644 index 0782428c44..0000000000 --- a/minionStatus.ts +++ /dev/null @@ -1,668 +0,0 @@ -import { toTitleCase } from '@oldschoolgg/toolkit'; -import { increaseNumByPercent, reduceNumByPercent } from 'e'; -import { SkillsEnum } from 'oldschooljs/dist/constants'; - -import { collectables } from '../../mahoji/lib/abstracted_commands/collectCommand'; -import { shades, shadesLogs } from '../../mahoji/lib/abstracted_commands/shadesOfMortonCommand'; -import { ClueTiers } from '../clues/clueTiers'; -import { Emoji } from '../constants'; -import killableMonsters from '../minions/data/killableMonsters'; -import { Planks } from '../minions/data/planks'; -import { quests } from '../minions/data/quests'; -import Agility from '../skilling/skills/agility'; -import Constructables from '../skilling/skills/construction/constructables'; -import Cooking from '../skilling/skills/cooking/cooking'; -import LeapingFish from '../skilling/skills/cooking/leapingFish'; -import Crafting from '../skilling/skills/crafting'; -import Farming from '../skilling/skills/farming'; -import Firemaking from '../skilling/skills/firemaking'; -import Fishing from '../skilling/skills/fishing'; -import Herblore from '../skilling/skills/herblore/herblore'; -import Hunter from '../skilling/skills/hunter/hunter'; -import { Castables } from '../skilling/skills/magic/castables'; -import { Enchantables } from '../skilling/skills/magic/enchantables'; -import Mining from '../skilling/skills/mining'; -import Prayer from '../skilling/skills/prayer'; -import Runecraft from '../skilling/skills/runecraft'; -import Smithing from '../skilling/skills/smithing'; -import { stealables } from '../skilling/skills/thieving/stealables'; -import Woodcutting from '../skilling/skills/woodcutting/woodcutting'; -import type { - ActivityTaskOptionsWithQuantity, - AgilityActivityTaskOptions, - AlchingActivityTaskOptions, - BuryingActivityTaskOptions, - ButlerActivityTaskOptions, - CastingActivityTaskOptions, - ClueActivityTaskOptions, - CollectingOptions, - ColoTaskOptions, - ConstructionActivityTaskOptions, - CookingActivityTaskOptions, - CraftingActivityTaskOptions, - CutLeapingFishActivityTaskOptions, - DarkAltarOptions, - EnchantingActivityTaskOptions, - FarmingActivityTaskOptions, - FightCavesActivityTaskOptions, - FiremakingActivityTaskOptions, - FishingActivityTaskOptions, - FletchingActivityTaskOptions, - GauntletOptions, - GroupMonsterActivityTaskOptions, - HerbloreActivityTaskOptions, - HunterActivityTaskOptions, - InfernoOptions, - KourendFavourActivityTaskOptions, - MinigameActivityTaskOptionsWithNoChanges, - MiningActivityTaskOptions, - MonsterActivityTaskOptions, - MotherlodeMiningActivityTaskOptions, - NexTaskOptions, - NightmareActivityTaskOptions, - OfferingActivityTaskOptions, - PickpocketActivityTaskOptions, - PlunderActivityTaskOptions, - RaidsOptions, - RunecraftActivityTaskOptions, - SawmillActivityTaskOptions, - ScatteringActivityTaskOptions, - SepulchreActivityTaskOptions, - ShadesOfMortonOptions, - SmeltingActivityTaskOptions, - SmithingActivityTaskOptions, - SpecificQuestOptions, - TOAOptions, - TheatreOfBloodTaskOptions, - TiaraRunecraftActivityTaskOptions, - WoodcuttingActivityTaskOptions, - ZalcanoActivityTaskOptions -} from '../types/minions'; -import { formatDuration, itemNameFromID, randomVariation, stringMatches } from '../util'; -import { getActivityOfUser } from './minionIsBusy'; - -export function minionStatus(user: MUser) { - const currentTask = getActivityOfUser(user.id); - const name = user.minionName; - if (!currentTask) { - return `${name} is currently doing nothing.`; - } - - const durationRemaining = currentTask.finishDate - Date.now(); - const formattedDuration = `${formatDuration(durationRemaining)} remaining.`; - - switch (currentTask.type) { - case 'MonsterKilling': { - const data = currentTask as MonsterActivityTaskOptions; - const monster = killableMonsters.find(mon => mon.id === data.monsterID); - - return `${name} is currently killing ${data.quantity}x ${monster?.name}. ${formattedDuration}`; - } - - case 'GroupMonsterKilling': { - const data = currentTask as GroupMonsterActivityTaskOptions; - const monster = killableMonsters.find(mon => mon.id === data.monsterID); - - return `${name} is currently killing ${data.quantity}x ${monster?.name} with a party of ${data.users.length - }. ${formattedDuration}`; - } - - case 'ClueCompletion': { - const data = currentTask as ClueActivityTaskOptions; - - const clueTier = ClueTiers.find(tier => tier.id === data.clueID); - - return `${name} is currently completing ${data.quantity}x ${clueTier?.name} clues. ${formattedDuration}`; - } - - case 'Crafting': { - const data = currentTask as CraftingActivityTaskOptions; - const craftable = Crafting.Craftables.find(item => item.id === data.craftableID); - - return `${name} is currently crafting ${data.quantity}x ${craftable?.name}. ${formattedDuration} Your ${Emoji.Crafting - } Crafting level is ${user.skillLevel(SkillsEnum.Crafting)}`; - } - - case 'Agility': { - const data = currentTask as AgilityActivityTaskOptions; - - const course = Agility.Courses.find(course => course.name === data.courseID); - - return `${name} is currently running ${data.quantity}x ${course?.name} laps. ${formattedDuration} Your ${Emoji.Agility - } Agility level is ${user.skillLevel(SkillsEnum.Agility)}`; - } - - case 'Cooking': { - const data = currentTask as CookingActivityTaskOptions; - - const cookable = Cooking.Cookables.find(cookable => cookable.id === data.cookableID); - - return `${name} is currently cooking ${data.quantity}x ${cookable?.name}. ${formattedDuration} Your ${Emoji.Cooking - } Cooking level is ${user.skillLevel(SkillsEnum.Cooking)}`; - } - - case 'Fishing': { - const data = currentTask as FishingActivityTaskOptions; - - const fish = Fishing.Fishes.find(fish => fish.id === data.fishID); - - return `${name} is currently fishing ${fish?.name}. ${formattedDuration} Your ${Emoji.Fishing - } Fishing level is ${user.skillLevel(SkillsEnum.Fishing)}`; - } - - case 'Mining': { - const data = currentTask as MiningActivityTaskOptions; - - const ore = Mining.Ores.find(ore => ore.id === data.oreID); - - return `${name} is currently mining ${ore?.name}. ${data.fakeDurationMax === data.fakeDurationMin - ? formattedDuration - : `approximately ${formatDuration( - randomVariation(reduceNumByPercent(durationRemaining, 25), 20) - )} **to** ${formatDuration( - randomVariation(increaseNumByPercent(durationRemaining, 25), 20) - )} remaining.` - } Your ${Emoji.Mining} Mining level is ${user.skillLevel(SkillsEnum.Mining)}`; - } - - case 'MotherlodeMining': { - const data = currentTask as MotherlodeMiningActivityTaskOptions; - - return `${name} is currently mining at the Motherlode Mine. ${data.fakeDurationMax === data.fakeDurationMin - ? formattedDuration - : `approximately ${formatDuration( - randomVariation(reduceNumByPercent(durationRemaining, 25), 20) - )} **to** ${formatDuration( - randomVariation(increaseNumByPercent(durationRemaining, 25), 20) - )} remaining.` - } Your ${Emoji.Mining} Mining level is ${user.skillLevel(SkillsEnum.Mining)}`; - } - - case 'Smelting': { - const data = currentTask as SmeltingActivityTaskOptions; - - const bar = Smithing.Bars.find(bar => bar.id === data.barID); - - return `${name} is currently smelting ${data.quantity}x ${bar?.name}. ${formattedDuration} Your ${Emoji.Smithing - } Smithing level is ${user.skillLevel(SkillsEnum.Smithing)}`; - } - - case 'Smithing': { - const data = currentTask as SmithingActivityTaskOptions; - - const SmithableItem = Smithing.SmithableItems.find(item => item.id === data.smithedBarID); - - return `${name} is currently smithing ${data.quantity}x ${SmithableItem?.name}. ${formattedDuration} Your ${Emoji.Smithing - } Smithing level is ${user.skillLevel(SkillsEnum.Smithing)}`; - } - - case 'Offering': { - const data = currentTask as OfferingActivityTaskOptions; - - const bones = Prayer.Bones.find(bones => bones.inputId === data.boneID); - - return `${name} is currently offering ${data.quantity}x ${bones?.name}. ${formattedDuration} Your ${Emoji.Prayer - } Prayer level is ${user.skillLevel(SkillsEnum.Prayer)}`; - } - - case 'Burying': { - const data = currentTask as BuryingActivityTaskOptions; - - const bones = Prayer.Bones.find(bones => bones.inputId === data.boneID); - - return `${name} is currently burying ${data.quantity}x ${bones?.name}. ${formattedDuration} Your ${Emoji.Prayer - } Prayer level is ${user.skillLevel(SkillsEnum.Prayer)}`; - } - - case 'Scattering': { - const data = currentTask as ScatteringActivityTaskOptions; - - const ashes = Prayer.Ashes.find(ashes => ashes.inputId === data.ashID); - - return `${name} is currently scattering ${data.quantity}x ${ashes?.name}. ${formattedDuration} Your ${Emoji.Prayer - } Prayer level is ${user.skillLevel(SkillsEnum.Prayer)}`; - } - - case 'Firemaking': { - const data = currentTask as FiremakingActivityTaskOptions; - - const burn = Firemaking.Burnables.find(burn => burn.inputLogs === data.burnableID); - - return `${name} is currently lighting ${data.quantity}x ${burn?.name}. ${formattedDuration} Your ${Emoji.Firemaking - } Firemaking level is ${user.skillLevel(SkillsEnum.Firemaking)}`; - } - - case 'Questing': { - return `${name} is currently Questing. ${formattedDuration} Your current Quest Point count is: ${user.QP}.`; - } - - case 'Woodcutting': { - const data = currentTask as WoodcuttingActivityTaskOptions; - - const log = Woodcutting.Logs.find(log => log.id === data.logID); - - return `${name} is currently chopping ${log?.name}. ${data.fakeDurationMax === data.fakeDurationMin - ? formattedDuration - : `approximately ${formatDuration( - randomVariation(reduceNumByPercent(durationRemaining, 25), 20) - )} **to** ${formatDuration( - randomVariation(increaseNumByPercent(durationRemaining, 25), 20) - )} remaining.` - } Your ${Emoji.Woodcutting} Woodcutting level is ${user.skillLevel(SkillsEnum.Woodcutting)}`; - } - case 'Runecraft': { - const data = currentTask as RunecraftActivityTaskOptions; - - const rune = Runecraft.Runes.find(_rune => _rune.id === data.runeID); - - return `${name} is currently turning ${data.essenceQuantity}x Essence into ${rune?.name - }. ${formattedDuration} Your ${Emoji.Runecraft} Runecraft level is ${user.skillLevel( - SkillsEnum.Runecraft - )}`; - } - - case 'TiaraRunecraft': { - const data = currentTask as TiaraRunecraftActivityTaskOptions; - const tiara = Runecraft.Tiaras.find(_tiara => _tiara.id === data.tiaraID); - - return `${name} is currently crafting ${data.tiaraQuantity} ${tiara?.name}. ${formattedDuration} Your ${Emoji.Runecraft - } Runecraft level is ${user.skillLevel(SkillsEnum.Runecraft)}`; - } - - case 'FightCaves': { - const data = currentTask as FightCavesActivityTaskOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - return `${name} is currently attempting the ${Emoji.AnimatedFireCape} **Fight caves** ${Emoji.TzRekJad - }. If they're successful and don't die, the trip should take ${formatDuration(durationRemaining)}.`; - } - case 'TitheFarm': { - return `${name} is currently farming at the **Tithe Farm**. ${formattedDuration}`; - } - - case 'Fletching': { - const data = currentTask as FletchingActivityTaskOptions; - - return `${name} is currently fletching ${data.quantity}x ${data.fletchableName - }. ${formattedDuration} Your ${Emoji.Fletching} Fletching level is ${user.skillLevel( - SkillsEnum.Fletching - )}`; - } - case 'Herblore': { - const data = currentTask as HerbloreActivityTaskOptions; - const mixable = Herblore.Mixables.find(i => i.item.id === data.mixableID); - - return `${name} is currently mixing ${data.quantity}x ${mixable?.item.name}. ${formattedDuration} Your ${Emoji.Herblore - } Herblore level is ${user.skillLevel(SkillsEnum.Herblore)}`; - } - case 'CutLeapingFish': { - const data = currentTask as CutLeapingFishActivityTaskOptions; - const barbarianFish = LeapingFish.find(item => item.item.id === data.id); - - return `${name} is currently cutting ${data.quantity}x ${barbarianFish?.item.name - }. ${formattedDuration} Your ${Emoji.Cooking} Cooking level is ${user.skillLevel(SkillsEnum.Cooking)}`; - } - case 'Wintertodt': { - const data = currentTask as ActivityTaskOptionsWithQuantity; - return `${name} is currently fighting Wintertodt ${data.quantity}x times. ${formattedDuration}`; - } - case 'Tempoross': { - return `${name} is currently fighting Tempoross. ${formattedDuration}`; - } - - case 'Alching': { - const data = currentTask as AlchingActivityTaskOptions; - - return `${name} is currently alching ${data.quantity}x ${itemNameFromID( - data.itemID - )}. ${formattedDuration}`; - } - - case 'Farming': { - const data = currentTask as FarmingActivityTaskOptions; - - const plants = Farming.Plants.find(plants => plants.name === data.plantsName); - - return `${name} is currently farming ${data.quantity}x ${plants?.name}. ${formattedDuration} Your ${Emoji.Farming - } Farming level is ${user.skillLevel(SkillsEnum.Farming)}.`; - } - - case 'Sawmill': { - const data = currentTask as SawmillActivityTaskOptions; - const plank = Planks.find(_plank => _plank.outputItem === data.plankID)!; - return `${name} is currently creating ${data.plankQuantity}x ${itemNameFromID( - plank.outputItem - )}s. ${formattedDuration}`; - } - - case 'Nightmare': { - const data = currentTask as NightmareActivityTaskOptions; - return `${name} is currently killing The Nightmare ${data.method === 'solo' ? 'solo' : 'in a team' - }. ${formattedDuration}`; - } - - case 'AnimatedArmour': { - return `${name} is currently fighting animated armour in the Warriors' Guild. ${formattedDuration}`; - } - - case 'Cyclops': { - return `${name} is currently fighting cyclopes in the Warriors' Guild. ${formattedDuration}`; - } - - case 'CamdozaalFishing': { - return `${name} is currently Fishing in the Ruins of Camdozaal. ${formattedDuration}`; - } - - case 'CamdozaalMining': { - return `${name} is currently Mining in the Ruins of Camdozaal. ${formattedDuration}`; - } - - case 'CamdozaalSmithing': { - return `${name} is currently Smithing in the Ruins of Camdozaal. ${formattedDuration}`; - } - - case 'Sepulchre': { - const data = currentTask as SepulchreActivityTaskOptions; - - return `${name} is currently doing ${data.quantity}x laps of the Hallowed Sepulchre. ${formattedDuration}`; - } - - case 'Plunder': { - const data = currentTask as PlunderActivityTaskOptions; - - return `${name} is currently doing Pyramid Plunder x ${data.quantity}x times. ${formattedDuration}`; - } - - case 'FishingTrawler': { - const data = currentTask as ActivityTaskOptionsWithQuantity; - return `${name} is currently aboard the Fishing Trawler, doing ${data.quantity}x trips. ${formattedDuration}`; - } - - case 'Zalcano': { - const data = currentTask as ZalcanoActivityTaskOptions; - return `${name} is currently killing Zalcano ${data.quantity}x times. ${formattedDuration}`; - } - - case 'Pickpocket': { - const data = currentTask as PickpocketActivityTaskOptions; - const obj = stealables.find(_obj => _obj.id === data.monsterID); - return `${name} is currently ${obj?.type === 'pickpockable' ? 'pickpocketing' : 'stealing'} from ${obj?.name - } ${data.quantity}x times. ${formattedDuration}`; - } - - case 'BarbarianAssault': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - return `${name} is currently doing ${data.quantity} waves of Barbarian Assault. ${formattedDuration}`; - } - - case 'AgilityArena': { - return `${name} is currently doing the Brimhaven Agility Arena. ${formattedDuration}`; - } - - case 'ChampionsChallenge': { - return `${name} is currently doing the **Champion's Challenge**. ${formattedDuration}`; - } - - case 'Hunter': { - const data = currentTask as HunterActivityTaskOptions; - - const creature = Hunter.Creatures.find(creature => - creature.aliases.some( - alias => - stringMatches(alias, data.creatureName) || stringMatches(alias.split(' ')[0], data.creatureName) - ) - ); - const crystalImpling = creature?.name === 'Crystal impling'; - return `${name} is currently hunting ${crystalImpling ? creature?.name : `${data.quantity}x ${creature?.name}` - }. ${formattedDuration}`; - } - - case 'Birdhouse': { - return `${name} is currently doing a bird house run. ${formattedDuration}`; - } - - case 'AerialFishing': { - return `${name} is currently aerial fishing. ${formattedDuration}`; - } - - case 'DriftNet': { - return `${name} is currently drift net fishing. ${formattedDuration}`; - } - - case 'Construction': { - const data = currentTask as ConstructionActivityTaskOptions; - const pohObject = Constructables.find(i => i.id === data.objectID); - if (!pohObject) throw new Error(`No POH object found with ID ${data.objectID}.`); - return `${name} is currently building ${data.quantity}x ${pohObject.name}. ${formattedDuration}`; - } - - case 'Butler': { - const data = currentTask as ButlerActivityTaskOptions; - const plank = Planks.find(_plank => _plank.outputItem === data.plankID)!; - return `${name} is currently creating ${data.plankQuantity}x ${itemNameFromID( - plank.outputItem - )}s. ${formattedDuration}`; - } - - case 'MahoganyHomes': { - return `${name} is currently doing Mahogany Homes. ${formattedDuration}`; - } - - case 'Enchanting': { - const data = currentTask as EnchantingActivityTaskOptions; - const enchantable = Enchantables.find(i => i.id === data.itemID); - return `${name} is currently enchanting ${data.quantity}x ${enchantable?.name}. ${formattedDuration}`; - } - - case 'Casting': { - const data = currentTask as CastingActivityTaskOptions; - const spell = Castables.find(i => i.id === data.spellID); - return `${name} is currently casting ${data.quantity}x ${spell?.name}. ${formattedDuration}`; - } - - case 'GloryCharging': { - const data = currentTask as ActivityTaskOptionsWithQuantity; - return `${name} is currently charging ${data.quantity}x inventories of glories at the Fountain of Rune. ${formattedDuration}`; - } - - case 'WealthCharging': { - const data = currentTask as ActivityTaskOptionsWithQuantity; - return `${name} is currently charging ${data.quantity}x inventories of rings of wealth at the Fountain of Rune. ${formattedDuration}`; - } - - case 'GnomeRestaurant': { - return `${name} is currently doing Gnome Restaurant deliveries. ${formattedDuration}`; - } - - case 'SoulWars': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - return `${name} is currently doing ${data.quantity}x games of Soul Wars. ${formattedDuration}`; - } - - case 'RoguesDenMaze': { - return `${name} is currently attempting the Rogues' Den maze. ${formattedDuration}`; - } - - case 'Gauntlet': { - const data = currentTask as GauntletOptions; - return `${name} is currently doing ${data.quantity}x ${data.corrupted ? 'Corrupted' : 'Normal' - } Gauntlet. ${formattedDuration}`; - } - - case 'CastleWars': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - return `${name} is currently doing ${data.quantity}x Castle Wars games. ${formattedDuration}`; - } - - case 'MageArena': { - return `${name} is currently doing the Mage Arena. ${formattedDuration}`; - } - - case 'Raids': { - const data = currentTask as RaidsOptions; - return `${name} is currently doing the Chambers of Xeric${data.challengeMode ? ' in Challenge Mode' : '' - }, ${data.users.length === 1 ? 'as a solo.' : `with a team of ${data.users.length} minions.` - } ${formattedDuration}`; - } - - case 'Collecting': { - const data = currentTask as CollectingOptions; - const collectable = collectables.find(c => c.item.id === data.collectableID)!; - return `${name} is currently collecting ${data.quantity * collectable.quantity}x ${collectable.item.name - }. ${formattedDuration}`; - } - - case 'MageTrainingArena': { - return `${name} is currently training at the Mage Training Arena. ${formattedDuration}`; - } - - case 'MageArena2': { - return `${name} is currently attempting the Mage Arena II. ${formattedDuration}`; - } - - case 'BigChompyBirdHunting': { - return `${name} is currently hunting Chompy Birds! ${formattedDuration}`; - } - - case 'DarkAltar': { - const data = currentTask as DarkAltarOptions; - return `${name} is currently runecrafting ${toTitleCase( - data.rune - )} runes at the Dark Altar. ${formattedDuration}`; - } - case 'Trekking': { - return `${name} is currently Temple Trekking. ${formattedDuration}`; - } - case 'PestControl': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - return `${name} is currently doing ${data.quantity} games of Pest Control. ${formattedDuration}`; - } - case 'VolcanicMine': { - const data = currentTask as ActivityTaskOptionsWithQuantity; - return `${name} is currently doing ${data.quantity} games of Volcanic Mine. ${formattedDuration}`; - } - case 'TearsOfGuthix': { - return `${name} is currently doing Tears Of Guthix. ${formattedDuration}`; - } - case 'KourendFavour': { - const data = currentTask as KourendFavourActivityTaskOptions; - return `${name} is currently doing ${data.favour} Favour tasks. ${formattedDuration}`; - } - case 'Inferno': { - const data = currentTask as InfernoOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - return `${name} is currently attempting the Inferno, if they're successful and don't die, the trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'TheatreOfBlood': { - const data = currentTask as TheatreOfBloodTaskOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - - return `${name} is currently attempting the Theatre of Blood, if your team is successful and doesn't die, the trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'LastManStanding': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - - return `${name} is currently doing ${data.quantity - } Last Man Standing matches, the trip should take ${formatDuration(durationRemaining)}.`; - } - case 'BirthdayEvent': { - return `${name} is currently doing the Birthday Event! The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'TokkulShop': { - return `${name} is currently shopping at Tzhaar stores. The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'Nex': { - const data = currentTask as NexTaskOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - return `${name} is currently killing Nex ${data.quantity} times with a team of ${data.users.length - }. The trip should take ${formatDuration(durationRemaining)}.`; - } - case 'TroubleBrewing': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - return `${name} is currently doing ${data.quantity - }x games of Trouble Brewing. The trip should take ${formatDuration(durationRemaining)}.`; - } - case 'PuroPuro': { - return `${name} is currently hunting in Puro-Puro. The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'ShootingStars': { - return `${name} is currently mining a Crashed Star. The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'GiantsFoundry': { - const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; - return `${name} is currently creating ${data.quantity - }x giant weapons for Kovac in the Giants' Foundry minigame. The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'GuardiansOfTheRift': { - return `${name} is currently helping the Great Guardian to close the rift. The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'NightmareZone': { - return `${name} is currently killing Monsters in the Nightmare Zone. The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'ShadesOfMorton': { - const data = currentTask as ShadesOfMortonOptions; - const log = shadesLogs.find(i => i.normalLog.id === data.logID)!; - const shade = shades.find(i => i.shadeName === data.shadeID)!; - return `${name} is currently doing ${data.quantity} trips of Shades of Mort'ton, cremating ${shade.shadeName - } remains with ${log.oiledLog.name}! The trip should take ${formatDuration(durationRemaining)}.`; - } - case 'TombsOfAmascut': { - const data = currentTask as TOAOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - - return `${name} is currently attempting the Tombs of Amascut, if your team is successful and doesn't die, the trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'UnderwaterAgilityThieving': { - return `${name} is currently doing Underwater Agility and Thieving. ${formattedDuration}`; - } - case 'StrongholdOfSecurity': { - return `${name} is currently doing the Stronghold of Security! The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'CombatRing': { - return `${name} is currently fighting in the Combat Ring! The trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'SpecificQuest': { - const data = currentTask as SpecificQuestOptions; - return `${name} is currently doing the ${quests.find(i => i.id === data.questID)?.name - }! The trip should take ${formatDuration(durationRemaining)}.`; - } - case 'Colosseum': { - const data = currentTask as ColoTaskOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - - return `${name} is currently attempting the Colosseum, if they are successful, the trip should take ${formatDuration( - durationRemaining - )}.`; - } - case 'HalloweenEvent': { - return `${name} is doing the Halloween event! The trip should take ${formatDuration(durationRemaining)}.`; - } - case 'Easter': - case 'BlastFurnace': { - throw new Error('Removed'); - } - } -} diff --git a/minions.ts b/minions.ts deleted file mode 100644 index edeb891466..0000000000 --- a/minions.ts +++ /dev/null @@ -1,622 +0,0 @@ -import type { CropUpgradeType } from '@prisma/client'; - -import type { ItemBank } from '.'; -import type { NMZStrategy, TwitcherGloves, UnderwaterAgilityThievingTrainingSkill } from '../constants'; -import type { IPatchData } from '../minions/farming/types'; -import type { MinigameName } from '../settings/minigames'; -import type { RaidLevel } from '../simulation/toa'; -import type { Peak } from '../tickers'; -import type { BirdhouseData } from './../skilling/skills/hunter/defaultBirdHouseTrap'; - -export interface ActivityTaskOptions { - userID: string; - duration: number; - id: number; - finishDate: number; - channelID: string; -} - -export interface ActivityTaskOptionsWithNoChanges extends ActivityTaskOptions { - type: - | 'Questing' - | 'Wintertodt' - | 'Cyclops' - | 'GloryCharging' - | 'WealthCharging' - | 'BarbarianAssault' - | 'AgilityArena' - | 'ChampionsChallenge' - | 'AerialFishing' - | 'DriftNet' - | 'SoulWars' - | 'RoguesDenMaze' - | 'CastleWars' - | 'MageArena' - | 'MageTrainingArena' - | 'BlastFurnace' - | 'MageArena2' - | 'BigChompyBirdHunting' - | 'PestControl' - | 'VolcanicMine' - | 'TearsOfGuthix' - | 'LastManStanding' - | 'BirthdayEvent' - | 'TroubleBrewing' - | 'Easter' - | 'ShootingStars' - | 'HalloweenEvent' - | 'StrongholdOfSecurity' - | 'CombatRing'; -} - -export interface ActivityTaskOptionsWithQuantity extends ActivityTaskOptions { - type: - | 'VolcanicMine' - | 'Cyclops' - | 'ShootingStars' - | 'DriftNet' - | 'WealthCharging' - | 'GloryCharging' - | 'AerialFishing' - | 'FishingTrawler' - | 'CamdozaalFishing' - | 'CamdozaalMining' - | 'CamdozaalSmithing'; - quantity: number; - // iQty is 'input quantity.' This is the number specified at command time, so we can accurately repeat such trips. - iQty?: number; -} - -export interface ShootingStarsOptions extends ActivityTaskOptions { - type: 'ShootingStars'; - size: number; - usersWith: number; - totalXp: number; - lootItems: ItemBank; -} -interface ActivityTaskOptionsWithUsers extends ActivityTaskOptions { - users: string[]; -} - -export interface RunecraftActivityTaskOptions extends ActivityTaskOptions { - type: 'Runecraft'; - runeID: number; - essenceQuantity: number; - imbueCasts: number; - useStaminas?: boolean; - daeyaltEssence?: boolean; -} - -export interface TiaraRunecraftActivityTaskOptions extends ActivityTaskOptions { - type: 'TiaraRunecraft'; - tiaraID: number; - tiaraQuantity: number; -} - -export interface DarkAltarOptions extends ActivityTaskOptions { - type: 'DarkAltar'; - quantity: number; - hasElite: boolean; - rune: 'blood' | 'soul'; -} - -export interface AgilityActivityTaskOptions extends ActivityTaskOptions { - type: 'Agility'; - courseID: string; - quantity: number; - alch: { - itemID: number; - quantity: number; - } | null; -} - -export interface CookingActivityTaskOptions extends ActivityTaskOptions { - type: 'Cooking'; - cookableID: number; - quantity: number; -} - -export interface ConstructionActivityTaskOptions extends ActivityTaskOptions { - type: 'Construction'; - objectID: number; - quantity: number; -} - -export interface MonsterActivityTaskOptions extends ActivityTaskOptions { - type: 'MonsterKilling'; - monsterID: number; - quantity: number; - iQty?: number; - usingCannon?: boolean; - cannonMulti?: boolean; - chinning?: boolean; - burstOrBarrage?: number; - died?: boolean; - pkEncounters?: number; - hasWildySupplies?: boolean; - isInWilderness?: boolean; -} - -export interface ClueActivityTaskOptions extends ActivityTaskOptions { - type: 'ClueCompletion'; - - clueID: number; - quantity: number; - implingID?: number; - implingClues?: number; -} - -export interface FishingActivityTaskOptions extends ActivityTaskOptions { - type: 'Fishing'; - fishID: number; - quantity?: number; - Qty1: number; - Qty2?: number; - Qty3?: number; - loot1?: number; - loot2?: number; - loot3?: number; - flakesToRemove?: number; - powerfish?: boolean; - spirit_flakes?: boolean; -} - - -export interface MiningActivityTaskOptions extends ActivityTaskOptions { - type: 'Mining'; - fakeDurationMax: number; - fakeDurationMin: number; - oreID: number; - quantity: number; - powermine: boolean; - iQty?: number; -} - -export interface MotherlodeMiningActivityTaskOptions extends ActivityTaskOptions { - type: 'MotherlodeMining'; - fakeDurationMax: number; - fakeDurationMin: number; - quantity: number; - iQty?: number; -} - -export interface SmeltingActivityTaskOptions extends ActivityTaskOptions { - type: 'Smelting'; - barID: number; - quantity: number; - blastf: boolean; -} - -export interface SmithingActivityTaskOptions extends ActivityTaskOptions { - type: 'Smithing'; - smithedBarID: number; - quantity: number; -} - -export interface FiremakingActivityTaskOptions extends ActivityTaskOptions { - type: 'Firemaking'; - burnableID: number; - quantity: number; -} - -export interface WoodcuttingActivityTaskOptions extends ActivityTaskOptions { - type: 'Woodcutting'; - fakeDurationMax: number; - fakeDurationMin: number; - powerchopping: boolean; - forestry?: boolean; - twitchers?: TwitcherGloves; - logID: number; - quantity: number; - iQty?: number; -} - -export interface CraftingActivityTaskOptions extends ActivityTaskOptions { - type: 'Crafting'; - craftableID: number; - quantity: number; -} - -export interface FletchingActivityTaskOptions extends ActivityTaskOptions { - type: 'Fletching'; - fletchableName: string; - quantity: number; -} - -export interface EnchantingActivityTaskOptions extends ActivityTaskOptions { - type: 'Enchanting'; - itemID: number; - quantity: number; -} - -export interface CastingActivityTaskOptions extends ActivityTaskOptions { - type: 'Casting'; - spellID: number; - quantity: number; -} -export interface PickpocketActivityTaskOptions extends ActivityTaskOptions { - type: 'Pickpocket'; - monsterID: number; - quantity: number; - xpReceived: number; - successfulQuantity: number; - damageTaken: number; -} - -export interface BuryingActivityTaskOptions extends ActivityTaskOptions { - type: 'Burying'; - boneID: number; - quantity: number; -} - -export interface ScatteringActivityTaskOptions extends ActivityTaskOptions { - type: 'Scattering'; - ashID: number; - quantity: number; -} - -export interface OfferingActivityTaskOptions extends ActivityTaskOptions { - type: 'Offering'; - boneID: number; - quantity: number; -} - -export interface AnimatedArmourActivityTaskOptions extends ActivityTaskOptions { - type: 'AnimatedArmour'; - armourID: string; - quantity: number; -} - -export interface HerbloreActivityTaskOptions extends ActivityTaskOptions { - type: 'Herblore'; - mixableID: number; - quantity: number; - zahur: boolean; - wesley: boolean; -} - -export interface CutLeapingFishActivityTaskOptions extends ActivityTaskOptions { - type: 'CutLeapingFish'; - fishID: number; - quantity: number; -} - -export interface HunterActivityTaskOptions extends ActivityTaskOptions { - type: 'Hunter'; - creatureName: string; - quantity: number; - usingHuntPotion: boolean; - wildyPeak: Peak | null; - usingStaminaPotion: boolean; -} - -export interface AlchingActivityTaskOptions extends ActivityTaskOptions { - type: 'Alching'; - itemID: number; - quantity: number; - alchValue: number; -} - -export interface FightCavesActivityTaskOptions extends ActivityTaskOptions { - type: 'FightCaves'; - jadDeathChance: number; - preJadDeathChance: number; - preJadDeathTime: number | null; - fakeDuration: number; - quantity: number; -} -export interface InfernoOptions extends ActivityTaskOptions { - type: 'Inferno'; - zukDeathChance: number; - preZukDeathChance: number; - deathTime: number | null; - fakeDuration: number; - diedZuk: boolean; - diedPreZuk: boolean; - cost: ItemBank; -} - -export interface FarmingActivityTaskOptions extends ActivityTaskOptions { - type: 'Farming'; - pid?: number; - plantsName: string | null; - quantity: number; - upgradeType: CropUpgradeType | null; - payment?: boolean; - patchType: IPatchData; - planting: boolean; - currentDate: number; - autoFarmed: boolean; -} - -export interface BirdhouseActivityTaskOptions extends ActivityTaskOptions { - type: 'Birdhouse'; - birdhouseName: string | null; - placing: boolean; - gotCraft: boolean; - birdhouseData: BirdhouseData; - currentDate: number; -} - -interface MinigameActivityTaskOptions extends ActivityTaskOptions { - minigameID: MinigameName; - quantity: number; -} - -export interface MinigameActivityTaskOptionsWithNoChanges extends MinigameActivityTaskOptions { - type: - | 'Wintertodt' - | 'TroubleBrewing' - | 'TearsOfGuthix' - | 'SoulWars' - | 'RoguesDenMaze' - | 'MageTrainingArena' - | 'LastManStanding' - | 'BigChompyBirdHunting' - | 'FishingTrawler' - | 'PestControl' - | 'BarbarianAssault' - | 'ChampionsChallenge' - | 'CastleWars' - | 'AgilityArena' - | 'GiantsFoundry'; -} - -export interface MahoganyHomesActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'MahoganyHomes'; - xp: number; - quantity: number; - points: number; - tier: number; -} - -export interface NightmareActivityTaskOptions extends ActivityTaskOptions { - type: 'Nightmare'; - method: 'solo' | 'mass'; - quantity: number; - isPhosani?: boolean; -} - -export interface TemporossActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'Tempoross'; - quantity: number; - rewardBoost: number; -} - -export interface TitheFarmActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'TitheFarm'; -} - -export interface SepulchreActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'Sepulchre'; - floors: number[]; -} - -export interface PlunderActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'Plunder'; - rooms: number[]; -} - -export interface ZalcanoActivityTaskOptions extends ActivityTaskOptions { - type: 'Zalcano'; - isMVP: boolean; - performance: number; - quantity: number; -} - -export interface TempleTrekkingActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'Trekking'; - difficulty: string; -} - -export interface SawmillActivityTaskOptions extends ActivityTaskOptions { - type: 'Sawmill'; - plankID: number; - plankQuantity: number; -} - -export interface ButlerActivityTaskOptions extends ActivityTaskOptions { - type: 'Butler'; - plankID: number; - plankQuantity: number; -} - -export interface GnomeRestaurantActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'GnomeRestaurant'; - gloriesRemoved: number; -} - -export interface GauntletOptions extends ActivityTaskOptions { - type: 'Gauntlet'; - corrupted: boolean; - quantity: number; -} - -export interface GroupMonsterActivityTaskOptions extends Omit { - type: 'GroupMonsterKilling'; - leader: string; - users: string[]; -} - -export interface RaidsOptions extends ActivityTaskOptionsWithUsers { - type: 'Raids'; - leader: string; - users: string[]; - challengeMode: boolean; - quantity?: number; -} - -export interface TheatreOfBloodTaskOptions extends ActivityTaskOptionsWithUsers { - type: 'TheatreOfBlood'; - leader: string; - users: string[]; - hardMode: boolean; - fakeDuration: number; - wipedRooms: (null | number)[]; - deaths: number[][][]; - quantity: number; - solo?: boolean; -} - -export interface ColoTaskOptions extends ActivityTaskOptions { - type: 'Colosseum'; - fakeDuration: number; - diedAt?: number; - loot?: ItemBank; - maxGlory: number; -} - -type UserID = string; -type Points = number; -type RoomIDsDiedAt = number[]; - -type TOAUser = [UserID, Points[], RoomIDsDiedAt[]]; -export interface TOAOptions extends ActivityTaskOptionsWithUsers { - type: 'TombsOfAmascut'; - leader: string; - detailedUsers: TOAUser[] | [UserID, Points, RoomIDsDiedAt][][]; - raidLevel: RaidLevel; - fakeDuration: number; - wipedRoom: null | number | (number | null)[]; - quantity: number; -} - -export interface NexTaskOptions extends ActivityTaskOptionsWithUsers { - type: 'Nex'; - quantity: number; - leader: string; - userDetails: [string, number, number[]][]; - fakeDuration: number; - wipedKill: number | null; -} - -export interface CollectingOptions extends ActivityTaskOptions { - type: 'Collecting'; - collectableID: number; - quantity: number; - noStaminas?: boolean; -} - -export interface KourendFavourActivityTaskOptions extends ActivityTaskOptions { - type: 'KourendFavour'; - favour: string; - quantity: number; -} - -export interface TokkulShopOptions extends ActivityTaskOptions { - type: 'TokkulShop'; - itemID: number; - quantity: number; -} - -export interface UnderwaterAgilityThievingTaskOptions extends ActivityTaskOptions { - type: 'UnderwaterAgilityThieving'; - trainingSkill: UnderwaterAgilityThievingTrainingSkill; - quantity: number; - noStams: boolean; -} - -export interface PuroPuroActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'PuroPuro'; - quantity: number; - darkLure: boolean; - implingTier: number | null; -} - -export interface GiantsFoundryActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'GiantsFoundry'; - alloyID: number; - quantity: number; - metalScore: number; -} - -export interface GuardiansOfTheRiftActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'GuardiansOfTheRift'; - minedFragments: number; - barrierAndGuardian: number; - rolls: number; - combinationRunes: boolean; -} - -export interface NightmareZoneActivityTaskOptions extends MinigameActivityTaskOptions { - type: 'NightmareZone'; - strategy: NMZStrategy; - quantity: number; -} - -export interface ShadesOfMortonOptions extends MinigameActivityTaskOptions { - type: 'ShadesOfMorton'; - shadeID: string; - logID: number; -} -export interface SpecificQuestOptions extends ActivityTaskOptions { - type: 'SpecificQuest'; - questID: number; -} - -export type ActivityTaskData = - | MonsterActivityTaskOptions - | WoodcuttingActivityTaskOptions - | CollectingOptions - | RaidsOptions - | GauntletOptions - | CastingActivityTaskOptions - | EnchantingActivityTaskOptions - | ConstructionActivityTaskOptions - | HunterActivityTaskOptions - | ZalcanoActivityTaskOptions - | SawmillActivityTaskOptions - | ButlerActivityTaskOptions - | FarmingActivityTaskOptions - | HerbloreActivityTaskOptions - | FletchingActivityTaskOptions - | RunecraftActivityTaskOptions - | TempleTrekkingActivityTaskOptions - | TemporossActivityTaskOptions - | PuroPuroActivityTaskOptions - | KourendFavourActivityTaskOptions - | AgilityActivityTaskOptions - | InfernoOptions - | TOAOptions - | NexTaskOptions - | ZalcanoActivityTaskOptions - | TheatreOfBloodTaskOptions - | GuardiansOfTheRiftActivityTaskOptions - | GiantsFoundryActivityTaskOptions - | NightmareZoneActivityTaskOptions - | ShadesOfMortonOptions - | UnderwaterAgilityThievingTaskOptions - | PickpocketActivityTaskOptions - | BuryingActivityTaskOptions - | ScatteringActivityTaskOptions - | OfferingActivityTaskOptions - | AnimatedArmourActivityTaskOptions - | CookingActivityTaskOptions - | CraftingActivityTaskOptions - | FiremakingActivityTaskOptions - | FishingActivityTaskOptions - | MiningActivityTaskOptions - | MotherlodeMiningActivityTaskOptions - | PlunderActivityTaskOptions - | SmithingActivityTaskOptions - | SmeltingActivityTaskOptions - | TiaraRunecraftActivityTaskOptions - | ClueActivityTaskOptions - | AlchingActivityTaskOptions - | DarkAltarOptions - | GroupMonsterActivityTaskOptions - | MahoganyHomesActivityTaskOptions - | NightmareActivityTaskOptions - | TitheFarmActivityTaskOptions - | SepulchreActivityTaskOptions - | GnomeRestaurantActivityTaskOptions - | SpecificQuestOptions - | ActivityTaskOptionsWithNoChanges - | TokkulShopOptions - | BirdhouseActivityTaskOptions - | FightCavesActivityTaskOptions - | ActivityTaskOptionsWithQuantity - | MinigameActivityTaskOptionsWithNoChanges - | CutLeapingFishActivityTaskOptions - | ColoTaskOptions; - diff --git a/repeatStoredTrip.ts b/repeatStoredTrip.ts deleted file mode 100644 index 329a168b0a..0000000000 --- a/repeatStoredTrip.ts +++ /dev/null @@ -1,716 +0,0 @@ -import type { Activity, Prisma } from '@prisma/client'; -import { activity_type_enum } from '@prisma/client'; -import type { ButtonInteraction } from 'discord.js'; -import { ButtonBuilder, ButtonStyle } from 'discord.js'; -import { Time } from 'e'; - -import { autocompleteMonsters } from '../../mahoji/commands/k'; -import type { PvMMethod } from '../constants'; -import { SlayerActivityConstants } from '../minions/data/combatConstants'; -import { darkAltarRunes } from '../minions/functions/darkAltarCommand'; -import { convertStoredActivityToFlatActivity } from '../settings/prisma'; -import { runCommand } from '../settings/settings'; -import type { - ActivityTaskOptionsWithQuantity, - AgilityActivityTaskOptions, - AlchingActivityTaskOptions, - AnimatedArmourActivityTaskOptions, - BuryingActivityTaskOptions, - ButlerActivityTaskOptions, - CastingActivityTaskOptions, - ClueActivityTaskOptions, - CollectingOptions, - ConstructionActivityTaskOptions, - CookingActivityTaskOptions, - CraftingActivityTaskOptions, - CutLeapingFishActivityTaskOptions, - DarkAltarOptions, - EnchantingActivityTaskOptions, - FarmingActivityTaskOptions, - FiremakingActivityTaskOptions, - FishingActivityTaskOptions, - FletchingActivityTaskOptions, - GauntletOptions, - GiantsFoundryActivityTaskOptions, - GroupMonsterActivityTaskOptions, - GuardiansOfTheRiftActivityTaskOptions, - HerbloreActivityTaskOptions, - HunterActivityTaskOptions, - MahoganyHomesActivityTaskOptions, - MiningActivityTaskOptions, - MonsterActivityTaskOptions, - MotherlodeMiningActivityTaskOptions, - NexTaskOptions, - NightmareActivityTaskOptions, - OfferingActivityTaskOptions, - PickpocketActivityTaskOptions, - PuroPuroActivityTaskOptions, - RaidsOptions, - RunecraftActivityTaskOptions, - SawmillActivityTaskOptions, - ScatteringActivityTaskOptions, - ShadesOfMortonOptions, - SmeltingActivityTaskOptions, - SmithingActivityTaskOptions, - TOAOptions, - TempleTrekkingActivityTaskOptions, - TheatreOfBloodTaskOptions, - TiaraRunecraftActivityTaskOptions, - WoodcuttingActivityTaskOptions, - ZalcanoActivityTaskOptions -} from '../types/minions'; -import { itemNameFromID } from '../util'; -import { giantsFoundryAlloys } from './../../mahoji/lib/abstracted_commands/giantsFoundryCommand'; -import type { NightmareZoneActivityTaskOptions, UnderwaterAgilityThievingTaskOptions } from './../types/minions'; -import getOSItem from './getOSItem'; -import { deferInteraction } from './interactionReply'; - -const taskCanBeRepeated = (activity: Activity) => { - if (activity.type === activity_type_enum.ClueCompletion) { - const realActivity = convertStoredActivityToFlatActivity(activity) as ClueActivityTaskOptions; - return realActivity.implingID !== undefined; - } - return !( - [ - activity_type_enum.TearsOfGuthix, - activity_type_enum.ShootingStars, - activity_type_enum.BirthdayEvent, - activity_type_enum.BlastFurnace, - activity_type_enum.Easter, - activity_type_enum.TokkulShop, - activity_type_enum.Birdhouse, - activity_type_enum.StrongholdOfSecurity, - activity_type_enum.CombatRing - ] as activity_type_enum[] - ).includes(activity.type); -}; - -const tripHandlers = { - [activity_type_enum.ClueCompletion]: { - commandName: 'clue', - args: (data: ClueActivityTaskOptions) => ({ tier: data.clueID, implings: getOSItem(data.implingID!).name }) - }, - [activity_type_enum.SpecificQuest]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.HalloweenEvent]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.Birdhouse]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.StrongholdOfSecurity]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.CombatRing]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.TearsOfGuthix]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.TokkulShop]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.ShootingStars]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.BirthdayEvent]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.BlastFurnace]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.Easter]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.Revenants]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.KourendFavour]: { - commandName: 'm', - args: () => ({}) - }, - [activity_type_enum.AerialFishing]: { - commandName: 'activities', - args: () => ({ aerial_fishing: {} }) - }, - [activity_type_enum.Agility]: { - commandName: 'laps', - args: (data: AgilityActivityTaskOptions) => ({ - name: data.courseID, - quantity: data.quantity, - alch: Boolean(data.alch) - }) - }, - [activity_type_enum.AgilityArena]: { - commandName: 'minigames', - args: () => ({ agility_arena: { start: {} } }) - }, - [activity_type_enum.Alching]: { - commandName: 'activities', - args: (data: AlchingActivityTaskOptions) => ({ - alch: { quantity: data.quantity, item: itemNameFromID(data.itemID) } - }) - }, - [activity_type_enum.AnimatedArmour]: { - commandName: 'activities', - args: (data: AnimatedArmourActivityTaskOptions) => ({ - warriors_guild: { action: 'tokens', quantity: data.quantity } - }) - }, - [activity_type_enum.CamdozaalMining]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ - camdozaal: { action: 'mining', quantity: data.iQty } - }) - }, - [activity_type_enum.CamdozaalSmithing]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ - camdozaal: { action: 'smithing', quantity: data.quantity } - }) - }, - [activity_type_enum.CamdozaalFishing]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ - camdozaal: { action: 'fishing', quantity: data.iQty } - }) - }, - [activity_type_enum.BarbarianAssault]: { - commandName: 'minigames', - args: () => ({ barb_assault: { start: {} } }) - }, - [activity_type_enum.BigChompyBirdHunting]: { - commandName: 'activities', - args: () => ({ chompy_hunt: { action: 'start' } }) - }, - [activity_type_enum.Smelting]: { - commandName: 'smelt', - args: (data: SmeltingActivityTaskOptions) => ({ - name: itemNameFromID(data.barID), - quantity: data.quantity, - blast_furnace: data.blastf - }) - }, - [activity_type_enum.Burying]: { - commandName: 'activities', - args: (data: BuryingActivityTaskOptions) => ({ - bury: { quantity: data.quantity, name: itemNameFromID(data.boneID) } - }) - }, - [activity_type_enum.Scattering]: { - commandName: 'activities', - args: (data: ScatteringActivityTaskOptions) => ({ - scatter: { quantity: data.quantity, name: itemNameFromID(data.ashID) } - }) - }, - [activity_type_enum.Casting]: { - commandName: 'activities', - args: (data: CastingActivityTaskOptions) => ({ cast: { spell: data.spellID, quantity: data.quantity } }) - }, - [activity_type_enum.CastleWars]: { - commandName: 'minigames', - args: () => ({ castle_wars: { start: {} } }) - }, - [activity_type_enum.ChampionsChallenge]: { - commandName: 'activities', - args: () => ({ champions_challenge: {} }) - }, - [activity_type_enum.Collecting]: { - commandName: 'activities', - args: (data: CollectingOptions) => ({ - collect: { item: itemNameFromID(data.collectableID), no_stams: data.noStaminas, quantity: data.quantity } - }) - }, - [activity_type_enum.Construction]: { - commandName: 'build', - args: (data: ConstructionActivityTaskOptions) => ({ name: data.objectID, quantity: data.quantity }) - }, - [activity_type_enum.Cooking]: { - commandName: 'cook', - args: (data: CookingActivityTaskOptions) => ({ - name: itemNameFromID(data.cookableID), - quantity: data.quantity - }) - }, - [activity_type_enum.Crafting]: { - commandName: 'craft', - args: (data: CraftingActivityTaskOptions) => ({ - name: itemNameFromID(data.craftableID), - quantity: data.quantity - }) - }, - [activity_type_enum.Cyclops]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ - warriors_guild: { action: 'cyclops', quantity: data.quantity } - }) - }, - [activity_type_enum.DarkAltar]: { - commandName: 'runecraft', - args: (data: DarkAltarOptions) => ({ rune: `${darkAltarRunes[data.rune].item.name} (zeah)` }) - }, - [activity_type_enum.Runecraft]: { - commandName: 'runecraft', - args: (data: RunecraftActivityTaskOptions) => ({ - rune: itemNameFromID(data.runeID), - quantity: data.essenceQuantity, - daeyalt_essence: data.daeyaltEssence, - usestams: data.useStaminas - }) - }, - [activity_type_enum.TiaraRunecraft]: { - commandName: 'runecraft', - args: (data: TiaraRunecraftActivityTaskOptions) => ({ - rune: itemNameFromID(data.tiaraID), - quantity: data.tiaraQuantity - }) - }, - [activity_type_enum.Enchanting]: { - commandName: 'activities', - args: (data: EnchantingActivityTaskOptions) => ({ - enchant: { quantity: data.quantity, name: itemNameFromID(data.itemID) } - }) - }, - [activity_type_enum.Farming]: { - commandName: 'farming', - args: (data: FarmingActivityTaskOptions) => - data.autoFarmed - ? { - auto_farm: {} - } - : {} - }, - [activity_type_enum.FightCaves]: { - commandName: 'activities', - args: () => ({ fight_caves: {} }) - }, - [activity_type_enum.Firemaking]: { - commandName: 'light', - args: (data: FiremakingActivityTaskOptions) => ({ - name: itemNameFromID(data.burnableID), - quantity: data.quantity - }) - }, - [activity_type_enum.Fishing]: { - commandName: 'fish', - args: (data: FishingActivityTaskOptions) => ({ - name: data.fishID, - quantity: data.quantity, - powerfish: data.powerfish ?? false, - spirit_flakes: data.spirit_flakes ?? false - }) - - }, - [activity_type_enum.FishingTrawler]: { - commandName: 'minigames', - args: () => ({ fishing_trawler: { start: {} } }) - }, - [activity_type_enum.Fletching]: { - commandName: 'fletch', - args: (data: FletchingActivityTaskOptions) => ({ name: data.fletchableName, quantity: data.quantity }) - }, - [activity_type_enum.Gauntlet]: { - commandName: 'minigames', - args: (data: GauntletOptions) => ({ gauntlet: { start: { corrupted: data.corrupted } } }) - }, - [activity_type_enum.GloryCharging]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ charge: { item: 'glory', quantity: data.quantity } }) - }, - [activity_type_enum.GnomeRestaurant]: { - commandName: 'minigames', - args: () => ({ gnome_restaurant: { start: {} } }) - }, - [activity_type_enum.GroupMonsterKilling]: { - commandName: 'mass', - args: (data: GroupMonsterActivityTaskOptions) => ({ - monster: autocompleteMonsters.find(i => i.id === data.monsterID)?.name ?? data.monsterID.toString() - }) - }, - [activity_type_enum.Herblore]: { - commandName: 'mix', - args: (data: HerbloreActivityTaskOptions) => ({ - name: itemNameFromID(data.mixableID), - quantity: data.quantity, - zahur: data.zahur - }) - }, - [activity_type_enum.CutLeapingFish]: { - commandName: 'cook', - args: (data: CutLeapingFishActivityTaskOptions) => ({ - name: itemNameFromID(data.fishID), - quantity: data.quantity - }) - }, - [activity_type_enum.Hunter]: { - commandName: 'hunt', - args: (data: HunterActivityTaskOptions) => ({ - name: data.creatureName, - quantity: data.quantity, - hunter_potion: data.usingHuntPotion, - stamina_potions: data.usingStaminaPotion - }) - }, - [activity_type_enum.Inferno]: { - commandName: 'activities', - args: () => ({ inferno: { action: 'start' } }) - }, - [activity_type_enum.LastManStanding]: { - commandName: 'minigames', - args: () => ({ lms: { start: {} } }) - }, - [activity_type_enum.MageArena]: { - commandName: 'minigames', - args: () => ({ mage_arena: { start: {} } }) - }, - [activity_type_enum.MageArena2]: { - commandName: 'minigames', - args: () => ({ mage_arena_2: { start: {} } }) - }, - [activity_type_enum.MageTrainingArena]: { - commandName: 'minigames', - args: () => ({ mage_training_arena: { start: {} } }) - }, - [activity_type_enum.MahoganyHomes]: { - commandName: 'minigames', - args: (data: MahoganyHomesActivityTaskOptions) => ({ mahogany_homes: { start: { tier: data.tier } } }) - }, - [activity_type_enum.Mining]: { - commandName: 'mine', - args: (data: MiningActivityTaskOptions) => ({ - name: data.oreID, - quantity: data.iQty, - powermine: data.powermine - }) - }, - [activity_type_enum.MotherlodeMining]: { - commandName: 'mine', - args: (data: MotherlodeMiningActivityTaskOptions) => ({ - name: 'Motherlode mine', - quantity: data.iQty - }) - }, - [activity_type_enum.MonsterKilling]: { - commandName: 'k', - args: (data: MonsterActivityTaskOptions) => { - let method: PvMMethod = 'none'; - if (data.usingCannon) method = 'cannon'; - if (data.chinning) method = 'chinning'; - else if (data.burstOrBarrage === SlayerActivityConstants.IceBarrage) method = 'barrage'; - else if (data.burstOrBarrage === SlayerActivityConstants.IceBurst) method = 'burst'; - return { - name: autocompleteMonsters.find(i => i.id === data.monsterID)?.name ?? data.monsterID.toString(), - quantity: data.iQty, - method, - wilderness: data.isInWilderness - }; - } - }, - [activity_type_enum.Nex]: { - commandName: 'k', - args: (data: NexTaskOptions) => { - return { - name: 'nex', - quantity: data.quantity, - solo: data.userDetails.length === 1 - }; - } - }, - [activity_type_enum.Zalcano]: { - commandName: 'k', - args: (data: ZalcanoActivityTaskOptions) => ({ - name: 'zalcano', - quantity: data.quantity - }) - }, - [activity_type_enum.Tempoross]: { - commandName: 'k', - args: () => ({ - name: 'tempoross' - }) - }, - [activity_type_enum.Wintertodt]: { - commandName: 'k', - args: (data: ActivityTaskOptionsWithQuantity) => ({ - name: 'wintertodt', - quantity: data.quantity - }) - }, - [activity_type_enum.Nightmare]: { - commandName: 'k', - args: (data: NightmareActivityTaskOptions) => ({ - name: data.isPhosani ? 'phosani nightmare' : data.method === 'mass' ? 'mass nightmare' : 'solo nightmare', - quantity: data.quantity - }) - }, - [activity_type_enum.Offering]: { - commandName: 'offer', - args: (data: OfferingActivityTaskOptions) => ({ quantity: data.quantity, name: itemNameFromID(data.boneID) }) - }, - [activity_type_enum.PestControl]: { - commandName: 'minigames', - args: () => ({ pest_control: { start: {} } }) - }, - [activity_type_enum.Pickpocket]: { - commandName: 'steal', - args: (data: PickpocketActivityTaskOptions) => ({ name: data.monsterID, quantity: data.quantity }) - }, - [activity_type_enum.Plunder]: { - commandName: 'minigames', - args: () => ({ pyramid_plunder: {} }) - }, - [activity_type_enum.PuroPuro]: { - commandName: 'activities', - args: (data: PuroPuroActivityTaskOptions) => ({ - puro_puro: { implingTier: data.implingTier || '', dark_lure: data.darkLure } - }) - }, - [activity_type_enum.Questing]: { - commandName: 'activities', - args: () => ({ - quest: {} - }) - }, - [activity_type_enum.Raids]: { - commandName: 'raid', - args: (data: RaidsOptions) => ({ - cox: { - start: { - challenge_mode: data.challengeMode, - type: data.users.length === 1 ? 'solo' : 'mass', - quantity: data.quantity - } - } - }) - }, - [activity_type_enum.RoguesDenMaze]: { - commandName: 'minigames', - args: () => ({ - rogues_den: {} - }) - }, - [activity_type_enum.Sawmill]: { - commandName: 'activities', - args: (data: SawmillActivityTaskOptions) => ({ - plank_make: { action: 'sawmill', quantity: data.plankQuantity, type: itemNameFromID(data.plankID) } - }) - }, - [activity_type_enum.Butler]: { - commandName: 'activities', - args: (data: ButlerActivityTaskOptions) => ({ - plank_make: { action: 'butler', quantity: data.plankQuantity, type: itemNameFromID(data.plankID) } - }) - }, - [activity_type_enum.Sepulchre]: { - commandName: 'minigames', - args: () => ({ sepulchre: { start: {} } }) - }, - [activity_type_enum.Smithing]: { - commandName: 'smith', - args: (data: SmithingActivityTaskOptions) => ({ - name: itemNameFromID(data.smithedBarID), - quantity: data.quantity - }) - }, - [activity_type_enum.SoulWars]: { - commandName: 'minigames', - args: () => ({ soul_wars: { start: {} } }) - }, - [activity_type_enum.TheatreOfBlood]: { - commandName: 'raid', - args: (data: TheatreOfBloodTaskOptions) => ({ - tob: { - start: { - hard_mode: data.hardMode, - solo: data.solo - } - } - }) - }, - [activity_type_enum.TitheFarm]: { - commandName: 'farming', - args: () => ({ tithe_farm: {} }) - }, - [activity_type_enum.Trekking]: { - commandName: 'minigames', - args: (data: TempleTrekkingActivityTaskOptions) => ({ - temple_trek: { start: { difficulty: data.difficulty, quantity: data.quantity } } - }) - }, - [activity_type_enum.TroubleBrewing]: { - commandName: 'minigames', - args: () => ({ trouble_brewing: { start: {} } }) - }, - [activity_type_enum.VolcanicMine]: { - commandName: 'minigames', - args: (data: ActivityTaskOptionsWithQuantity) => ({ volcanic_mine: { start: { quantity: data.quantity } } }) - }, - [activity_type_enum.WealthCharging]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ charge: { item: 'wealth', quantity: data.quantity } }) - }, - [activity_type_enum.Woodcutting]: { - commandName: 'chop', - args: (data: WoodcuttingActivityTaskOptions) => ({ - name: itemNameFromID(data.logID), - quantity: data.iQty, - powerchop: data.powerchopping, - forestry_events: data.forestry, - twitchers_gloves: data.twitchers - }) - }, - [activity_type_enum.GiantsFoundry]: { - commandName: 'minigames', - args: (data: GiantsFoundryActivityTaskOptions) => ({ - giants_foundry: { - start: { name: giantsFoundryAlloys.find(i => i.id === data.alloyID)?.name, quantity: data.quantity } - } - }) - }, - [activity_type_enum.GuardiansOfTheRift]: { - commandName: 'minigames', - args: (data: GuardiansOfTheRiftActivityTaskOptions) => ({ - gotr: { - start: { combination_runes: data.combinationRunes } - } - }) - }, - [activity_type_enum.NightmareZone]: { - commandName: 'minigames', - args: (data: NightmareZoneActivityTaskOptions) => ({ - nmz: { - start: { strategy: data.strategy } - } - }) - }, - [activity_type_enum.ShadesOfMorton]: { - commandName: 'minigames', - args: (data: ShadesOfMortonOptions) => ({ - shades_of_morton: { - start: { shade: data.shadeID, logs: itemNameFromID(data.logID) } - } - }) - }, - [activity_type_enum.TombsOfAmascut]: { - commandName: 'raid', - args: (data: TOAOptions) => ({ - toa: { - start: { - raid_level: data.raidLevel, - max_team_size: data.users.length, - solo: data.users.length === 1, - quantity: data.quantity - } - } - }) - }, - [activity_type_enum.UnderwaterAgilityThieving]: { - commandName: 'activities', - args: (data: UnderwaterAgilityThievingTaskOptions) => ({ - underwater: { - agility_thieving: { - training_skill: data.trainingSkill, - minutes: Math.floor(data.duration / Time.Minute), - no_stams: data.noStams - } - } - }) - }, - [activity_type_enum.DriftNet]: { - commandName: 'activities', - args: (data: ActivityTaskOptionsWithQuantity) => ({ - underwater: { - drift_net_fishing: { minutes: Math.floor(data.duration / Time.Minute) } - } - }) - }, - [activity_type_enum.Colosseum]: { - commandName: 'k', - args: () => ({ - name: 'colosseum' - }) - } -} as const; - -for (const type of Object.values(activity_type_enum)) { - if (!tripHandlers[type]) { - throw new Error(`Missing trip handler for ${type}`); - } -} - -export async function fetchRepeatTrips(userID: string) { - const res: Activity[] = await prisma.activity.findMany({ - where: { - user_id: BigInt(userID), - finish_date: { - gt: new Date(Date.now() - Time.Day * 7) - } - }, - orderBy: { - id: 'desc' - }, - take: 20 - }); - const filtered: { - type: activity_type_enum; - data: Prisma.JsonValue; - }[] = []; - for (const trip of res) { - if (!taskCanBeRepeated(trip)) continue; - if (trip.type === activity_type_enum.Farming && !(trip.data as any as FarmingActivityTaskOptions).autoFarmed) { - continue; - } - if (!filtered.some(i => i.type === trip.type)) { - filtered.push(trip); - } - } - return filtered; -} - -export async function makeRepeatTripButtons(user: MUser) { - const trips = await fetchRepeatTrips(user.id); - const buttons: ButtonBuilder[] = []; - const limit = Math.min(user.perkTier() + 1, 5); - for (const trip of trips.slice(0, limit)) { - buttons.push( - new ButtonBuilder() - .setLabel(`Repeat ${trip.type}`) - .setCustomId(`REPEAT_TRIP_${trip.type}`) - .setStyle(ButtonStyle.Secondary) - ); - } - return buttons; -} - -export async function repeatTrip( - interaction: ButtonInteraction, - data: { data: Prisma.JsonValue; type: activity_type_enum } -) { - await deferInteraction(interaction); - const handler = tripHandlers[data.type]; - return runCommand({ - commandName: handler.commandName, - isContinue: true, - args: handler.args(data.data as any), - interaction, - guildID: interaction.guildId, - member: interaction.member, - channelID: interaction.channelId, - user: interaction.user, - continueDeltaMillis: interaction.createdAt.getTime() - interaction.message.createdTimestamp - }); -} - diff --git a/types.ts b/types.ts deleted file mode 100644 index a6b11fee6f..0000000000 --- a/types.ts +++ /dev/null @@ -1,362 +0,0 @@ -import type { Bank } from 'oldschooljs'; -import type { Item } from 'oldschooljs/dist/meta/types'; -import type LootTable from 'oldschooljs/dist/structures/LootTable'; - -import type { Emoji } from '../constants'; -import type { SlayerTaskUnlocksEnum } from '../slayer/slayerUnlocks'; -import type { ItemBank } from '../types'; -import type { FarmingPatchName } from '../util/farmingHelpers'; - -export enum SkillsEnum { - Agility = 'agility', - Cooking = 'cooking', - Fishing = 'fishing', - Mining = 'mining', - Smithing = 'smithing', - Woodcutting = 'woodcutting', - Firemaking = 'firemaking', - Runecraft = 'runecraft', - Crafting = 'crafting', - Prayer = 'prayer', - Fletching = 'fletching', - Farming = 'farming', - Herblore = 'herblore', - Thieving = 'thieving', - Hunter = 'hunter', - Construction = 'construction', - Magic = 'magic', - Attack = 'attack', - Strength = 'strength', - Defence = 'defence', - Ranged = 'ranged', - Hitpoints = 'hitpoints', - Slayer = 'slayer' -} - -export const SkillsArray = [ - 'agility', - 'cooking', - 'fishing', - 'mining', - 'smithing', - 'woodcutting', - 'firemaking', - 'runecraft', - 'crafting', - 'prayer', - 'fletching', - 'farming', - 'herblore', - 'thieving', - 'hunter', - 'construction', - 'magic', - 'attack', - 'strength', - 'defence', - 'ranged', - 'hitpoints', - 'slayer' -] as const; - -export type SkillNameType = (typeof SkillsArray)[number]; -for (const skill of SkillsArray) { - const matching = Object.keys(SkillsEnum).find(key => key.toLowerCase() === skill); - if (!matching) throw new Error(`Missing skill enum for ${skill}`); -} -if (SkillsArray.length !== Object.keys(SkillsEnum).length) { - throw new Error('Not all skills have been added to the SkillsArray.'); -} - -export interface Ore { - level: number; - xp: number; - id: number; - name: string; - respawnTime: number; - bankingTime: number; - slope: number; - intercept: number; - petChance?: number; - minerals?: number; - clueScrollChance?: number; - aliases?: string[]; -} - -export interface Log { - level: number; - xp: number; - id: number; - lootTable?: LootTable; - name: string; - leaf?: number; - aliases?: string[]; - findNewTreeTime: number; - bankingTime: number; - slope: number; - intercept: number; - depletionChance: number; - wcGuild?: boolean; - petChance?: number; - qpRequired: number; - clueScrollChance?: number; - clueNestsOnly?: boolean; -} - -export interface Burnable { - level: number; - xp: number; - name: string; - inputLogs: number; -} - -export interface Fish { - name: string; - alias?: string[]; - level: number; - xp: number; - id: number; - chance1Lvl1?: number; - chance1Lvl99?: number; - level2?: number; - xp2?: number; - id2?: number; - chance2Lvl1?: number; - chance2Lvl99?: number; - level3?: number; - xp3?: number; - id3?: number; - chance3Lvl1?: number; - chance3Lvl99?: number; - - petChance?: number; - clueScrollChance?: number; - lostTicks?: number; - bankingTime?: number; - ticksPerRoll?: number; - - bait?: number; - qpRequired?: number; - bigFish?: number; - bigFishRate?: number; - - timePerFish?: number; -} - -export interface Course { - id: number; - name: string; - level: number; - xp: number | ((agilityLevel: number) => number); - marksPer60?: number; - lapTime: number; - petChance: number; - aliases: string[]; - qpRequired?: number; -} - -export interface Cookable { - level: number; - xp: number; - id: number; - name: string; - inputCookables: ItemBank; - stopBurnAt: number; - stopBurnAtCG?: number; - // Burn level with hosidius/diary: [ noGauntletsHosidius, noGauntletsElite, gauntletsHosidius, gauntletsElite ] - burnKourendBonus?: number[]; - burntCookable: number; - alias?: string[]; -} - -export interface Bar { - level: number; - xp: number; - id: number; - name: string; - inputOres: Bank; - /** - * Chance that the ore will fail to smelt (i.e iron), out of 100 - */ - chanceOfFail: number; - timeToUse: number; -} - -export interface BlastableBar { - level: number; - xp: number; - id: number; - name: string; - inputOres: Bank; - timeToUse: number; -} - -export interface SmithedItem { - level: number; - xp: number; - id: number; - name: string; - inputBars: ItemBank; - timeToUse: number; - outputMultiple: number; - qpRequired?: number; -} - -export interface Craftable { - name: string; - alias?: string[]; - id: number; - level: number; - xp: number; - inputItems: Bank; - tickRate: number; - crushChance?: number[]; - bankChest?: boolean; - outputMultiple?: number; - qpRequired?: number; - wcLvl?: number; -} - -export interface Fletchable { - name: string; - id: number; - level: number; - xp: number; - inputItems: Bank; - tickRate: number; - outputMultiple?: number; - requiredSlayerUnlocks?: SlayerTaskUnlocksEnum[]; - craftingXp?: number; -} - -export interface Mixable { - item: Item; - aliases: string[]; - level: number; - xp: number; - inputItems: Bank; - tickRate: number; - bankTimePerPotion: number; - outputMultiple?: number; - zahur?: boolean; - wesley?: boolean; - qpRequired?: number; -} - -export interface CutLeapingFish { - item: Item; - aliases: string[]; - tickRate: number; -} - -export interface Bone { - level: number; - xp: number; - name: string; - inputId: number; -} - -export interface Ash { - level: number; - xp: number; - name: string; - inputId: number; -} - -export type LevelRequirements = Partial<{ - [key in SkillsEnum]: number; -}>; - -export interface Skill { - aliases: string[]; - id: SkillsEnum; - emoji: Emoji; - name: string; -} - -export interface Plankable { - name: string; - inputItem: number; - outputItem: number; - gpCost: number; -} - -export interface Plant { - id: number; - level: number; - plantXp: number; - checkXp: number; - harvestXp: number; - name: string; - inputItems: Bank; - aliases: string[]; - outputCrop?: number; - cleanHerbCrop?: number; - herbXp?: number; - herbLvl?: number; - outputLogs?: number; - outputRoots?: number; - treeWoodcuttingLevel?: number; - fixedOutputAmount?: number; - variableYield?: boolean; - variableOutputAmount?: [string | null, number, number][]; - woodcuttingXp?: number; - needsChopForHarvest: boolean; - fixedOutput: boolean; - givesLogs: boolean; - givesCrops: boolean; - petChance: number; - seedType: FarmingPatchName; - growthTime: number; - numOfStages: number; - chance1: number; - chance99: number; - chanceOfDeath: number; - protectionPayment?: Bank; - defaultNumOfPatches: number; - canPayFarmer: boolean; - canCompostPatch: boolean; - canCompostandPay: boolean; - additionalPatchesByQP: number[][]; - additionalPatchesByFarmLvl: number[][]; - additionalPatchesByFarmGuildAndLvl: number[][]; - timePerPatchTravel: number; - timePerHarvest: number; -} - -export enum HunterTechniqueEnum { - AerialFishing = 'aerial fishing', - DriftNet = 'drift net fishing', - BirdSnaring = 'bird snaring', - BoxTrapping = 'box trapping', - ButterflyNetting = 'butterfly netting', - DeadfallTrapping = 'deadfall trapping', - Falconry = 'falconry', - MagicBoxTrapping = 'magic box trapping', - NetTrapping = 'net trapping', - PitfallTrapping = 'pitfall trapping', - RabbitSnaring = 'rabbit snaring', - Tracking = 'tracking' -} - -export interface Creature { - name: string; - id: number; - aliases: string[]; - level: number; - hunterXP: number; - fishLvl?: number; - fishingXP?: number; - itemsRequired?: Bank; - itemsConsumed?: Bank; - table: LootTable; - huntTechnique: HunterTechniqueEnum; - multiTraps?: boolean; - wildy?: boolean; - prayerLvl?: number; - herbloreLvl?: number; - catchTime: number; - qpRequired?: number; - slope: number; - intercept: number; -}