From d4a37d6eadfea480f6382c5f37fcf9a8c94c6d01 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 10:43:50 +0100 Subject: [PATCH 01/31] Updated TomeRepo to add new bonus --- data/domain/data/TomeRepo.ts | 230 ++++++++++++++++++----------------- 1 file changed, 119 insertions(+), 111 deletions(-) diff --git a/data/domain/data/TomeRepo.ts b/data/domain/data/TomeRepo.ts index 037995d1..2b5465b7 100644 --- a/data/domain/data/TomeRepo.ts +++ b/data/domain/data/TomeRepo.ts @@ -6,8 +6,16 @@ export class TomeBase { constructor(public index: number, public data: TomeModel export const initTomeRepo = () => { - return [ + return [ new TomeBase(0, { + "name": "Stamp Total LV", + "keyQty": 10000, + "scalingType": TomeScalingEnum.decay, + "totalVal": 1000, + "decimalDisplay": undefined, + "desc": undefined + }), + new TomeBase(1, { "name": "Statue Total LV", "keyQty": 2300, "scalingType": TomeScalingEnum.decay, @@ -15,7 +23,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(1, { + new TomeBase(2, { "name": "Cards Total LV", "keyQty": 1344, "scalingType": TomeScalingEnum.linearToMax, @@ -23,7 +31,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(2, { + new TomeBase(3, { "name": "Total Talent Max LV 膛 (Tap for more info)", "keyQty": 12000, "scalingType": TomeScalingEnum.decay, @@ -31,7 +39,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "For each talent, the tome counts the highest Max LV out of all your players." }), - new TomeBase(3, { + new TomeBase(4, { "name": "Unique Quests Completed 膛", "keyQty": 323, "scalingType": TomeScalingEnum.linearToMax, @@ -39,7 +47,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Doing the same quest on multiple players doesn't count for this." }), - new TomeBase(4, { + new TomeBase(5, { "name": "Account LV", "keyQty": 7000, "scalingType": TomeScalingEnum.decay, @@ -47,7 +55,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(5, { + new TomeBase(6, { "name": "Total Tasks Completed", "keyQty": 470, "scalingType": TomeScalingEnum.linearToMax, @@ -55,7 +63,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(6, { + new TomeBase(7, { "name": "Total Achievements Completed", "keyQty": 266, "scalingType": TomeScalingEnum.linearToMax, @@ -63,7 +71,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(7, { + new TomeBase(8, { "name": "Most Money held in Storage", "keyQty": 25, "scalingType": TomeScalingEnum.decayLog, @@ -71,7 +79,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(8, { + new TomeBase(9, { "name": "Most Spore Caps held in Inventory at once", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -79,7 +87,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(9, { + new TomeBase(10, { "name": "Trophies Found", "keyQty": 22, "scalingType": TomeScalingEnum.linearToMax, @@ -87,7 +95,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(10, { + new TomeBase(11, { "name": "Account Skills LV", "keyQty": 18000, "scalingType": TomeScalingEnum.decay, @@ -95,7 +103,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(11, { + new TomeBase(12, { "name": "Best Spiketrap Surprise round", "keyQty": 13, "scalingType": TomeScalingEnum.linearToMax, @@ -103,7 +111,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(12, { + new TomeBase(13, { "name": "Total AFK Hours claimed", "keyQty": 2000000, "scalingType": TomeScalingEnum.decay, @@ -111,7 +119,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(13, { + new TomeBase(14, { "name": "DPS Record on Shimmer Island", "keyQty": 20, "scalingType": TomeScalingEnum.decayLog, @@ -119,7 +127,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(14, { + new TomeBase(15, { "name": "Star Talent Points Owned", "keyQty": 2500, "scalingType": TomeScalingEnum.decay, @@ -127,7 +135,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(15, { + new TomeBase(16, { "name": "Average kills for a Crystal Spawn 膛", "keyQty": 30, "scalingType": TomeScalingEnum.inverseDecay, @@ -135,7 +143,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This tracks your Crystal Mob spawn chance! While this is capped at 1 in 100, you get BONUS Exp and Drops if your Crystal Spawn is better! For example, if your average kills is 20, you're getting 5x Exp and Drops from Crystals!" }), - new TomeBase(16, { + new TomeBase(17, { "name": "Dungeon Rank", "keyQty": 30, "scalingType": TomeScalingEnum.decay, @@ -143,7 +151,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(17, { + new TomeBase(18, { "name": "Highest Drop Rarity Multi", "keyQty": 40, "scalingType": TomeScalingEnum.decay, @@ -151,7 +159,7 @@ export const initTomeRepo = () => { "decimalDisplay": 1, "desc": undefined }), - new TomeBase(18, { + new TomeBase(19, { "name": "Constellations Completed", "keyQty": 49, "scalingType": TomeScalingEnum.linearToMax, @@ -159,7 +167,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(19, { + new TomeBase(20, { "name": "Most DMG Dealt to Gravestone in a Weekly Battle 膛", "keyQty": 300000, "scalingType": TomeScalingEnum.decay, @@ -167,7 +175,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Gravestone appears when you defeat all weekly bosses. This is the negative number shown after." }), - new TomeBase(20, { + new TomeBase(21, { "name": "Unique Obols Found", "keyQty": 107, "scalingType": TomeScalingEnum.linearToMax, @@ -175,7 +183,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(21, { + new TomeBase(22, { "name": "Total Bubble LV", "keyQty": 1000000, "scalingType": TomeScalingEnum.boundedDecay, @@ -183,7 +191,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(22, { + new TomeBase(23, { "name": "Total Vial LV", "keyQty": 962, "scalingType": TomeScalingEnum.linearToMax, @@ -191,7 +199,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(23, { + new TomeBase(24, { "name": "Total Sigil LV", "keyQty": 72, "scalingType": TomeScalingEnum.linearToMax, @@ -199,7 +207,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(24, { + new TomeBase(25, { "name": "Jackpots Hit in Arcade", "keyQty": 1, "scalingType": TomeScalingEnum.decay, @@ -207,7 +215,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(25, { + new TomeBase(26, { "name": "Post Office PO Boxes Earned", "keyQty": 20000, "scalingType": TomeScalingEnum.decay, @@ -215,7 +223,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(26, { + new TomeBase(27, { "name": "Highest Killroy Score on a Warrior", "keyQty": 3000, "scalingType": TomeScalingEnum.decay, @@ -223,7 +231,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(27, { + new TomeBase(28, { "name": "Highest Killroy Score on an Archer", "keyQty": 3000, "scalingType": TomeScalingEnum.decay, @@ -231,7 +239,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(28, { + new TomeBase(29, { "name": "Highest Killroy Score on a Mage", "keyQty": 3000, "scalingType": TomeScalingEnum.decay, @@ -239,7 +247,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(29, { + new TomeBase(30, { "name": "Fastest Time to kill Chaotic Efaunt (in Seconds)", "keyQty": 10, "scalingType": TomeScalingEnum.inverseDecay, @@ -247,7 +255,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(30, { + new TomeBase(31, { "name": "Largest Oak Log Printer Sample", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -255,7 +263,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(31, { + new TomeBase(32, { "name": "Largest Copper Ore Printer Sample", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -263,7 +271,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(32, { + new TomeBase(33, { "name": "Largest Spore Cap Printer Sample", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -271,7 +279,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(33, { + new TomeBase(34, { "name": "Largest Goldfish Printer Sample", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -279,7 +287,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(34, { + new TomeBase(35, { "name": "Largest Fly Printer Sample", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -287,7 +295,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(35, { + new TomeBase(36, { "name": "Best Non Duplicate Goblin Gorefest Wave 膛", "keyQty": 120, "scalingType": TomeScalingEnum.decay, @@ -295,7 +303,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Non Duplicate means you can only place 1 of each Wizard Type, 2 or more invalidates the attempt." }), - new TomeBase(36, { + new TomeBase(37, { "name": "Total Best Wave in Worship", "keyQty": 1000, "scalingType": TomeScalingEnum.decay, @@ -303,7 +311,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(37, { + new TomeBase(38, { "name": "Total Digits of all Deathnote Kills 膛", "keyQty": 700, "scalingType": TomeScalingEnum.decay, @@ -311,7 +319,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "For example, 1,520 kills would be 4 digits, and this is for all monster types." }), - new TomeBase(38, { + new TomeBase(39, { "name": "Equinox Clouds Completed", "keyQty": 31, "scalingType": TomeScalingEnum.linearToMax, @@ -319,7 +327,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(39, { + new TomeBase(40, { "name": "Total Refinery Rank", "keyQty": 120, "scalingType": TomeScalingEnum.decay, @@ -327,7 +335,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(40, { + new TomeBase(41, { "name": "Total Atom Upgrade LV", "keyQty": 150, "scalingType": TomeScalingEnum.decay, @@ -335,7 +343,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(41, { + new TomeBase(42, { "name": "Total Construct Buildings LV", "keyQty": 4000, "scalingType": TomeScalingEnum.decay, @@ -343,7 +351,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(42, { + new TomeBase(43, { "name": "Most Tottoise in Storage 膛", "keyQty": 5, "scalingType": TomeScalingEnum.decayLog, @@ -351,7 +359,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Tottoise is the 11th Shiny Critter unlocked from the Jade Emporium in World 6" }), - new TomeBase(43, { + new TomeBase(44, { "name": "Most Greenstacks in Storage 膛", "keyQty": 150, "scalingType": TomeScalingEnum.decay, @@ -359,7 +367,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Greenstack is when you have 10,000,000 or more of a single item in your Storage Chest." }), - new TomeBase(44, { + new TomeBase(45, { "name": "Rift Levels Completed", "keyQty": 49, "scalingType": TomeScalingEnum.linearToMax, @@ -367,7 +375,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(45, { + new TomeBase(46, { "name": "Highest Power Pet", "keyQty": 5, "scalingType": TomeScalingEnum.decayLog, @@ -375,7 +383,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(46, { + new TomeBase(47, { "name": "Fastest Time reaching Round 100 Arena (in Seconds)", "keyQty": 50, "scalingType": TomeScalingEnum.inverseDecay, @@ -383,7 +391,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(47, { + new TomeBase(48, { "name": "Total Kitchen Upgrade LV", "keyQty": 8000, "scalingType": TomeScalingEnum.decay, @@ -391,7 +399,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(48, { + new TomeBase(49, { "name": "Total Shiny Pet LV", "keyQty": 750, "scalingType": TomeScalingEnum.decay, @@ -399,7 +407,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(49, { + new TomeBase(50, { "name": "Total Cooking Meals LV", "keyQty": 5400, "scalingType": TomeScalingEnum.decay, @@ -407,7 +415,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(50, { + new TomeBase(51, { "name": "Total Pet Breedability LV", "keyQty": 500, "scalingType": TomeScalingEnum.linearToMax, @@ -415,7 +423,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(51, { + new TomeBase(52, { "name": "Total Lab Chips Owned", "keyQty": 100, "scalingType": TomeScalingEnum.decay, @@ -423,7 +431,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(52, { + new TomeBase(53, { "name": "Total Colosseum Score", "keyQty": 10, "scalingType": TomeScalingEnum.decayLog, @@ -431,7 +439,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(53, { + new TomeBase(54, { "name": "Most Giants Killed in a Single Week", "keyQty": 25, "scalingType": TomeScalingEnum.decay, @@ -439,7 +447,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(54, { + new TomeBase(55, { "name": "Total Onyx Statues", "keyQty": 28, "scalingType": TomeScalingEnum.linearToMax, @@ -447,7 +455,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(55, { + new TomeBase(56, { "name": "Fastest Time to Kill 200 Tremor Wurms (in Seconds)", "keyQty": 30, "scalingType": TomeScalingEnum.inverseDecay, @@ -455,7 +463,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(56, { + new TomeBase(57, { "name": "Total Boat Upgrade LV", "keyQty": 10000, "scalingType": TomeScalingEnum.decay, @@ -463,7 +471,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(57, { + new TomeBase(58, { "name": "God Rank in Divinity", "keyQty": 10, "scalingType": TomeScalingEnum.decay, @@ -471,7 +479,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(58, { + new TomeBase(59, { "name": "Total Gaming Plants Evolved", "keyQty": 100000, "scalingType": TomeScalingEnum.decay, @@ -479,7 +487,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(59, { + new TomeBase(60, { "name": "Total Artifacts Found 膛", "keyQty": 185, "scalingType": TomeScalingEnum.linearToMax, @@ -487,7 +495,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Rarer versions of an artifact count for more, so Ancient would count as 2 Artifacts." }), - new TomeBase(60, { + new TomeBase(61, { "name": "Gold Bar Sailing Treasure Owned", "keyQty": 14, "scalingType": TomeScalingEnum.decayLog, @@ -495,7 +503,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(61, { + new TomeBase(62, { "name": "Highest Captain LV", "keyQty": 25, "scalingType": TomeScalingEnum.decay, @@ -503,7 +511,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(62, { + new TomeBase(63, { "name": "Highest Immortal Snail LV", "keyQty": 50, "scalingType": TomeScalingEnum.linearToMax, @@ -511,7 +519,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(63, { + new TomeBase(64, { "name": "Best Gold Nugget", "keyQty": 9, "scalingType": TomeScalingEnum.decayLog, @@ -519,7 +527,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(64, { + new TomeBase(65, { "name": "Items Found", "keyQty": 1800, "scalingType": TomeScalingEnum.linearToMax, @@ -527,7 +535,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(65, { + new TomeBase(66, { "name": "Most Gaming Bits Owned", "keyQty": 80, "scalingType": TomeScalingEnum.decayLog, @@ -535,7 +543,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(66, { + new TomeBase(67, { "name": "Highest Crop OG", "keyQty": 6, "scalingType": TomeScalingEnum.decayLog, @@ -543,7 +551,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(67, { + new TomeBase(68, { "name": "Total Crops Discovered", "keyQty": 120, "scalingType": TomeScalingEnum.linearToMax, @@ -551,7 +559,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(68, { + new TomeBase(69, { "name": "Total Golden Food Beanstacks 膛", "keyQty": 30, "scalingType": TomeScalingEnum.linearToMax, @@ -559,7 +567,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Supersized Gold Food Beanstacks count as 2 Beanstacks!" }), - new TomeBase(69, { + new TomeBase(70, { "name": "Total Summoning Upgrades LV", "keyQty": 10000, "scalingType": TomeScalingEnum.decay, @@ -567,7 +575,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(70, { + new TomeBase(71, { "name": "Total Career Summoning Wins 膛", "keyQty": 160, "scalingType": TomeScalingEnum.decay, @@ -575,7 +583,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Rack up those wins! Endless Summoning wins count for this too, of course!" }), - new TomeBase(71, { + new TomeBase(72, { "name": "Ninja Floors Unlocked", "keyQty": 12, "scalingType": TomeScalingEnum.linearToMax, @@ -583,7 +591,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(72, { + new TomeBase(73, { "name": "Familiars Owned in Summoning 膛", "keyQty": 600, "scalingType": TomeScalingEnum.decay, @@ -591,7 +599,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Measured in terms of Grey Slime, so a Vrumbi would count as 3, Bloomy as 12, and so on." }), - new TomeBase(73, { + new TomeBase(74, { "name": "Jade Emporium Upgrades Purchased", "keyQty": 50, "scalingType": TomeScalingEnum.linearToMax, @@ -599,7 +607,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(74, { + new TomeBase(75, { "name": "Total Minigame Highscore 膛", "keyQty": 450, "scalingType": TomeScalingEnum.linearToMax, @@ -607,7 +615,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This is Choppin game, Mining Cart game, Fishing game, Catching Hoops game, and Trapping game" }), - new TomeBase(75, { + new TomeBase(76, { "name": "Total Prayer Upgrade LV", "keyQty": 673, "scalingType": TomeScalingEnum.linearToMax, @@ -615,7 +623,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(76, { + new TomeBase(77, { "name": "Total Land Rank 膛", "keyQty": 5000, "scalingType": TomeScalingEnum.decay, @@ -623,7 +631,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Land Ranks are from the Farming skill, in World 6. Unlocked from the Night Market!" }), - new TomeBase(77, { + new TomeBase(78, { "name": "Largest Magic Bean Trade", "keyQty": 1000, "scalingType": TomeScalingEnum.decay, @@ -631,7 +639,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(78, { + new TomeBase(79, { "name": "Most Balls earned from LBoFaF 膛", "keyQty": 1000, "scalingType": TomeScalingEnum.decay, @@ -639,7 +647,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "LBoFaF means Lava's Ballpit of Fire and Fury, the bonus round in Arcade" }), - new TomeBase(79, { + new TomeBase(80, { "name": "Total Arcade Gold Ball Shop Upgrade LV", "keyQty": 3800, "scalingType": TomeScalingEnum.linearToMax, @@ -647,7 +655,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(80, { + new TomeBase(81, { "name": "Vault Upgrade bonus LV", "keyQty": 500, "scalingType": TomeScalingEnum.linearToMax, @@ -655,7 +663,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(81, { + new TomeBase(82, { "name": "Total Gambit Time (in Seconds) 膛", "keyQty": 3600, "scalingType": TomeScalingEnum.decay, @@ -663,7 +671,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Gambit is the 14th Cavern in The Hole." }), - new TomeBase(82, { + new TomeBase(83, { "name": "Total Digits of all Cavern Resources 膛", "keyQty": 500, "scalingType": TomeScalingEnum.decay, @@ -671,7 +679,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "For example, if you had 1273 gravel and 422 gold dust, thats 7 Digits. If you then got 23 quaver notes from harp, thats another 2 digits, making your total 9 Digits." }), - new TomeBase(83, { + new TomeBase(84, { "name": "Total LV of Cavern Villagers", "keyQty": 200, "scalingType": TomeScalingEnum.decay, @@ -679,7 +687,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(84, { + new TomeBase(85, { "name": "Megafeathers Earned from Orion", "keyQty": 12, "scalingType": TomeScalingEnum.decay, @@ -687,7 +695,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(85, { + new TomeBase(86, { "name": "Megafish Earned from Poppy", "keyQty": 12, "scalingType": TomeScalingEnum.decay, @@ -695,7 +703,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(86, { + new TomeBase(87, { "name": "Best Bravery Monument Round 膛", "keyQty": 50, "scalingType": TomeScalingEnum.decay, @@ -703,7 +711,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Bravery Monument is the 4th Cavern in The Hole. The Hole is found in World 5." }), - new TomeBase(87, { + new TomeBase(88, { "name": "Best Justice Monument Round 膛", "keyQty": 200, "scalingType": TomeScalingEnum.decay, @@ -711,7 +719,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Justice Monument is the 10th Cavern in The Hole. 'Best Round' here means your highest Court Case reached in a run." }), - new TomeBase(88, { + new TomeBase(89, { "name": "Best Wisdom Monument Round 膛", "keyQty": 18, "scalingType": TomeScalingEnum.linearToMax, @@ -719,7 +727,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Wisdom Monument is the 13th Cavern in The Hole." }), - new TomeBase(89, { + new TomeBase(90, { "name": "Best Deathbringer Max Damage in Wraith Mode 膛", "keyQty": 10, "scalingType": TomeScalingEnum.decayLog, @@ -727,7 +735,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Deathbringer is the Blood Berserker's Master Class, given by Masterius NPC in World 6. You need to open your grimoire to register damage." }), - new TomeBase(90, { + new TomeBase(91, { "name": "Best Dawg Den score 膛", "keyQty": 7, "scalingType": TomeScalingEnum.decayLog, @@ -735,7 +743,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "The Dawg Den is the 3rd Cavern in The Hole. The Hole is found in World 5." }), - new TomeBase(91, { + new TomeBase(92, { "name": "Total Resource Layers Destroyed 膛", "keyQty": 150, "scalingType": TomeScalingEnum.decay, @@ -743,7 +751,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Destroying Layers includes the following caverns... Motherlode, Eternal Hive, and Evertree Cavern, with more added later!" }), - new TomeBase(92, { + new TomeBase(93, { "name": "Total Opals Found", "keyQty": 500, "scalingType": TomeScalingEnum.decay, @@ -751,7 +759,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(93, { + new TomeBase(94, { "name": "Best Pure Memory Round Reached 膛", "keyQty": 13, "scalingType": TomeScalingEnum.linearToMax, @@ -759,7 +767,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Yea nah, I aint snitchin'. This is a SECRET mode." }), - new TomeBase(94, { + new TomeBase(95, { "name": "Spirited Valley Emperor Boss Kills 膛", "keyQty": 100, "scalingType": TomeScalingEnum.linearToMax, @@ -767,7 +775,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This counts your current Showdown for the Emperor boss in World 6, not the total amount of kills." }), - new TomeBase(95, { + new TomeBase(96, { "name": "Total Summoning Boss Stone victories 膛", "keyQty": 28, "scalingType": TomeScalingEnum.decay, @@ -775,7 +783,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This is the TOTAL wins you have against all Summoning Bosses combined. These are the bossfights from the stones, like the one next to Tribal Shaman NPC!" }), - new TomeBase(96, { + new TomeBase(97, { "name": "Total Coral Reef upgrades 膛", "keyQty": 37, "scalingType": TomeScalingEnum.linearToMax, @@ -783,7 +791,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "The Coral Reef is a feature in World 7 town, unlocked by rescuing Humble Hugh's missing Fishies!" }), - new TomeBase(97, { + new TomeBase(98, { "name": "Deepest Depth reached in a single Delve 膛", "keyQty": 100, "scalingType": TomeScalingEnum.decay, @@ -791,7 +799,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This is for the Spelunking skill, it's just the deepest you've gone in a single attempt." }), - new TomeBase(98, { + new TomeBase(99, { "name": "Total Ninja Knowledge Upgrades LV 膛", "keyQty": 5000, "scalingType": TomeScalingEnum.decay, @@ -799,7 +807,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Ninja Knowledge is the upgrade tree accessed within Sneaking. This includes mini knowledge upgrades, but you'll unlock those later..." }), - new TomeBase(99, { + new TomeBase(100, { "name": "Best Windwalker Max Damage in Tempest Mode 膛", "keyQty": 10, "scalingType": TomeScalingEnum.decayLog, @@ -807,7 +815,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Windwalker is the Beast Masters's Master Class, given by Masterius NPC in World 6. You need to open your Compass to register damage." }), - new TomeBase(100, { + new TomeBase(101, { "name": "Best Arcane Cultist Max Damage in Arcanist Mode 膛", "keyQty": 10, "scalingType": TomeScalingEnum.decayLog, @@ -815,7 +823,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Arcane Cultist is the Bubonic Conjuror's Master Class, given by Masterius NPC in World 6. You need to open your Tesseract to register damage." }), - new TomeBase(101, { + new TomeBase(102, { "name": "Biggest Haul in a single Delve 膛", "keyQty": 25, "scalingType": TomeScalingEnum.decayLog, @@ -823,7 +831,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This is for the Spelunking skill, it's just the most amount of Amber you've gotten in a single attempt." }), - new TomeBase(102, { + new TomeBase(103, { "name": "Total Spelunk Shop Upgrades LV", "keyQty": 2000, "scalingType": TomeScalingEnum.decay, @@ -831,7 +839,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(103, { + new TomeBase(104, { "name": "Total Spelunk Discoveries made 膛", "keyQty": 76, "scalingType": TomeScalingEnum.linearToMax, @@ -839,7 +847,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "A Discovery is when you destroy a rock for the first time in a cave. It's basically how many unique 'things' you've encountered while spelunking!" }), - new TomeBase(104, { + new TomeBase(105, { "name": "Highest leveled Spelunker 膛", "keyQty": 200, "scalingType": TomeScalingEnum.decay, @@ -847,7 +855,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "In other words, this is the Spelunking LV of the highest leveled spelunker in your account." }), - new TomeBase(105, { + new TomeBase(106, { "name": "Lava Dev Streams watched 膛", "keyQty": 10, "scalingType": TomeScalingEnum.linearToMax, @@ -855,7 +863,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "Hey this one's about me! In order to get credit for watching one of my streams, you need to get a gem drop from me while I'm live on twitch at Twitch.tv/ lava贫flame2" }), - new TomeBase(106, { + new TomeBase(107, { "name": "Nametags Found 膛", "keyQty": 20, "scalingType": TomeScalingEnum.linearToMax, @@ -863,7 +871,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This only counts the amount of unique nametags you found... but don't throw away your duplicate nametags! You'll need them for The Gallery in World 7!" }), - new TomeBase(107, { + new TomeBase(108, { "name": "Megaflesh Earned from Bubba", "keyQty": 12, "scalingType": TomeScalingEnum.decay, @@ -871,7 +879,7 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": undefined }), - new TomeBase(108, { + new TomeBase(109, { "name": "Premium Hats Found 膛", "keyQty": 75, "scalingType": TomeScalingEnum.linearToMax, @@ -879,5 +887,5 @@ export const initTomeRepo = () => { "decimalDisplay": undefined, "desc": "This metric is based on the total hats you've deposited to the Hat Rack in World 3!" }) -] -} + ] +} \ No newline at end of file From 9fe5fae68d940bc5a410341648cd014eaaf0c4aa Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 11:05:22 +0100 Subject: [PATCH 02/31] Added ingame indexes Just to be sure about it next time someone works on it --- data/domain/enum/tomeScalingEnum.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/domain/enum/tomeScalingEnum.ts b/data/domain/enum/tomeScalingEnum.ts index e687d313..dc0039a3 100644 --- a/data/domain/enum/tomeScalingEnum.ts +++ b/data/domain/enum/tomeScalingEnum.ts @@ -1,7 +1,7 @@ export enum TomeScalingEnum { - decay = "decay", - decayLog = "decayLog", - linearToMax = "linearToMax", - inverseDecay = "inverseDecay", - boundedDecay = "boundedDecay" + decay = "decay", // 0 + decayLog = "decayLog", // 1 + linearToMax = "linearToMax", // 2 + inverseDecay = "inverseDecay", // 3 + boundedDecay = "boundedDecay" // 4 } From 59f30e5604293d527ce372a7f0eaea1fc3555e2f Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 11:06:29 +0100 Subject: [PATCH 03/31] Changed impacted indexes As the indexes have changed in the TomeRepo, might need some changes again latter as there are new bonuses --- data/domain/data/TomeRepo.ts | 2 +- data/domain/tome.tsx | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/data/domain/data/TomeRepo.ts b/data/domain/data/TomeRepo.ts index 2b5465b7..a3c9a11f 100644 --- a/data/domain/data/TomeRepo.ts +++ b/data/domain/data/TomeRepo.ts @@ -6,7 +6,7 @@ export class TomeBase { constructor(public index: number, public data: TomeModel export const initTomeRepo = () => { - return [ + return [ new TomeBase(0, { "name": "Stamp Total LV", "keyQty": 10000, diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 09c015a3..faeb324c 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -119,25 +119,25 @@ export class TomeLine { switch (this.index) { // Big values - case 8: case 9: - case 13: + case 10: case 14: - case 31: + case 15: case 32: case 33: case 34: case 35: - case 46: - case 53: - case 61: - case 64: - case 66: - case 78: + case 36: + case 47: + case 54: + case 62: + case 65: + case 67: + case 79: return nFormatter(this.currentValues[playerIndex]); // Not so big values but with lots of decimals and wanna keep a bit of it - case 16: - case 18: + case 17: + case 19: return (Math.round(100 * this.currentValues[playerIndex]) / 100).toString(); default: return this.currentValues[playerIndex].toString(); From 62a7b83657513312bf966de648c45cf08ad0c597 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 11:52:37 +0100 Subject: [PATCH 04/31] Updated display order array --- data/domain/tome.tsx | 67 +++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index faeb324c..20f56753 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -848,50 +848,55 @@ export const updateTomeScores = (data: Map) => { // engine.getGameAttribute("CustomLists").h.NinjaInfo[32] const tomeLineDisplayOrder = [ + 5, + 11, + 3, + 65, + 22, 0, - 1, 2, - 3, + 1, + 7, 4, - 5, 6, - 7, 81, 8, 9, 53, 10, - 11, + 107, + 109, 12, + 106, 75, 13, 14, 80, + 79, + 25, 15, 16, 17, 18, 19, 21, - 22, 23, 24, - 79, - 25, 26, 27, 28, + 29, 85, 86, - 29, + 108, 30, 31, 32, 33, 34, 35, - 36, 37, + 36, 76, 38, 54, @@ -900,26 +905,25 @@ const tomeLineDisplayOrder = [ 42, 39, 44, + 50, + 48, 46, 47, - 48, 49, - 50, 51, 52, 45, 55, - 57, - 58, - 59, 60, + 57, 61, 62, - 63, + 66, + 59, 64, + 63, + 58, 56, - 65, - 66, 93, 84, 83, @@ -930,17 +934,28 @@ const tomeLineDisplayOrder = [ 89, 82, 94, - 67, 68, 69, - 20, - 70, - 71, - 43, + 67, + 77, + 78, 72, + 74, + 99, + 71, + 70, 73, + 96, + 20, + 43, 90, - 74, - 77, - 78 + 100, + 101, + 95, + 97, + 103, + 104, + 98, + 102, + 105 ] \ No newline at end of file From d364c5c7ca2374a373a659558fa9bb6df4b6736d Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:33:45 +0100 Subject: [PATCH 05/31] Added New utility log2 from lava code --- data/utility.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/utility.tsx b/data/utility.tsx index c5985d6e..267a2a0f 100644 --- a/data/utility.tsx +++ b/data/utility.tsx @@ -6,6 +6,10 @@ export const lavaLog = (num: number) => { return Math.log(Math.max(num, 1)) / 2.30259; } +export const lavaLog2 = (num: number) => { + return Math.log(Math.max(num, 1)) / Math.log(2) +} + export const lavaFunc = (func: string, level: number, x1: number, x2: number, roundResult: boolean = false) => { var result = 0; switch (func) { From 67f3189c0662c5d843f6354301552ef5448116b8 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:35:12 +0100 Subject: [PATCH 06/31] Updated Tome fixed decay calculation, bugged when a value was too high (thinking it was a string and concatenating it with the this.data.keyQty) Added the calculation for boundedDecay Changed how values are displayed Added new lines, with placeholder for values which can be done for now --- data/domain/tome.tsx | 188 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 171 insertions(+), 17 deletions(-) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 20f56753..49a1f5c1 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -74,7 +74,7 @@ export class TomeLine { if (0 > this.currentValues[playerIndex]) { return 0; } else { - return Math.pow(1.7 * this.currentValues[playerIndex] / (this.currentValues[playerIndex] + this.data.keyQty), .7); + return Math.pow(1.7 * this.currentValues[playerIndex] / (Number(this.currentValues[playerIndex]) + this.data.keyQty), .7); } case TomeScalingEnum.decayLog: return 2.4 * lavaLog(this.currentValues[playerIndex]) / (2 * lavaLog(this.currentValues[playerIndex]) + this.data.keyQty); @@ -86,6 +86,8 @@ export class TomeLine { } else { return Math.pow(1.2 * (6 * this.data.keyQty - this.currentValues[playerIndex]) / (7 * this.data.keyQty - this.currentValues[playerIndex]), 5); } + case TomeScalingEnum.boundedDecay: + return Math.pow(2 * Math.min(this.data.keyQty, this.currentValues[playerIndex]) / (Math.min(this.data.keyQty, this.currentValues[playerIndex]) + this.data.keyQty), .7) default: return 0; } @@ -119,28 +121,33 @@ export class TomeLine { switch (this.index) { // Big values - case 9: - case 10: + case 8: case 14: - case 15: + case 31: case 32: case 33: case 34: case 35: - case 36: - case 47: - case 54: - case 62: - case 65: - case 67: - case 79: + case 61: + case 64: + case 78: + case 102: return nFormatter(this.currentValues[playerIndex]); // Not so big values but with lots of decimals and wanna keep a bit of it - case 17: - case 19: - return (Math.round(100 * this.currentValues[playerIndex]) / 100).toString(); + case 18: + case 66: + return nFormatter(Math.round(100 * this.currentValues[playerIndex]) / 100, "CommaNotation"); + // Not so big values with lots of decimals and wanna round it to match in-game display + case 13: + case 16: + case 26: + case 46: + case 47: + case 53: + case 91: + return nFormatter(Math.round(this.currentValues[playerIndex]), "CommaNotation"); default: - return this.currentValues[playerIndex].toString(); + return nFormatter(this.currentValues[playerIndex], "CommaNotation"); } } @@ -305,17 +312,21 @@ export const updateTomeScores = (data: Map) => { const arcade = data.get("arcade") as Arcade; const prayers = data.get("prayers") as Prayer[]; const upgVault = data.get("upgradeVault") as UpgradeVault; + const hole = data.get("hole") as Hole; // Calculate how many trophy and obols have been found const slab = data.get("slab") as Slab; var trophyCount: number = 0; var obolCount: number = 0; + var nametagCount: number = 0; slab.obtainableItems.forEach((item) => { if (item.obtained) { if (item.internalName.indexOf("Trophy") == 0) { trophyCount++; } else if (item.internalName.indexOf("Obol") == 0) { obolCount++; + } else if (item.internalName.indexOf("EquipmentNametag") == 0) { + nametagCount++; } } }); @@ -355,7 +366,6 @@ export const updateTomeScores = (data: Map) => { const cardsTotalLevels = cards.reduce((sum, card) => sum + (card.count > 0 ? card.getLevels() : 0), 0); // Sum of highest level for each talent - // TODO: Rethink if rounding is correct, need to look at game code. const talentsSumHighestLevel = account.talentsMaxLevels.reduce((sum, talentMaxLevel) => sum + Math.round(talentMaxLevel), 0); // Sum of players Levels @@ -383,6 +393,7 @@ export const updateTomeScores = (data: Map) => { const totalSigilsLevels = sigils.sigils.reduce((sum, sigil) => sum + (sigil.boostLevel + 1), 0); // Sum of best worship waves + // TODO : update worship to include the new totem const totalBestWorshipWaves = worshipData.totemInfo.reduce((sum, totem) => sum + totem.maxWave, 0); // Sum of all deathnote kills digit @@ -437,6 +448,7 @@ export const updateTomeScores = (data: Map) => { const totalBoatLevels = sailing.boats.reduce((sum, boat) => sum + boat.lootUpgrades + boat.speedUpgrades, 0); // Number of artifact found + // TODO : update this once new status is added, result is 0 right now const totalArtifactFound = sailing.artifacts.reduce((sum, artifact) => artifact.status == ArtifactStatus.Obtained ? sum + 1 : artifact.status == ArtifactStatus.Ancient ? sum + 2 @@ -462,6 +474,7 @@ export const updateTomeScores = (data: Map) => { const totalSummoningUpgradeLevels = summoning.summonUpgrades.reduce((sum, upgrade) => sum + upgrade.level, 0); // Sum of summoning victories + // TODO : update summoning to include the new color battles and upgrades const summoningVictories = summoning.summonBattles.getTotalVictories(); // Number of Ninja floors unlocked @@ -481,9 +494,16 @@ export const updateTomeScores = (data: Map) => { multiplyer *= i + 3; } + // Total of all summoning boss victories + // TODO once implemented + const totalSummoningBossesVictories = 0; + // Number of Jade Emporium upgrades bought const jadeEmporiumUpgradesBought = sneaking.jadeUpgrades.filter(upgrade => upgrade.display && upgrade.purchased).length; + // Sum of all ninja upgrades levels + const totalNinjaUpgradeLevels = sneaking.sneakingUpgrades.reduce((sum, upgrade) => sum + upgrade.level, 0); + // Sum of all minigame scores, including basket const totalMinigamesScores = account.minigameHighscores.reduce((sum, score) => sum + score, 0) + (optionListAccount[99] ?? 0); @@ -493,9 +513,24 @@ export const updateTomeScores = (data: Map) => { // Sum of all farming plots land rank const totalPlotRank = farming.farmPlots.reduce((sum, plot) => sum + plot.landRank, 0); - // SUm of all gold ball upgrade levels in arcade + // Sum of all gold ball upgrade levels in arcade const totalArcadeUpgradeLevel = arcade.bonuses.reduce((sum, bonus) => sum + bonus.level, 0); + // Sum of all gambit time from the Hole + const totalGambitTime = hole.gambit.getGambitTotalTime(); + + // Sum of digits of all ressources owned from the Hole + const totalDigitsHoleRessources = Object.entries(hole.resourceCavrens.cavrens).reduce((sum, [_, cavren]) => sum + Math.ceil(lavaLog(cavren.resourceExtracted)), 0); + + // Sum of all villagers levels + const totalVillagersLevels = hole.villagers.reduce((sum, villager) => sum + villager.level, 0); + + // Total of Layers Destroyed in The Hole ressources + const totalDestroyedRessourcesLayers = Object.entries(hole.resourceCavrens.cavrens).reduce((sum, [_, cavren]) => sum + cavren.layer, 0); + + // Highest leveled Spelunker of the account + const highestSpelunkingLevel = Math.max(0, ...players.map(player => player.skills.get(SkillsIndex.Spelunking)?.level ?? 0)); + tome.totalAccountLevel = totalPlayersLevels; tome.lines.forEach(line => { line.updateIsLineUnlocked(tome.totalAccountLevel); @@ -727,6 +762,7 @@ export const updateTomeScores = (data: Map) => { break; case 55: // Number of Onyx statues + // TODO : add the new statue type and fix this for (var i = 0; i < statues.length; i++) { line.updatePlayerCurrentValue((statues[i].statues.filter(statue => statue && statue.type == StatusType.Onyx).length ?? 0), i); } @@ -835,6 +871,124 @@ export const updateTomeScores = (data: Map) => { // Bonus from Teh TOM, index 57 in upgrade vault. line.updateAllPlayersCurrentValue(upgVault.bonuses.find(bonus => bonus.id == 57)?.getBonus(upgVault.bonuses) ?? 0); break; + case 82: + // Total Gambit time (in seconds) + line.updateAllPlayersCurrentValue(totalGambitTime); + break; + case 83: + // Total digits of The Hole ressources + line.updateAllPlayersCurrentValue(totalDigitsHoleRessources); + break; + case 84: + // Total villagers levels + line.updateAllPlayersCurrentValue(totalVillagersLevels); + break; + case 85: + // Megafeathers from the Orion minigame + line.updateAllPlayersCurrentValue((optionListAccount[262] ?? 0)); + break; + case 86: + // Megafish from the Poppy minigame + line.updateAllPlayersCurrentValue((optionListAccount[279] ?? 0)); + break; + case 87: + // Best bravery monument round + line.updateAllPlayersCurrentValue(hole.monuments.monuments["Bravery"].highestRound); + break; + case 88: + // Best justice monument round + line.updateAllPlayersCurrentValue(hole.monuments.monuments["Justice"].highestRound); + break; + case 89: + // Best wisdom monument round + line.updateAllPlayersCurrentValue(hole.monuments.monuments["Wisdom"].highestRound); + break; + case 90: + // Best Deathbringer Max Damade in Wraith mode + line.updateAllPlayersCurrentValue((optionListAccount[356] ?? 0)); + break; + case 91: + // Best Dawg Den score + line.updateAllPlayersCurrentValue(hole.dawgDen.bestScore); + break; + case 92: + // Total layers ressources destroyed in The Hole + line.updateAllPlayersCurrentValue(totalDestroyedRessourcesLayers); + break; + case 93: + // Total Opals found in The Hole + line.updateAllPlayersCurrentValue(hole.ownedOpals); + break; + case 94: + // Best Pure Memory Round Reached + line.updateAllPlayersCurrentValue((hole.monuments.monuments["Wisdom"] as WisdomMonument).highestPureMemoryRound); + break; + case 95: + // Current w6 boss kills (reset when you reset the bonuses) + line.updateAllPlayersCurrentValue(Math.round(optionListAccount[369] ?? 0)); + break; + case 96: + // Total summoning boss victories + line.updateAllPlayersCurrentValue(totalSummoningBossesVictories); + break; + case 97: + // Total coral reef upgrades + // TODO : get the values once implemented + line.updateAllPlayersCurrentValue(0); + break; + case 98: + // Deepest delve depth reach in a single run + // TODO : get the values once implemented + line.updateAllPlayersCurrentValue(0); + break; + case 99: + // Total ninja knowledge upgrades levels + line.updateAllPlayersCurrentValue(totalNinjaUpgradeLevels); + break; + case 100: + // Best Windwalker Max Damage in Tempest Mode + line.updateAllPlayersCurrentValue(optionListAccount[445] ?? 0); + break; + case 101: + // Best Arcane Cultist Max Damage in Arcanist Mode + line.updateAllPlayersCurrentValue(optionListAccount[446] ?? 0); + break; + case 102: + // Biggest Haul in a single Delve + line.updateAllPlayersCurrentValue(0); + break; + case 103: + // Total Spelunk Shop Upgrades LV + // TODO : add this once implemented + line.updateAllPlayersCurrentValue(0); + break; + case 104: + // Total Spelunk Discoveries made + // TODO : add this once implemented + line.updateAllPlayersCurrentValue(0); + break; + case 105: + // Highest leveled Spelunker + line.updateAllPlayersCurrentValue(highestSpelunkingLevel); + break; + case 106: + // Lava Dev Streams watched + line.updateAllPlayersCurrentValue(optionListAccount[443] ?? 0); + break; + case 107: + // Nametags found + line.updateAllPlayersCurrentValue(nametagCount); + break; + case 108: + // Megaflesh Earned from Bubba + // TODO : add this once implemented + line.updateAllPlayersCurrentValue(0); + break; + case 109: + // Premium Hats Found + // TODO : add this once Hat rack from world 3 is implemented + line.updateAllPlayersCurrentValue(0); + break; default: line.updateAllPlayersCurrentValue(0); break; From 8bf556416aa733e90230a451a0d4ebe0f896c432 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:37:26 +0100 Subject: [PATCH 07/31] Updated import for Tome --- data/domain/tome.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 49a1f5c1..abf5b25f 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -38,6 +38,8 @@ import { Summoning } from './world-6/summoning'; import { Arcade } from './arcade'; import { Prayer } from './prayers'; import { UpgradeVault } from './upgradeVault'; +import { Hole, WisdomMonument } from './world-5/hole/hole'; +import { SkillsIndex } from './SkillsIndex'; export enum TomeScoreColors { Platinum = "#6EE3FF", From 184f3a1daffa4c383dab2141c958f589d65a777a Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:40:56 +0100 Subject: [PATCH 08/31] Created Gambit Used to add everything Gambit related without cluttering too much the main file --- data/domain/world-5/hole/gambit.tsx | 154 ++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 data/domain/world-5/hole/gambit.tsx diff --git a/data/domain/world-5/hole/gambit.tsx b/data/domain/world-5/hole/gambit.tsx new file mode 100644 index 00000000..673da3b6 --- /dev/null +++ b/data/domain/world-5/hole/gambit.tsx @@ -0,0 +1,154 @@ +import { lavaLog, lavaLog2 } from "../../../utility"; +import { initGambitBonusRepo } from "../../data/GambitBonusRepo"; +import { GambitBonusModel } from "../../model/gambitBonusModel"; + +export enum GambitLevelIndex { + King = 0, + Horse = 1, + Bishop = 2, + Queen = 3, + Tower = 4, + Pawn = 5 +} + +const gambitLevelMetadata = { + [GambitLevelIndex.King]: { + name: "King's Gambit", + description: "Survive as long as you can...", + }, + [GambitLevelIndex.Horse]: { + name: "Horsey's Gambit", + description: "You have but one HP...", + }, + [GambitLevelIndex.Bishop]: { + name: "Bishop's Gambit", + description: "Damage done to me is done to thee...", + }, + [GambitLevelIndex.Queen]: { + name: "Queen's Gambit", + description: "Jewels everywhere...", + }, + [GambitLevelIndex.Tower]: { + name: "Castle's Gambit", + description: "One lane, one outcome...", + }, + [GambitLevelIndex.Pawn]: { + name: "Noobs' Gambit", + description: "I like the grey ones!!!", + }, +} + +export class GambitLevel { + maxTime: number = 0; // in seconds, will have decimals + + constructor(public index: number, public name: string, public description: string) { } + + getDisplayTime(): string { + let timeLeft = this.maxTime; + const hours = Math.floor(timeLeft / 3600); + timeLeft -= (hours * 3600); + const minutes = Math.floor(timeLeft / 60); + timeLeft -= (minutes * 60); + + return (hours > 0 ? hours+"h " : "") + (minutes > 0 ? minutes+"min " : "") + (timeLeft > 0 ? (Math.trunc(timeLeft * 10) / 10)+"sec" : ""); + } + + getScoreValue(): number { + let points = 100 * (this.maxTime + (3 * Math.floor(this.maxTime / 10) + 10 * Math.floor(this.maxTime / 60))); + + if (this.index != 0) { + // Levels which are not king get double points + return points * 2; + } + + return points ; + } +} + +export class GambitLevels { + static getLevels(): GambitLevel[] { + return Object.entries(gambitLevelMetadata).map(([index, metadata]) => { + return new GambitLevel(Number(index), metadata.name, metadata.description); + }); + } +} + +export class GambitBonus { + unlocked: boolean = false; + + constructor(public index: number, public data: GambitBonusModel) {} + + getBonus(gambitTotalScore: number): number { + if(!this.unlocked) + { + return 0; + } + + // Special case + if (this.index == 0) { + return Math.max(1, Math.ceil(lavaLog2(gambitTotalScore) - 8 + (lavaLog(gambitTotalScore) - 1))) + } + + if (this.data.x1 == 1) { + return this.data.x0 * gambitTotalScore; + } else { + return this.data.x0; + } + } + + getScoreThreshold(): number { + return 2E3 + 1E3 * (this.index + 1) * (1 + this.index / 5) * Math.pow(1.26, this.index); + } +} + +export class Gambit { + bonuses: GambitBonus[] = []; + levels: GambitLevel[] = GambitLevels.getLevels(); + gambitPointsMulti: number = 1; + + constructor() { + const gambitBonusesData = initGambitBonusRepo(); + gambitBonusesData.forEach(bonus => { + this.bonuses.push(new GambitBonus(bonus.index, bonus.data)); + }); + } + + getBonus(index: number): number { + const bonus = this.bonuses.find(bonus => bonus.index == index); + if (bonus) + { + return bonus.getBonus(this.getGambitTotalTime()); + } + + return 0; + } + + getBonusText(index: number): string { + const bonus = this.bonuses.find(bonus => bonus.index == index); + if (bonus) + { + switch(bonus.index) { + + } + const value = bonus.getBonus(this.getGambitTotalTime()); + } + + return ""; + } + + getGambitTotalTime(): number { + return this.levels.reduce((sum, level) => sum + level.maxTime, 0); + } + + getGambitTotalScore(): number { + return this.levels.reduce((sum, level) => level.getScoreValue(), 0) * this.gambitPointsMulti; + } + + updateUnlockedBonuses() { + const totalGambitScore = this.getGambitTotalScore(); + + this.bonuses.forEach(bonus => { + bonus.unlocked = totalGambitScore >= bonus.getScoreThreshold(); + }); + } +} \ No newline at end of file From 2fb145fdc433d084aa03d32d9c4019ec3ac6ec19 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:41:51 +0100 Subject: [PATCH 09/31] Added Gambit to Hole --- data/domain/world-5/hole/hole.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/domain/world-5/hole/hole.tsx b/data/domain/world-5/hole/hole.tsx index 1c7d9e39..36026c38 100644 --- a/data/domain/world-5/hole/hole.tsx +++ b/data/domain/world-5/hole/hole.tsx @@ -29,6 +29,7 @@ import { initBellBonusRepo } from "../../data/BellBonusRepo"; import { initHarpNotesRepo } from "../../data/HarpNotesRepo"; import { HarpStringModel } from "../../model/harpStringModel"; import { initHarpStringsRepo } from "../../data/HarpStringsRepo"; +import { Gambit, GambitBonus, GambitLevel, GambitLevels } from "./gambit"; export class Villager { level: number = 0; @@ -691,6 +692,7 @@ export class Hole extends Domain { resourceCavrens = new ResourceCavrens(); harp: Harp = new Harp(); lamp: Lamp = new Lamp(); + gambit: Gambit = new Gambit(); // TODO: // Well - DONE? // Caverns @@ -883,4 +885,12 @@ export const updateHole = (data: Map) => { // TODO: This doesn't work on load, investigate why. measurement.deathnotePts = deathnote.getTotalRank(); }); + + // Update the gambit multiplier + let gambitMultipliers = (hole.measurements.find(measurement => measurement.index == 13)?.getBonus() ?? 0) + hole.getStudyBolaiaBonuses(13); + gambitMultipliers += tesseract.getUpgradeBonus(47) + (hole.monuments.monuments["Wisdom"].bonuses.find(bonus => bonus.index == 7)?.getBonus() ?? 0); + gambitMultipliers += hole.schematics.find(schem => schem.index == 78)?.getBonus(10) ?? 0; + // TODO add this : m._customBlock_Holes("JarCollectibleBonus", 23, 0) + (m._customBlock_Holes("JarCollectibleBonus", 30, 0) + hole.gambit.gambitPointsMulti = 1 + gambitMultipliers / 100; + hole.gambit.updateUnlockedBonuses(); } From 6ee19705315f538b96ee99eaf743bbef98d256e9 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:42:35 +0100 Subject: [PATCH 10/31] Added DawgDen and Total opals --- data/domain/world-5/hole/hole.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/data/domain/world-5/hole/hole.tsx b/data/domain/world-5/hole/hole.tsx index 36026c38..73f1d021 100644 --- a/data/domain/world-5/hole/hole.tsx +++ b/data/domain/world-5/hole/hole.tsx @@ -675,6 +675,9 @@ export class Lamp { } } +export class DawgDen { + bestScore: number = 0; +} export class Hole extends Domain { // Raw @@ -692,7 +695,9 @@ export class Hole extends Domain { resourceCavrens = new ResourceCavrens(); harp: Harp = new Harp(); lamp: Lamp = new Lamp(); + dawgDen: DawgDen = new DawgDen(); gambit: Gambit = new Gambit(); + ownedOpals: number = 0; // TODO: // Well - DONE? // Caverns @@ -861,6 +866,10 @@ export class Hole extends Domain { hole.well.parse(hole, holeData); // TODO: Finish this, missing information hole.harp.parse(holeData); + + hole.dawgDen.bestScore = holeData[11][8] || 0; + + this.ownedOpals = (holeData[7] as number[]).reduce((sum, value) => sum + value, 0); } } From ef5df5dfc453af8f4c532a3997c43eb6ce399ef1 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 17:43:26 +0100 Subject: [PATCH 11/31] Added more info in monuments --- data/domain/world-5/hole/hole.tsx | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/data/domain/world-5/hole/hole.tsx b/data/domain/world-5/hole/hole.tsx index 73f1d021..0321ede7 100644 --- a/data/domain/world-5/hole/hole.tsx +++ b/data/domain/world-5/hole/hole.tsx @@ -30,6 +30,7 @@ import { initHarpNotesRepo } from "../../data/HarpNotesRepo"; import { HarpStringModel } from "../../model/harpStringModel"; import { initHarpStringsRepo } from "../../data/HarpStringsRepo"; import { Gambit, GambitBonus, GambitLevel, GambitLevels } from "./gambit"; +import { Tesseract } from "../../tesseract"; export class Villager { level: number = 0; @@ -474,6 +475,7 @@ export class Monument { hours: number = 0; bonuses: MonumentBonus[] = []; unlocks: MonumentUnlock[] = []; + highestRound: number = 0; constructor( public index: number, @@ -490,12 +492,20 @@ export class Monument { } } +export class WisdomMonument extends Monument { + highestPureMemoryRound: number = 0; +} + export class Monuments { monuments: Record = {} constructor() { const data = initMonumentRepo(); data.forEach(monument => { - this.monuments[monument.data.name] = new Monument(monument.index, monument.data.name, monument.data.bonuses, monument.data.unlocks); + if (monument.data.name == "Wisdom") { + this.monuments[monument.data.name] = new WisdomMonument(monument.index, monument.data.name, monument.data.bonuses, monument.data.unlocks); + } else { + this.monuments[monument.data.name] = new Monument(monument.index, monument.data.name, monument.data.bonuses, monument.data.unlocks); + } }) } } @@ -751,6 +761,7 @@ export class Hole extends Domain { parse(data: Map): void { const hole = data.get(this.getDataKey()) as Hole; const holeData = data.get("Holes") as number[][]; + const optionListAccount = data.get("OptLacc") as number[]; // Old accounts won't have data, so exit early. if (!holeData || holeData.length == 0) { @@ -829,12 +840,16 @@ export class Hole extends Domain { // Monument Jazz const braveryMonument = hole.monuments.monuments["Bravery"]; braveryMonument.hours = holeData[14][2 * braveryMonument.index] || 0; + braveryMonument.highestRound = holeData[11][73] || 0; const justiceMonument = hole.monuments.monuments["Justice"]; justiceMonument.hours = holeData[14][2 * justiceMonument.index] || 0; + justiceMonument.highestRound = holeData[11][74] || 0; - const wisdomMonument = hole.monuments.monuments["Wisdom"]; + const wisdomMonument = hole.monuments.monuments["Wisdom"] as WisdomMonument; wisdomMonument.hours = holeData[14][2 * wisdomMonument.index] || 0; + wisdomMonument.highestRound = holeData[11][75] || 0; + wisdomMonument.highestPureMemoryRound = Math.round(Math.min(12, optionListAccount[353] ?? 0) + 1); [braveryMonument, justiceMonument, wisdomMonument].forEach(monument => { monument.unlocks.forEach(unlock => { @@ -880,12 +895,12 @@ export const updateHole = (data: Map) => { const tome = data.get("tome") as Tome; const farming = data.get("farming") as Farming; const deathnote = data.get("deathnote") as Deathnote; + const tesseract = data.get("tesseract") as Tesseract; // Update measurements with various cross domain data hole.measurements.forEach(measurement => { measurement.slabItems = slab.rawObtainedCount; measurement.highestDmg = taskboard.tasks.find(task => task.name == "Road to Max Damage")?.count || 0; - // TODO: Tome score isn't correct right now, need to update it. measurement.tomeScore = tome.getHighestScore(); measurement.cropsCount = farming.discoveredCrops; measurement.accountLevel = tome.totalAccountLevel; From d393b4b7347ef6a5af4b3dea859046160fdceb10 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:00:26 +0100 Subject: [PATCH 12/31] Added Jare types information In case we need it at some point for UI (might be missing some information tho) --- data/domain/data/HoleJarRepo.ts | 50 +++++++++++++++++++++++++++++++ data/domain/model/holeJarModel.ts | 4 +++ 2 files changed, 54 insertions(+) create mode 100644 data/domain/data/HoleJarRepo.ts create mode 100644 data/domain/model/holeJarModel.ts diff --git a/data/domain/data/HoleJarRepo.ts b/data/domain/data/HoleJarRepo.ts new file mode 100644 index 00000000..dcc50f93 --- /dev/null +++ b/data/domain/data/HoleJarRepo.ts @@ -0,0 +1,50 @@ +import { HoleJarModel } from "../model/holeJarModel"; + +export class HoleJarInfoBase { constructor(public index: number, public data: HoleJarModel) { } } + + + +export const initHoleJarRepo = () => { + return [ + new HoleJarInfoBase(0, { + name: "Simple Jar", + description: "Contains a random basic rupie" + }), + new HoleJarInfoBase(1, { + name: "Tall Jar", + description: "Has a {% chance to contain an Opal" + }), + new HoleJarInfoBase(2, { + name: "Ornate Jar", + description: "Has a {% chance to contain a new collectible" + }), + new HoleJarInfoBase(3, { + name: "Great Jar", + description: "Contains a random decent rupie" + }), + new HoleJarInfoBase(4, { + name: "Enchanted Jar", + description: "Has a {% chance to enchant a collectible doubling its bonus" + }), + new HoleJarInfoBase(5, { + name: "Artisan Jar", + description: "Contains a white rupee" + }), + new HoleJarInfoBase(6, { + name: "Epic Jar", + description: "Contains a random elegant rupie" + }), + new HoleJarInfoBase(7, { + name: "Gilded Jar", + description: "Doubles the amount of rupies from the next jar opened" + }), + new HoleJarInfoBase(8, { + name: "Ceremony Jar", + description: "Contains a dark rupie" + }), + new HoleJarInfoBase(9, { + name: "Heirloom Jar", + description: "Contains the one and only master rupie" + }), + ] +} \ No newline at end of file diff --git a/data/domain/model/holeJarModel.ts b/data/domain/model/holeJarModel.ts new file mode 100644 index 00000000..ee31eda7 --- /dev/null +++ b/data/domain/model/holeJarModel.ts @@ -0,0 +1,4 @@ +export interface HoleJarModel { + name: string, + description: string +} \ No newline at end of file From 20869a72f3504a862e320b59222560b5365643b9 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:03:01 +0100 Subject: [PATCH 13/31] Manually updated some repo values --- data/domain/data/GambitBonusRepo.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/domain/data/GambitBonusRepo.ts b/data/domain/data/GambitBonusRepo.ts index aed9c4b3..3880fe8d 100644 --- a/data/domain/data/GambitBonusRepo.ts +++ b/data/domain/data/GambitBonusRepo.ts @@ -81,7 +81,7 @@ export const initGambitBonusRepo = () => { "x0": 1, "x1": 0, "description": "no", - "name": "2 extra Snail Mail every day" + "name": "2x extra Snail Mail every day" }), new GambitBonusBase(11, { "index": 11, @@ -95,14 +95,14 @@ export const initGambitBonusRepo = () => { "x0": 1, "x1": 0, "description": "no", - "name": "2 Extra Bones on Deathbringer" + "name": "2x Extra Bones on Deathbringer" }), new GambitBonusBase(13, { "index": 13, "x0": 1, "x1": 0, "description": "no", - "name": "2 daily particle bubble upg" + "name": "2x daily particle bubble upg" }), new GambitBonusBase(14, { "index": 14, From 6de1d60e760ed27f101ac33dd1fb3c410324a017 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:13:15 +0100 Subject: [PATCH 14/31] Small renames --- data/domain/data/HoleJarRepo.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/data/domain/data/HoleJarRepo.ts b/data/domain/data/HoleJarRepo.ts index dcc50f93..6fc57c32 100644 --- a/data/domain/data/HoleJarRepo.ts +++ b/data/domain/data/HoleJarRepo.ts @@ -1,48 +1,48 @@ import { HoleJarModel } from "../model/holeJarModel"; -export class HoleJarInfoBase { constructor(public index: number, public data: HoleJarModel) { } } +export class HoleJarBase { constructor(public index: number, public data: HoleJarModel) { } } export const initHoleJarRepo = () => { return [ - new HoleJarInfoBase(0, { + new HoleJarBase(0, { name: "Simple Jar", description: "Contains a random basic rupie" }), - new HoleJarInfoBase(1, { + new HoleJarBase(1, { name: "Tall Jar", description: "Has a {% chance to contain an Opal" }), - new HoleJarInfoBase(2, { + new HoleJarBase(2, { name: "Ornate Jar", description: "Has a {% chance to contain a new collectible" }), - new HoleJarInfoBase(3, { + new HoleJarBase(3, { name: "Great Jar", description: "Contains a random decent rupie" }), - new HoleJarInfoBase(4, { + new HoleJarBase(4, { name: "Enchanted Jar", description: "Has a {% chance to enchant a collectible doubling its bonus" }), - new HoleJarInfoBase(5, { + new HoleJarBase(5, { name: "Artisan Jar", description: "Contains a white rupee" }), - new HoleJarInfoBase(6, { + new HoleJarBase(6, { name: "Epic Jar", description: "Contains a random elegant rupie" }), - new HoleJarInfoBase(7, { + new HoleJarBase(7, { name: "Gilded Jar", description: "Doubles the amount of rupies from the next jar opened" }), - new HoleJarInfoBase(8, { + new HoleJarBase(8, { name: "Ceremony Jar", description: "Contains a dark rupie" }), - new HoleJarInfoBase(9, { + new HoleJarBase(9, { name: "Heirloom Jar", description: "Contains the one and only master rupie" }), From 0415840cda80f3cbfa774171959ec08a2d6f080f Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:13:29 +0100 Subject: [PATCH 15/31] Added Jar bonuses model and repo --- data/domain/data/HoleJarBonusRepo.ts | 249 +++++++++++++++++++++++++ data/domain/model/holeJarBonusModel.ts | 6 + 2 files changed, 255 insertions(+) create mode 100644 data/domain/data/HoleJarBonusRepo.ts create mode 100644 data/domain/model/holeJarBonusModel.ts diff --git a/data/domain/data/HoleJarBonusRepo.ts b/data/domain/data/HoleJarBonusRepo.ts new file mode 100644 index 00000000..4cf7505a --- /dev/null +++ b/data/domain/data/HoleJarBonusRepo.ts @@ -0,0 +1,249 @@ +import { HoleJarBonusModel } from "../model/holeJarBonusModel"; + +export class HoleJarBonusBase { constructor(public index: number, public data: HoleJarBonusModel) { } } + + +export const initHoleBuildingRepo = () => { + return [ + new HoleJarBonusBase(0, { + name: "ABNORMAL RUPIE", + bonus: 20, + filler1: "Filler", + description: "Rupies found are worth +{% more. @ Current Rupie Value:$" + }), + new HoleJarBonusBase(1, { + name: "SAPPHIRE DROPLET", + bonus: 10, + filler1: "Filler", + description: "Jar production rate is +{% faster." + }), + new HoleJarBonusBase(2, { + name: "EFFERVESCENT DIAMOND", + bonus: 20, + filler1: "Filler", + description: "}x higher chance to find Opals in Tall Jars." + }), + new HoleJarBonusBase(3, { + name: "TORTOLE ROCK", + bonus: 25, + filler1: "Filler", + description: "All rupies found are worth a whopping }x more!" + }), + new HoleJarBonusBase(4, { + name: "NATURAL PEARL", + bonus: 15, + filler1: "Filler", + description: "All villagers gain +{% more EXP." + }), + new HoleJarBonusBase(5, { + name: "AMETHYST HEARTSTONE", + bonus: 10, + filler1: "Filler", + description: "All skilling caverns require {% less Resources to get opals!" + }), + new HoleJarBonusBase(6, { + name: "AMBER SQUARE", + bonus: 25, + filler1: "Filler", + description: "Rupies found are worth +{% more." + }), + new HoleJarBonusBase(7, { + name: "VERDANT THORNS", + bonus: 25, + filler1: "Filler", + description: "}x higher chance to find new Collectibles." + }), + new HoleJarBonusBase(8, { + name: "VIOLENT VIOLETS", + bonus: 20, + filler1: "Filler", + description: "All buckets get }x Bucket Fill Rate!" + }), + new HoleJarBonusBase(9, { + name: "BLUE FABERGE EGG", + bonus: 15, + filler1: "Filler", + description: "}x higher chance to enchant a Collectible" + }), + new HoleJarBonusBase(10, { + name: "SHADOW PRISM", + bonus: 20, + filler1: "Filler", + description: "All villagers gain +{% more EXP." + }), + new HoleJarBonusBase(11, { + name: "BIG BEEF ROCK", + bonus: 25, + filler1: "Filler", + description: "}x faster Bell Ring Rate!" + }), + new HoleJarBonusBase(12, { + name: "EMERALD ORE", + bonus: 30, + filler1: "Filler", + description: "All villagers gain +{% more EXP." + }), + new HoleJarBonusBase(13, { + name: "DAWN PRISM", + bonus: 30, + filler1: "Filler", + description: "Rupies found are worth +{% more." + }), + new HoleJarBonusBase(14, { + name: "SWAMPSTONE", + bonus: 25, + filler1: "Filler", + description: "}x higher chance to find Opals in Tall Jars." + }), + new HoleJarBonusBase(15, { + name: "FROST SPIRESTONE", + bonus: 12, + filler1: "Filler", + description: "Jar production rate is +{% faster." + }), + new HoleJarBonusBase(16, { + name: "ROSEMERALD", + bonus: 10, + filler1: "Filler", + description: "}x Faster study rate for villager Bolaia" + }), + new HoleJarBonusBase(17, { + name: "BLOOD GLASS", + bonus: 40, + filler1: "Filler", + description: "All rupies found are worth a whopping }x more!" + }), + new HoleJarBonusBase(18, { + name: "SUNRISE DIAMOND", + bonus: 25, + filler1: "Filler", + description: "}x higher chance to enchant a Collectible" + }), + new HoleJarBonusBase(19, { + name: "MINCERAFT GEM", + bonus: 20, + filler1: "Filler", + description: "+{% Monument AFK Gain rate." + }), + new HoleJarBonusBase(20, { + name: "CRIMSON SPADE", + bonus: 20, + filler1: "Filler", + description: "The harp produces }x more Notes!" + }), + new HoleJarBonusBase(21, { + name: "STAINED GLASSDROP", + bonus: 35, + filler1: "Filler", + description: "Rupies found are worth +{% more." + }), + new HoleJarBonusBase(22, { + name: "TABULA RASASTONE", + bonus: 32, + filler1: "Filler", + description: "All villagers gain +{% more EXP." + }), + new HoleJarBonusBase(23, { + name: "DEEP BLUE SQUARE", + bonus: 1, + filler1: "Filler", + description: "+{% Gambit PTS" + }), + new HoleJarBonusBase(24, { + name: "EARTHBOUND GEODE", + bonus: 15, + filler1: "Filler", + description: "Jar production rate is +{% faster." + }), + new HoleJarBonusBase(25, { + name: "INFERNO DROPLET", + bonus: 40, + filler1: "Filler", + description: "}x higher chance to find new Collectibles." + }), + new HoleJarBonusBase(26, { + name: "OCTOGONAL GEM", + bonus: 30, + filler1: "Filler", + description: "}x higher chance to enchant a Collectible" + }), + new HoleJarBonusBase(27, { + name: "SOLARFANG", + bonus: 32, + filler1: "Filler", + description: "}x higher chance to find Opals in Tall Jars." + }), + new HoleJarBonusBase(28, { + name: "MYSTIC ORE", + bonus: 50, + filler1: "Filler", + description: "All rupies found are worth a whopping }x more!" + }), + new HoleJarBonusBase(29, { + name: "ARCANE PRISM", + bonus: 38, + filler1: "Filler", + description: "All villagers gain +{% more EXP." + }), + new HoleJarBonusBase(30, { + name: "MURKY FABREGE EGG", + bonus: 1, + filler1: "Filler", + description: "+{% Gambit PTS" + }), + new HoleJarBonusBase(31, { + name: "CORPORE ROCK", + bonus: 1, + filler1: "Filler", + description: "Boosts a future cavern... futuuure..!" + }), + new HoleJarBonusBase(32, { + name: "TWILIGHT PRISM", + bonus: 1, + filler1: "Filler", + description: "Boosts a future cavern... futuuure..!" + }), + new HoleJarBonusBase(33, { + name: "TEWBALL ORBSTONE", + bonus: 40, + filler1: "Filler", + description: "Rupies found are worth +{% more." + }), + new HoleJarBonusBase(34, { + name: "MAD MUSCLE ROCK", + bonus: 40, + filler1: "Filler", + description: "}x higher chance to enchant a Collectible" + }), + new HoleJarBonusBase(35, { + name: "SUNROOT SPLINTERS", + bonus: 40, + filler1: "Filler", + description: "All villagers gain +{% more EXP." + }), + new HoleJarBonusBase(36, { + name: "TWISTED RUPIE", + bonus: 75, + filler1: "Filler", + description: "}x faster Bell Ring Rate!" + }), + new HoleJarBonusBase(37, { + name: "OVERLOADED RELIC", + bonus: 1, + filler1: "Filler", + description: "Boosts a future cavern... futuuure..!" + }), + new HoleJarBonusBase(38, { + name: "SUNBURST PEARL", + bonus: 1, + filler1: "Filler", + description: "Boosts a future cavern... futuuure..!" + }), + new HoleJarBonusBase(39, { + name: "BLOODFANG SPIRES", + bonus: 1, + filler1: "Filler", + description: "Boosts a future cavern... futuuure..!" + }) + ] +} \ No newline at end of file diff --git a/data/domain/model/holeJarBonusModel.ts b/data/domain/model/holeJarBonusModel.ts new file mode 100644 index 00000000..ed7432c7 --- /dev/null +++ b/data/domain/model/holeJarBonusModel.ts @@ -0,0 +1,6 @@ +export interface HoleJarBonusModel { + name: string, + bonus: number, + filler1: string + description: string +} \ No newline at end of file From 3895899c403c261742a97818bafec6e452dfec84 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:38:21 +0100 Subject: [PATCH 16/31] small rename --- data/domain/data/HoleJarBonusRepo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/domain/data/HoleJarBonusRepo.ts b/data/domain/data/HoleJarBonusRepo.ts index 4cf7505a..77d558a9 100644 --- a/data/domain/data/HoleJarBonusRepo.ts +++ b/data/domain/data/HoleJarBonusRepo.ts @@ -3,7 +3,7 @@ import { HoleJarBonusModel } from "../model/holeJarBonusModel"; export class HoleJarBonusBase { constructor(public index: number, public data: HoleJarBonusModel) { } } -export const initHoleBuildingRepo = () => { +export const initHoleJarBonusRepo = () => { return [ new HoleJarBonusBase(0, { name: "ABNORMAL RUPIE", From b85ef03142243ca5ed7a2d156783c7a50acb8a1e Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:38:45 +0100 Subject: [PATCH 17/31] Created Jar Includes Jar bonuses and Jar types --- data/domain/world-5/hole/jar.tsx | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 data/domain/world-5/hole/jar.tsx diff --git a/data/domain/world-5/hole/jar.tsx b/data/domain/world-5/hole/jar.tsx new file mode 100644 index 00000000..c10cbcde --- /dev/null +++ b/data/domain/world-5/hole/jar.tsx @@ -0,0 +1,47 @@ +import { HoleJarBonusBase, initHoleJarBonusRepo } from "../../data/HoleJarBonusRepo"; +import { HoleJarBase, initHoleJarRepo } from "../../data/HoleJarRepo"; +import { HoleJarBonusModel } from "../../model/holeJarBonusModel"; +import { HoleJarModel } from "../../model/holeJarModel"; + +export class JarBonus { + level: number = 0; + legendTalentBonus: number = 1; + + constructor(public index: number, public data: HoleJarBonusModel) {} + + getBonus(): number { + return this.level * this.data.bonus * this.legendTalentBonus; + } +} + +export class JarType { + unlocked: boolean = false; + + constructor(public index: number, public data: HoleJarModel) {} +} + +export class Jar { + jarTypes: JarType[] = []; + jarBonuses: JarBonus[] = []; + + constructor() { + const jarTypes = initHoleJarRepo(); + jarTypes.forEach(jar => { + jarTypes.push(new JarType(jar.index, jar.data)); + }); + const jarBonuses = initHoleJarBonusRepo(); + jarBonuses.forEach(bonus => { + jarBonuses.push(new JarBonus(bonus.index, bonus.data)); + }); + } + + getBonus(index: number): number { + const bonus = this.jarBonuses.find(bonus => bonus.index == index); + + if (bonus) { + return bonus.getBonus(); + } + + return 0; + } +} \ No newline at end of file From d6dba744dce0110c8f07abe3cb2f8b67dfd53762 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:39:05 +0100 Subject: [PATCH 18/31] Imported Jar in Hole --- data/domain/world-5/hole/hole.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/data/domain/world-5/hole/hole.tsx b/data/domain/world-5/hole/hole.tsx index 0321ede7..23551537 100644 --- a/data/domain/world-5/hole/hole.tsx +++ b/data/domain/world-5/hole/hole.tsx @@ -31,6 +31,7 @@ import { HarpStringModel } from "../../model/harpStringModel"; import { initHarpStringsRepo } from "../../data/HarpStringsRepo"; import { Gambit, GambitBonus, GambitLevel, GambitLevels } from "./gambit"; import { Tesseract } from "../../tesseract"; +import { Jar } from "./jar"; export class Villager { level: number = 0; @@ -706,6 +707,7 @@ export class Hole extends Domain { harp: Harp = new Harp(); lamp: Lamp = new Lamp(); dawgDen: DawgDen = new DawgDen(); + jar: Jar = new Jar(); gambit: Gambit = new Gambit(); ownedOpals: number = 0; // TODO: @@ -885,6 +887,12 @@ export class Hole extends Domain { hole.dawgDen.bestScore = holeData[11][8] || 0; this.ownedOpals = (holeData[7] as number[]).reduce((sum, value) => sum + value, 0); + + // TODO get data for gambit + + // TODO get data for jar + /*if ("JarTypesOwned" == d) + return Math.round(c.asNumber(a.engine.getGameAttribute("Holes")[11][37]));*/ } } @@ -910,11 +918,18 @@ export const updateHole = (data: Map) => { measurement.deathnotePts = deathnote.getTotalRank(); }); + // Update jar bonuses from legendary talents + // TODO add legens talents bonuses to jar before gambit part + const legendTalentBonus = 1//(1 + m._customBlock_Thingies("LegendPTS_bonus", 29, 0) / 100) + hole.jar.jarBonuses.forEach(bonus => { + bonus.legendTalentBonus = legendTalentBonus; + }); + // Update the gambit multiplier let gambitMultipliers = (hole.measurements.find(measurement => measurement.index == 13)?.getBonus() ?? 0) + hole.getStudyBolaiaBonuses(13); gambitMultipliers += tesseract.getUpgradeBonus(47) + (hole.monuments.monuments["Wisdom"].bonuses.find(bonus => bonus.index == 7)?.getBonus() ?? 0); gambitMultipliers += hole.schematics.find(schem => schem.index == 78)?.getBonus(10) ?? 0; - // TODO add this : m._customBlock_Holes("JarCollectibleBonus", 23, 0) + (m._customBlock_Holes("JarCollectibleBonus", 30, 0) + gambitMultipliers += hole.jar.getBonus(23) + hole.jar.getBonus(30); hole.gambit.gambitPointsMulti = 1 + gambitMultipliers / 100; hole.gambit.updateUnlockedBonuses(); } From 8ad3d8bf1be7e7fa7b816a3e049eb6da1bf0ec19 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:58:24 +0100 Subject: [PATCH 19/31] Renamed gambit level to challenge In-game says challenge --- data/domain/world-5/hole/gambit.tsx | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/data/domain/world-5/hole/gambit.tsx b/data/domain/world-5/hole/gambit.tsx index 673da3b6..90129b88 100644 --- a/data/domain/world-5/hole/gambit.tsx +++ b/data/domain/world-5/hole/gambit.tsx @@ -2,7 +2,7 @@ import { lavaLog, lavaLog2 } from "../../../utility"; import { initGambitBonusRepo } from "../../data/GambitBonusRepo"; import { GambitBonusModel } from "../../model/gambitBonusModel"; -export enum GambitLevelIndex { +export enum GambitChallengeIndex { King = 0, Horse = 1, Bishop = 2, @@ -11,34 +11,34 @@ export enum GambitLevelIndex { Pawn = 5 } -const gambitLevelMetadata = { - [GambitLevelIndex.King]: { +const gambitChallengeMetadata = { + [GambitChallengeIndex.King]: { name: "King's Gambit", description: "Survive as long as you can...", }, - [GambitLevelIndex.Horse]: { + [GambitChallengeIndex.Horse]: { name: "Horsey's Gambit", description: "You have but one HP...", }, - [GambitLevelIndex.Bishop]: { + [GambitChallengeIndex.Bishop]: { name: "Bishop's Gambit", description: "Damage done to me is done to thee...", }, - [GambitLevelIndex.Queen]: { + [GambitChallengeIndex.Queen]: { name: "Queen's Gambit", description: "Jewels everywhere...", }, - [GambitLevelIndex.Tower]: { + [GambitChallengeIndex.Tower]: { name: "Castle's Gambit", description: "One lane, one outcome...", }, - [GambitLevelIndex.Pawn]: { + [GambitChallengeIndex.Pawn]: { name: "Noobs' Gambit", description: "I like the grey ones!!!", }, } -export class GambitLevel { +export class GambitChallenge { maxTime: number = 0; // in seconds, will have decimals constructor(public index: number, public name: string, public description: string) { } @@ -57,7 +57,7 @@ export class GambitLevel { let points = 100 * (this.maxTime + (3 * Math.floor(this.maxTime / 10) + 10 * Math.floor(this.maxTime / 60))); if (this.index != 0) { - // Levels which are not king get double points + // Challenges which are not king get double points return points * 2; } @@ -65,10 +65,10 @@ export class GambitLevel { } } -export class GambitLevels { - static getLevels(): GambitLevel[] { - return Object.entries(gambitLevelMetadata).map(([index, metadata]) => { - return new GambitLevel(Number(index), metadata.name, metadata.description); +export class GambitChallenges { + static getChallenges(): GambitChallenge[] { + return Object.entries(gambitChallengeMetadata).map(([index, metadata]) => { + return new GambitChallenge(Number(index), metadata.name, metadata.description); }); } } @@ -103,7 +103,7 @@ export class GambitBonus { export class Gambit { bonuses: GambitBonus[] = []; - levels: GambitLevel[] = GambitLevels.getLevels(); + challenges: GambitChallenge[] = GambitChallenges.getChallenges(); gambitPointsMulti: number = 1; constructor() { @@ -137,11 +137,11 @@ export class Gambit { } getGambitTotalTime(): number { - return this.levels.reduce((sum, level) => sum + level.maxTime, 0); + return this.challenges.reduce((sum, challenge) => sum + challenge.maxTime, 0); } getGambitTotalScore(): number { - return this.levels.reduce((sum, level) => level.getScoreValue(), 0) * this.gambitPointsMulti; + return this.challenges.reduce((sum, challenge) => challenge.getScoreValue(), 0) * this.gambitPointsMulti; } updateUnlockedBonuses() { From f139f8bb766c9b7f33ccbf79bf1ea244358d2a86 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:58:40 +0100 Subject: [PATCH 20/31] Removed unused import --- data/domain/world-5/hole/hole.tsx | 2 +- data/domain/world-5/hole/jar.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/domain/world-5/hole/hole.tsx b/data/domain/world-5/hole/hole.tsx index 23551537..8e8bf15a 100644 --- a/data/domain/world-5/hole/hole.tsx +++ b/data/domain/world-5/hole/hole.tsx @@ -29,7 +29,7 @@ import { initBellBonusRepo } from "../../data/BellBonusRepo"; import { initHarpNotesRepo } from "../../data/HarpNotesRepo"; import { HarpStringModel } from "../../model/harpStringModel"; import { initHarpStringsRepo } from "../../data/HarpStringsRepo"; -import { Gambit, GambitBonus, GambitLevel, GambitLevels } from "./gambit"; +import { Gambit } from "./gambit"; import { Tesseract } from "../../tesseract"; import { Jar } from "./jar"; diff --git a/data/domain/world-5/hole/jar.tsx b/data/domain/world-5/hole/jar.tsx index c10cbcde..5586d0fc 100644 --- a/data/domain/world-5/hole/jar.tsx +++ b/data/domain/world-5/hole/jar.tsx @@ -1,5 +1,5 @@ -import { HoleJarBonusBase, initHoleJarBonusRepo } from "../../data/HoleJarBonusRepo"; -import { HoleJarBase, initHoleJarRepo } from "../../data/HoleJarRepo"; +import { initHoleJarBonusRepo } from "../../data/HoleJarBonusRepo"; +import { initHoleJarRepo } from "../../data/HoleJarRepo"; import { HoleJarBonusModel } from "../../model/holeJarBonusModel"; import { HoleJarModel } from "../../model/holeJarModel"; From cb253537acc55de8c4709af473c374477d379243 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Sun, 4 Jan 2026 18:59:01 +0100 Subject: [PATCH 21/31] Update Hole parsing Now include Gambit and Jar --- data/domain/world-5/hole/hole.tsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/data/domain/world-5/hole/hole.tsx b/data/domain/world-5/hole/hole.tsx index 8e8bf15a..719433a3 100644 --- a/data/domain/world-5/hole/hole.tsx +++ b/data/domain/world-5/hole/hole.tsx @@ -886,13 +886,24 @@ export class Hole extends Domain { hole.dawgDen.bestScore = holeData[11][8] || 0; - this.ownedOpals = (holeData[7] as number[]).reduce((sum, value) => sum + value, 0); + hole.ownedOpals = (holeData[7] as number[]).reduce((sum, value) => sum + value, 0); - // TODO get data for gambit + // Gambit + hole.gambit.challenges.forEach(challenge => { + challenge.maxTime = holeData[11][challenge.index + 65] || 0; + }); - // TODO get data for jar - /*if ("JarTypesOwned" == d) - return Math.round(c.asNumber(a.engine.getGameAttribute("Holes")[11][37]));*/ + // Jar + const ownedJars = holeData[11][37] || 0; + hole.jar.jarTypes.forEach(jar => { + jar.unlocked = ownedJars >= jar.index; + }); + const jarBonusesLevels = holeData[24] as number[]; + this.jar.jarBonuses.forEach(bonus => { + if (bonus.index < jarBonusesLevels.length) { + bonus.level = jarBonusesLevels[bonus.index]; + } + }); } } From cb0dd20091fc502cafd44f2b53e40fdb1c4a2b42 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Mon, 5 Jan 2026 12:46:21 +0100 Subject: [PATCH 22/31] Fixed some variables to please ESLint --- data/domain/tome.tsx | 6 +++--- data/domain/world-5/hole/gambit.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 9079a51d..54e5a2c9 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -318,9 +318,9 @@ export const updateTomeScores = (data: Map) => { // Calculate how many trophy and obols have been found const slab = data.get("slab") as Slab; - var trophyCount: number = 0; - var obolCount: number = 0; - var nametagCount: number = 0; + let trophyCount: number = 0; + let obolCount: number = 0; + let nametagCount: number = 0; slab.obtainableItems.forEach((item) => { if (item.obtained) { if (item.internalName.indexOf("Trophy") == 0) { diff --git a/data/domain/world-5/hole/gambit.tsx b/data/domain/world-5/hole/gambit.tsx index 90129b88..0b87d039 100644 --- a/data/domain/world-5/hole/gambit.tsx +++ b/data/domain/world-5/hole/gambit.tsx @@ -54,7 +54,7 @@ export class GambitChallenge { } getScoreValue(): number { - let points = 100 * (this.maxTime + (3 * Math.floor(this.maxTime / 10) + 10 * Math.floor(this.maxTime / 60))); + const points = 100 * (this.maxTime + (3 * Math.floor(this.maxTime / 10) + 10 * Math.floor(this.maxTime / 60))); if (this.index != 0) { // Challenges which are not king get double points From a74158623e9aad67899d1def962783bc4faa10d7 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Mon, 5 Jan 2026 12:54:38 +0100 Subject: [PATCH 23/31] Updated Gambit ESLint made me remember I forgot to complete this function (won't be used until we do some UI tho) --- data/domain/world-5/hole/gambit.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/data/domain/world-5/hole/gambit.tsx b/data/domain/world-5/hole/gambit.tsx index 0b87d039..3cad1858 100644 --- a/data/domain/world-5/hole/gambit.tsx +++ b/data/domain/world-5/hole/gambit.tsx @@ -127,10 +127,13 @@ export class Gambit { const bonus = this.bonuses.find(bonus => bonus.index == index); if (bonus) { - switch(bonus.index) { - - } - const value = bonus.getBonus(this.getGambitTotalTime()); + // Bonuses increasing with Gambit Score + if (bonus.data.x1 == 1) { + const value = bonus.getBonus(this.getGambitTotalTime()); + return bonus.data.name.replace('{', value.toString()).replace('}', (1 + value / 100).toString()+"x"); + } else { + return bonus.data.name.replace('{', bonus.data.x0.toString()).replace('}', bonus.data.x0.toString()+"x"); + } } return ""; From d5604a3fa1eec7f905ce1afd9d68c410da8e5bfa Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Mon, 5 Jan 2026 13:02:15 +0100 Subject: [PATCH 24/31] Minor changes to please ESLint --- app/world-1/stamps/content.tsx | 4 ++-- app/world-3/construction/content.tsx | 12 +++++++----- app/world-4/lab/content.tsx | 2 +- components/account/grimoireDisplay.tsx | 2 +- components/account/tesseractDisplay.tsx | 2 +- components/base/Stat.tsx | 2 +- components/world-4/breeding/pets.tsx | 2 +- data/domain/base/lavaRand.tsx | 4 ++-- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/app/world-1/stamps/content.tsx b/app/world-1/stamps/content.tsx index cabfaf95..ae83c722 100644 --- a/app/world-1/stamps/content.tsx +++ b/app/world-1/stamps/content.tsx @@ -105,7 +105,7 @@ function StampDisplay({ stamp, index, highlight, storageAmount = 0 }: { stamp: S { - Object.entries(stamp.maxCarryInfo).map(([maxLevel, costInfo], index) => ( + Object.entries(stamp.maxCarryInfo).map(([maxLevel, costInfo], _) => ( {maxLevel} @@ -136,7 +136,7 @@ function StampDisplay({ stamp, index, highlight, storageAmount = 0 }: { stamp: S { - Object.entries(stamp.maxCarryInfo).slice(0, -1).map(([maxLevel, costInfo], index) => ( + Object.entries(stamp.maxCarryInfo).slice(0, -1).map(([maxLevel, costInfo], _) => ( {maxLevel} {costInfo.costToLevel > 0 && {nFormatter(costInfo.costToLevel)}{costInfo.currentDiscount ? " *" : ""}} diff --git a/app/world-3/construction/content.tsx b/app/world-3/construction/content.tsx index 60c38abe..f9430daa 100644 --- a/app/world-3/construction/content.tsx +++ b/app/world-3/construction/content.tsx @@ -72,9 +72,11 @@ function RefineryDisplay() { const toReturn: number[] = []; Object.entries(refineryData.salts).forEach(([salt, info], index) => { const currentCooldowns: [Player, number][] = []; - squireInfo && squireInfo.forEach(squire => { - currentCooldowns.push([squire, squire.getCurrentCooldown(130)]); - }); + if (squireInfo) { + squireInfo.forEach(squire => { + currentCooldowns.push([squire, squire.getCurrentCooldown(130)]); + }); + } let totalWait = 0; const refineryCycle = Math.floor(index / 3) == 0 ? refineryData.cycleInfo["Combustion"] : refineryData.cycleInfo["Synthesis"]; let timeToNextRank = info.getTimeToNextRank(refineryCycle.cycleTime); @@ -142,7 +144,7 @@ function RefineryDisplay() { }) } {squireInfo && squireInfo.map((squire, index) => { - const [refineryTalent, cooldown] = [...squire.cooldown.entries()].filter(([talent, cooldown]) => talent.skillIndex == 130)?.pop() as [Talent, number]; + const [refineryTalent, cooldown] = [...squire.cooldown.entries()].filter(([talent, _]) => talent.skillIndex == 130)?.pop() as [Talent, number]; const realCD = cooldown - squire.afkFor; return ( @@ -412,7 +414,7 @@ function PrinterDisplay() { {masteroInfo && masteroInfo.map((mastero, index) => { - const [printerTalent, cooldown] = [...mastero.cooldown.entries()].filter(([talent, cooldown]) => talent.skillIndex == 32)?.pop() as [Talent, number]; + const [printerTalent, cooldown] = [...mastero.cooldown.entries()].filter(([talent, _]) => talent.skillIndex == 32)?.pop() as [Talent, number]; const realCD = cooldown - mastero.afkFor; return ( diff --git a/app/world-4/lab/content.tsx b/app/world-4/lab/content.tsx index b130cfcc..fbe446c4 100644 --- a/app/world-4/lab/content.tsx +++ b/app/world-4/lab/content.tsx @@ -131,7 +131,7 @@ function ChipDisplay() { { - Object.entries(lab.playerChips).map(([playerNumber, chips], index) => { + Object.entries(lab.playerChips).map(([playerNumber, _], index) => { const playerId = parseInt(playerNumber); if (playerId >= playersData.length) { return null; diff --git a/components/account/grimoireDisplay.tsx b/components/account/grimoireDisplay.tsx index ea4e07f9..8839ffcf 100644 --- a/components/account/grimoireDisplay.tsx +++ b/components/account/grimoireDisplay.tsx @@ -128,7 +128,7 @@ function EfficiencySection() { "Unlock Path": { valueHeader: '', valueColor: 'accent-2', - formatValue: (value: number) => ``, + formatValue: (_: number) => ``, noResultsText: 'No efficient upgrades available' } }; diff --git a/components/account/tesseractDisplay.tsx b/components/account/tesseractDisplay.tsx index 786cb2f7..9aad4d84 100644 --- a/components/account/tesseractDisplay.tsx +++ b/components/account/tesseractDisplay.tsx @@ -110,7 +110,7 @@ export function TesseractDisplay() { "Unlock Path": { valueHeader: '', valueColor: 'accent-2', - formatValue: (value: number) => ``, + formatValue: (_: number) => ``, noResultsText: 'No efficient upgrades available' }, 'Arcane Damage': { valueHeader: 'Damage +', valueColor: 'accent-2', formatValue: (value: number) => `${nFormatter(value, "CommaNotation")}`, noResultsText: 'No efficient damage upgrades available' }, diff --git a/components/base/Stat.tsx b/components/base/Stat.tsx index 8e483bfd..b7a38924 100644 --- a/components/base/Stat.tsx +++ b/components/base/Stat.tsx @@ -10,7 +10,7 @@ export default function Stat({ stat }: { stat: StatDomain }) { heading={`${stat.name}${stat.max ? `(Max value: ${stat.max})` : ""}`} body={ - {stat.sources.map((source, index) => { + {stat.sources.map((source, _) => { if (typeof source.value === 'number') { return ( {source.name}: {nFormatter(source.value as number, "Smaller")} diff --git a/components/world-4/breeding/pets.tsx b/components/world-4/breeding/pets.tsx index 9a85296d..0c3f2ea7 100644 --- a/components/world-4/breeding/pets.tsx +++ b/components/world-4/breeding/pets.tsx @@ -122,7 +122,7 @@ function AllPetDisplay() { worldsToDisplay.map(world => { return breeding.basePets.filter(pet => pet.data.world == world).slice().sort((pet1, pet2) => pet1.data.unlockOrder > pet2.data.unlockOrder ? 1 : -1); }) - ), [theData, breeding]); + ), [theData, breeding, worldsToDisplay]); if (!breeding) { return ( diff --git a/data/domain/base/lavaRand.tsx b/data/domain/base/lavaRand.tsx index 76f07a75..41a5c1c3 100644 --- a/data/domain/base/lavaRand.tsx +++ b/data/domain/base/lavaRand.tsx @@ -26,8 +26,8 @@ export default class LavaRand { constructor(seed: number) { this.seed = seed; this.seed2 = this.hash(seed); - 0 == this.seed && (this.seed = 1); - 0 == this.seed2 && (this.seed2 = 1); + if (0 == this.seed) (this.seed = 1); + if (0 == this.seed2) (this.seed2 = 1); } random = (a: number) => { From c6ebedbe0e5d46517552b49e7db96c23a5f3d76a Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral <34089184+Zoma-Ancestral@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:00:25 +0100 Subject: [PATCH 25/31] Update data/domain/tome.tsx Co-authored-by: Sludging <30924533+Sludging@users.noreply.github.com> --- data/domain/tome.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 54e5a2c9..11f0aa0d 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -905,7 +905,7 @@ export const updateTomeScores = (data: Map) => { line.updateAllPlayersCurrentValue(hole.monuments.monuments["Wisdom"].highestRound); break; case 90: - // Best Deathbringer Max Damade in Wraith mode + // Best Deathbringer Max Damage in Wraith mode line.updateAllPlayersCurrentValue((optionListAccount[356] ?? 0)); break; case 91: From 825581849d639d8d10f6964f1de8b21d12c4e468 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral <34089184+Zoma-Ancestral@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:00:39 +0100 Subject: [PATCH 26/31] Update data/domain/tome.tsx Co-authored-by: Sludging <30924533+Sludging@users.noreply.github.com> --- data/domain/tome.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 11f0aa0d..77814b44 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -913,7 +913,7 @@ export const updateTomeScores = (data: Map) => { line.updateAllPlayersCurrentValue(hole.dawgDen.bestScore); break; case 92: - // Total layers ressources destroyed in The Hole + // Total layers resources destroyed in The Hole line.updateAllPlayersCurrentValue(totalDestroyedRessourcesLayers); break; case 93: From d35ad6e77986a9d87c7ae80ff5ad91e4c91f0d93 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral <34089184+Zoma-Ancestral@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:01:15 +0100 Subject: [PATCH 27/31] Update data/domain/tome.tsx Co-authored-by: Sludging <30924533+Sludging@users.noreply.github.com> --- data/domain/tome.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 77814b44..42b2dad9 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -956,6 +956,7 @@ export const updateTomeScores = (data: Map) => { break; case 102: // Biggest Haul in a single Delve + // TODO: add this once implemented line.updateAllPlayersCurrentValue(0); break; case 103: From b509a1f0dbe907aff2108b5fd69cae5f47a6949b Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Wed, 7 Jan 2026 16:22:46 +0100 Subject: [PATCH 28/31] Updated ToTime func Now have a preciseTime boolean parameter Let you hide hours and minutes if there's none, and let you get the first decimal of the seconds if there's some --- data/utility.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/data/utility.tsx b/data/utility.tsx index dda1adc7..83f59683 100644 --- a/data/utility.tsx +++ b/data/utility.tsx @@ -312,7 +312,7 @@ export const dateToIntString = (input: Date) => { return Intl.DateTimeFormat(resolvedFormat.locale, options).format(input); } -export const toTime = (fromSeconds: number) => { +export const toTime = (fromSeconds: number, preciseTime: boolean = false) => { let days = 0; let hour = Math.floor(fromSeconds / 3600); if (hour > 24) { @@ -320,8 +320,13 @@ export const toTime = (fromSeconds: number) => { hour -= days * 24; } const minutes = Math.floor(fromSeconds % 3600 / 60); - const seconds = Math.floor(fromSeconds % 3600 % 60); - return `${days > 0 ? `${days}days` : ''} ${hour}hr ${days == 0 ? `${minutes}min ${seconds}sec` : ""}`; + let seconds = fromSeconds % 3600 % 60; + if (preciseTime) { + seconds = Math.trunc(seconds * 10) / 10; + } else { + seconds = Math.floor(seconds); + } + return `${days > 0 ? `${days}days` : ''} ${(preciseTime && hour > 0) || !preciseTime ? `${hour}hour` : ``} ${days == 0 || preciseTime ? `${(preciseTime && minutes > 0) || !preciseTime ? `${minutes}min` : ``} ${seconds}sec` : ""}`; } export function notUndefined(x: T | undefined): x is T { From 1c2f7972faf90175faec1627b8415bbc56084d09 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Wed, 7 Jan 2026 16:23:13 +0100 Subject: [PATCH 29/31] Update gambit to use toTime utility func --- data/domain/world-5/hole/gambit.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/data/domain/world-5/hole/gambit.tsx b/data/domain/world-5/hole/gambit.tsx index 3cad1858..f2b28c9b 100644 --- a/data/domain/world-5/hole/gambit.tsx +++ b/data/domain/world-5/hole/gambit.tsx @@ -1,4 +1,4 @@ -import { lavaLog, lavaLog2 } from "../../../utility"; +import { lavaLog, lavaLog2, toTime } from "../../../utility"; import { initGambitBonusRepo } from "../../data/GambitBonusRepo"; import { GambitBonusModel } from "../../model/gambitBonusModel"; @@ -44,13 +44,7 @@ export class GambitChallenge { constructor(public index: number, public name: string, public description: string) { } getDisplayTime(): string { - let timeLeft = this.maxTime; - const hours = Math.floor(timeLeft / 3600); - timeLeft -= (hours * 3600); - const minutes = Math.floor(timeLeft / 60); - timeLeft -= (minutes * 60); - - return (hours > 0 ? hours+"h " : "") + (minutes > 0 ? minutes+"min " : "") + (timeLeft > 0 ? (Math.trunc(timeLeft * 10) / 10)+"sec" : ""); + return toTime(this.maxTime, true); } getScoreValue(): number { From ab6a064164799e369c0379f758fcc11046873473 Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Wed, 7 Jan 2026 16:32:54 +0100 Subject: [PATCH 30/31] Updated GambitBonus init Now use a static fromBase for consistency --- data/domain/world-5/hole/gambit.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data/domain/world-5/hole/gambit.tsx b/data/domain/world-5/hole/gambit.tsx index f2b28c9b..3f6cbd40 100644 --- a/data/domain/world-5/hole/gambit.tsx +++ b/data/domain/world-5/hole/gambit.tsx @@ -1,5 +1,5 @@ import { lavaLog, lavaLog2, toTime } from "../../../utility"; -import { initGambitBonusRepo } from "../../data/GambitBonusRepo"; +import { initGambitBonusRepo, GambitBonusBase } from "../../data/GambitBonusRepo"; import { GambitBonusModel } from "../../model/gambitBonusModel"; export enum GambitChallengeIndex { @@ -72,6 +72,10 @@ export class GambitBonus { constructor(public index: number, public data: GambitBonusModel) {} + static fromBase(data: GambitBonusBase[]) { + return data.map(d => new GambitBonus(d.index, d.data)); + } + getBonus(gambitTotalScore: number): number { if(!this.unlocked) { @@ -101,10 +105,7 @@ export class Gambit { gambitPointsMulti: number = 1; constructor() { - const gambitBonusesData = initGambitBonusRepo(); - gambitBonusesData.forEach(bonus => { - this.bonuses.push(new GambitBonus(bonus.index, bonus.data)); - }); + this.bonuses = GambitBonus.fromBase(initGambitBonusRepo()); } getBonus(index: number): number { From 5d4cff23914348f0826510383249c27c5ad7342c Mon Sep 17 00:00:00 2001 From: Zoma-Ancestral Date: Wed, 7 Jan 2026 16:44:00 +0100 Subject: [PATCH 31/31] Updated Most Bits Owned display format --- data/domain/tome.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/data/domain/tome.tsx b/data/domain/tome.tsx index 42b2dad9..6cfc3ed2 100644 --- a/data/domain/tome.tsx +++ b/data/domain/tome.tsx @@ -137,7 +137,6 @@ export class TomeLine { return nFormatter(this.currentValues[playerIndex]); // Not so big values but with lots of decimals and wanna keep a bit of it case 18: - case 66: return nFormatter(Math.round(100 * this.currentValues[playerIndex]) / 100, "CommaNotation"); // Not so big values with lots of decimals and wanna round it to match in-game display case 13: @@ -148,6 +147,8 @@ export class TomeLine { case 53: case 91: return nFormatter(Math.round(this.currentValues[playerIndex]), "CommaNotation"); + case 66: + return nFormatter(this.currentValues[playerIndex], "Bits"); default: return nFormatter(this.currentValues[playerIndex], "CommaNotation"); } @@ -399,6 +400,7 @@ export const updateTomeScores = (data: Map) => { const totalBestWorshipWaves = worshipData.totemInfo.reduce((sum, totem) => sum + totem.maxWave, 0); // Sum of all deathnote kills digit + // TODO : check if accurate once Deathnote is updated with w7 mobs let totalDeathnoteDigits = 0; const killsMap = deathnote.getKillsMap(); [...killsMap.entries()].forEach(([_, deathnoteMobs]) => { @@ -602,6 +604,7 @@ export const updateTomeScores = (data: Map) => { break; case 15: // Sum of star talent points owned + // TODO : fix this, difference between this and IE for (let i = 0; i < players.length; i++) { line.updatePlayerCurrentValue((players[i].talentPoints.find(talentPoints => talentPoints.tab == TalentTab.SpecialTab)?.totalOwned ?? 0), i); }