From cacb62d3f6defde3fdf747045ef9d69304222147 Mon Sep 17 00:00:00 2001 From: minimicronano Date: Wed, 10 Jul 2024 01:19:36 +0200 Subject: [PATCH 1/3] Add ability to use spirit flakes for regular fishing --- src/lib/types/minions.ts | 1 + src/lib/util/repeatStoredTrip.ts | 6 +++- src/lib/util/smallUtils.ts | 6 ++++ src/mahoji/commands/fish.ts | 47 ++++++++++++++++++++++------ src/tasks/minions/fishingActivity.ts | 6 ++++ tests/unit/commands/fish.test.ts | 37 ++++++++++++++++++++++ tests/unit/util.test.ts | 16 +++++++++- 7 files changed, 108 insertions(+), 11 deletions(-) diff --git a/src/lib/types/minions.ts b/src/lib/types/minions.ts index 583d39b8cf..46fbd2b585 100644 --- a/src/lib/types/minions.ts +++ b/src/lib/types/minions.ts @@ -150,6 +150,7 @@ export interface FishingActivityTaskOptions extends ActivityTaskOptions { type: 'Fishing'; fishID: number; quantity: number; + flakesQuantity?: number; iQty?: number; } diff --git a/src/lib/util/repeatStoredTrip.ts b/src/lib/util/repeatStoredTrip.ts index 25549dad68..179270c099 100644 --- a/src/lib/util/repeatStoredTrip.ts +++ b/src/lib/util/repeatStoredTrip.ts @@ -306,7 +306,11 @@ const tripHandlers = { }, [activity_type_enum.Fishing]: { commandName: 'fish', - args: (data: FishingActivityTaskOptions) => ({ name: data.fishID, quantity: data.iQty }) + args: (data: FishingActivityTaskOptions) => ({ + name: data.fishID, + quantity: data.iQty, + flakes: data.flakesQuantity !== undefined + }) }, [activity_type_enum.FishingTrawler]: { commandName: 'minigames', diff --git a/src/lib/util/smallUtils.ts b/src/lib/util/smallUtils.ts index 82229775b6..71d9e86234 100644 --- a/src/lib/util/smallUtils.ts +++ b/src/lib/util/smallUtils.ts @@ -70,6 +70,12 @@ export function pluraliseItemName(name: string): string { return name + (name.endsWith('s') ? '' : 's'); } +export function pluraliseItemNameWithQuantity(name: string, quantity: number): string { + const result = `${quantity} ${name}`; + if (quantity === 1) return result; + return pluraliseItemName(result); +} + export function shuffleRandom(input: number, arr: readonly T[]): T[] { const engine = MersenneTwister19937.seed(input); return shuffle(engine, [...arr]); diff --git a/src/mahoji/commands/fish.ts b/src/mahoji/commands/fish.ts index 8e585bb919..ddbf3e2a9e 100644 --- a/src/mahoji/commands/fish.ts +++ b/src/mahoji/commands/fish.ts @@ -8,7 +8,7 @@ import TzTokJad from 'oldschooljs/dist/simulation/monsters/special/TzTokJad'; import Fishing from '../../lib/skilling/skills/fishing'; import { SkillsEnum } from '../../lib/skilling/types'; import type { FishingActivityTaskOptions } from '../../lib/types/minions'; -import { formatDuration, itemID, itemNameFromID } from '../../lib/util'; +import { formatDuration, itemID, itemNameFromID, pluraliseItemNameWithQuantity } from '../../lib/util'; import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask'; import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength'; import type { OSBMahojiCommand } from '../lib/util'; @@ -42,9 +42,19 @@ export const fishCommand: OSBMahojiCommand = { description: 'The quantity you want to fish (optional).', required: false, min_value: 1 + }, + { + type: ApplicationCommandOptionType.Boolean, + name: 'flakes', + description: 'Use spirit flakes?', + required: false } ], - run: async ({ options, userID, channelID }: CommandRunOptions<{ name: string; quantity?: number }>) => { + run: async ({ + options, + userID, + channelID + }: CommandRunOptions<{ name: string; quantity?: number; flakes?: boolean }>) => { const user = await mUserFetch(userID); const fish = Fishing.Fishes.find( fish => @@ -132,8 +142,24 @@ export const fishCommand: OSBMahojiCommand = { const maxTripLength = calcMaxTripLength(user, 'Fishing'); - let { quantity } = options; - if (!quantity) quantity = Math.floor(maxTripLength / scaledTimePerFish); + let { quantity, flakes } = options; + if (!quantity) { + quantity = Math.floor(maxTripLength / scaledTimePerFish); + } + let shouldRemoveFromBank = false; + let flakesQuantity: number | undefined; + const cost = new Bank(); + + if (flakes) { + if (!user.bank.has('Spirit flakes')) { + return 'You need to have at least one spirit flake!'; + } + + flakesQuantity = Math.min(user.bank.amount('Spirit flakes'), quantity); + boosts.push(`More fish from using ${pluraliseItemNameWithQuantity('spirit flake', flakesQuantity)}`); + shouldRemoveFromBank = true; + cost.add('Spirit flakes', flakesQuantity); + } if (fish.bait) { const baseCost = new Bank().add(fish.bait); @@ -146,11 +172,13 @@ export const fishCommand: OSBMahojiCommand = { quantity = maxCanDo; } - const cost = new Bank(); - cost.add(baseCost.multiply(quantity)); + shouldRemoveFromBank = true; + cost.add(fish.bait, quantity); + } - // Remove the bait from their bank. - await user.removeItemsFromBank(new Bank().add(fish.bait, quantity)); + if (shouldRemoveFromBank) { + // Remove the bait and/or spirit flakes from their bank. + await user.removeItemsFromBank(cost); } let duration = quantity * scaledTimePerFish; @@ -173,7 +201,8 @@ export const fishCommand: OSBMahojiCommand = { quantity, iQty: options.quantity ? options.quantity : undefined, duration, - type: 'Fishing' + type: 'Fishing', + flakesQuantity }); let response = `${user.minionName} is now fishing ${quantity}x ${fish.name}, it'll take around ${formatDuration( diff --git a/src/tasks/minions/fishingActivity.ts b/src/tasks/minions/fishingActivity.ts index 1eb322259e..6e51ef4e63 100644 --- a/src/tasks/minions/fishingActivity.ts +++ b/src/tasks/minions/fishingActivity.ts @@ -41,6 +41,7 @@ export const fishingTask: MinionTask = { }), async run(data: FishingActivityTaskOptions) { const { fishID, quantity, userID, channelID, duration } = data; + let { flakesQuantity } = data; const user = await mUserFetch(userID); const currentLevel = user.skillLevel(SkillsEnum.Fishing); const { blessingEquipped, blessingChance } = radasBlessing(user); @@ -160,6 +161,11 @@ export const fishingTask: MinionTask = { } else { lootQuantity += blessingEquipped && percentChance(blessingChance) ? 2 : 1; } + + if (flakesQuantity && flakesQuantity > 0) { + lootQuantity += percentChance(50) ? 1 : 0; + flakesQuantity--; + } } const loot = new Bank({ diff --git a/tests/unit/commands/fish.test.ts b/tests/unit/commands/fish.test.ts index 469a6720fe..f447d05138 100644 --- a/tests/unit/commands/fish.test.ts +++ b/tests/unit/commands/fish.test.ts @@ -92,4 +92,41 @@ describe('Fish Command', () => { **Boosts:** +9 trip minutes for having a Fish sack barrel.` }); }); + + it('should handle using flakes without flakes in bank', () => { + testRunCmd({ + cmd: fishCommand, + opts: { name: 'shrimps', flakes: true }, + user: { + skills_fishing: 999_999 + }, + result: 'You need to have at least one spirit flake!' + }); + }); + + it('should fish with flakes', () => { + testRunCmd({ + cmd: fishCommand, + opts: { name: 'shrimps', flakes: true }, + user: { + bank: new Bank({ 'Spirit flakes': 10000 }) + }, + result: `<:minion:778418736180494347> Your minion is now fishing 251x Shrimps, it'll take around 29 minutes, 58 seconds to finish. + +**Boosts:** More fish from using 251 spirit flakes.` + }); + }); + + it('should still use flakes if bank contains fewer flakes than fish quantity', () => { + testRunCmd({ + cmd: fishCommand, + opts: { name: 'shrimps', flakes: true }, + user: { + bank: new Bank({ 'Spirit flakes': 100 }) + }, + result: `<:minion:778418736180494347> Your minion is now fishing 251x Shrimps, it'll take around 29 minutes, 58 seconds to finish. + +**Boosts:** More fish from using 100 spirit flakes.` + }); + }); }); diff --git a/tests/unit/util.test.ts b/tests/unit/util.test.ts index e2a3e0110d..c37d7098a6 100644 --- a/tests/unit/util.test.ts +++ b/tests/unit/util.test.ts @@ -8,7 +8,13 @@ import { baseModifyBusyCounter } from '../../src/lib/busyCounterCache'; import { deduplicateClueScrolls } from '../../src/lib/clues/clueUtils'; import getUserFoodFromBank from '../../src/lib/minions/functions/getUserFoodFromBank'; import { SkillsEnum } from '../../src/lib/skilling/types'; -import { pluraliseItemName, sanitizeBank, skillingPetDropRate, stripEmojis } from '../../src/lib/util'; +import { + pluraliseItemName, + pluraliseItemNameWithQuantity, + sanitizeBank, + skillingPetDropRate, + stripEmojis +} from '../../src/lib/util'; import getOSItem from '../../src/lib/util/getOSItem'; import { sellPriceOfItem, sellStorePriceOfItem } from '../../src/mahoji/commands/sell'; import { mockMUser } from './utils'; @@ -142,4 +148,12 @@ describe('util', () => { expect(pluraliseItemName('Steel Arrowtips')).toEqual('Steel Arrowtips'); expect(pluraliseItemName('Adamantite nails')).toEqual('Adamantite nails'); }); + + test('pluraliseItemWithQuantity correctly pluralises items', async () => { + expect(pluraliseItemNameWithQuantity('Shrimp', 0)).toEqual('0 Shrimps'); + expect(pluraliseItemNameWithQuantity('Twisted bow', 999)).toEqual('999 Twisted bows'); + expect(pluraliseItemNameWithQuantity('Bronze Arrowtips', 0)).toEqual('0 Bronze Arrowtips'); + expect(pluraliseItemNameWithQuantity('Spirit flakes', 10)).toEqual('10 Spirit flakes'); + expect(pluraliseItemNameWithQuantity('Yellow square', 1)).toEqual('1 Yellow square'); + }); }); From 683601e66091c163095f1ddbf9bd0c742630aa32 Mon Sep 17 00:00:00 2001 From: minimicronano Date: Sat, 10 Aug 2024 19:34:23 +0200 Subject: [PATCH 2/3] Remove unnecessary variable --- src/mahoji/commands/fish.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mahoji/commands/fish.ts b/src/mahoji/commands/fish.ts index ddbf3e2a9e..35de221021 100644 --- a/src/mahoji/commands/fish.ts +++ b/src/mahoji/commands/fish.ts @@ -146,7 +146,6 @@ export const fishCommand: OSBMahojiCommand = { if (!quantity) { quantity = Math.floor(maxTripLength / scaledTimePerFish); } - let shouldRemoveFromBank = false; let flakesQuantity: number | undefined; const cost = new Bank(); @@ -157,7 +156,6 @@ export const fishCommand: OSBMahojiCommand = { flakesQuantity = Math.min(user.bank.amount('Spirit flakes'), quantity); boosts.push(`More fish from using ${pluraliseItemNameWithQuantity('spirit flake', flakesQuantity)}`); - shouldRemoveFromBank = true; cost.add('Spirit flakes', flakesQuantity); } @@ -172,11 +170,10 @@ export const fishCommand: OSBMahojiCommand = { quantity = maxCanDo; } - shouldRemoveFromBank = true; cost.add(fish.bait, quantity); } - if (shouldRemoveFromBank) { + if (cost.length > 0) { // Remove the bait and/or spirit flakes from their bank. await user.removeItemsFromBank(cost); } From 5f311ab523d92ac9482909a27c78072851879294 Mon Sep 17 00:00:00 2001 From: minimicronano Date: Thu, 22 Aug 2024 23:38:35 +0200 Subject: [PATCH 3/3] Remove pluralization function in favor of 1x item format --- src/lib/util/smallUtils.ts | 6 ------ src/mahoji/commands/fish.ts | 4 ++-- tests/unit/commands/fish.test.ts | 4 ++-- tests/unit/util.test.ts | 16 +--------------- 4 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/lib/util/smallUtils.ts b/src/lib/util/smallUtils.ts index 71d9e86234..82229775b6 100644 --- a/src/lib/util/smallUtils.ts +++ b/src/lib/util/smallUtils.ts @@ -70,12 +70,6 @@ export function pluraliseItemName(name: string): string { return name + (name.endsWith('s') ? '' : 's'); } -export function pluraliseItemNameWithQuantity(name: string, quantity: number): string { - const result = `${quantity} ${name}`; - if (quantity === 1) return result; - return pluraliseItemName(result); -} - export function shuffleRandom(input: number, arr: readonly T[]): T[] { const engine = MersenneTwister19937.seed(input); return shuffle(engine, [...arr]); diff --git a/src/mahoji/commands/fish.ts b/src/mahoji/commands/fish.ts index 35de221021..b6dd34e273 100644 --- a/src/mahoji/commands/fish.ts +++ b/src/mahoji/commands/fish.ts @@ -8,7 +8,7 @@ import TzTokJad from 'oldschooljs/dist/simulation/monsters/special/TzTokJad'; import Fishing from '../../lib/skilling/skills/fishing'; import { SkillsEnum } from '../../lib/skilling/types'; import type { FishingActivityTaskOptions } from '../../lib/types/minions'; -import { formatDuration, itemID, itemNameFromID, pluraliseItemNameWithQuantity } from '../../lib/util'; +import { formatDuration, itemID, itemNameFromID } from '../../lib/util'; import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask'; import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength'; import type { OSBMahojiCommand } from '../lib/util'; @@ -155,7 +155,7 @@ export const fishCommand: OSBMahojiCommand = { } flakesQuantity = Math.min(user.bank.amount('Spirit flakes'), quantity); - boosts.push(`More fish from using ${pluraliseItemNameWithQuantity('spirit flake', flakesQuantity)}`); + boosts.push(`More fish from using ${flakesQuantity}x Spirit flakes`); cost.add('Spirit flakes', flakesQuantity); } diff --git a/tests/unit/commands/fish.test.ts b/tests/unit/commands/fish.test.ts index f447d05138..57582c0efc 100644 --- a/tests/unit/commands/fish.test.ts +++ b/tests/unit/commands/fish.test.ts @@ -113,7 +113,7 @@ describe('Fish Command', () => { }, result: `<:minion:778418736180494347> Your minion is now fishing 251x Shrimps, it'll take around 29 minutes, 58 seconds to finish. -**Boosts:** More fish from using 251 spirit flakes.` +**Boosts:** More fish from using 251x Spirit flakes.` }); }); @@ -126,7 +126,7 @@ describe('Fish Command', () => { }, result: `<:minion:778418736180494347> Your minion is now fishing 251x Shrimps, it'll take around 29 minutes, 58 seconds to finish. -**Boosts:** More fish from using 100 spirit flakes.` +**Boosts:** More fish from using 100x Spirit flakes.` }); }); }); diff --git a/tests/unit/util.test.ts b/tests/unit/util.test.ts index c37d7098a6..e2a3e0110d 100644 --- a/tests/unit/util.test.ts +++ b/tests/unit/util.test.ts @@ -8,13 +8,7 @@ import { baseModifyBusyCounter } from '../../src/lib/busyCounterCache'; import { deduplicateClueScrolls } from '../../src/lib/clues/clueUtils'; import getUserFoodFromBank from '../../src/lib/minions/functions/getUserFoodFromBank'; import { SkillsEnum } from '../../src/lib/skilling/types'; -import { - pluraliseItemName, - pluraliseItemNameWithQuantity, - sanitizeBank, - skillingPetDropRate, - stripEmojis -} from '../../src/lib/util'; +import { pluraliseItemName, sanitizeBank, skillingPetDropRate, stripEmojis } from '../../src/lib/util'; import getOSItem from '../../src/lib/util/getOSItem'; import { sellPriceOfItem, sellStorePriceOfItem } from '../../src/mahoji/commands/sell'; import { mockMUser } from './utils'; @@ -148,12 +142,4 @@ describe('util', () => { expect(pluraliseItemName('Steel Arrowtips')).toEqual('Steel Arrowtips'); expect(pluraliseItemName('Adamantite nails')).toEqual('Adamantite nails'); }); - - test('pluraliseItemWithQuantity correctly pluralises items', async () => { - expect(pluraliseItemNameWithQuantity('Shrimp', 0)).toEqual('0 Shrimps'); - expect(pluraliseItemNameWithQuantity('Twisted bow', 999)).toEqual('999 Twisted bows'); - expect(pluraliseItemNameWithQuantity('Bronze Arrowtips', 0)).toEqual('0 Bronze Arrowtips'); - expect(pluraliseItemNameWithQuantity('Spirit flakes', 10)).toEqual('10 Spirit flakes'); - expect(pluraliseItemNameWithQuantity('Yellow square', 1)).toEqual('1 Yellow square'); - }); });