Skip to content

Commit

Permalink
Merge branch 'master' into xp_gains-monthly
Browse files Browse the repository at this point in the history
  • Loading branch information
TastyPumPum authored Oct 14, 2023
2 parents d0af85c + 4319464 commit f14f5b5
Show file tree
Hide file tree
Showing 24 changed files with 356 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/lib/MUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ GROUP BY data->>'clueID';`);
const { bank } = this;
const items = resolveItems(_items);
for (const baseID of items) {
const similarItems = [...getSimilarItems(baseID), baseID];
const similarItems = getSimilarItems(baseID);
const hasOneEquipped = similarItems.some(id => this.hasEquipped(id, true));
const hasOneInBank = similarItems.some(id => bank.has(id));
// If only one needs to be equipped, return true now if it is equipped.
Expand Down
4 changes: 3 additions & 1 deletion src/lib/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { fishingTask } from '../tasks/minions/fishingActivity';
import { fletchingTask } from '../tasks/minions/fletchingActivity';
import { gloryChargingTask } from '../tasks/minions/gloryChargingActivity';
import { groupoMonsterTask } from '../tasks/minions/groupMonsterActivity';
import { halloweenTask } from '../tasks/minions/halloweenActivity';
import { herbloreTask } from '../tasks/minions/herbloreActivity';
import { aerialFishingTask } from '../tasks/minions/HunterActivity/aerialFishingActivity';
import { birdHouseTask } from '../tasks/minions/HunterActivity/birdhouseActivity';
Expand Down Expand Up @@ -177,7 +178,8 @@ export const tasks: MinionTask[] = [
toaTask,
underwaterAgilityThievingTask,
strongholdTask,
specificQuestTask
specificQuestTask,
halloweenTask
];

export async function syncActivityCache() {
Expand Down
40 changes: 40 additions & 0 deletions src/lib/combat_achievements/caUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
import { CAViewType } from '../../mahoji/commands/ca';
import type { ActivityTaskData, MonsterActivityTaskOptions } from '../types/minions';
import { CombatAchievement } from './combatAchievements';

export function isCertainMonsterTrip(monsterID: number) {
return (data: ActivityTaskData) =>
data.type === 'MonsterKilling' && (data as MonsterActivityTaskOptions).monsterID === monsterID;
}

interface CombatAchievementGroup {
name: string;
tasks: CombatAchievement[];
}

export const buildCombatAchievementsResult = (
completedTaskIDs: Set<number>,
combatAchievements: CombatAchievementGroup,
type: CAViewType,
maxContentLength: number
) => {
const { name, tasks } = combatAchievements;
let result = `Combat Achievement tasks for ${name}:\n\n`;

const completedTasks = tasks.filter(task => completedTaskIDs.has(task.id));
const allTasksCompleted = completedTasks.length === tasks.length;

if (type === 'complete' && completedTasks.length === 0) {
return `No tasks completed for ${name}.`;
}

if (type === 'incomplete' && allTasksCompleted) {
return `All tasks completed for ${name}.`;
}

for (const task of tasks) {
if (type === 'complete' && !completedTaskIDs.has(task.id)) continue;
if (type === 'incomplete' && completedTaskIDs.has(task.id)) continue;
const completionStatus = completedTaskIDs.has(task.id) ? 'Completed' : 'Incomplete';
result += `Name: ${task.name}\nDescription: ${task.desc}\nStatus: ${completionStatus}\n\n`;
}

return {
content: result.length <= maxContentLength ? result : 'Result too large. Check the attached file for details.',
files: result.length > maxContentLength ? [{ attachment: Buffer.from(result), name: 'caBoss.txt' }] : undefined
};
};
19 changes: 19 additions & 0 deletions src/lib/combat_achievements/combatAchievements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ import { hardCombatAchievements } from './hard';
import { masterCombatAchievements } from './master';
import { mediumCombatAchievements } from './medium';

const collectMonsterNames = (...achievements: CombatAchievement[][]) => {
const allMonsterNamesSet = new Set<string>();
for (const achievementGroup of achievements) {
for (const achievement of achievementGroup) {
allMonsterNamesSet.add(achievement.monster);
}
}
return Array.from(allMonsterNamesSet);
};

export const allCAMonsterNames = collectMonsterNames(
easyCombatAchievements,
mediumCombatAchievements,
hardCombatAchievements,
eliteCombatAchievements,
masterCombatAchievements,
grandmasterCombatAchievements
);

type CAType = 'kill_count' | 'mechanical' | 'perfection' | 'restriction' | 'speed' | 'stamina';

export type CombatAchievement = {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/combat_achievements/grandmaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ export const grandmasterCombatAchievements: CombatAchievement[] = [
monster: 'Theatre of Blood',
rng: {
chancePerKill: 50,
hasChance: data => data.type === 'TheatreOfBlood' && (data as TheatreOfBloodTaskOptions).hardMode
hasChance: 'TheatreOfBlood'
}
},
{
Expand Down
48 changes: 48 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,3 +578,51 @@ META_CONSTANTS.RENDERED_STR = `**Date/Time:** ${dateFm(META_CONSTANTS.STARTUP_DA
**Git Hash:** ${META_CONSTANTS.GIT_HASH.slice(0, 7)}
**Commit:** <${META_CONSTANTS.GITHUB_URL}>
**Code Difference:** <${META_CONSTANTS.GIT_DIFF_URL}>`;

export const hweenGiveableItems = resolveItems([
'Gravedigger mask',
'Gravedigger top',
'Gravedigger leggings',
'Gravedigger gloves',
'Gravedigger boots',
'Jack lantern mask',
'Scythe',
'Grim reaper hood',
'Jonas mask',
'Skeleton mask',
'Skeleton shirt',
'Skeleton leggings',
'Skeleton gloves',
'Skeleton boots',
'Anti-panties',
'Banshee mask',
'Banshee top',
'Banshee robe',
'Hunting knife',
'Eek',
'Clown mask',
'Clown bow tie',
'Clown gown',
'Clown trousers',
'Clown shoes',
'Pumpkin lantern',
'Skeleton lantern',
'Spooky hood',
'Spooky robe',
'Spooky skirt',
'Spooky gloves',
'Spooky boots',
'Headless head',
'Magical pumpkin',
'Haunted wine bottle',
'Ugly halloween jumper (black)',
'Ugly halloween jumper (orange)',
'Saucepan',
"Black h'ween mask",
'Witch hat',
'Witch top',
'Witch robes',
'Witch boots',
'Witch cape',
'Halloween wig'
]);
2 changes: 1 addition & 1 deletion src/lib/data/similarItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,5 +369,5 @@ for (const [baseItem, similarItems] of source) {

export function getSimilarItems(itemID: number): number[] {
const similars = similarItems.get(itemID);
return similars ? [itemID, ...similars] : [];
return similars ? [itemID, ...similars] : [itemID];
}
2 changes: 2 additions & 0 deletions src/lib/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ const mentionCommands: MentionCommand[] = [
if (items.length === 0) return msg.reply('No results for that item.');

const gettedItem = items[0];
const { sacrificed_bank: sacrificedBank } = await user.fetchStats({ sacrificed_bank: true });

let str = `Found ${items.length} items:\n${items
.slice(0, 5)
Expand All @@ -197,6 +198,7 @@ const mentionCommands: MentionCommand[] = [
if (user.cl.has(item.id)) icons.push(Emoji.CollectionLog);
if (user.bank.has(item.id)) icons.push(Emoji.Bank);
if (((sacrificedBank as ItemBank)[item.id] ?? 0) > 0) icons.push(Emoji.Incinerator);
const price = toKMB(Math.floor(item.price));
Expand Down
6 changes: 4 additions & 2 deletions src/lib/rolesTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,10 @@ SELECT id, (cardinality(u.cl_keys) - u.inverse_length) as qty
let topSacrificers: string[] = [];
const mostValue = await q<any[]>('SELECT id FROM users ORDER BY "sacrificedValue" DESC LIMIT 3;');
for (let i = 0; i < 3; i++) {
topSacrificers.push(mostValue[i].id);
addToUserMap(userMap, mostValue[i].id, `Rank ${i + 1} Sacrifice Value`);
if (mostValue[i] !== undefined) {
topSacrificers.push(mostValue[i].id);
addToUserMap(userMap, mostValue[i].id, `Rank ${i + 1} Sacrifice Value`);
}
}
const mostValueIronman = await q<any[]>(
'SELECT id FROM users WHERE "minion.ironman" = true ORDER BY "sacrificedValue" DESC LIMIT 1;'
Expand Down
10 changes: 3 additions & 7 deletions src/lib/structures/Gear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,10 +438,7 @@ export class Gear {
if (inverse) {
values.push(...inverse.values());
}
const similarItems = getSimilarItems(item);
if (similarItems) {
values.push(...similarItems);
}
values.push(...getSimilarItems(item));
}
}

Expand Down Expand Up @@ -471,16 +468,15 @@ export class Gear {
let currentCount = 0;
for (const i of [...items]) {
const similarItems = getSimilarItems(i);
if (similarItems.length > 0) {
if (similarItems.some(si => allItems.includes(si))) currentCount++;
if (similarItems.some(si => allItems.includes(si))) {
currentCount++;
} else if (allItems.includes(i)) currentCount++;
}
return currentCount === targetCount;
}
// similar = true, every = false
for (const i of [...items]) {
const similarItems = getSimilarItems(i);
similarItems.push(i);
if (similarItems.some(si => allItems.includes(si))) return true;
}
return false;
Expand Down
8 changes: 7 additions & 1 deletion src/lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { ADMIN_IDS, OWNER_IDS, SupportServer } from '../config';
import { ClueTiers } from './clues/clueTiers';
import { badgesCache, BitField, projectiles, usernameCache } from './constants';
import { UserStatsDataNeededForCL } from './data/Collections';
import { getSimilarItems } from './data/similarItems';
import { DefenceGearStat, GearSetupType, GearSetupTypes, GearStat, OffenceGearStat } from './gear/types';
import type { Consumable } from './minions/types';
import { MUserClass } from './MUser';
Expand Down Expand Up @@ -515,7 +516,12 @@ export function checkRangeGearWeapon(gear: Gear) {
const { ammo } = gear;
if (!ammo) return 'You have no ammo equipped.';

const projectileCategory = objectEntries(projectiles).find(i => i[1].weapons.includes(weapon.id));
const projectileCategory = objectEntries(projectiles).find(i =>
i[1].weapons
.map(w => getSimilarItems(w))
.flat()
.includes(weapon.id)
);
if (!projectileCategory) return 'You have an invalid range weapon.';
if (!projectileCategory[1].items.includes(ammo.item)) {
return `You have invalid ammo for your equipped weapon. For ${
Expand Down
4 changes: 2 additions & 2 deletions src/lib/util/handleTripFinish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ export async function handleTripFinish(
components.push(..._components);
}

handleTriggerShootingStar(user, data, components);

if (components.length > 0) {
message.components = makeComponents(components);
}

handleTriggerShootingStar(user, data, components);

sendToChannelID(channelID, message);
}
4 changes: 3 additions & 1 deletion src/lib/util/minionStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,8 +670,10 @@ export function minionStatus(user: MUser) {
quests.find(i => i.id === data.questID)!.name
}! The trip should take ${formatDuration(durationRemaining)}.`;
}
case 'HalloweenEvent': {
return `${name} is doing the Halloween event! The trip should take ${formatDuration(durationRemaining)}.`;
}
case 'Easter':
case 'HalloweenEvent':
case 'BlastFurnace': {
throw new Error('Removed');
}
Expand Down
45 changes: 42 additions & 3 deletions src/mahoji/commands/ca.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { calcWhatPercent, objectEntries } from 'e';
import { ApplicationCommandOptionType, CommandRunOptions } from 'mahoji';
import { Bank } from 'oldschooljs';

import { buildCombatAchievementsResult } from '../../lib/combat_achievements/caUtils';
import {
allCAMonsterNames,
allCombatAchievementTasks,
caToPlayerString,
CombatAchievement,
Expand All @@ -14,7 +16,10 @@ import { deferInteraction } from '../../lib/util/interactionReply';
import { OSBMahojiCommand } from '../lib/util';

const viewTypes = ['all', 'incomplete', 'complete'] as const;
type ViewType = (typeof viewTypes)[number];

export type CAViewType = (typeof viewTypes)[number];

type MonsterNames = (typeof allCAMonsterNames)[number];

export const caCommand: OSBMahojiCommand = {
name: 'ca',
Expand All @@ -25,12 +30,23 @@ export const caCommand: OSBMahojiCommand = {
name: 'view',
description: 'View your Combat Achievements progress.',
options: [
{
type: ApplicationCommandOptionType.String,
name: 'name',
description: 'What boss do you want to view?',
autocomplete: async (value: string) => {
return allCAMonsterNames
.filter(i => (!value ? true : i.toLowerCase().includes(value.toLowerCase())))
.map(i => ({ name: i, value: i }));
},
required: false
},
{
type: ApplicationCommandOptionType.String,
name: 'type',
description: 'What do you want to view?',
choices: viewTypes.map(i => ({ name: i, value: i })),
required: true
required: false
}
]
},
Expand All @@ -48,7 +64,8 @@ export const caCommand: OSBMahojiCommand = {
}: CommandRunOptions<{
claim?: {};
view?: {
type: ViewType;
name?: MonsterNames;
type?: CAViewType;
};
}>) => {
await deferInteraction(interaction);
Expand Down Expand Up @@ -118,6 +135,27 @@ export const caCommand: OSBMahojiCommand = {
}

if (options.view) {
let selectedMonster = options.view.name;
let tasksView: CAViewType = options.view.type !== undefined ? options.view.type : 'all';

if (selectedMonster) {
const tasksForSelectedMonster = allCombatAchievementTasks.filter(
task => task.monster === selectedMonster
);

if (tasksForSelectedMonster.length === 0)
return 'No Combat Achievement tasks found for the specified monster.';

const maxContentLength = 750;
const result = buildCombatAchievementsResult(
completedTaskIDs,
{ name: `${selectedMonster}`, tasks: tasksForSelectedMonster },
tasksView,
maxContentLength
);
return result;
}

let result = '';

for (const group of Object.values(CombatAchievements)) {
Expand All @@ -141,6 +179,7 @@ export const caCommand: OSBMahojiCommand = {
files: [{ attachment: Buffer.from(result), name: 'ca.txt' }]
};
}

return 'Invalid command.';
}
};
5 changes: 4 additions & 1 deletion src/mahoji/commands/gear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ export const gearCommand: OSBMahojiCommand = {
name: 'setup',
description: 'The setup you want to view.',
required: true,
choices: ['All', ...GearSetupTypes].map(i => ({ name: toTitleCase(i), value: i }))
choices: ['All', ...GearSetupTypes, 'Lost on wildy death'].map(i => ({
name: toTitleCase(i),
value: i
}))
},
{
type: ApplicationCommandOptionType.Boolean,
Expand Down
Loading

0 comments on commit f14f5b5

Please sign in to comment.