Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update QP and Slayer Block Formula #5778

Merged
merged 12 commits into from
May 10, 2024
19 changes: 14 additions & 5 deletions src/lib/slayer/slayerUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Bank, Monsters, MonsterSlayerMaster } from 'oldschooljs';
import Monster from 'oldschooljs/dist/structures/Monster';

import { KourendKebosDiary, userhasDiaryTier } from '../../lib/diaries';
import { KourendKebosDiary, LumbridgeDraynorDiary, userhasDiaryTier } from '../../lib/diaries';
import { CombatAchievements } from '../combat_achievements/combatAchievements';
import { PvMMethod } from '../constants';
import { CombatOptionsEnum } from '../minions/data/combatConstants';
Expand All @@ -20,7 +20,7 @@
import { bossTasks } from './tasks/bossTasks';
import { AssignableSlayerTask, SlayerMaster } from './types';

export enum SlayerMasterEnum {

Check warning on line 23 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

'SlayerMasterEnum' is already declared in the upper scope on line 23 column 13

Check warning on line 23 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

'SlayerMasterEnum' is already declared in the upper scope on line 23 column 13
Reserved,
Turael,
Mazchna,
Expand All @@ -41,16 +41,16 @@
export function determineBoostChoice(params: DetermineBoostParams) {
let boostChoice = 'none';

if (params.method && params.method === 'none') {

Check warning on line 44 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required

Check warning on line 44 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required
return boostChoice;
}
if (params.method && params.method === 'chinning') {

Check warning on line 47 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required

Check warning on line 47 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required
boostChoice = 'chinning';
} else if (params.method && params.method === 'barrage') {

Check warning on line 49 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required

Check warning on line 49 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required
boostChoice = 'barrage';
} else if (params.method && params.method === 'burst') {

Check warning on line 51 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required

Check warning on line 51 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required
boostChoice = 'burst';
} else if (params.method && params.method === 'cannon') {

Check warning on line 53 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required

Check warning on line 53 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected value in conditional. A boolean expression is required
boostChoice = 'cannon';
} else if (params.cbOpts.includes(CombatOptionsEnum.AlwaysIceBarrage) && params.monster!.canBarrage) {
boostChoice = 'barrage';
Expand Down Expand Up @@ -220,12 +220,21 @@
return { currentTask, assignedTask };
}

export function calcMaxBlockedTasks(user: MUser) {
export async function calcMaxBlockedTasks(user: MUser) {
const qps = user.QP;
// 6 Blocks total 5 for 250 qps, + 1 for lumby.
// For now we're do 1 free + 1 for every 50 qps.
return Math.min(1 + Math.floor(qps / 50), 6);
let blocks = 0;
const [hasLumbyDiary] = await userhasDiaryTier(user, LumbridgeDraynorDiary.elite);
if (hasLumbyDiary) {
blocks += 1;
}
blocks += Math.floor(qps / 50);

// Limit blocks to 7 due to BSO quest points
blocks = Math.min(blocks, 7);

return blocks;
}

export function getCommonTaskName(task: Monster) {
let commonName = task.name;
switch (task.id) {
Expand Down Expand Up @@ -388,7 +397,7 @@
numHydraEyes += myLoot.amount("Hydra's heart");
const numDarkTotemBases = myLoot.amount('Dark totem base');
const numBludgeonPieces = myLoot.amount('Bludgeon claw');
if (!numBludgeonPieces && !numDarkTotemBases && !numHydraEyes) {

Check warning on line 400 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required

Check warning on line 400 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required

Check warning on line 400 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required

Check warning on line 400 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required

Check warning on line 400 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required

Check warning on line 400 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required
return { bankLoot: myLoot, clLoot: myLoot };
}

Expand All @@ -397,7 +406,7 @@
const myClLoot = new Bank(myLoot.bank);

const combinedBank = new Bank(myBank).add(myLoot);
if (numBludgeonPieces) {

Check warning on line 409 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v18.12.0 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required

Check warning on line 409 in src/lib/slayer/slayerUtil.ts

View workflow job for this annotation

GitHub Actions / Node v20 - ubuntu-latest

Unexpected number value in conditional. An explicit zero/NaN check is required
for (let x = 0; x < numBludgeonPieces; x++) {
const bank: number[] = [];

Expand Down
34 changes: 34 additions & 0 deletions src/mahoji/lib/abstracted_commands/lampCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,40 @@ export const XPLamps: IXPLamp[] = [
SkillsEnum.Prayer
]
},
{
itemID: 28_587,
amount: 30_000,
name: 'Magic lamp (strength)',
minimumLevel: 1,
allowedSkills: [SkillsEnum.Strength]
},
{
itemID: 28_588,
amount: 20_000,
name: 'Magic lamp (slayer)',
minimumLevel: 1,
allowedSkills: [SkillsEnum.Slayer]
},
{
itemID: 28_589,
amount: 5000,
name: 'Magic lamp (thieving)',
minimumLevel: 1,
allowedSkills: [SkillsEnum.Thieving]
},
{
itemID: 28_590,
amount: 500,
name: 'Magic lamp (magic)',
minimumLevel: 1,
allowedSkills: [SkillsEnum.Magic]
},
{
itemID: 28_820,
amount: 5000,
name: 'Antique lamp (defender of varrock)',
minimumLevel: 1
},
{
itemID: itemID('Antique lamp (easy ca)'),
amount: 5000,
Expand Down
198 changes: 190 additions & 8 deletions src/mahoji/lib/abstracted_commands/questCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Bank } from 'oldschooljs';

import { Skills } from '../../../lib/types';
import { ActivityTaskOptionsWithNoChanges, SpecificQuestOptions } from '../../../lib/types/minions';
import { formatDuration } from '../../../lib/util';
import { formatDuration, hasSkillReqs } from '../../../lib/util';
import addSubTaskToActivityTask from '../../../lib/util/addSubTaskToActivityTask';
import { minionIsBusy } from '../../../lib/util/minionIsBusy';
import { userHasGracefulEquipped } from '../../mahojiSettings';
Expand All @@ -14,15 +14,27 @@ interface Quest {
id: QuestID;
qp: number;
name: string;
skillReqs: Skills;
qpReq: number;
rewards: Bank;
combatLevelReq: number;
skillReqs?: Skills;
ironmanSkillReqs?: Skills;
qpReq?: number;
rewards?: Bank;
skillsRewards?: {
[skill: string]: number;
};
combatLevelReq?: number;
prerequisitesQuests?: QuestID[];
calcTime: (user: MUser) => number;
}

export enum QuestID {
DesertTreasureII = 1
DesertTreasureII = 1,
ThePathOfGlouphrie = 2,
ChildrenOfTheSun = 3,
DefenderOfVarrock = 4,
TheRibbitingTaleOfALillyPadLabourDispute = 5,
PerilousMoons = 6,
AtFirstLight = 7,
TwilightsPromise = 8
}

export const quests: Quest[] = [
Expand Down Expand Up @@ -61,6 +73,150 @@ export const quests: Quest[] = [
}
return duration;
}
},
{
id: QuestID.ThePathOfGlouphrie,
qp: 2,
name: 'The Path of Glouphrie',
skillReqs: {
strength: 60,
slayer: 56,
thieving: 56,
ranged: 47,
agility: 45
},
ironmanSkillReqs: {
fletching: 59,
smithing: 59
},
combatLevelReq: 50,
qpReq: 10,
rewards: new Bank().add(28_587).add(28_587).add(28_588).add(28_589).add(28_590).freeze(),
calcTime: (user: MUser) => {
let duration = Time.Minute * 10;
if (user.combatLevel < 90) {
duration += Time.Minute * 5;
}
return duration;
}
},
{
id: QuestID.ChildrenOfTheSun,
qp: 1,
name: 'Children of the Sun',
calcTime: () => {
const duration = Time.Minute * 3;
return duration;
}
},
{
id: QuestID.DefenderOfVarrock,
qp: 2,
name: 'Defender of Varrock',
skillReqs: {
smithing: 55,
hunter: 52
},
combatLevelReq: 65,
qpReq: 20,
// Awaiting item update for the lamp to be added
// rewards: new Bank().add(28_820).freeze(),
skillsRewards: {
smithing: 15_000,
hunter: 15_000
},
calcTime: (user: MUser) => {
let duration = Time.Minute * 12;
if (user.combatLevel < 100) {
duration += Time.Minute * 8;
}
return duration;
}
},
{
id: QuestID.TheRibbitingTaleOfALillyPadLabourDispute,
qp: 1,
name: 'The Ribbiting Tale of a Lily Pad Labour Dispute',
skillReqs: {
woodcutting: 15
},
prerequisitesQuests: [QuestID.ChildrenOfTheSun],
skillsRewards: {
woodcutting: 2000
},
calcTime: () => {
const duration = Time.Minute * 3;
return duration;
}
},
{
id: QuestID.PerilousMoons,
qp: 2,
name: 'Perilous Moons',
skillReqs: {
slayer: 48,
hunter: 20,
fishing: 20,
runecraft: 20,
construction: 10
},
combatLevelReq: 75,
prerequisitesQuests: [QuestID.ChildrenOfTheSun, QuestID.TwilightsPromise],
skillsRewards: {
slayer: 40_000,
runecraft: 5000,
hunter: 5000,
fishing: 5000
},
calcTime: (user: MUser) => {
let duration = Time.Minute * 20;
if (user.combatLevel < 120) {
duration += Time.Minute * 5;
}
if (user.combatLevel < 100) {
duration += Time.Minute * 10;
}
return duration;
}
},
{
id: QuestID.AtFirstLight,
qp: 1,
name: 'At First Light',
skillReqs: {
hunter: 46,
herblore: 30,
construction: 27
},
combatLevelReq: 75,
qpReq: 2,
prerequisitesQuests: [QuestID.ChildrenOfTheSun],
skillsRewards: {
hunter: 4500,
construction: 800,
herblore: 500
},
calcTime: () => {
let duration = Time.Minute * 6;
return duration;
}
},
{
id: QuestID.TwilightsPromise,
qp: 1,
name: "Twilight's Promise",
skillsRewards: {
thieving: 3000
},
combatLevelReq: 40,
prerequisitesQuests: [QuestID.ChildrenOfTheSun],
calcTime: (user: MUser) => {
let duration = Time.Minute * 9;
if (user.combatLevel < 75) {
duration += Time.Minute * 5;
}
return duration;
}
}
];

Expand All @@ -84,8 +240,34 @@ export async function questCommand(user: MUser, channelID: string, name?: string
return `You've already completed ${quest.name}.`;
}

if (user.QP < quest.qpReq) {
return `You need ${quest.qpReq} QP to do ${quest.name}.`;
if (quest.qpReq) {
if (user.QP < quest.qpReq) {
return `You need ${quest.qpReq} QP to do ${quest.name}.`;
}
}

// Check if the user has completed the required quests (if any)
if (quest.prerequisitesQuests) {
for (const prerequisite of quest.prerequisitesQuests) {
if (!user.user.finished_quest_ids.includes(prerequisite)) {
return `You need to complete "${quests.find(q => q.id === prerequisite)?.name}" before starting ${
quest.name
}.`;
}
}
}

if (quest.skillReqs) {
const [hasReqs, reason] = hasSkillReqs(user, quest.skillReqs);
if (!hasReqs) {
return `To complete ${quest.name}, you need: ${reason}.`;
}
}
if (user.isIronman && quest.ironmanSkillReqs) {
const [hasIronReqs, ironReason] = hasSkillReqs(user, quest.ironmanSkillReqs);
if (!hasIronReqs) {
return `To complete ${quest.name} as an ironman, you need: ${ironReason}.`;
}
}

const duration = quest.calcTime(user);
Expand Down
6 changes: 3 additions & 3 deletions src/mahoji/lib/abstracted_commands/slayerTaskCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ function getAlternateMonsterList(assignedTask: AssignableSlayerTask | null) {
return '';
}

export function slayerListBlocksCommand(mahojiUser: MUser) {
const maxBlocks = calcMaxBlockedTasks(mahojiUser);
export async function slayerListBlocksCommand(mahojiUser: MUser) {
const maxBlocks = await calcMaxBlockedTasks(mahojiUser);
const myBlockList = mahojiUser.user.slayer_blocked_ids;

let outstr =
Expand Down Expand Up @@ -399,7 +399,7 @@ export async function slayerSkipTaskCommand({
const user = await mUserFetch(userID);
const { currentTask } = await getUsersCurrentSlayerInfo(user.id);
const myBlockList = user.user.slayer_blocked_ids;
const maxBlocks = calcMaxBlockedTasks(user);
const maxBlocks = await calcMaxBlockedTasks(user);
if (minionIsBusy(user.id)) {
interactionReply(interaction, 'You cannot change your task while your minion is busy.');
return;
Expand Down
29 changes: 20 additions & 9 deletions src/tasks/minions/specificQuestActivity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { bold } from 'discord.js';

import { SkillsEnum } from '../../lib/skilling/types';
import type { SpecificQuestOptions } from '../../lib/types/minions';
import { handleTripFinish } from '../../lib/util/handleTripFinish';
import { quests } from '../../mahoji/lib/abstracted_commands/questCommand';
Expand All @@ -11,7 +12,24 @@ export const specificQuestTask: MinionTask = {
const user = await mUserFetch(userID);
const quest = quests.find(quest => quest.id === questID)!;

await user.addItemsToBank({ items: quest.rewards, collectionLog: true });
let completionMessage = `${user}, ${user.minionName} finished ${bold(quest.name)}.`;

if (quest.rewards) {
await user.addItemsToBank({ items: quest.rewards, collectionLog: true });
completionMessage += ` You received ${quest.rewards}.`;
}

if (quest.skillsRewards) {
for (const [skillName, amount] of Object.entries(quest.skillsRewards)) {
if (Object.values(SkillsEnum).includes(skillName as SkillsEnum)) {
await user.addXP({ skillName: skillName as SkillsEnum, amount });
}
}
completionMessage += ` You gained the following skills rewards: ${Object.entries(quest.skillsRewards)
.map(([skill, xp]) => `${xp} XP in ${skill}`)
.join(', ')}.`;
}

await user.update({
finished_quest_ids: {
push: quest.id
Expand All @@ -21,13 +39,6 @@ export const specificQuestTask: MinionTask = {
}
});

handleTripFinish(
user,
channelID,
`${user}, ${user.minionName} finished ${bold(quest.name)}. You received ${quest.rewards}.`,
undefined,
data,
null
);
handleTripFinish(user, channelID, completionMessage, undefined, data, null);
}
};
Loading
Loading