Skip to content

Commit 5ac6aac

Browse files
authored
Easter 2025 (#6360)
1 parent d60cfab commit 5ac6aac

File tree

7 files changed

+345
-3
lines changed

7 files changed

+345
-3
lines changed

src/lib/MUser.ts

+5
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,11 @@ Charge your items using ${mentionCommand(globalClient, 'minion', 'charge')}.`
715715
return this.user.minion_equippedPet === itemID(name);
716716
}
717717

718+
get equippedPet(): Item | null {
719+
if (this.user.minion_equippedPet === null) return null;
720+
return getOSItem(this.user.minion_equippedPet);
721+
}
722+
718723
materialsOwned() {
719724
return new MaterialBank(this.user.materials_owned as IMaterialBank);
720725
}

src/lib/customItems/customItems.ts

+198
Original file line numberDiff line numberDiff line change
@@ -14077,3 +14077,201 @@ setCustomItem(
1407714077
},
1407814078
200_000_000
1407914079
);
14080+
14081+
setCustomItem(73_377, 'Easter Bunny hat', 'Bronze full helm', {
14082+
customItemData: {
14083+
cantDropFromMysteryBoxes: true
14084+
}
14085+
});
14086+
14087+
setCustomItem(73_378, 'Easter Bunny top', 'Bronze platebody', {
14088+
customItemData: {
14089+
cantDropFromMysteryBoxes: true
14090+
}
14091+
});
14092+
14093+
setCustomItem(73_379, 'Easter Bunny legs', 'Bronze platelegs', {
14094+
customItemData: {
14095+
cantDropFromMysteryBoxes: true
14096+
}
14097+
});
14098+
14099+
setCustomItem(73_380, 'Easter Bunny gloves', 'Bronze gloves', {
14100+
customItemData: {
14101+
cantDropFromMysteryBoxes: true
14102+
}
14103+
});
14104+
14105+
setCustomItem(73_381, 'Easter Bunny boots', 'Bronze boots', {
14106+
customItemData: {
14107+
cantDropFromMysteryBoxes: true
14108+
}
14109+
});
14110+
14111+
setCustomItem(73_382, 'Easter Bunny tail', 'Red cape', {
14112+
customItemData: {
14113+
cantDropFromMysteryBoxes: true
14114+
}
14115+
});
14116+
14117+
setCustomItem(73_383, 'Elven bunny ears', 'Bronze full helm', {
14118+
customItemData: {
14119+
cantDropFromMysteryBoxes: true
14120+
}
14121+
});
14122+
14123+
setCustomItem(73_384, 'Dragon bunny ears', 'Bronze full helm', {
14124+
customItemData: {
14125+
cantDropFromMysteryBoxes: true
14126+
}
14127+
});
14128+
14129+
setCustomItem(73_385, 'Tzhaar bunny ears', 'Bronze full helm', {
14130+
customItemData: {
14131+
cantDropFromMysteryBoxes: true
14132+
}
14133+
});
14134+
14135+
setCustomItem(73_387, 'Rune bunny ears', 'Bronze full helm', {
14136+
customItemData: {
14137+
cantDropFromMysteryBoxes: true
14138+
}
14139+
});
14140+
14141+
setCustomItem(73_388, 'Vyrewatch bunny ears', 'Bronze full helm', {
14142+
customItemData: {
14143+
cantDropFromMysteryBoxes: true
14144+
}
14145+
});
14146+
14147+
setCustomItem(73_389, 'Arceuus bunny ears', 'Bronze full helm', {
14148+
customItemData: {
14149+
cantDropFromMysteryBoxes: true
14150+
}
14151+
});
14152+
14153+
setCustomItem(73_390, 'Waddles', 'Herbi', {
14154+
customItemData: {
14155+
cantDropFromMysteryBoxes: true
14156+
}
14157+
});
14158+
14159+
setCustomItem(73_391, 'Easter egg (1)', 'Coal', {
14160+
customItemData: {
14161+
cantDropFromMysteryBoxes: true
14162+
}
14163+
});
14164+
14165+
setCustomItem(73_392, 'Easter egg (2)', 'Coal', {
14166+
customItemData: {
14167+
cantDropFromMysteryBoxes: true
14168+
}
14169+
});
14170+
14171+
setCustomItem(73_393, 'Easter egg (3)', 'Coal', {
14172+
customItemData: {
14173+
cantDropFromMysteryBoxes: true
14174+
}
14175+
});
14176+
14177+
setCustomItem(73_394, 'Easter egg (4)', 'Coal', {
14178+
customItemData: {
14179+
cantDropFromMysteryBoxes: true
14180+
}
14181+
});
14182+
14183+
setCustomItem(73_395, 'Easter egg (5)', 'Coal', {
14184+
customItemData: {
14185+
cantDropFromMysteryBoxes: true
14186+
}
14187+
});
14188+
14189+
setCustomItem(73_396, 'Easter egg (6)', 'Coal', {
14190+
customItemData: {
14191+
cantDropFromMysteryBoxes: true
14192+
}
14193+
});
14194+
14195+
setCustomItem(73_397, 'Easter egg (7)', 'Coal', {
14196+
customItemData: {
14197+
cantDropFromMysteryBoxes: true
14198+
}
14199+
});
14200+
14201+
setCustomItem(73_398, 'Easter egg (8)', 'Coal', {
14202+
customItemData: {
14203+
cantDropFromMysteryBoxes: true
14204+
}
14205+
});
14206+
14207+
setCustomItem(73_399, 'Easter egg (9)', 'Coal', {
14208+
customItemData: {
14209+
cantDropFromMysteryBoxes: true
14210+
}
14211+
});
14212+
14213+
setCustomItem(73_400, 'Easter egg (10)', 'Coal', {
14214+
customItemData: {
14215+
cantDropFromMysteryBoxes: true
14216+
}
14217+
});
14218+
14219+
setCustomItem(73_401, 'Easter egg (11)', 'Coal', {
14220+
customItemData: {
14221+
cantDropFromMysteryBoxes: true
14222+
}
14223+
});
14224+
14225+
setCustomItem(73_402, 'Easter egg (12)', 'Coal', {
14226+
customItemData: {
14227+
cantDropFromMysteryBoxes: true
14228+
}
14229+
});
14230+
14231+
setCustomItem(73_403, 'Easter egg (13)', 'Coal', {
14232+
customItemData: {
14233+
cantDropFromMysteryBoxes: true
14234+
}
14235+
});
14236+
14237+
setCustomItem(73_404, 'Easter egg (14)', 'Coal', {
14238+
customItemData: {
14239+
cantDropFromMysteryBoxes: true
14240+
}
14241+
});
14242+
14243+
setCustomItem(73_405, 'Easter cape (1)', 'Red cape', {
14244+
customItemData: {
14245+
cantDropFromMysteryBoxes: true
14246+
}
14247+
});
14248+
14249+
setCustomItem(73_406, 'Easter cape (2)', 'Red cape', {
14250+
customItemData: {
14251+
cantDropFromMysteryBoxes: true
14252+
}
14253+
});
14254+
14255+
setCustomItem(73_407, 'Tasty', 'Herbi', {
14256+
customItemData: {
14257+
cantDropFromMysteryBoxes: true
14258+
}
14259+
});
14260+
14261+
setCustomItem(73_408, 'Monkey egg (Edible)', 'Coal', {
14262+
customItemData: {
14263+
cantDropFromMysteryBoxes: true
14264+
}
14265+
});
14266+
14267+
setCustomItem(73_409, 'Tuah', 'Herbi', {
14268+
customItemData: {
14269+
cantDropFromMysteryBoxes: true
14270+
}
14271+
});
14272+
14273+
setCustomItem(73_410, 'Burnie', 'Herbi', {
14274+
customItemData: {
14275+
cantDropFromMysteryBoxes: true
14276+
}
14277+
});

src/lib/data/Collections.ts

+36
Original file line numberDiff line numberDiff line change
@@ -1622,6 +1622,42 @@ export const allCollectionLogs: ICollection = {
16221622
]),
16231623
counts: false
16241624
},
1625+
'Easter 2025': {
1626+
items: resolveItems([
1627+
'Easter egg (1)',
1628+
'Easter egg (2)',
1629+
'Easter egg (3)',
1630+
'Easter egg (4)',
1631+
'Easter egg (5)',
1632+
'Easter egg (6)',
1633+
'Easter egg (7)',
1634+
'Easter egg (8)',
1635+
'Easter egg (9)',
1636+
'Easter egg (10)',
1637+
'Easter egg (11)',
1638+
'Easter egg (12)',
1639+
'Easter egg (13)',
1640+
'Easter egg (14)',
1641+
'Easter cape (1)',
1642+
'Easter cape (2)',
1643+
'Monkey egg (Edible)',
1644+
'Easter Bunny hat',
1645+
'Easter Bunny top',
1646+
'Easter Bunny legs',
1647+
'Easter Bunny gloves',
1648+
'Easter Bunny boots',
1649+
'Easter Bunny tail',
1650+
'Elven bunny ears',
1651+
'Dragon bunny ears',
1652+
'Tzhaar bunny ears',
1653+
'Rune bunny ears',
1654+
'Vyrewatch bunny ears',
1655+
'Arceuus bunny ears',
1656+
'Waddles',
1657+
'Tasty'
1658+
]),
1659+
counts: false
1660+
},
16251661
'Thanksgiving 2021': {
16261662
items: resolveItems(['Raw turkey', 'Turkey', 'Turkey drumstick', 'Burnt turkey', 'Cornucopia']),
16271663
counts: false

src/lib/easter.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { resolveItems } from './util.js';
2+
3+
export const easterEventMainTable = resolveItems([
4+
'Easter egg (1)',
5+
'Easter egg (2)',
6+
'Easter egg (3)',
7+
'Easter egg (4)',
8+
'Easter egg (5)',
9+
'Easter egg (6)',
10+
'Easter egg (7)',
11+
'Easter egg (8)',
12+
'Easter egg (9)',
13+
'Easter egg (10)',
14+
'Easter egg (11)',
15+
'Easter egg (12)',
16+
'Easter egg (13)',
17+
'Easter egg (14)',
18+
'Easter cape (1)',
19+
'Easter cape (2)',
20+
'Monkey egg (Edible)',
21+
'Easter Bunny hat',
22+
'Easter Bunny top',
23+
'Easter Bunny legs',
24+
'Easter Bunny gloves',
25+
'Easter Bunny boots',
26+
'Easter Bunny tail',
27+
'Elven bunny ears',
28+
'Dragon bunny ears',
29+
'Tzhaar bunny ears',
30+
'Rune bunny ears',
31+
'Vyrewatch bunny ears',
32+
'Arceuus bunny ears',
33+
'Waddles'
34+
]);
35+
36+
export const ALL_EASTER_PETS = resolveItems(['Leia', 'Eggy', 'Waddles', 'Tasty']);
37+
38+
const hoursActive = 12 * 10;
39+
const totalMinutes = hoursActive * 60;
40+
export const easterEventItemChance = Math.ceil((totalMinutes / easterEventMainTable.length) * 0.65);
41+
export const tastyPetChance = easterEventItemChance * 30 * 2 * 1.5;

src/lib/util/handleTripFinish.ts

+60-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import {
66
type ButtonBuilder,
77
type MessageCollector,
88
type MessageCreateOptions,
9-
bold
9+
bold,
10+
codeBlock
1011
} from 'discord.js';
11-
import { Time, notEmpty, randArrItem, randInt } from 'e';
12+
import { Time, notEmpty, randArrItem, randInt, reduceNumByPercent, shuffleArr } from 'e';
1213
import { Bank } from 'oldschooljs';
1314

1415
import { alching } from '../../mahoji/commands/laps';
@@ -24,6 +25,7 @@ import { buildClueButtons } from '../clues/clueUtils';
2425
import { combatAchievementTripEffect } from '../combat_achievements/combatAchievements';
2526
import { BitField, COINS_ID, Emoji, PerkTier } from '../constants';
2627
import pets from '../data/pets.js';
28+
import { ALL_EASTER_PETS, easterEventItemChance, easterEventMainTable, tastyPetChance } from '../easter.js';
2729
import { handleGrowablePetGrowth } from '../growablePets';
2830
import { handlePassiveImplings } from '../implings';
2931
import { InventionID, inventionBoosts, inventionItemBoost } from '../invention/inventions';
@@ -49,7 +51,7 @@ import {
4951
import { handleCrateSpawns } from './handleCrateSpawns';
5052
import itemID from './itemID';
5153
import { logError } from './logError';
52-
import { perHourChance } from './smallUtils';
54+
import { itemNameFromID, perHourChance } from './smallUtils';
5355
import { updateBankSetting } from './updateBankSetting';
5456
import { sendToChannelID } from './webhook';
5557

@@ -527,6 +529,61 @@ export async function handleTripFinish(
527529
debugLog(`Finished ${effect.name} trip effect for ${user.id} in ${stopwatch}`);
528530
}
529531
}
532+
533+
const minutes = Math.floor(data.duration / Time.Minute);
534+
if (minutes >= 1) {
535+
const shuffledEasterItems = shuffleArr(easterEventMainTable);
536+
let effectiveTastyPetChance = tastyPetChance;
537+
let effectiveEasterItemChance = easterEventItemChance;
538+
539+
const pet = user.equippedPet;
540+
if (pet && ALL_EASTER_PETS.some(p => user.usingPet(p))) {
541+
effectiveTastyPetChance = Math.floor(reduceNumByPercent(effectiveTastyPetChance, 20));
542+
effectiveEasterItemChance = Math.floor(reduceNumByPercent(effectiveEasterItemChance, 20));
543+
messages.push(`Your ${pet.name} pet is making you 20% more likely to get Easter items`);
544+
}
545+
const effectiveCl = user.cl.clone();
546+
547+
if (user.bitfield.includes(BitField.ShowDetailedInfo) && message.content) {
548+
const tastyPerHourChance = 1 - Math.pow(1 - 1 / effectiveTastyPetChance, 60);
549+
const easterPerHourChance = 1 - Math.pow(1 - 1 / effectiveEasterItemChance, 60);
550+
const estimatedHoursForTasty = 1 / tastyPerHourChance;
551+
const estimatedHoursPerEasterItem = 1 / easterPerHourChance;
552+
const totalEasterItems = easterEventMainTable.length;
553+
const estimatedHoursForAllEasterItems = estimatedHoursPerEasterItem * totalEasterItems;
554+
555+
message.content += codeBlock(`
556+
Easter Event:
557+
- Tasty Chance: 1 in ${effectiveTastyPetChance} per minute
558+
- Easter Item Chance: 1 in ${effectiveEasterItemChance} per minute
559+
- ~${(tastyPerHourChance * 100).toFixed(2)}% chance for Tasty per hour
560+
- ~${(easterPerHourChance * 100).toFixed(2)}% chance for an Easter item per hour
561+
- Estimated ~${estimatedHoursForTasty.toFixed(1)} hours to get a Tasty
562+
- Estimated ~${estimatedHoursPerEasterItem.toFixed(1)} hours to get one Easter item
563+
- Estimated ~${estimatedHoursForAllEasterItems.toFixed(1)} hours to collect all ${totalEasterItems} Easter items
564+
`);
565+
}
566+
567+
for (let i = 0; i < minutes; i++) {
568+
if (roll(effectiveTastyPetChance)) {
569+
itemsToAddWithCL.add('Tasty');
570+
if (message.content) {
571+
message.content +=
572+
'\n:easterEgg:695473553314938920> **You received a very tasty looking chocolate bunny!**';
573+
}
574+
}
575+
if (!roll(effectiveEasterItemChance)) continue;
576+
const unownedItem = shuffledEasterItems.find(_item => !effectiveCl.has(_item)) ?? shuffledEasterItems[0];
577+
if (unownedItem) {
578+
effectiveCl.add(unownedItem);
579+
itemsToAddWithCL.add(unownedItem);
580+
if (message.content) {
581+
message.content += `\n<:easterEgg:695473553314938920> **You received a ${itemNameFromID(unownedItem)} from the Easter event!**`;
582+
}
583+
}
584+
}
585+
}
586+
530587
if (itemsToAddWithCL.length > 0 || itemsToRemove.length > 0) {
531588
await user.transactItems({ itemsToAdd: itemsToAddWithCL, collectionLog: true, itemsToRemove });
532589
}

0 commit comments

Comments
 (0)