From 840f23e5e84b4085043ecb3894f711261b4e7297 Mon Sep 17 00:00:00 2001 From: TastyPumPum <79149170+TastyPumPum@users.noreply.github.com> Date: Tue, 17 Oct 2023 06:24:25 +0100 Subject: [PATCH] Remove RevenantsCommand file and activity (#5435) * Remove Revenants Command and Activity Move revenants into the normal minionKill/monsterActivity files, this will help streamline wildy slayer. Allows quantity to be defined for revenants now. Adds salve amulet boost, which is huge for revs. Changed salve/blackmask/dragon hunter boosts to check for equipped gear if wilderness activties. * prisma * Update monsterActivity.ts --- prisma/schema.prisma | 1 - src/lib/Task.ts | 2 - src/lib/minions/data/killableMonsters/revs.ts | 122 ++++++++---- src/lib/types/minions.ts | 11 -- src/lib/util/minionStatus.ts | 9 - src/lib/util/repeatStoredTrip.ts | 7 - .../lib/abstracted_commands/minionKill.ts | 174 +++++++++++++----- .../lib/abstracted_commands/revsCommand.ts | 149 --------------- src/tasks/minions/monsterActivity.ts | 16 +- src/tasks/minions/revenantsActivity.ts | 138 -------------- 10 files changed, 235 insertions(+), 394 deletions(-) delete mode 100644 src/mahoji/lib/abstracted_commands/revsCommand.ts delete mode 100644 src/tasks/minions/revenantsActivity.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2f3321871d..a16a66aa00 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -896,7 +896,6 @@ enum activity_type_enum { BigChompyBirdHunting DarkAltar Trekking - Revenants PestControl VolcanicMine KourendFavour diff --git a/src/lib/Task.ts b/src/lib/Task.ts index 5a46133d42..c2db0c4f2f 100644 --- a/src/lib/Task.ts +++ b/src/lib/Task.ts @@ -69,7 +69,6 @@ import { buryingTask } from '../tasks/minions/PrayerActivity/buryingActivity'; import { offeringTask } from '../tasks/minions/PrayerActivity/offeringActivity'; import { scatteringTask } from '../tasks/minions/PrayerActivity/scatteringActivity'; import { questingTask } from '../tasks/minions/questingActivity'; -import { revenantsTask } from '../tasks/minions/revenantsActivity'; import { runecraftTask } from '../tasks/minions/runecraftActivity'; import { sawmillTask } from '../tasks/minions/sawmillActivity'; import { shootingStarTask } from '../tasks/minions/shootingStarsActivity'; @@ -150,7 +149,6 @@ export const tasks: MinionTask[] = [ motherlodeMiningTask, runecraftTask, sawmillTask, - revenantsTask, woodcuttingTask, wealthChargeTask, tokkulShopTask, diff --git a/src/lib/minions/data/killableMonsters/revs.ts b/src/lib/minions/data/killableMonsters/revs.ts index 1bfd7ff969..f1923e29ff 100644 --- a/src/lib/minions/data/killableMonsters/revs.ts +++ b/src/lib/minions/data/killableMonsters/revs.ts @@ -1,5 +1,5 @@ import { Time } from 'e'; -import { Monsters } from 'oldschooljs'; +import { Bank, Monsters } from 'oldschooljs'; import { KillableMonster } from '../../types'; @@ -8,132 +8,188 @@ export const revenantMonsters: KillableMonster[] = [ id: Monsters.RevenantCyclops.id, name: Monsters.RevenantCyclops.name, aliases: Monsters.RevenantCyclops.aliases, - timeToFinish: Time.Second * 50, + timeToFinish: Time.Second * 82, table: Monsters.RevenantCyclops, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 6, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantDarkBeast.id, name: Monsters.RevenantDarkBeast.name, aliases: Monsters.RevenantDarkBeast.aliases, - timeToFinish: Time.Second * 70, + timeToFinish: Time.Second * 114, table: Monsters.RevenantDarkBeast, wildy: true, difficultyRating: 9, qpRequired: 0, pkActivityRating: 9, - pkBaseDeathChance: 4 + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantDemon.id, name: Monsters.RevenantDemon.name, aliases: Monsters.RevenantDemon.aliases, - timeToFinish: Time.Second * 50, + timeToFinish: Time.Second * 82, table: Monsters.RevenantDemon, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 6, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantDragon.id, name: Monsters.RevenantDragon.name, aliases: Monsters.RevenantDragon.aliases, - timeToFinish: Time.Second * 90, + timeToFinish: Time.Second * 147, table: Monsters.RevenantDragon, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 8, - pkBaseDeathChance: 7 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantGoblin.id, name: Monsters.RevenantGoblin.name, aliases: Monsters.RevenantGoblin.aliases, - timeToFinish: Time.Second * 25, + timeToFinish: Time.Second * 41, table: Monsters.RevenantGoblin, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 5, - pkBaseDeathChance: 5 + pkActivityRating: 8, + pkBaseDeathChance: 8, + canBePked: true }, { id: Monsters.RevenantHellhound.id, name: Monsters.RevenantHellhound.name, aliases: Monsters.RevenantHellhound.aliases, - timeToFinish: Time.Second * 55, + timeToFinish: Time.Second * 90, table: Monsters.RevenantHellhound, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 6, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantHobgoblin.id, name: Monsters.RevenantHobgoblin.name, aliases: Monsters.RevenantHobgoblin.aliases, - timeToFinish: Time.Second * 45, + timeToFinish: Time.Second * 74, table: Monsters.RevenantHobgoblin, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 5, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantImp.id, name: Monsters.RevenantImp.name, aliases: Monsters.RevenantImp.aliases, - timeToFinish: Time.Second * 20, + timeToFinish: Time.Second * 33, table: Monsters.RevenantImp, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 4, - pkBaseDeathChance: 3 + pkActivityRating: 8, + pkBaseDeathChance: 8, + canBePked: true }, { id: Monsters.RevenantKnight.id, name: Monsters.RevenantKnight.name, aliases: Monsters.RevenantKnight.aliases, - timeToFinish: Time.Second * 75, + timeToFinish: Time.Second * 123, table: Monsters.RevenantKnight, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 8, - pkBaseDeathChance: 6 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantOrk.id, name: Monsters.RevenantOrk.name, aliases: Monsters.RevenantOrk.aliases, - timeToFinish: Time.Second * 65, + timeToFinish: Time.Second * 106, table: Monsters.RevenantOrk, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 7, - pkBaseDeathChance: 6 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantPyrefiend.id, name: Monsters.RevenantPyrefiend.name, aliases: Monsters.RevenantPyrefiend.aliases, - timeToFinish: Time.Second * 40, + timeToFinish: Time.Second * 65, table: Monsters.RevenantPyrefiend, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 7, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true } ]; diff --git a/src/lib/types/minions.ts b/src/lib/types/minions.ts index 2119d22897..d7f823fa16 100644 --- a/src/lib/types/minions.ts +++ b/src/lib/types/minions.ts @@ -129,16 +129,6 @@ export interface MonsterActivityTaskOptions extends ActivityTaskOptions { hasWildySupplies?: boolean; } -export interface RevenantOptions extends ActivityTaskOptions { - type: 'Revenants'; - monsterID: number; - quantity: number; - died: boolean; - fakeDuration: number; - usingPrayerPots: boolean; - skulled: boolean; - style: 'melee' | 'range' | 'mage'; -} export interface ClueActivityTaskOptions extends ActivityTaskOptions { type: 'ClueCompletion'; @@ -574,7 +564,6 @@ export type ActivityTaskData = | MiningActivityTaskOptions | MotherlodeMiningActivityTaskOptions | PlunderActivityTaskOptions - | RevenantOptions | SmithingActivityTaskOptions | SmeltingActivityTaskOptions | TiaraRunecraftActivityTaskOptions diff --git a/src/lib/util/minionStatus.ts b/src/lib/util/minionStatus.ts index 801cfa3b74..f053b9f2e1 100644 --- a/src/lib/util/minionStatus.ts +++ b/src/lib/util/minionStatus.ts @@ -1,6 +1,5 @@ import { toTitleCase } from '@oldschoolgg/toolkit'; import { increaseNumByPercent, reduceNumByPercent } from 'e'; -import { Monsters } from 'oldschooljs'; import { SkillsEnum } from 'oldschooljs/dist/constants'; import { collectables } from '../../mahoji/lib/abstracted_commands/collectCommand'; @@ -64,7 +63,6 @@ import { PickpocketActivityTaskOptions, PlunderActivityTaskOptions, RaidsOptions, - RevenantOptions, RunecraftActivityTaskOptions, SawmillActivityTaskOptions, ScatteringActivityTaskOptions, @@ -545,13 +543,6 @@ export function minionStatus(user: MUser) { case 'Trekking': { return `${name} is currently Temple Trekking. ${formattedDuration}`; } - case 'Revenants': { - const data = currentTask as RevenantOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - return `${data.skulled ? `${Emoji.OSRSSkull} ` : ''} ${name} is currently killing ${data.quantity}x ${ - Monsters.get(data.monsterID)!.name - } in the wilderness. If they don't die, the trip should take ${formatDuration(durationRemaining)}.`; - } case 'PestControl': { const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; return `${name} is currently doing ${data.quantity} games of Pest Control. ${formattedDuration}`; diff --git a/src/lib/util/repeatStoredTrip.ts b/src/lib/util/repeatStoredTrip.ts index 452e7491a9..5387f1b1eb 100644 --- a/src/lib/util/repeatStoredTrip.ts +++ b/src/lib/util/repeatStoredTrip.ts @@ -44,7 +44,6 @@ import { PickpocketActivityTaskOptions, PuroPuroActivityTaskOptions, RaidsOptions, - RevenantOptions, RunecraftActivityTaskOptions, SawmillActivityTaskOptions, ScatteringActivityTaskOptions, @@ -451,12 +450,6 @@ export const tripHandlers = { } }) }, - [activity_type_enum.Revenants]: { - commandName: 'k', - args: (data: RevenantOptions) => ({ - name: autocompleteMonsters.find(i => i.id === data.monsterID)?.name ?? data.monsterID.toString() - }) - }, [activity_type_enum.RoguesDenMaze]: { commandName: 'minigames', args: () => ({ diff --git a/src/mahoji/lib/abstracted_commands/minionKill.ts b/src/mahoji/lib/abstracted_commands/minionKill.ts index 7f7db986f3..d0a5675661 100644 --- a/src/mahoji/lib/abstracted_commands/minionKill.ts +++ b/src/mahoji/lib/abstracted_commands/minionKill.ts @@ -38,7 +38,12 @@ import { } from '../../../lib/minions/data/combatConstants'; import { revenantMonsters } from '../../../lib/minions/data/killableMonsters/revs'; import { Favours, gotFavour } from '../../../lib/minions/data/kourendFavour'; -import { AttackStyles, calculateMonsterFood, resolveAttackStyles } from '../../../lib/minions/functions'; +import { + AttackStyles, + calculateMonsterFood, + convertAttackStylesToSetup, + resolveAttackStyles +} from '../../../lib/minions/functions'; import reducedTimeFromKC from '../../../lib/minions/functions/reducedTimeFromKC'; import removeFoodFromUser from '../../../lib/minions/functions/removeFoodFromUser'; import { Consumable } from '../../../lib/minions/types'; @@ -46,6 +51,7 @@ import { calcPOHBoosts } from '../../../lib/poh'; import { SkillsEnum } from '../../../lib/skilling/types'; import { SlayerTaskUnlocksEnum } from '../../../lib/slayer/slayerUnlocks'; import { determineBoostChoice, getUsersCurrentSlayerInfo } from '../../../lib/slayer/slayerUtil'; +import { maxOffenceStats } from '../../../lib/structures/Gear'; import { Peak } from '../../../lib/tickers'; import { MonsterActivityTaskOptions } from '../../../lib/types/minions'; import { @@ -68,6 +74,7 @@ import { calcMaxTripLength } from '../../../lib/util/calcMaxTripLength'; import { calcWildyPKChance, increaseWildEvasionXp } from '../../../lib/util/calcWildyPkChance'; import { generateChart } from '../../../lib/util/chart'; import findMonster from '../../../lib/util/findMonster'; +import getOSItem from '../../../lib/util/getOSItem'; import { handleMahojiConfirmation } from '../../../lib/util/handleMahojiConfirmation'; import { updateBankSetting } from '../../../lib/util/updateBankSetting'; import { hasMonsterRequirements, resolveAvailableItemBoosts } from '../../mahojiSettings'; @@ -75,13 +82,18 @@ import { nexCommand } from './nexCommand'; import { nightmareCommand } from './nightmareCommand'; import { getPOH } from './pohCommand'; import { quests } from './questCommand'; -import { revsCommand } from './revsCommand'; import { temporossCommand } from './temporossCommand'; import { wintertodtCommand } from './wintertodtCommand'; import { zalcanoCommand } from './zalcanoCommand'; const invalidMonsterMsg = "That isn't a valid monster.\n\nFor example, `/k name:zulrah quantity:5`"; +const revSpecialWeapons = { + melee: getOSItem("Viggora's chainmace"), + range: getOSItem("Craw's bow"), + mage: getOSItem("Thammaron's sceptre") +} as const; + function formatMissingItems(consumables: Consumable[], timeToFinish: number) { const str = []; @@ -126,6 +138,9 @@ export async function minionKillCommand( return 'Your minion is busy.'; } const { minionName } = user; + const wildyGear = user.gear.wildy; + const style = convertAttackStylesToSetup(user.user.attack_style); + const key = ({ melee: 'attack_crush', mage: 'attack_magic', range: 'attack_ranged' } as const)[style]; const boosts = []; let messages: string[] = []; @@ -138,11 +153,17 @@ export async function minionKillCommand( if (name.toLowerCase().includes('nightmare')) return nightmareCommand(user, channelID, name); if (name.toLowerCase().includes('wintertodt')) return wintertodtCommand(user, channelID); - if (revenantMonsters.some(i => i.aliases.some(a => stringMatches(a, name)))) { - return revsCommand(user, channelID, interaction, name); + let monster = findMonster(name); + let revenants = false; + + const matchedRevenantMonster = revenantMonsters.find(monster => + monster.aliases.some(alias => stringMatches(alias, name)) + ); + if (matchedRevenantMonster) { + monster = matchedRevenantMonster; + revenants = true; } - const monster = findMonster(name); if (!monster) return invalidMonsterMsg; const usersTask = await getUsersCurrentSlayerInfo(user.id); @@ -155,6 +176,20 @@ export async function minionKillCommand( return `You can't kill ${monster.name}, because you're not on a slayer task.`; } + const wildyGearStat = wildyGear.getStats()[key]; + const revGearPercent = Math.max(0, calcWhatPercent(wildyGearStat, maxOffenceStats[key])); + + if (revenants) { + const weapon = wildyGear.equippedWeapon(); + if (!weapon) { + return 'You have no weapon equipped in your Wildy outfit.'; + } + + if (weapon.equipment![key] < 10) { + return `Your weapon is terrible, you can't kill Revenants. You should have ${style} gear equipped in your wildy outfit, as this is what you're currently training. You can change this using \`/minion train\``; + } + } + // Set chosen boost based on priority: const myCBOpts = user.combatOptions; const boostChoice = determineBoostChoice({ @@ -210,21 +245,6 @@ export async function minionKillCommand( const monsterHP = osjsMon?.data.hitpoints ?? 100; - // Removed vorkath because he has a special boost. - if (monster.name.toLowerCase() !== 'vorkath' && osjsMon?.data?.attributes?.includes(MonsterAttribute.Dragon)) { - if ( - user.hasEquippedOrInBank('Dragon hunter lance') && - !attackStyles.includes(SkillsEnum.Ranged) && - !attackStyles.includes(SkillsEnum.Magic) - ) { - timeToFinish = reduceNumByPercent(timeToFinish, 15); - boosts.push('15% for Dragon hunter lance'); - } else if (user.hasEquippedOrInBank('Dragon hunter crossbow') && attackStyles.includes(SkillsEnum.Ranged)) { - timeToFinish = reduceNumByPercent(timeToFinish, 15); - boosts.push('15% for Dragon hunter crossbow'); - } - } - // Black mask and salve don't stack. const oneSixthBoost = 16.67; let blackMaskBoost = 0; @@ -232,31 +252,90 @@ export async function minionKillCommand( let salveAmuletBoost = 0; let salveAmuletBoostMsg = ''; - // Calculate Slayer helmet boost on task if they have black mask or similar - if (attackStyles.includes(SkillsEnum.Ranged) || attackStyles.includes(SkillsEnum.Magic)) { - if (isOnTask && user.hasEquippedOrInBank('Black mask (i)')) { + const dragonBoost = 15; // Common boost percentage for dragon-related gear + + const isUndead = osjsMon?.data?.attributes?.includes(MonsterAttribute.Undead); + const isDragon = osjsMon?.data?.attributes?.includes(MonsterAttribute.Dragon); + + function applyDragonBoost() { + const hasDragonLance = monster?.canBePked + ? wildyGear.hasEquipped('Dragon hunter lance') + : user.hasEquippedOrInBank('Dragon hunter lance'); + const hasDragonCrossbow = monster?.canBePked + ? wildyGear.hasEquipped('Dragon hunter crossbow') + : user.hasEquippedOrInBank('Dragon hunter crossbow'); + + if ( + (hasDragonLance && !attackStyles.includes(SkillsEnum.Ranged) && !attackStyles.includes(SkillsEnum.Magic)) || + (hasDragonCrossbow && attackStyles.includes(SkillsEnum.Ranged)) + ) { + const boostMessage = hasDragonLance ? '15% for Dragon hunter lance' : '15% for Dragon hunter crossbow'; + timeToFinish = reduceNumByPercent(timeToFinish, dragonBoost); + boosts.push(boostMessage); + } + } + + function applyBlackMaskBoost() { + const hasBlackMask = monster?.canBePked + ? wildyGear.hasEquipped('Black mask') + : user.hasEquippedOrInBank('Black mask'); + const hasBlackMaskI = isOnTask + ? wildyGear.hasEquipped('Black mask (i)') + : user.hasEquippedOrInBank('Black mask (i)'); + + if (attackStyles.includes(SkillsEnum.Ranged) || attackStyles.includes(SkillsEnum.Magic)) { + if (hasBlackMaskI) { + blackMaskBoost = oneSixthBoost; + blackMaskBoostMsg = `${blackMaskBoost}% for Black mask (i) on non-melee task`; + } + } else if (hasBlackMask) { blackMaskBoost = oneSixthBoost; - blackMaskBoostMsg = `${blackMaskBoost}% for Black mask (i) on non-melee task`; + blackMaskBoostMsg = `${blackMaskBoost}% for Black mask on melee task`; } - } else if (isOnTask && user.hasEquippedOrInBank('Black mask')) { - blackMaskBoost = oneSixthBoost; - blackMaskBoostMsg = `${blackMaskBoost}% for Black mask on melee task`; - } - - // Calculate Salve amulet boost on task if the monster is undead or similar - const undeadMonster = osjsMon?.data?.attributes?.includes(MonsterAttribute.Undead); - if (undeadMonster && (attackStyles.includes(SkillsEnum.Ranged) || attackStyles.includes(SkillsEnum.Magic))) { - if (user.hasEquippedOrInBank('Salve amulet(i)')) { - const enhancedBoost = user.hasEquippedOrInBank('Salve amulet(ei)'); - salveAmuletBoost = enhancedBoost ? 20 : oneSixthBoost; - salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${ - enhancedBoost ? '(ei)' : '(i)' - } on non-melee task`; + } + + function calculateSalveAmuletBoost() { + let salveBoost = false; + let salveEnhanced = false; + const style = attackStyles[0]; + if (style === 'ranged' || style === 'magic') { + salveBoost = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet(i)') + : user.hasEquippedOrInBank('Salve amulet (i)'); + salveEnhanced = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet(ei)') + : user.hasEquippedOrInBank('Salve amulet (ei)'); + if (salveBoost) { + salveAmuletBoost = salveEnhanced ? 20 : oneSixthBoost; + salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${ + salveEnhanced ? '(ei)' : '(i)' + } on non-melee task`; + } + } else { + salveBoost = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet') + : user.hasEquippedOrInBank('Salve amulet'); + salveEnhanced = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet (e)') + : user.hasEquippedOrInBank('Salve amulet (e)'); + if (salveBoost) { + salveAmuletBoost = salveEnhanced ? 20 : oneSixthBoost; + salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${ + salveEnhanced ? ' (e)' : '' + } on melee task`; + } } - } else if (undeadMonster && user.hasEquippedOrInBank('Salve amulet')) { - const enhancedBoost = user.hasEquippedOrInBank('Salve amulet(e)'); - salveAmuletBoost = enhancedBoost ? 20 : oneSixthBoost; - salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${enhancedBoost ? ' (e)' : ''} on melee task`; + } + if (isDragon && monster.name.toLowerCase() !== 'vorkath') { + applyDragonBoost(); + } + + if (isOnTask) { + applyBlackMaskBoost(); + } + + if (isUndead) { + calculateSalveAmuletBoost(); } // Only choose greater boost: @@ -270,6 +349,17 @@ export async function minionKillCommand( } } + if (revenants) { + timeToFinish = reduceNumByPercent(timeToFinish, revGearPercent / 4); + boosts.push(`${(revGearPercent / 4).toFixed(2)}% (out of a possible 25%) for ${key}`); + + const specialWeapon = revSpecialWeapons[style]; + if (wildyGear.hasEquipped(specialWeapon.name)) { + timeToFinish = reduceNumByPercent(timeToFinish, 35); + boosts.push(`${35}% for ${specialWeapon.name}`); + } + } + // Initialize consumable costs before any are calculated. const consumableCosts: Consumable[] = []; diff --git a/src/mahoji/lib/abstracted_commands/revsCommand.ts b/src/mahoji/lib/abstracted_commands/revsCommand.ts deleted file mode 100644 index fd918057b2..0000000000 --- a/src/mahoji/lib/abstracted_commands/revsCommand.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { ChatInputCommandInteraction } from 'discord.js'; -import { calcWhatPercent, randInt, reduceNumByPercent, Time } from 'e'; -import { CommandResponse } from 'mahoji/dist/lib/structures/ICommand'; -import { Bank } from 'oldschooljs'; - -import { Emoji } from '../../../lib/constants'; -import { trackLoot } from '../../../lib/lootTrack'; -import { revenantMonsters } from '../../../lib/minions/data/killableMonsters/revs'; -import { convertAttackStylesToSetup } from '../../../lib/minions/functions'; -import { SkillsEnum } from '../../../lib/skilling/types'; -import { maxDefenceStats, maxOffenceStats } from '../../../lib/structures/Gear'; -import { RevenantOptions } from '../../../lib/types/minions'; -import { formatDuration, percentChance, stringMatches } from '../../../lib/util'; -import addSubTaskToActivityTask from '../../../lib/util/addSubTaskToActivityTask'; -import { calcMaxTripLength } from '../../../lib/util/calcMaxTripLength'; -import { getWildEvasionPercent, increaseWildEvasionXp } from '../../../lib/util/calcWildyPkChance'; -import getOSItem from '../../../lib/util/getOSItem'; -import { handleMahojiConfirmation } from '../../../lib/util/handleMahojiConfirmation'; -import { updateBankSetting } from '../../../lib/util/updateBankSetting'; - -const specialWeapons = { - melee: getOSItem("Viggora's chainmace"), - range: getOSItem("Craw's bow"), - mage: getOSItem("Thammaron's sceptre") -} as const; - -export async function revsCommand( - user: MUser, - channelID: string, - interaction: ChatInputCommandInteraction | null, - name: string -): CommandResponse { - const style = convertAttackStylesToSetup(user.user.attack_style); - const userGear = user.gear.wildy; - - const boosts = []; - const monster = revenantMonsters.find( - m => - stringMatches(m.name, name) || - m.aliases.some(a => stringMatches(a, name)) || - m.name.split(' ').some(a => stringMatches(a, name)) - ); - if (!monster || !name) { - return `That's not a valid Revenant. The valid Revenants are: ${revenantMonsters.map(m => m.name).join(', ')}.`; - } - - const key = ({ melee: 'attack_crush', mage: 'attack_magic', range: 'attack_ranged' } as const)[style]; - const gearStat = userGear.getStats()[key]; - const gearPercent = Math.max(0, calcWhatPercent(gearStat, maxOffenceStats[key])); - - const weapon = userGear.equippedWeapon(); - if (!weapon) { - return 'You have no weapon equipped in your Wildy outfit.'; - } - - if (weapon.equipment![key] < 10) { - return `Your weapon is terrible, you can't kill Revenants. You should have ${style} gear equipped in your wildy outfit, as this is what you're currently training. You can change this using \`/minion train\``; - } - - let timePerMonster = monster.timeToFinish; - timePerMonster = reduceNumByPercent(timePerMonster, gearPercent / 4); - boosts.push(`${(gearPercent / 4).toFixed(2)}% (out of a possible 25%) for ${key}`); - - const specialWeapon = specialWeapons[style]; - if (userGear.hasEquipped(specialWeapon.name)) { - timePerMonster = reduceNumByPercent(timePerMonster, 35); - boosts.push(`${35}% for ${specialWeapon.name}`); - } - - const quantity = Math.floor(calcMaxTripLength(user, 'Revenants') / timePerMonster); - let duration = quantity * timePerMonster; - - const cost = new Bank(); - - let hasPrayerPots = true; - if (user.bank.amount('Prayer potion(4)') < 5) { - hasPrayerPots = false; - if (interaction) { - await handleMahojiConfirmation( - interaction, - 'Are you sure you want to kill revenants without prayer potions? You should bring at least 5 Prayer potion(4).' - ); - } - } else { - cost.add('Prayer potion(4)', 5); - } - - updateBankSetting('economyStats_PVMCost', cost); - await transactItems({ userID: user.id, itemsToRemove: cost }); - if (cost.length > 0) { - await trackLoot({ - id: monster.name, - totalCost: cost, - type: 'Monster', - changeType: 'cost', - users: [ - { - id: user.id, - cost - } - ] - }); - } - - let deathChance = 5; - let defLvl = user.skillLevel(SkillsEnum.Defence); - let deathChanceFromDefenceLevel = (100 - (defLvl === 99 ? 100 : defLvl)) / 4; - deathChance += deathChanceFromDefenceLevel; - - const defensiveGearPercent = Math.max( - 0, - calcWhatPercent(userGear.getStats().defence_magic, maxDefenceStats['defence_magic']) - ); - let deathChanceFromGear = Math.max(20, 100 - defensiveGearPercent) / 4; - deathChance += deathChanceFromGear; - - const evasionDeathReduction = await getWildEvasionPercent(user); - deathChance = reduceNumByPercent(deathChance, evasionDeathReduction); - - const died = percentChance(deathChance); - - await increaseWildEvasionXp(user, duration); - - await addSubTaskToActivityTask({ - monsterID: monster.id, - userID: user.id, - channelID: channelID.toString(), - quantity, - fakeDuration: duration, - duration: died ? randInt(Math.min(Time.Minute * 3, duration), duration) : duration, - type: 'Revenants', - died, - skulled: true, - style, - usingPrayerPots: hasPrayerPots - }); - - let response = `${user.minionName} is now killing ${quantity}x ${monster.name}, it'll take around ${formatDuration( - duration - )} to finish. -${Emoji.OSRSSkull} Skulled -**Death Chance:** ${deathChance.toFixed(2)}% (${deathChanceFromGear.toFixed(2)}% from magic def${ - deathChanceFromDefenceLevel > 0 ? `, ${deathChanceFromDefenceLevel.toFixed(2)}% from defence level` : '' - } + 5% as default chance).${cost.length > 0 ? `\nRemoved from bank: ${cost}` : ''}${ - boosts.length > 0 ? `\nBoosts: ${boosts.join(', ')}` : '' - }`; - - return response; -} diff --git a/src/tasks/minions/monsterActivity.ts b/src/tasks/minions/monsterActivity.ts index 6ffe396072..60cb015f1a 100644 --- a/src/tasks/minions/monsterActivity.ts +++ b/src/tasks/minions/monsterActivity.ts @@ -6,6 +6,7 @@ import { Emoji } from '../../lib/constants'; import { KourendKebosDiary, userhasDiaryTier } from '../../lib/diaries'; import { trackLoot } from '../../lib/lootTrack'; import killableMonsters from '../../lib/minions/data/killableMonsters'; +import { revenantMonsters } from '../../lib/minions/data/killableMonsters/revs'; import { addMonsterXP } from '../../lib/minions/functions'; import announceLoot from '../../lib/minions/functions/announceLoot'; import { prisma } from '../../lib/settings/prisma'; @@ -36,7 +37,18 @@ export const monsterTask: MinionTask = { pkEncounters, hasWildySupplies } = data; - const monster = killableMonsters.find(mon => mon.id === monsterID)!; + + let monster = killableMonsters.find(mon => mon.id === monsterID)!; + let revenants = false; + + const matchedRevenantMonster = revenantMonsters.find(mon => mon.id === monsterID)!; + if (matchedRevenantMonster) { + monster = matchedRevenantMonster; + revenants = true; + } + + let skulled = false; + if (revenants) skulled = true; const messages: string[] = []; @@ -101,7 +113,7 @@ export const monsterTask: MinionTask = { smited: hasPrayerLevel && !protectItem, protectItem: hasPrayerLevel, after20wilderness: monster.pkBaseDeathChance && monster.pkBaseDeathChance >= 5 ? true : false, - skulled: false + skulled }); let reEquipedItems = false; diff --git a/src/tasks/minions/revenantsActivity.ts b/src/tasks/minions/revenantsActivity.ts deleted file mode 100644 index 0b7bb0f0dc..0000000000 --- a/src/tasks/minions/revenantsActivity.ts +++ /dev/null @@ -1,138 +0,0 @@ -import type { Prisma } from '@prisma/client'; -import { deepClone, roll } from 'e'; -import { Bank } from 'oldschooljs'; - -import { generateGearImage } from '../../lib/gear/functions/generateGearImage'; -import { trackLoot } from '../../lib/lootTrack'; -import { revenantMonsters } from '../../lib/minions/data/killableMonsters/revs'; -import announceLoot from '../../lib/minions/functions/announceLoot'; -import { SkillsEnum } from '../../lib/skilling/types'; -import { Gear } from '../../lib/structures/Gear'; -import type { RevenantOptions } from '../../lib/types/minions'; -import { hasSkillReqs } from '../../lib/util'; -import calculateGearLostOnDeathWilderness from '../../lib/util/calculateGearLostOnDeathWilderness'; -import { handleTripFinish } from '../../lib/util/handleTripFinish'; -import { makeBankImage } from '../../lib/util/makeBankImage'; -import { updateBankSetting } from '../../lib/util/updateBankSetting'; - -export const revenantsTask: MinionTask = { - type: 'Revenants', - async run(data: RevenantOptions) { - const { monsterID, userID, channelID, quantity, died, skulled, duration } = data; - const monster = revenantMonsters.find(mon => mon.id === monsterID)!; - const user = await mUserFetch(userID); - if (died) { - // 1 in 20 to get smited without prayer potions and 1 in 300 if the user has prayer potions - const hasPrayerLevel = hasSkillReqs(user, { [SkillsEnum.Prayer]: 25 })[0]; - const protectItem = roll(data.usingPrayerPots ? 300 : 20) ? false : hasPrayerLevel; - const userGear = { ...deepClone(user.gear.wildy.raw()) }; - - const calc = calculateGearLostOnDeathWilderness({ - gear: userGear, - smited: hasPrayerLevel && !protectItem, - protectItem: hasPrayerLevel, - after20wilderness: true, - skulled - }); - - const image = await generateGearImage(user, new Gear(calc.newGear), 'wildy', null); - await user.update({ - gear_wildy: calc.newGear as Prisma.InputJsonObject - }); - - updateBankSetting('revs_cost', calc.lostItems); - // Track items lost - await trackLoot({ - totalCost: calc.lostItems, - id: monster.name, - type: 'Monster', - changeType: 'cost', - users: [ - { - id: user.id, - cost: calc.lostItems - } - ] - }); - // Track loot (For duration) - await trackLoot({ - totalLoot: new Bank(), - id: monster.name, - type: 'Monster', - changeType: 'loot', - duration, - kc: quantity, - users: [ - { - id: user.id, - loot: new Bank(), - duration - } - ] - }); - - handleTripFinish( - user, - channelID, - `${user} ${ - hasPrayerLevel && !protectItem - ? `Oh no! While running for your life, you panicked, got smited ${ - skulled ? 'and lost everything!' : "and couldn't protect a 4th item." - }` - : '' - } You died, you lost all your loot, and these equipped items: ${ - calc.lostItems - }.\nHere is what you saved:`, - image, - data, - null - ); - return; - } - - const { newKC } = await user.incrementKC(monsterID, quantity); - - const loot = monster.table.kill(quantity, { skulled }); - let str = - `${user}, ${user.minionName} finished killing ${quantity} ${monster.name}.` + - ` Your ${monster.name} KC is now ${newKC}.\n`; - - announceLoot({ - user, - monsterID: monster.id, - loot, - notifyDrops: monster.notifyDrops - }); - - const { previousCL, itemsAdded } = await transactItems({ - userID: user.id, - itemsToAdd: loot, - collectionLog: true - }); - - await trackLoot({ - totalLoot: itemsAdded, - id: monster.name, - type: 'Monster', - changeType: 'loot', - duration, - kc: quantity, - users: [ - { - id: user.id, - loot: itemsAdded, - duration - } - ] - }); - - const image = await makeBankImage({ - bank: itemsAdded, - title: `Loot From ${quantity} ${monster.name} (${skulled ? 'skulled' : 'unskulled'}):`, - user, - previousCL - }); - - handleTripFinish(user, channelID, str, image.file.attachment, data, itemsAdded); - } -};