From c804bda44daf6d9a2f7ecd12de2b2f81db80c680 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:47:38 +1100 Subject: [PATCH] Mining command/trip refactoring and wiki page --- docs/src/content/docs/getting-started/wiki.md | 40 ++- .../mining => Activities}/motherlode-mine.md | 0 .../mining => Activities}/shooting-stars.md | 0 .../mining => Activities}/volcanic-mine.md | 0 .../mining => Miscelleanous}/zalcano.md | 0 .../Skills/{mining/README.md => mining.md} | 50 +++- scripts/wiki.ts | 6 +- scripts/wiki/miningXphr.ts | 54 ++++ src/lib/MUser.ts | 3 +- .../functions/addSkillingClueToLoot.ts | 5 +- .../skilling/functions/determineMiningTime.ts | 14 +- src/lib/skilling/skills/mining.ts | 5 + src/lib/structures/GearBank.ts | 13 +- src/lib/structures/XPBank.ts | 11 + src/lib/util.ts | 3 +- src/mahoji/commands/mine.ts | 234 ++++++++++-------- .../abstracted_commands/camdozaalCommand.ts | 5 +- .../motherlodeMineCommand.ts | 6 +- .../shootingStarsCommand.ts | 5 +- src/tasks/minions/miningActivity.ts | 233 ++++++++--------- tests/unit/utils.ts | 3 +- 21 files changed, 429 insertions(+), 261 deletions(-) rename docs/src/content/docs/osb/{Skills/mining => Activities}/motherlode-mine.md (100%) rename docs/src/content/docs/osb/{Skills/mining => Activities}/shooting-stars.md (100%) rename docs/src/content/docs/osb/{Skills/mining => Activities}/volcanic-mine.md (100%) rename docs/src/content/docs/osb/{Skills/mining => Miscelleanous}/zalcano.md (100%) rename docs/src/content/docs/osb/Skills/{mining/README.md => mining.md} (72%) create mode 100644 scripts/wiki/miningXphr.ts diff --git a/docs/src/content/docs/getting-started/wiki.md b/docs/src/content/docs/getting-started/wiki.md index f762a00fb4..3677c6010a 100644 --- a/docs/src/content/docs/getting-started/wiki.md +++ b/docs/src/content/docs/getting-started/wiki.md @@ -151,9 +151,9 @@ This is an automatically generated list of pages with possible issues to be look [/bso/leagues.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/leagues.md): Doesnt use the new command formatting -[/bso/Minigames/balthazars-big-bonanza.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Minigames/balthazars-big-bonanza.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) +[/bso/Minigames/balthazars-big-bonanza.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Minigames/balthazars-big-bonanza.md): Doesnt use the new command formatting -[/bso/Minigames/baxtorian-bathhouses.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Minigames/baxtorian-bathhouses.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) +[/bso/Minigames/baxtorian-bathhouses.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Minigames/baxtorian-bathhouses.md): Doesnt use the new command formatting [/bso/Minigames/emerged-zuk-inferno.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Minigames/emerged-zuk-inferno.md): Doesnt use the new command formatting @@ -227,13 +227,9 @@ This is an automatically generated list of pages with possible issues to be look [/bso/Skills/crafting.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/crafting.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) -[/bso/Skills/Divination/efficient-divination-training.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Divination/efficient-divination-training.md): Doesnt use the new command formatting +[/bso/Skills/divination.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/divination.md): Doesnt use the new command formatting -[/bso/Skills/Divination/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Divination/README.md): Doesnt use the new command formatting - -[/bso/Skills/Dungeoneering Training/dg-rewards.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Dungeoneering%20Training/dg-rewards.md): Doesnt use the new command formatting - -[/bso/Skills/Dungeoneering Training/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Dungeoneering%20Training/README.md): Doesnt use the new command formatting +[/bso/Skills/dungeoneering.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/dungeoneering.md): Doesnt use the new command formatting [/bso/Skills/farming.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/farming.md): Doesnt use the new command formatting @@ -247,9 +243,7 @@ This is an automatically generated list of pages with possible issues to be look [/bso/Skills/hunter.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/hunter.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) -[/bso/Skills/Invention/efficient-disassembling-to-99.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Invention/efficient-disassembling-to-99.md): Doesnt use the new command formatting - -[/bso/Skills/Invention/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Invention/README.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) +[/bso/Skills/invention.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/invention.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) [/bso/Skills/mining.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/mining.md): Doesnt use the new command formatting @@ -269,16 +263,12 @@ This is an automatically generated list of pages with possible issues to be look [/bso/Tames/eagle-tame.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/eagle-tame.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) -[/bso/Tames/igne-equipment.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/igne-equipment.md): Doesnt use the new command formatting - [/bso/Tames/igne-tame.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/igne-tame.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) -[/bso/Tames/monkey-staff-and-spells.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/monkey-staff-and-spells.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) +[/bso/Tames/introduction.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/introduction.md): Doesnt use the new command formatting [/bso/Tames/monkey-tame.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/monkey-tame.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) -[/bso/Tames/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/README.md): Doesnt use the new command formatting - [/getting-started/bingo.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/bingo.mdx): Doesnt use the new command formatting [/getting-started/BSO.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/BSO.mdx): Doesnt use the new command formatting @@ -307,6 +297,12 @@ This is an automatically generated list of pages with possible issues to be look [/osb/Activities/mahogany-homes.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Activities/mahogany-homes.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) +[/osb/Activities/motherlode-mine.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Activities/motherlode-mine.md): Doesnt use the new command formatting + +[/osb/Activities/shooting-stars.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Activities/shooting-stars.md): Doesnt use the new command formatting + +[/osb/Activities/volcanic-mine.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Activities/volcanic-mine.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) + [/osb/Activities/wintertodt.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Activities/wintertodt.md): Doesnt use the new command formatting [/osb/Bosses/colosseum.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Bosses/colosseum.md): Doesnt use the new command formatting @@ -387,6 +383,8 @@ This is an automatically generated list of pages with possible issues to be look [/osb/Miscelleanous/tears-of-guthix.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/tears-of-guthix.md): Doesnt use the new command formatting +[/osb/Miscelleanous/zalcano.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/zalcano.md): Doesnt use the new command formatting + [/osb/monsters.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/monsters.mdx): Doesnt use the new command formatting [/osb/quests.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/quests.mdx): Doesnt use the new command formatting @@ -449,15 +447,7 @@ This is an automatically generated list of pages with possible issues to be look [/osb/Skills/magic.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/magic.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) -[/osb/Skills/mining/motherlode-mine.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/mining/motherlode-mine.md): Doesnt use the new command formatting - -[/osb/Skills/mining/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/mining/README.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) - -[/osb/Skills/mining/shooting-stars.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/mining/shooting-stars.md): Doesnt use the new command formatting - -[/osb/Skills/mining/volcanic-mine.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/mining/volcanic-mine.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) - -[/osb/Skills/mining/zalcano.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/mining/zalcano.md): Doesnt use the new command formatting +[/osb/Skills/mining.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/mining.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. ``) [/osb/Skills/prayer.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Skills/prayer.md): Doesnt use the new command formatting diff --git a/docs/src/content/docs/osb/Skills/mining/motherlode-mine.md b/docs/src/content/docs/osb/Activities/motherlode-mine.md similarity index 100% rename from docs/src/content/docs/osb/Skills/mining/motherlode-mine.md rename to docs/src/content/docs/osb/Activities/motherlode-mine.md diff --git a/docs/src/content/docs/osb/Skills/mining/shooting-stars.md b/docs/src/content/docs/osb/Activities/shooting-stars.md similarity index 100% rename from docs/src/content/docs/osb/Skills/mining/shooting-stars.md rename to docs/src/content/docs/osb/Activities/shooting-stars.md diff --git a/docs/src/content/docs/osb/Skills/mining/volcanic-mine.md b/docs/src/content/docs/osb/Activities/volcanic-mine.md similarity index 100% rename from docs/src/content/docs/osb/Skills/mining/volcanic-mine.md rename to docs/src/content/docs/osb/Activities/volcanic-mine.md diff --git a/docs/src/content/docs/osb/Skills/mining/zalcano.md b/docs/src/content/docs/osb/Miscelleanous/zalcano.md similarity index 100% rename from docs/src/content/docs/osb/Skills/mining/zalcano.md rename to docs/src/content/docs/osb/Miscelleanous/zalcano.md diff --git a/docs/src/content/docs/osb/Skills/mining/README.md b/docs/src/content/docs/osb/Skills/mining.md similarity index 72% rename from docs/src/content/docs/osb/Skills/mining/README.md rename to docs/src/content/docs/osb/Skills/mining.md index 2654773a45..35856455ea 100644 --- a/docs/src/content/docs/osb/Skills/mining/README.md +++ b/docs/src/content/docs/osb/Skills/mining.md @@ -100,6 +100,50 @@ The only other thing unidentified minerals can be used to purchase are: - [[/buy name\:Bag full of gems (minerals)]] - 20 Unidentified minerals -## Ores - -
Ore NameMineralsRequired LevelExperienceXP/Hr @ 99
Ore NameMineralsRequired LevelExperienceXP/Hr @ 99
Rune essence1510,288
Copper ore117.526,881
Tin ore117.526,881
Saltpetre100
Iron ore153550,332
Silver ore204022,454
Volcanic ash22109,810
Pure essence30510,288
Coal305031,644
Gold ore406536,556
Gem rock406520,865
Mithril ore558017,231
Adamantite ore709512,654
Runite ore851256,731
Amethyst9224014,321
+## XP/hr + +[[embed.miningxphr.start]] +{/_ DO NOT EDIT - This section is auto-generated by the build script _/} +| Ore | XP/hr | Powermining | +| --- | --- | --- | +| [[6983]] | 114,000 | Yes | +| [[6975]] | 81,000 | Yes | +| [[440]] | 77,000 | Yes | +| [[6975]] | 73,000 | No | +| [[442]] | 62,000 | Yes | +| [[6983]] | 60,000 | No | +| [[442]] | 57,000 | No | +| [[440]] | 55,000 | No | +| [[453]] | 44,000 | Yes | +| [[453]] | 38,000 | No | +| [[436]] | 38,000 | Yes | +| [[1625]] | 38,000 | Yes | +| [[444]] | 38,000 | Yes | +| [[438]] | 38,000 | Yes | +| [[444]] | 37,000 | No | +| [[1625]] | 36,000 | No | +| [[447]] | 27,000 | Yes | +| [[447]] | 26,000 | No | +| [[21347]] | 23,000 | Yes | +| [[21347]] | 22,000 | No | +| [[436]] | 19,000 | No | +| [[438]] | 19,000 | No | +| [[449]] | 16,000 | Yes | +| [[449]] | 15,000 | No | +| [[21622]] | 13,000 | Yes | +| [[21622]] | 13,000 | No | +| [[434]] | 11,000 | Yes | +| [[24706]] | 10,000 | Yes | +| [[24706]] | 10,000 | No | +| [[7936]] | 10,000 | Yes | +| [[1436]] | 10,000 | Yes | +| [[451]] | 10,000 | Yes | +| [[451]] | 10,000 | No | +| [[7936]] | 7,000 | No | +| [[1436]] | 7,000 | No | +| [[434]] | 5,000 | No | +| [[13421]] | 0 | Yes | +| [[13421]] | 0 | No | + +{/_ DO NOT EDIT - This section is auto-generated by the build script _/} +[[embed.miningxphr.end]] diff --git a/scripts/wiki.ts b/scripts/wiki.ts index 0aba2c506d..c88644157a 100644 --- a/scripts/wiki.ts +++ b/scripts/wiki.ts @@ -4,6 +4,7 @@ import { glob } from 'glob'; import { Bank, Monsters } from 'oldschooljs'; import '../src/lib/safeglobals'; +import process from 'node:process'; import { groupBy } from 'remeda'; import { type CombatAchievement, CombatAchievements } from '../src/lib/combat_achievements/combatAchievements'; import { COXMaxMageGear, COXMaxMeleeGear, COXMaxRangeGear, itemBoosts } from '../src/lib/data/cox'; @@ -12,6 +13,7 @@ import { quests } from '../src/lib/minions/data/quests'; import { sorts } from '../src/lib/sorts'; import { itemNameFromID } from '../src/lib/util'; import { Markdown, Tab, Tabs } from './markdown/markdown'; +import { miningXpHr } from './wiki/miningXphr'; function combatAchievementHowToFinish(ca: CombatAchievement) { if ('rng' in ca) { @@ -27,7 +29,7 @@ function combatAchievementHowToFinish(ca: CombatAchievement) { throw ca; } -function handleMarkdownEmbed(identifier: string, filePath: string, contentToInject: string) { +export function handleMarkdownEmbed(identifier: string, filePath: string, contentToInject: string) { const contentToReplace = readFileSync(`./docs/src/content/docs/${filePath}`, 'utf8'); const startMarker = `[[embed.${identifier}.start]]`; const endMarker = `[[embed.${identifier}.end]]`; @@ -435,7 +437,9 @@ async function wiki() { renderQuestsMarkdown(); rendeCoxMarkdown(); wikiIssues(); + miningXpHr(); await Promise.all([renderCAMarkdown(), renderMonstersMarkdown()]); + process.exit(0); } wiki(); diff --git a/scripts/wiki/miningXphr.ts b/scripts/wiki/miningXphr.ts new file mode 100644 index 0000000000..119b37ffc2 --- /dev/null +++ b/scripts/wiki/miningXphr.ts @@ -0,0 +1,54 @@ +import { calcPerHour } from '@oldschoolgg/toolkit'; +import { Time } from 'e'; + +import Mining from '../../src/lib/skilling/skills/mining'; +import type { Ore } from '../../src/lib/skilling/types'; +import { determineMiningTrip } from '../../src/mahoji/commands/mine'; +import { determineMiningResult } from '../../src/tasks/minions/miningActivity'; +import { makeGearBank } from '../../tests/unit/utils'; +import { Table } from '../markdown/markdown'; +import { handleMarkdownEmbed } from '../wiki'; + +export function miningXpHr() { + const gearBank = makeGearBank(); + gearBank.skillsAsLevels.mining = 99; + gearBank.skillsAsXP.mining = 13_500_000; + gearBank.gear.skilling.equip('Varrock armour 4'); + gearBank.gear.skilling.equip('Expert mining gloves'); + gearBank.gear.skilling.equip('Crystal pickaxe'); + gearBank.skillsAsLevels.crafting = 99; + + const results: { xpHr: number; ore: Ore; isPowermining: boolean }[] = []; + for (const ore of Mining.Ores) { + for (const isPowermining of [true, false]) { + const trip = determineMiningTrip({ + gearBank, + ore, + maxTripLength: Time.Hour * 1000, + isPowermining, + quantityInput: undefined + }); + const result = determineMiningResult({ + ore, + quantity: trip.quantity, + gearBank, + duration: trip.duration, + isPowermining + }); + const xp = result.updateBank.xpBank.amount('mining'); + const xpHr = Math.floor(calcPerHour(xp, trip.duration) / 1000) * 1000; + results.push({ xpHr, ore, isPowermining }); + } + } + + results.sort((a, b) => a.ore.name.localeCompare(b.ore.name)); + results.sort((a, b) => b.xpHr - a.xpHr); + + const table = new Table(); + table.addHeader('Ore', 'XP/hr', 'Powermining'); + for (const result of results) { + table.addRow(`[[${result.ore.id}]]`, result.xpHr.toLocaleString(), result.isPowermining ? 'Yes' : 'No'); + } + + handleMarkdownEmbed('miningxphr', 'osb/Skills/mining.md', table.toString()); +} diff --git a/src/lib/MUser.ts b/src/lib/MUser.ts index 55cfe934fa..f0c34d3530 100644 --- a/src/lib/MUser.ts +++ b/src/lib/MUser.ts @@ -145,7 +145,8 @@ export class MUserClass { gear: this.gear, bank: this.bank, skillsAsLevels: this.skillsAsLevels, - chargeBank: this.ownedChargeBank() + chargeBank: this.ownedChargeBank(), + skillsAsXP: this.skillsAsXP }); } diff --git a/src/lib/minions/functions/addSkillingClueToLoot.ts b/src/lib/minions/functions/addSkillingClueToLoot.ts index a605422286..9c19fb4c39 100644 --- a/src/lib/minions/functions/addSkillingClueToLoot.ts +++ b/src/lib/minions/functions/addSkillingClueToLoot.ts @@ -11,6 +11,7 @@ import { treeSeedsNest } from '../../simulation/birdsNest'; import { SkillsEnum } from '../../skilling/types'; +import { GearBank } from '../../structures/GearBank'; import { randFloat, roll } from '../../util'; import itemID from '../../util/itemID'; @@ -22,7 +23,7 @@ const clues = [ ]; export default function addSkillingClueToLoot( - user: MUser, + user: MUser | GearBank, skill: SkillsEnum, quantity: number, clueChance: number, @@ -32,7 +33,7 @@ export default function addSkillingClueToLoot( twitcherSetting?: string, wcCapeNestBoost?: boolean ) { - const userLevel = user.skillLevel(skill); + const userLevel = user instanceof GearBank ? user.skillsAsLevels[skill] : user.skillLevel(skill); const nestChance = wcCapeNestBoost ? Math.floor(256 * 0.9) : 256; const cluesTotalWeight = sumArr(clues.map(c => c[1])); let chance = Math.floor(clueChance / (100 + userLevel)); diff --git a/src/lib/skilling/functions/determineMiningTime.ts b/src/lib/skilling/functions/determineMiningTime.ts index b60c1eb4fc..7516752518 100644 --- a/src/lib/skilling/functions/determineMiningTime.ts +++ b/src/lib/skilling/functions/determineMiningTime.ts @@ -1,11 +1,10 @@ import { Time, percentChance } from 'e'; -import { calcMaxTripLength } from '../../util/calcMaxTripLength'; +import type { GearBank } from '../../structures/GearBank'; import type { Ore } from './../types'; interface MiningTimeOptions { quantity: number | undefined; - user: MUser; ore: Ore; ticksBetweenRolls: number; glovesRate: number; @@ -15,11 +14,12 @@ interface MiningTimeOptions { goldSilverBoost: boolean; miningLvl: number; passedDuration?: number; + maxTripLength: number; + gearBank: GearBank; } export function determineMiningTime({ quantity, - user, ore, ticksBetweenRolls, glovesRate, @@ -28,10 +28,12 @@ export function determineMiningTime({ powermining, goldSilverBoost, miningLvl, - passedDuration + passedDuration, + maxTripLength, + gearBank }: MiningTimeOptions): [number, number] { let { intercept } = ore; - if (ore.name === 'Gem rock' && user.hasEquipped('Amulet of glory')) { + if (ore.name === 'Gem rock' && gearBank.hasEquipped('Amulet of glory')) { intercept *= 3; } let timeElapsed = 0; @@ -46,7 +48,7 @@ export function determineMiningTime({ passedDuration = 0; } - let userMaxTripTicks = (calcMaxTripLength(user, 'Mining') - passedDuration) / (Time.Second * 0.6); + let userMaxTripTicks = (maxTripLength - passedDuration) / (Time.Second * 0.6); if (ore.name === 'Amethyst' || ore.name === 'Daeyalt essence rock') { userMaxTripTicks *= 1.5; diff --git a/src/lib/skilling/skills/mining.ts b/src/lib/skilling/skills/mining.ts index 0202ace93d..96b05851c7 100644 --- a/src/lib/skilling/skills/mining.ts +++ b/src/lib/skilling/skills/mining.ts @@ -296,6 +296,11 @@ const prospectorItems: { [key: number]: number } = { [itemID('Prospector boots')]: 0.2 }; +export const prospectorItemsArr = Object.entries(prospectorItems).map(([itemID, bonus]) => ({ + id: Number.parseInt(itemID), + boostPercent: bonus +})); + const Mining = { aliases: ['mining'], Ores: ores, diff --git a/src/lib/structures/GearBank.ts b/src/lib/structures/GearBank.ts index ba22793e9a..28154f47b8 100644 --- a/src/lib/structures/GearBank.ts +++ b/src/lib/structures/GearBank.ts @@ -10,18 +10,27 @@ export class GearBank { gear: UserFullGearSetup; bank: Bank; skillsAsLevels: SkillsRequired; + skillsAsXP: SkillsRequired; chargeBank: ChargeBank; constructor({ gear, bank, skillsAsLevels, - chargeBank - }: { gear: UserFullGearSetup; bank: Bank; skillsAsLevels: SkillsRequired; chargeBank: ChargeBank }) { + chargeBank, + skillsAsXP + }: { + gear: UserFullGearSetup; + bank: Bank; + skillsAsLevels: SkillsRequired; + chargeBank: ChargeBank; + skillsAsXP: SkillsRequired; + }) { this.gear = gear; this.bank = bank; this.skillsAsLevels = skillsAsLevels; this.chargeBank = chargeBank; + this.skillsAsXP = skillsAsXP; } wildyGearCheck(item: string | number, isWildy: boolean) { diff --git a/src/lib/structures/XPBank.ts b/src/lib/structures/XPBank.ts index f371094653..de67f81251 100644 --- a/src/lib/structures/XPBank.ts +++ b/src/lib/structures/XPBank.ts @@ -1,6 +1,8 @@ import { sumArr } from 'e'; +import { skillEmoji } from '../data/emojis'; import type { AddXpParams } from '../minions/types'; import type { SkillNameType, SkillsEnum } from '../skilling/types'; +import type { Skills } from '../types'; export class XPBank { public xpList: AddXpParams[] = []; @@ -32,4 +34,13 @@ export class XPBank { public amount(skill: SkillNameType) { return sumArr(this.xpList.filter(i => i.skillName === skill).map(i => i.amount)); } + + toString() { + if (this.xpList.length === 0) return 'No XP'; + const grouped: Skills = {}; + for (const i of this.xpList) grouped[i.skillName] = (grouped[i.skillName] ?? 0) + i.amount; + return Object.entries(grouped) + .map(([skill, xp]) => `${xp.toLocaleString()} ${skillEmoji[skill as keyof typeof skillEmoji]} XP`) + .join(', '); + } } diff --git a/src/lib/util.ts b/src/lib/util.ts index 9be3535089..025ebd9ccb 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -37,6 +37,7 @@ import type { Consumable } from './minions/types'; import type { POHBoosts } from './poh'; import { SkillsEnum } from './skilling/types'; import type { Gear } from './structures/Gear'; +import type { GearBank } from './structures/GearBank'; import type { Skills } from './types'; import type { GroupMonsterActivityTaskOptions, @@ -279,7 +280,7 @@ export function roughMergeMahojiResponse( } export function skillingPetDropRate( - user: MUserClass, + user: MUserClass | GearBank, skill: SkillsEnum, baseDropRate: number ): { petDropRate: number } { diff --git a/src/mahoji/commands/mine.ts b/src/mahoji/commands/mine.ts index 3ee0dbd8c5..95c082bfbf 100644 --- a/src/mahoji/commands/mine.ts +++ b/src/mahoji/commands/mine.ts @@ -7,14 +7,135 @@ import { determineMiningTime } from '../../lib/skilling/functions/determineMinin import { miningCapeOreEffect, miningGloves, pickaxes, varrockArmours } from '../../lib/skilling/functions/miningBoosts'; import { sinsOfTheFatherSkillRequirements } from '../../lib/skilling/functions/questRequirements'; import Mining from '../../lib/skilling/skills/mining'; +import type { Ore } from '../../lib/skilling/types'; +import type { GearBank } from '../../lib/structures/GearBank'; import type { MiningActivityTaskOptions } from '../../lib/types/minions'; import { formatDuration, formatSkillRequirements, itemNameFromID, randomVariation } from '../../lib/util'; import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask'; +import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength'; import itemID from '../../lib/util/itemID'; import { minionName } from '../../lib/util/minionUtils'; import { motherlodeMineCommand } from '../lib/abstracted_commands/motherlodeMineCommand'; import type { OSBMahojiCommand } from '../lib/util'; +export function determineMiningTrip({ + gearBank, + ore, + maxTripLength, + isPowermining, + quantityInput +}: { + gearBank: GearBank; + ore: Ore; + maxTripLength: number; + isPowermining: boolean; + quantityInput: number | undefined; +}) { + const boosts = []; + // Invisible mining level, dosen't help equip pickaxe etc + let miningLevel = gearBank.skillsAsLevels.mining; + if (ore.minerals && miningLevel >= 60) { + boosts.push('+7 invisible Mining lvls at the Mining guild'); + miningLevel += 7; + } + // Checks if user own Celestial ring or Celestial signet + if (gearBank.hasEquippedOrInBank(['Celestial ring (uncharged)'])) { + boosts.push('+4 invisible Mining lvls for Celestial ring'); + miningLevel += 4; + } + // Default bronze pickaxe, last in the array + let currentPickaxe = pickaxes[pickaxes.length - 1]; + boosts.push(`**${currentPickaxe.ticksBetweenRolls}** ticks between rolls for ${itemNameFromID(currentPickaxe.id)}`); + + // For each pickaxe, if they have it, give them its' bonus and break. + for (const pickaxe of pickaxes) { + if (!gearBank.hasEquippedOrInBank([pickaxe.id]) || gearBank.skillsAsLevels.mining < pickaxe.miningLvl) continue; + currentPickaxe = pickaxe; + boosts.pop(); + boosts.push(`**${pickaxe.ticksBetweenRolls}** ticks between rolls for ${itemNameFromID(pickaxe.id)}`); + break; + } + + let glovesRate = 0; + if (gearBank.skillsAsLevels.mining >= 60) { + for (const glove of miningGloves) { + if (!gearBank.hasEquipped(glove.id) || !glove.Percentages[ore.name]) continue; + glovesRate = glove.Percentages[ore.name]; + if (glovesRate) { + boosts.push(`Lowered rock depletion rate by **${glovesRate}%** for ${itemNameFromID(glove.id)}`); + break; + } + } + } + + let armourEffect = 0; + for (const armour of varrockArmours) { + if (!gearBank.hasEquippedOrInBank(armour.id) || !armour.Percentages[ore.name]) continue; + armourEffect = armour.Percentages[ore.name]; + if (armourEffect) { + boosts.push(`**${armourEffect}%** chance to mine an extra ore using ${itemNameFromID(armour.id)}`); + break; + } + } + + let goldSilverBoost = false; + if (gearBank.skillsAsLevels.crafting >= 99 && (ore.name === 'Gold ore' || ore.name === 'Silver ore')) { + goldSilverBoost = true; + boosts.push(`**70%** faster ${ore.name} banking for 99 Crafting`); + } + + let miningCapeEffect = 0; + if (gearBank.hasEquippedOrInBank([itemID('Mining cape')]) && miningCapeOreEffect[ore.name]) { + miningCapeEffect = miningCapeOreEffect[ore.name]; + if (miningCapeEffect) { + boosts.push(`**${miningCapeEffect}%** chance to mine an extra ore using Mining cape`); + } + } + + if (ore.bankingTime === 0) { + isPowermining = false; + } else { + boosts.push('**Powermining**'); + } + + // Calculate the time it takes to mine specific quantity or as many as possible + const [timeToMine, newQuantity] = determineMiningTime({ + quantity: quantityInput, + gearBank, + ore, + ticksBetweenRolls: currentPickaxe.ticksBetweenRolls, + glovesRate, + armourEffect, + miningCapeEffect, + powermining: isPowermining, + goldSilverBoost, + miningLvl: miningLevel, + maxTripLength + }); + + const duration = timeToMine; + + const fakeDurationMin = quantityInput ? randomVariation(reduceNumByPercent(duration, 25), 20) : duration; + const fakeDurationMax = quantityInput ? randomVariation(increaseNumByPercent(duration, 25), 20) : duration; + + if (ore.name === 'Gem rock' && gearBank.hasEquipped('Amulet of glory')) { + boosts.push('3x success rate for having an Amulet of glory equipped'); + } + + if (Number.isNaN(newQuantity) || newQuantity < 1) { + throw new Error(`Invalid quantity ${newQuantity} for mining ${ore.name}`); + } + + return { + duration, + quantity: newQuantity, + boosts, + fakeDurationMin, + fakeDurationMax, + isPowermining + }; +} + export const mineCommand: OSBMahojiCommand = { name: 'mine', description: 'Send your minion to mine things.', @@ -58,7 +179,7 @@ export const mineCommand: OSBMahojiCommand = { channelID }: CommandRunOptions<{ name: string; quantity?: number; powermine?: boolean }>) => { const user = await mUserFetch(userID); - let { quantity, powermine } = options; + const { quantity, powermine } = options; const motherlodeMine = stringMatches(Mining.MotherlodeMine.name, options.name) || @@ -95,107 +216,24 @@ export const mineCommand: OSBMahojiCommand = { } } - const boosts = []; - // Invisible mining level, dosen't help equip pickaxe etc - let miningLevel = user.skillsAsLevels.mining; - if (ore.minerals && miningLevel >= 60) { - boosts.push('+7 invisible Mining lvls at the Mining guild'); - miningLevel += 7; - } - // Checks if user own Celestial ring or Celestial signet - if (user.hasEquippedOrInBank(['Celestial ring (uncharged)'])) { - boosts.push('+4 invisible Mining lvls for Celestial ring'); - miningLevel += 4; - } - // Default bronze pickaxe, last in the array - let currentPickaxe = pickaxes[pickaxes.length - 1]; - boosts.push( - `**${currentPickaxe.ticksBetweenRolls}** ticks between rolls for ${itemNameFromID(currentPickaxe.id)}` - ); - - // For each pickaxe, if they have it, give them its' bonus and break. - for (const pickaxe of pickaxes) { - if (!user.hasEquippedOrInBank([pickaxe.id]) || user.skillsAsLevels.mining < pickaxe.miningLvl) continue; - currentPickaxe = pickaxe; - boosts.pop(); - boosts.push(`**${pickaxe.ticksBetweenRolls}** ticks between rolls for ${itemNameFromID(pickaxe.id)}`); - break; - } - - let glovesRate = 0; - if (user.skillsAsLevels.mining >= 60) { - for (const glove of miningGloves) { - if (!user.hasEquipped(glove.id) || !glove.Percentages[ore.name]) continue; - glovesRate = glove.Percentages[ore.name]; - if (glovesRate) { - boosts.push(`Lowered rock depletion rate by **${glovesRate}%** for ${itemNameFromID(glove.id)}`); - break; - } - } - } - - let armourEffect = 0; - for (const armour of varrockArmours) { - if (!user.hasEquippedOrInBank(armour.id) || !armour.Percentages[ore.name]) continue; - armourEffect = armour.Percentages[ore.name]; - if (armourEffect) { - boosts.push(`**${armourEffect}%** chance to mine an extra ore using ${itemNameFromID(armour.id)}`); - break; - } - } - - let goldSilverBoost = false; - if (user.skillsAsLevels.crafting >= 99 && (ore.name === 'Gold ore' || ore.name === 'Silver ore')) { - goldSilverBoost = true; - boosts.push(`**70%** faster ${ore.name} banking for 99 Crafting`); - } - - let miningCapeEffect = 0; - if (user.hasEquippedOrInBank([itemID('Mining cape')]) && miningCapeOreEffect[ore.name]) { - miningCapeEffect = miningCapeOreEffect[ore.name]; - if (miningCapeEffect) { - boosts.push(`**${miningCapeEffect}%** chance to mine an extra ore using Mining cape`); - } - } - - if (!powermine || ore.bankingTime === 0) { - powermine = false; - } else { - boosts.push('**Powermining**'); - } - // Calculate the time it takes to mine specific quantity or as many as possible - const [timeToMine, newQuantity] = determineMiningTime({ - quantity, - user, + const res = determineMiningTrip({ + gearBank: user.gearBank, ore, - ticksBetweenRolls: currentPickaxe.ticksBetweenRolls, - glovesRate, - armourEffect, - miningCapeEffect, - powermining: powermine, - goldSilverBoost, - miningLvl: miningLevel + maxTripLength: calcMaxTripLength(user, 'Mining'), + isPowermining: !!powermine, + quantityInput: quantity }); - const duration = timeToMine; - - const fakeDurationMin = quantity ? randomVariation(reduceNumByPercent(duration, 25), 20) : duration; - const fakeDurationMax = quantity ? randomVariation(increaseNumByPercent(duration, 25), 20) : duration; - - if (ore.name === 'Gem rock' && user.hasEquipped('Amulet of glory')) { - boosts.push('3x success rate for having an Amulet of glory equipped'); - } - await addSubTaskToActivityTask({ oreID: ore.id, userID: userID.toString(), channelID: channelID.toString(), - quantity: newQuantity, + quantity: res.quantity, iQty: options.quantity ? options.quantity : undefined, - powermine, - duration, - fakeDurationMax, - fakeDurationMin, + powermine: res.isPowermining, + duration: res.duration, + fakeDurationMax: res.fakeDurationMax, + fakeDurationMin: res.fakeDurationMin, type: 'Mining' }); @@ -203,12 +241,12 @@ export const mineCommand: OSBMahojiCommand = { quantity ? `mined ${quantity}x or gets tired` : 'is satisfied' }, it'll take ${ quantity - ? `between ${formatDuration(fakeDurationMin)} **and** ${formatDuration(fakeDurationMax)}` - : formatDuration(duration) + ? `between ${formatDuration(res.fakeDurationMin)} **and** ${formatDuration(res.fakeDurationMax)}` + : formatDuration(res.duration) } to finish.`; - if (boosts.length > 0) { - response += `\n\n**Boosts:** ${boosts.join(', ')}.`; + if (res.boosts.length > 0) { + response += `\n\n**Boosts:** ${res.boosts.join(', ')}.`; } return response; diff --git a/src/mahoji/lib/abstracted_commands/camdozaalCommand.ts b/src/mahoji/lib/abstracted_commands/camdozaalCommand.ts index 5d6a720a47..f735502e1d 100644 --- a/src/mahoji/lib/abstracted_commands/camdozaalCommand.ts +++ b/src/mahoji/lib/abstracted_commands/camdozaalCommand.ts @@ -47,7 +47,7 @@ async function miningCommand(user: MUser, channelID: string, quantity: number | // Calculate the time it takes to mine specific quantity or as many as possible const [duration, newQuantity] = determineMiningTime({ quantity, - user, + gearBank: user.gearBank, ore: barroniteRocks, ticksBetweenRolls: currentPickaxe.ticksBetweenRolls, glovesRate, @@ -55,7 +55,8 @@ async function miningCommand(user: MUser, channelID: string, quantity: number | miningCapeEffect, powermining: powermine, goldSilverBoost, - miningLvl: miningLevel + miningLvl: miningLevel, + maxTripLength: calcMaxTripLength(user, 'CamdozaalMining') }); const fakeDurationMin = quantity ? randomVariation(reduceNumByPercent(duration, 25), 20) : duration; diff --git a/src/mahoji/lib/abstracted_commands/motherlodeMineCommand.ts b/src/mahoji/lib/abstracted_commands/motherlodeMineCommand.ts index 7883c01ff5..7d3d99e431 100644 --- a/src/mahoji/lib/abstracted_commands/motherlodeMineCommand.ts +++ b/src/mahoji/lib/abstracted_commands/motherlodeMineCommand.ts @@ -7,6 +7,7 @@ import Mining from '../../../lib/skilling/skills/mining'; import type { MotherlodeMiningActivityTaskOptions } from '../../../lib/types/minions'; import { formatDuration, itemNameFromID } from '../../../lib/util'; import addSubTaskToActivityTask from '../../../lib/util/addSubTaskToActivityTask'; +import { calcMaxTripLength } from '../../../lib/util/calcMaxTripLength'; import { minionName } from '../../../lib/util/minionUtils'; export async function motherlodeMineCommand({ @@ -63,7 +64,7 @@ export async function motherlodeMineCommand({ // Calculate the time it takes to mine specific quantity or as many as possible const [duration, newQuantity] = determineMiningTime({ quantity, - user, + gearBank: user.gearBank, ore: motherlode, ticksBetweenRolls: currentPickaxe.ticksBetweenRolls, glovesRate, @@ -71,7 +72,8 @@ export async function motherlodeMineCommand({ miningCapeEffect, powermining: powermine, goldSilverBoost, - miningLvl: miningLevel + miningLvl: miningLevel, + maxTripLength: calcMaxTripLength(user, 'MotherlodeMining') }); const fakeDurationMin = quantity ? randomVariation(reduceNumByPercent(duration, 25), 20) : duration; diff --git a/src/mahoji/lib/abstracted_commands/shootingStarsCommand.ts b/src/mahoji/lib/abstracted_commands/shootingStarsCommand.ts index 38d48d13a0..93c38493b2 100644 --- a/src/mahoji/lib/abstracted_commands/shootingStarsCommand.ts +++ b/src/mahoji/lib/abstracted_commands/shootingStarsCommand.ts @@ -206,7 +206,7 @@ export async function shootingStarsCommand(channelID: string, user: MUserClass, for (const star of stars) { const [timeToMine, newQuantity] = determineMiningTime({ quantity: Math.round(star.dustAvailable / usersWith), - user, + gearBank: user.gearBank, ore: star, ticksBetweenRolls: currentPickaxe.ticksBetweenRolls, glovesRate: 0, @@ -215,7 +215,8 @@ export async function shootingStarsCommand(channelID: string, user: MUserClass, powermining: false, goldSilverBoost: false, miningLvl: miningLevel, - passedDuration: duration + passedDuration: duration, + maxTripLength: calcMaxTripLength(user, 'ShootingStars') }); duration += timeToMine; dustReceived += newQuantity; diff --git a/src/tasks/minions/miningActivity.ts b/src/tasks/minions/miningActivity.ts index 141ac8fbc6..7d765e222b 100644 --- a/src/tasks/minions/miningActivity.ts +++ b/src/tasks/minions/miningActivity.ts @@ -1,143 +1,146 @@ -import { Time, randInt, roll } from 'e'; -import { Bank } from 'oldschooljs'; +import { Time, increaseNumByPercent, randInt, roll, sumArr } from 'e'; import { Emoji, Events } from '../../lib/constants'; import addSkillingClueToLoot from '../../lib/minions/functions/addSkillingClueToLoot'; -import Mining from '../../lib/skilling/skills/mining'; -import { SkillsEnum } from '../../lib/skilling/types'; +import Mining, { prospectorItemsArr } from '../../lib/skilling/skills/mining'; +import { type Ore, SkillsEnum } from '../../lib/skilling/types'; +import type { GearBank } from '../../lib/structures/GearBank'; +import { UpdateBank } from '../../lib/structures/UpdateBank'; import type { MiningActivityTaskOptions } from '../../lib/types/minions'; import { skillingPetDropRate } from '../../lib/util'; import { handleTripFinish } from '../../lib/util/handleTripFinish'; -export const miningTask: MinionTask = { - type: 'Mining', - async run(data: MiningActivityTaskOptions) { - const { oreID, userID, channelID, duration, powermine } = data; - const { quantity } = data; - const user = await mUserFetch(userID); - const ore = Mining.Ores.find(ore => ore.id === oreID)!; +export function determineMiningResult({ + ore, + quantity, + gearBank, + duration, + isPowermining +}: { ore: Ore; quantity: number; gearBank: GearBank; duration: number; isPowermining: boolean }) { + const miningLvl = gearBank.skillsAsLevels.mining; + const messages: string[] = []; + let xpToReceive = quantity * ore.xp; + + const equippedProsItems = prospectorItemsArr.filter(item => gearBank.hasEquipped(item.id)); + const bonusPercent = + equippedProsItems.length === 4 ? 2.5 : sumArr(equippedProsItems.map(item => item.boostPercent)); + if (bonusPercent > 0) { + const newXP = Math.floor(increaseNumByPercent(xpToReceive, bonusPercent)); + messages.push(`${bonusPercent}% (${newXP - xpToReceive}) XP for prospector`); + xpToReceive = newXP; + } - let xpReceived = quantity * ore.xp; - let bonusXP = 0; - - // If they have the entire prospector outfit, give an extra 0.5% xp bonus - if ( - user.gear.skilling.hasEquipped( - Object.keys(Mining.prospectorItems).map(i => Number.parseInt(i)), - true - ) - ) { - const amountToAdd = Math.floor(xpReceived * (2.5 / 100)); - xpReceived += amountToAdd; - bonusXP += amountToAdd; - } else { - // For each prospector item, check if they have it, give its' XP boost if so. - for (const [itemID, bonus] of Object.entries(Mining.prospectorItems)) { - if (user.hasEquipped(Number.parseInt(itemID))) { - const amountToAdd = Math.floor(xpReceived * (bonus / 100)); - xpReceived += amountToAdd; - bonusXP += amountToAdd; - } - } - } - const currentLevel = user.skillLevel(SkillsEnum.Mining); - const xpRes = await user.addXP({ - skillName: SkillsEnum.Mining, - amount: xpReceived, - duration - }); + const updateBank = new UpdateBank(); + if (ore.xp) { + updateBank.xpBank.add('mining', xpToReceive, { duration }); + } + + // Add clue scrolls + if (ore.clueScrollChance) { + addSkillingClueToLoot(gearBank, SkillsEnum.Mining, quantity, ore.clueScrollChance, updateBank.itemLootBank); + } - let str = `${user}, ${user.minionName} finished mining ${quantity} ${ore.name}. ${xpRes}`; + // Roll for pet + if (ore.petChance) { + const { petDropRate } = skillingPetDropRate(gearBank, SkillsEnum.Mining, ore.petChance); + if (roll(petDropRate / quantity)) { + updateBank.itemLootBank.add('Rock golem'); + messages.push("You have a funny feeling you're being followed..."); + } + } - const loot = new Bank(); + const numberOfMinutes = duration / Time.Minute; - // Add clue scrolls - if (ore.clueScrollChance) { - addSkillingClueToLoot(user, SkillsEnum.Mining, quantity, ore.clueScrollChance, loot); + if (numberOfMinutes > 10 && ore.minerals && miningLvl >= 60) { + let numberOfMinerals = 0; + for (let i = 0; i < quantity; i++) { + if (roll(ore.minerals)) numberOfMinerals++; } - // Roll for pet - if (ore.petChance) { - const { petDropRate } = skillingPetDropRate(user, SkillsEnum.Mining, ore.petChance); - if (roll(petDropRate / quantity)) { - loot.add('Rock golem'); - str += "\nYou have a funny feeling you're being followed..."; - globalClient.emit( - Events.ServerNotification, - `${Emoji.Mining} **${user.badgedUsername}'s** minion, ${user.minionName}, just received a Rock golem while mining ${ore.name} at level ${currentLevel} Mining!` - ); - } + if (numberOfMinerals > 0) { + updateBank.itemLootBank.add('Unidentified minerals', numberOfMinerals); } + } - const numberOfMinutes = duration / Time.Minute; + let daeyaltQty = 0; - if (numberOfMinutes > 10 && ore.minerals && user.skillLevel(SkillsEnum.Mining) >= 60) { - let numberOfMinerals = 0; + if (!isPowermining) { + // Gem rocks roll off the GemRockTable + if (ore.name === 'Gem rock') { for (let i = 0; i < quantity; i++) { - if (roll(ore.minerals)) numberOfMinerals++; + updateBank.itemLootBank.add(Mining.GemRockTable.roll()); } - - if (numberOfMinerals > 0) { - loot.add('Unidentified minerals', numberOfMinerals); + } else if (ore.name === 'Volcanic ash') { + // Volcanic ash + const tiers = [ + [22, 1], + [37, 2], + [52, 3], + [67, 4], + [82, 5], + [97, 6] + ]; + for (const [lvl, multiplier] of tiers.reverse()) { + if (miningLvl >= lvl) { + updateBank.itemLootBank.add(ore.id, quantity * multiplier); + break; + } + } + } else if (ore.name === 'Sandstone') { + // Sandstone roll off the SandstoneRockTable + for (let i = 0; i < quantity; i++) { + updateBank.itemLootBank.add(Mining.SandstoneRockTable.roll()); } + } else if (ore.name === 'Granite') { + // Granite roll off the GraniteRockTable + for (let i = 0; i < quantity; i++) { + updateBank.itemLootBank.add(Mining.GraniteRockTable.roll()); + } + } else if (ore.name === 'Daeyalt essence rock') { + for (let i = 0; i < quantity; i++) { + daeyaltQty += randInt(2, 3); + } + updateBank.itemLootBank.add(ore.id, daeyaltQty); + } else { + updateBank.itemLootBank.add(ore.id, quantity); } + } - let daeyaltQty = 0; + return { + updateBank, + messages + }; +} - if (!powermine) { - // Gem rocks roll off the GemRockTable - if (ore.name === 'Gem rock') { - for (let i = 0; i < quantity; i++) { - loot.add(Mining.GemRockTable.roll()); - } - } else if (ore.name === 'Volcanic ash') { - // Volcanic ash - const userLevel = user.skillLevel(SkillsEnum.Mining); - const tiers = [ - [22, 1], - [37, 2], - [52, 3], - [67, 4], - [82, 5], - [97, 6] - ]; - for (const [lvl, multiplier] of tiers.reverse()) { - if (userLevel >= lvl) { - loot.add(ore.id, quantity * multiplier); - break; - } - } - } else if (ore.name === 'Sandstone') { - // Sandstone roll off the SandstoneRockTable - for (let i = 0; i < quantity; i++) { - loot.add(Mining.SandstoneRockTable.roll()); - } - } else if (ore.name === 'Granite') { - // Granite roll off the GraniteRockTable - for (let i = 0; i < quantity; i++) { - loot.add(Mining.GraniteRockTable.roll()); - } - } else if (ore.name === 'Daeyalt essence rock') { - for (let i = 0; i < quantity; i++) { - daeyaltQty += randInt(2, 3); - } - loot.add(ore.id, daeyaltQty); - } else { - loot.add(ore.id, quantity); - } - } +export const miningTask: MinionTask = { + type: 'Mining', + async run(data: MiningActivityTaskOptions) { + const { oreID, userID, channelID, duration, powermine } = data; + const { quantity } = data; + const user = await mUserFetch(userID); + const ore = Mining.Ores.find(ore => ore.id === oreID)!; - str += `\n\nYou received: ${loot}.`; - if (bonusXP > 0) { - str += `\n\n**Bonus XP:** ${bonusXP.toLocaleString()}`; + const { updateBank, messages } = determineMiningResult({ + ore, + quantity, + gearBank: user.gearBank, + duration, + isPowermining: powermine + }); + const updateResult = await updateBank.transact(user); + if (typeof updateResult === 'string') throw new Error(updateResult); + let str = `${user}, ${user.minionName} finished mining ${quantity} ${ore.name}. You received ${updateResult.itemTransactionResult?.itemsAdded} and ${updateBank.xpBank}.`; + if (messages.length > 0) { + str += `\n${messages.join(', ')}.`; } - await transactItems({ - userID: user.id, - collectionLog: true, - itemsToAdd: loot - }); + if (updateBank.itemLootBank.has('Rock golem')) { + globalClient.emit( + Events.ServerNotification, + `${Emoji.Mining} **${user.badgedUsername}'s** minion, ${user.minionName}, just received a Rock golem while mining ${ore.name} at level ${user.skillsAsLevels.mining} Mining!` + ); + } - handleTripFinish(user, channelID, str, undefined, data, loot); + handleTripFinish(user, channelID, str, undefined, data, updateResult.itemTransactionResult?.itemsAdded ?? null); } }; diff --git a/tests/unit/utils.ts b/tests/unit/utils.ts index fa86797109..87c9a810dd 100644 --- a/tests/unit/utils.ts +++ b/tests/unit/utils.ts @@ -28,7 +28,8 @@ export function makeGearBank({ bank }: { bank?: Bank } = {}) { gear: makeFullGear(), bank: bank ?? new Bank(), skillsAsLevels: makeSkillsAsLevels(), - chargeBank: new ChargeBank() + chargeBank: new ChargeBank(), + skillsAsXP: makeSkillsAsLevels(13034431) }); }