UNPKG

osrs-tools

Version:

A comprehensive TypeScript library for Old School RuneScape (OSRS) data and utilities, including quest data, skill requirements, and game item information

184 lines (183 loc) 6.9 kB
import { LevelRequirement } from "../Requirement"; import { Skill } from "../account/Skill"; /** * Hunting methods used for Hunters' Rumours. * Each method has its own drop rate for rare creature parts. * Reference: https://oldschool.runescape.wiki/w/Hunters%27_Rumours */ export var HuntingMethod; (function (HuntingMethod) { HuntingMethod["BirdSnare"] = "Bird snare"; HuntingMethod["BoxTrap"] = "Box trap"; HuntingMethod["ButterflyNet"] = "Butterfly net"; HuntingMethod["Deadfall"] = "Deadfall"; HuntingMethod["Falconry"] = "Falconry"; HuntingMethod["NetTrap"] = "Net trap"; HuntingMethod["SpikedPit"] = "Spiked pit"; HuntingMethod["TrackingKebbit"] = "Tracking (kebbit)"; HuntingMethod["TrackingHerbiboar"] = "Tracking (herbiboar)"; })(HuntingMethod || (HuntingMethod = {})); /** * Tier of a Hunter's Rumour. * Each tier has its own Hunter level requirement and reward quality. */ export var RumourTier; (function (RumourTier) { RumourTier["Novice"] = "Novice"; RumourTier["Adept"] = "Adept"; RumourTier["Expert"] = "Expert"; RumourTier["Master"] = "Master"; })(RumourTier || (RumourTier = {})); /** * Hunters' loot sack variants by rumour tier. */ export var HunterLootSackType; (function (HunterLootSackType) { HunterLootSackType["Basic"] = "Hunters' loot sack (basic)"; HunterLootSackType["Adept"] = "Hunters' loot sack (adept)"; HunterLootSackType["Expert"] = "Hunters' loot sack (expert)"; HunterLootSackType["Master"] = "Hunters' loot sack (master)"; })(HunterLootSackType || (HunterLootSackType = {})); /** * Guild hunters who assign Hunters' Rumours. * Each hunter has a distinct list of rumours they can assign. */ export var GuildHunterName; (function (GuildHunterName) { GuildHunterName["Gilman"] = "Huntmaster Gilman"; GuildHunterName["Cervus"] = "Guild Hunter Cervus"; GuildHunterName["Ornus"] = "Guild Hunter Ornus"; GuildHunterName["Aco"] = "Guild Hunter Aco"; GuildHunterName["Teco"] = "Guild Hunter Teco"; GuildHunterName["Wolf"] = "Guild Hunter Wolf"; })(GuildHunterName || (GuildHunterName = {})); /** * Drop rates for rare creature parts by hunting method. * Reference: https://oldschool.runescape.wiki/w/Hunters%27_Rumours#Drop_rates */ export const DROP_RATES = { [HuntingMethod.BirdSnare]: { baseRate: 20, pityThreshold: 40, pityThresholdWithOutfit: 38 }, [HuntingMethod.BoxTrap]: { baseRate: 50, pityThreshold: 100, pityThresholdWithOutfit: 94 }, [HuntingMethod.ButterflyNet]: { baseRate: 75, pityThreshold: 150, pityThresholdWithOutfit: 142 }, [HuntingMethod.Deadfall]: { baseRate: 15, pityThreshold: 30, pityThresholdWithOutfit: 28 }, [HuntingMethod.Falconry]: { baseRate: 10, pityThreshold: 20, pityThresholdWithOutfit: 18 }, [HuntingMethod.NetTrap]: { baseRate: 25, pityThreshold: 50, pityThresholdWithOutfit: 46 }, [HuntingMethod.SpikedPit]: { baseRate: 15, pityThreshold: 30, pityThresholdWithOutfit: 28 }, [HuntingMethod.TrackingKebbit]: { baseRate: 15, pityThreshold: 30, pityThresholdWithOutfit: 28 }, [HuntingMethod.TrackingHerbiboar]: { baseRate: 7, pityThreshold: 14, pityThresholdWithOutfit: 12 }, }; /** * Experience modifier per rumour tier, used in the reward formula: * Experience = (HunterLevel + 5) * Modifier */ export const TIER_XP_MODIFIER = { [RumourTier.Novice]: 50, [RumourTier.Adept]: 50, [RumourTier.Expert]: 55, [RumourTier.Master]: 60, }; /** * Loot sack metadata from the wiki's rewards table. */ export const HUNTER_LOOT_SACK_INFO = { [RumourTier.Novice]: { sackType: HunterLootSackType.Basic, estimatedGpValue: 7705.71, minimumHunterLevel: 46, minimumHunterXp: 2550, maximumHunterXp: 5200, }, [RumourTier.Adept]: { sackType: HunterLootSackType.Adept, estimatedGpValue: 21802.42, minimumHunterLevel: 57, minimumHunterXp: 3100, maximumHunterXp: 5200, }, [RumourTier.Expert]: { sackType: HunterLootSackType.Expert, estimatedGpValue: 28609.94, minimumHunterLevel: 72, minimumHunterXp: 4235, maximumHunterXp: 5720, }, [RumourTier.Master]: { sackType: HunterLootSackType.Master, estimatedGpValue: 34604.61, minimumHunterLevel: 91, minimumHunterXp: 5760, maximumHunterXp: 6240, }, }; /** * Rumour completion milestone unlocks. */ export const RUMOUR_MILESTONE_UNLOCKS = [ { rumoursCompleted: 10, unlock: "A basic quetzal whistle blueprint from Soar Leader Pitri, to craft a basic quetzal whistle.", }, { rumoursCompleted: 25, unlock: "The ability to cook raw graahk, raw kyatt, and raw pyre foxes.", }, { rumoursCompleted: 50, unlock: "The ability to cook raw dashing kebbit, raw sunlight antelope, and raw moonlight antelope.", }, { rumoursCompleted: 50, unlock: "A tattered request note from Guildmaster Apatura.", }, { rumoursCompleted: 100, unlock: "A torn enhanced quetzal whistle blueprint from any hunters' loot sack, to craft an enhanced quetzal whistle.", }, { rumoursCompleted: 100, unlock: "A guild history excerpt from Guildmaster Apatura.", }, { rumoursCompleted: 150, unlock: "A special chest key from Guildmaster Apatura.", }, { rumoursCompleted: 250, unlock: "A torn perfected quetzal whistle blueprint from any expert or master hunters' loot sack, to craft a perfected quetzal whistle.", }, ]; /** * Calculate the Hunter experience rewarded for completing a rumour. * @param hunterLevel - The player's current Hunter level * @param tier - The tier of the completed rumour * @returns The experience awarded */ export function calculateRumourExperience(hunterLevel, tier) { return (hunterLevel + 5) * TIER_XP_MODIFIER[tier]; } /** * Create an unboostable Hunter level requirement helper. */ export function createHunterLevelRequirement(level) { return new LevelRequirement(Skill.Hunter, level, false); } /** * Get milestones unlocked at a total rumour completion count. */ export function getMilestoneUnlocks(rumoursCompleted) { return RUMOUR_MILESTONE_UNLOCKS.filter((milestone) => milestone.rumoursCompleted === rumoursCompleted); } /** * Open a hunters' loot sack for a completed rumour. * Returns deterministic reward metadata and XP calculation from official formula. */ export function openHuntersLootSack(tier, hunterLevel, rumoursCompleted = 0) { const info = HUNTER_LOOT_SACK_INFO[tier]; return { sackType: info.sackType, tier, estimatedGpValue: info.estimatedGpValue, hunterExperience: calculateRumourExperience(hunterLevel, tier), milestonesUnlocked: getMilestoneUnlocks(rumoursCompleted), }; }