diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 884a588cc9..f85775eb9c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -895,7 +895,6 @@ enum activity_type_enum { AgilityArena ChampionsChallenge AerialFishing - CrystalImpling DriftNet MahoganyHomes GnomeRestaurant diff --git a/src/lib/Task.ts b/src/lib/Task.ts index 264515eeef..a6cbefcc1c 100644 --- a/src/lib/Task.ts +++ b/src/lib/Task.ts @@ -26,7 +26,6 @@ import { groupoMonsterTask } from '../tasks/minions/groupMonsterActivity'; import { herbloreTask } from '../tasks/minions/herbloreActivity'; import { aerialFishingTask } from '../tasks/minions/HunterActivity/aerialFishingActivity'; import { birdHouseTask } from '../tasks/minions/HunterActivity/birdhouseActivity'; -import { crystalImplingTask } from '../tasks/minions/HunterActivity/crystalImplingActivity'; import { driftNetTask } from '../tasks/minions/HunterActivity/driftNetActivity'; import { hunterTask } from '../tasks/minions/HunterActivity/hunterActivity'; import { mageArenaTwoTask } from '../tasks/minions/mageArena2Activity'; @@ -182,8 +181,7 @@ export const tasks: MinionTask[] = [ specificQuestTask, camdozaalMiningTask, camdozaalSmithingTask, - camdozaalFishingTask, - crystalImplingTask + camdozaalFishingTask ]; export async function processPendingActivities() { diff --git a/src/lib/implings.ts b/src/lib/implings.ts index 1aa1834bce..2f1b8beb7b 100644 --- a/src/lib/implings.ts +++ b/src/lib/implings.ts @@ -117,8 +117,7 @@ export function handlePassiveImplings(user: MUser, data: ActivityTaskData) { activity_type_enum.Construction, activity_type_enum.TombsOfAmascut, activity_type_enum.DriftNet, - activity_type_enum.UnderwaterAgilityThieving, - activity_type_enum.CrystalImpling + activity_type_enum.UnderwaterAgilityThieving ].includes(data.type) ) return null; diff --git a/src/lib/types/minions.ts b/src/lib/types/minions.ts index 679ed7529e..05ec0ab5e3 100644 --- a/src/lib/types/minions.ts +++ b/src/lib/types/minions.ts @@ -279,14 +279,6 @@ export interface HunterActivityTaskOptions extends ActivityTaskOptions { usingStaminaPotion: boolean; } -export interface CrystalImplingActivityTaskOptions extends ActivityTaskOptions { - type: 'CrystalImpling'; - creatureName: string; - quantity: number; - usingHuntPotion: boolean; - usingStaminaPotion: boolean; -} - export interface AlchingActivityTaskOptions extends ActivityTaskOptions { type: 'Alching'; itemID: number; @@ -606,5 +598,4 @@ export type ActivityTaskData = | FightCavesActivityTaskOptions | ActivityTaskOptionsWithQuantity | MinigameActivityTaskOptionsWithNoChanges - | CutLeapingFishActivityTaskOptions - | CrystalImplingActivityTaskOptions; + | CutLeapingFishActivityTaskOptions; diff --git a/src/lib/util/activityInArea.ts b/src/lib/util/activityInArea.ts index ebfe7408e8..dbedf8855b 100644 --- a/src/lib/util/activityInArea.ts +++ b/src/lib/util/activityInArea.ts @@ -3,6 +3,7 @@ import { Monsters } from 'oldschooljs'; import { ActivityTaskData, AgilityActivityTaskOptions, + HunterActivityTaskOptions, MonsterActivityTaskOptions, PickpocketActivityTaskOptions } from '../types/minions'; @@ -37,6 +38,12 @@ const WorldLocationsChecker = [ ) { return true; } + if ( + activity.type === 'Hunter' && + (activity as HunterActivityTaskOptions).creatureName === 'Crystal impling' + ) { + return true; + } return false; } diff --git a/src/lib/util/minionStatus.ts b/src/lib/util/minionStatus.ts index f333575b1c..e770be0684 100644 --- a/src/lib/util/minionStatus.ts +++ b/src/lib/util/minionStatus.ts @@ -435,10 +435,6 @@ export function minionStatus(user: MUser) { return `${name} is currently hunting ${data.quantity}x ${creature!.name}. ${formattedDuration}`; } - case 'CrystalImpling': { - return `${name} is currently hunting crystal implings. ${formattedDuration}`; - } - case 'Birdhouse': { return `${name} is currently doing a bird house run. ${formattedDuration}`; } diff --git a/src/lib/util/repeatStoredTrip.ts b/src/lib/util/repeatStoredTrip.ts index dbfe9f0bea..6d30f31d2b 100644 --- a/src/lib/util/repeatStoredTrip.ts +++ b/src/lib/util/repeatStoredTrip.ts @@ -21,7 +21,6 @@ import { ConstructionActivityTaskOptions, CookingActivityTaskOptions, CraftingActivityTaskOptions, - CrystalImplingActivityTaskOptions, CutLeapingFishActivityTaskOptions, DarkAltarOptions, EnchantingActivityTaskOptions, @@ -348,15 +347,6 @@ export const tripHandlers = { stamina_potions: data.usingStaminaPotion }) }, - [activity_type_enum.CrystalImpling]: { - commandName: 'hunt', - args: (data: CrystalImplingActivityTaskOptions) => ({ - name: data.creatureName, - quantity: data.quantity, - hunter_potion: data.usingHuntPotion, - stamina_potions: data.usingStaminaPotion - }) - }, [activity_type_enum.Inferno]: { commandName: 'activities', args: () => ({ inferno: { action: 'start' } }) diff --git a/src/mahoji/commands/hunt.ts b/src/mahoji/commands/hunt.ts index 92e7578360..45031478f3 100644 --- a/src/mahoji/commands/hunt.ts +++ b/src/mahoji/commands/hunt.ts @@ -15,7 +15,6 @@ import { formatDuration, itemID } from '../../lib/util'; import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask'; import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength'; import { updateBankSetting } from '../../lib/util/updateBankSetting'; -import { crystalImplingCommand } from '../lib/abstracted_commands/crystalImplingCommand'; import { OSBMahojiCommand } from '../lib/util'; import { userHasGracefulEquipped } from '../mahojiSettings'; @@ -119,14 +118,10 @@ export const huntCommand: OSBMahojiCommand = { } } + let crystalImpling = false; + if (creature.name === 'Crystal impling') { - return crystalImplingCommand({ - user, - quantity: options.quantity, - stamina_potions: options.stamina_potions, - hunter_potions: options.hunter_potion, - channelID: channelID.toString() - }); + crystalImpling = true; } // Reduce time if user is experienced hunting the creature, every hour become 1% better to a cap of 10% or 20% if tracking technique. @@ -169,7 +164,13 @@ export const huntCommand: OSBMahojiCommand = { const maxTripLength = calcMaxTripLength(user, 'Hunter'); let { quantity } = options; - if (!quantity) quantity = Math.floor(maxTripLength / ((catchTime * Time.Second) / traps)); + if (!quantity) { + if (crystalImpling) { + quantity = Math.floor(maxTripLength / Time.Minute); + } else { + quantity = Math.floor(maxTripLength / ((catchTime * Time.Second) / traps)); + } + } let duration = Math.floor(((quantity * catchTime) / traps) * Time.Second); @@ -267,9 +268,9 @@ export const huntCommand: OSBMahojiCommand = { type: 'Hunter' }); - let response = `${user.minionName} is now ${creature.huntTechnique} ${quantity}x ${ - creature.name - }, it'll take around ${formatDuration(duration)} to finish.`; + let response = `${user.minionName} is now ${crystalImpling ? 'hunting' : `${creature.huntTechnique}`} ${ + crystalImpling ? '' : `${quantity}x ` + }${creature.name}, it'll take around ${formatDuration(duration)} to finish.`; if (boosts.length > 0) { response += `\n\n**Boosts:** ${boosts.join(', ')}.`; diff --git a/src/mahoji/lib/abstracted_commands/crystalImplingCommand.ts b/src/mahoji/lib/abstracted_commands/crystalImplingCommand.ts deleted file mode 100644 index 07756ba812..0000000000 --- a/src/mahoji/lib/abstracted_commands/crystalImplingCommand.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Time } from 'e'; -import { Bank } from 'oldschooljs'; - -import { trackLoot } from '../../../lib/lootTrack'; -import Hunter from '../../../lib/skilling/skills/hunter/hunter'; -import { CrystalImplingActivityTaskOptions } from '../../../lib/types/minions'; -import { formatDuration, itemID } from '../../../lib/util'; -import addSubTaskToActivityTask from '../../../lib/util/addSubTaskToActivityTask'; -import { calcMaxTripLength } from '../../../lib/util/calcMaxTripLength'; -import { updateBankSetting } from '../../../lib/util/updateBankSetting'; -import { userHasGracefulEquipped } from '../../mahojiSettings'; - -export async function crystalImplingCommand({ - user, - quantity, - stamina_potions, - hunter_potions, - channelID -}: { - user: MUser; - quantity?: number; - stamina_potions?: boolean; - hunter_potions?: boolean; - channelID: string; -}) { - const userBank = user.bank; - let usingStaminaPotion = Boolean(stamina_potions); - let usingHuntPotion = Boolean(hunter_potions); - const creature = Hunter.Creatures.find(c => c.name === 'Crystal impling'); - - if (!creature) return "That's not a valid creature to hunt."; - - const boosts = []; - - if (userHasGracefulEquipped(user)) { - boosts.push('5% boost for using Graceful'); - } - - const maxTripLength = calcMaxTripLength(user, 'Hunter'); - if (!quantity) quantity = Math.floor(maxTripLength / Time.Minute); - - let duration = Math.floor(quantity * Time.Minute); - - if (duration > maxTripLength) { - return `${user.minionName} can't go on trips longer than ${formatDuration( - maxTripLength - )}, try a lower quantity. The highest amount of minutes you can spend hunting ${creature.name} is ${Math.floor( - maxTripLength / (quantity * Time.Minute) - )}.`; - } - - let removeBank = new Bank(); - - if (usingStaminaPotion) { - let staminaPotionQuantity = Math.round(duration / (9 * Time.Minute)); - - if (userBank.amount('Stamina potion(4)') < staminaPotionQuantity) { - return `You need ${staminaPotionQuantity}x Stamina potion(4) to hunt for the whole trip, try a lower quantity or make/buy more potions.`; - } - removeBank.add('Stamina potion(4)', staminaPotionQuantity); - boosts.push(`20% boost for using ${staminaPotionQuantity}x Stamina potion(4)`); - } - - if (usingHuntPotion) { - const hunterPotionQuantity = Math.round(duration / (8 * Time.Minute)); - if (userBank.amount('Hunter potion(4)') < hunterPotionQuantity) { - return `You need ${hunterPotionQuantity}x Hunter potion(4) to boost your level for the whole trip, try a lower quantity or make/buy more potions.`; - } - removeBank.add(itemID('Hunter potion(4)'), hunterPotionQuantity); - boosts.push(`+2 hunter level for using ${hunterPotionQuantity}x Hunter potion(4) every 2nd minute.`); - } - - updateBankSetting('hunter_cost', removeBank); - await user.removeItemsFromBank(removeBank); - - await trackLoot({ - id: creature.name, - totalCost: removeBank, - type: 'Skilling', - changeType: 'cost', - users: [ - { - id: user.id, - cost: removeBank - } - ] - }); - - await addSubTaskToActivityTask({ - creatureName: creature.name, - userID: user.id, - quantity, - duration, - usingHuntPotion, - usingStaminaPotion, - type: 'CrystalImpling', - channelID: channelID.toString() - }); - - let response = `${user.minionName} is now hunting ${creature.name}, it'll take around ${formatDuration( - duration - )} to finish.`; - - if (boosts.length > 0) { - response += `\n\n**Boosts:** ${boosts.join(', ')}.`; - } - - return response; -} diff --git a/src/tasks/minions/HunterActivity/crystalImplingActivity.ts b/src/tasks/minions/HunterActivity/crystalImplingActivity.ts deleted file mode 100644 index fa86f409d9..0000000000 --- a/src/tasks/minions/HunterActivity/crystalImplingActivity.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { percentChance } from 'e'; -import { Bank } from 'oldschooljs'; - -import { trackLoot } from '../../../lib/lootTrack'; -import Hunter from '../../../lib/skilling/skills/hunter/hunter'; -import { SkillsEnum } from '../../../lib/skilling/types'; -import { CrystalImplingActivityTaskOptions } from '../../../lib/types/minions'; -import { handleTripFinish } from '../../../lib/util/handleTripFinish'; -import { makeBankImage } from '../../../lib/util/makeBankImage'; -import { updateBankSetting } from '../../../lib/util/updateBankSetting'; -import { userHasGracefulEquipped } from '../../../mahoji/mahojiSettings'; - -export const crystalImplingTask: MinionTask = { - type: 'CrystalImpling', - async run(data: CrystalImplingActivityTaskOptions) { - const { quantity, userID, duration, channelID, usingStaminaPotion } = data; - const user = await mUserFetch(userID); - - const creature = Hunter.Creatures.find(c => c.name === 'Crystal impling'); - if (!creature) return; - - let creatureTable = creature.table; - let successfulQuantity = 0; - - const maxImplingsPer60 = 21; - const maxImplings = Math.round((maxImplingsPer60 / 60) * duration) + 1; - - let catchChance = 20; - - if (userHasGracefulEquipped(user)) { - catchChance *= 1.05; - } - - if (usingStaminaPotion) { - catchChance *= 1.2; - } - - catchChance = Math.round(catchChance); - - for (let i = 0; i < quantity; i++) { - if (percentChance(catchChance)) { - successfulQuantity++; - } - } - - successfulQuantity = Math.min(successfulQuantity, maxImplings); - - let xpStr = ''; - let xpReceived = creature.hunterXP * successfulQuantity; - - const loot = new Bank(); - - for (let i = 0; i < successfulQuantity; i++) { - loot.add(creatureTable.roll()); - } - await user.incrementCreatureScore(creature.id, Math.floor(successfulQuantity)); - const { previousCL, itemsAdded } = await transactItems({ - userID: user.id, - collectionLog: true, - itemsToAdd: loot - }); - xpStr += await user.addXP({ - skillName: SkillsEnum.Hunter, - amount: xpReceived, - duration - }); - - let str = `${user}, ${user.minionName} finished hunting ${creature.name} for ${quantity}x minutes. You managed to catch ${successfulQuantity} implings. ${xpStr}`; - - const image = - itemsAdded.length === 0 - ? undefined - : await makeBankImage({ - bank: itemsAdded, - title: `Loot From ${successfulQuantity} ${creature.name}:`, - user, - previousCL - }); - - await trackLoot({ - id: creature.name, - changeType: 'loot', - duration, - kc: successfulQuantity, - totalLoot: itemsAdded, - type: 'Skilling', - users: [ - { - id: user.id, - duration, - loot: itemsAdded - } - ] - }); - - updateBankSetting('hunter_loot', itemsAdded); - - return handleTripFinish(user, channelID, str, image?.file.attachment, data, itemsAdded); - } -}; diff --git a/src/tasks/minions/HunterActivity/hunterActivity.ts b/src/tasks/minions/HunterActivity/hunterActivity.ts index fb70b8191b..f4934be918 100644 --- a/src/tasks/minions/HunterActivity/hunterActivity.ts +++ b/src/tasks/minions/HunterActivity/hunterActivity.ts @@ -1,5 +1,5 @@ import { Prisma } from '@prisma/client'; -import { randInt, Time } from 'e'; +import { percentChance, randInt, Time } from 'e'; import { Bank } from 'oldschooljs'; import { EquipmentSlot } from 'oldschooljs/dist/meta/types'; @@ -13,7 +13,9 @@ import { HunterActivityTaskOptions } from '../../../lib/types/minions'; import { roll, skillingPetDropRate, stringMatches } from '../../../lib/util'; import { handleTripFinish } from '../../../lib/util/handleTripFinish'; import itemID from '../../../lib/util/itemID'; +import { makeBankImage } from '../../../lib/util/makeBankImage'; import { updateBankSetting } from '../../../lib/util/updateBankSetting'; +import { userHasGracefulEquipped } from '../../../mahoji/mahojiSettings'; import { BLACK_CHIN_ID, HERBIBOAR_ID } from './../../../lib/constants'; const riskDeathNumbers = [ @@ -34,7 +36,8 @@ const riskDeathNumbers = [ export const hunterTask: MinionTask = { type: 'Hunter', async run(data: HunterActivityTaskOptions) { - const { creatureName, quantity, userID, channelID, usingHuntPotion, wildyPeak, duration } = data; + const { creatureName, quantity, userID, channelID, usingHuntPotion, wildyPeak, duration, usingStaminaPotion } = + data; const user = await mUserFetch(userID); const userBank = user.bank; const currentLevel = user.skillLevel(SkillsEnum.Hunter); @@ -53,6 +56,11 @@ export const hunterTask: MinionTask = { if (!creature) return; + let crystalImpling = false; + if (creature.name === 'Crystal impling') { + crystalImpling = true; + } + let [successfulQuantity, xpReceived] = calcLootXPHunting( Math.min(Math.floor(currentLevel + (usingHuntPotion ? 2 : 0)), MAX_LEVEL), creature, @@ -136,6 +144,32 @@ export const hunterTask: MinionTask = { }); } } + if (crystalImpling) { + let successfulQuantity = 0; + + const maxImplingsPer60 = 21; + const maxImplings = Math.round((maxImplingsPer60 / 60) * duration) + 1; + + let catchChance = 20; + + if (userHasGracefulEquipped(user)) { + catchChance *= 1.05; + } + if (usingStaminaPotion) { + catchChance *= 1.2; + } + + catchChance = Math.round(catchChance); + + for (let i = 0; i < quantity; i++) { + if (percentChance(catchChance)) { + successfulQuantity++; + } + } + + successfulQuantity = Math.min(successfulQuantity, maxImplings); + } + const loot = new Bank(); for (let i = 0; i < successfulQuantity - pkedQuantity; i++) { loot.add(creatureTable.roll()); @@ -145,7 +179,7 @@ export const hunterTask: MinionTask = { } await user.incrementCreatureScore(creature.id, Math.floor(successfulQuantity)); - await transactItems({ + const { previousCL, itemsAdded } = await transactItems({ userID: user.id, collectionLog: true, itemsToAdd: loot @@ -162,7 +196,7 @@ export const hunterTask: MinionTask = { quantity - successfulQuantity }x catches. ${xpStr}`; - str += `\n\nYou received: ${loot}.${magicSecStr.length > 1 ? magicSecStr : ''}`; + str += `\n\nYou received: ${itemsAdded}.${magicSecStr.length > 1 ? magicSecStr : ''}`; if (gotPked && !died) { str += `\n${pkStr}`; @@ -172,25 +206,35 @@ export const hunterTask: MinionTask = { str += `\n${diedStr}`; } - if (loot.amount('Baby chinchompa') > 0 || loot.amount('Herbi') > 0) { + if (itemsAdded.amount('Baby chinchompa') > 0 || itemsAdded.amount('Herbi') > 0) { str += "\n\n**You have a funny feeling like you're being followed....**"; globalClient.emit( Events.ServerNotification, `**${user.usernameOrMention}'s** minion, ${user.minionName}, just received a ${ - loot.amount('Baby chinchompa') > 0 + itemsAdded.amount('Baby chinchompa') > 0 ? '**Baby chinchompa** <:Baby_chinchompa_red:324127375539306497>' : '**Herbi** <:Herbi:357773175318249472>' } while hunting a ${creature.name}, their Hunter level is ${currentLevel}!` ); } - updateBankSetting('hunter_loot', loot); + const image = + itemsAdded.length === 0 + ? undefined + : await makeBankImage({ + bank: itemsAdded, + title: `Loot From ${successfulQuantity} ${creature.name}:`, + user, + previousCL + }); + + updateBankSetting('hunter_loot', itemsAdded); await trackLoot({ id: creature.name, changeType: 'loot', duration, kc: quantity, - totalLoot: loot, + totalLoot: itemsAdded, type: 'Skilling', users: [ { @@ -200,7 +244,9 @@ export const hunterTask: MinionTask = { } ] }); - + if (crystalImpling) { + return handleTripFinish(user, channelID, str, image?.file.attachment, data, itemsAdded); + } handleTripFinish(user, channelID, str, undefined, data, loot); } };