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

347 lines (346 loc) 11.9 kB
import { LevelRequirement, QuestRequirement } from "../Requirement"; import { Skill } from "../account/Skill"; import { GuildHunterName, HuntingMethod, RumourTier, createHunterLevelRequirement } from "./HunterRumour"; // ========== Rumour Definitions ========== // Each rumour represents a hunter creature that can be assigned. // Reference: https://oldschool.runescape.wiki/w/Hunters%27_Rumours#List_of_rumours const hunterLevel = (level) => createHunterLevelRequirement(level); const tropicalWagtail = { creature: "Tropical wagtail", hunterRequirement: hunterLevel(19), method: HuntingMethod.BirdSnare, locations: ["Feldip Hunter area", "The Great Conch", "Tlati Rainforest"], requirements: [], }; const wildKebbit = { creature: "Wild kebbit", hunterRequirement: hunterLevel(23), method: HuntingMethod.Deadfall, locations: ["Piscatoris Hunter area", "Auburnvale"], requirements: [], }; const sapphireGlacialis = { creature: "Sapphire glacialis", hunterRequirement: hunterLevel(25), method: HuntingMethod.ButterflyNet, locations: ["Rellekka Hunter area", "Farming Guild", "Mons Gratia"], requirements: [], }; const swampLizard = { creature: "Swamp lizard", hunterRequirement: hunterLevel(29), method: HuntingMethod.NetTrap, locations: ["Canifis Hunter area", "North-west of Slepe"], requirements: [new QuestRequirement("Priest in Peril")], }; const spinedLarupia = { creature: "Spined larupia", hunterRequirement: hunterLevel(31), method: HuntingMethod.SpikedPit, locations: ["Feldip Hunter area"], requirements: [], }; const barbTailedKebbit = { creature: "Barb-tailed kebbit", hunterRequirement: hunterLevel(33), method: HuntingMethod.Deadfall, locations: ["Feldip Hunter area"], requirements: [], }; const snowyKnight = { creature: "Snowy knight", hunterRequirement: hunterLevel(35), method: HuntingMethod.ButterflyNet, locations: ["Rellekka Hunter area", "Weiss", "Farming Guild", "Mons Gratia"], requirements: [], }; const pricklyKebbit = { creature: "Prickly kebbit", hunterRequirement: hunterLevel(37), method: HuntingMethod.Deadfall, locations: ["Piscatoris Hunter area"], requirements: [], }; const embertailedJerboa = { creature: "Embertailed jerboa", hunterRequirement: hunterLevel(39), method: HuntingMethod.BoxTrap, locations: ["West of Hunter Guild", "North-west of the Locus Oasis"], requirements: [new QuestRequirement("Eagles' Peak")], }; const hornedGraahk = { creature: "Horned graahk", hunterRequirement: hunterLevel(41), method: HuntingMethod.SpikedPit, locations: ["Karamja Hunter area"], requirements: [], }; const spottedKebbit = { creature: "Spotted kebbit", hunterRequirement: hunterLevel(43), method: HuntingMethod.Falconry, locations: ["Piscatoris falconry area"], requirements: [], }; const blackWarlock = { creature: "Black warlock", hunterRequirement: hunterLevel(45), method: HuntingMethod.ButterflyNet, locations: ["Feldip Hunter area", "Farming Guild", "Crypt of Tonali hunter area", "Tlati Rainforest", "Shimmering Atoll"], requirements: [], }; const orangeSalamander = { creature: "Orange salamander", hunterRequirement: hunterLevel(47), method: HuntingMethod.NetTrap, locations: ["The Great Conch", "Uzer Hunter area", "Necropolis Hunter area"], requirements: [], }; const razorBackedKebbit = { creature: "Razor-backed kebbit", hunterRequirement: hunterLevel(49), method: HuntingMethod.TrackingKebbit, locations: ["Piscatoris Hunter area"], requirements: [], }; const sabreToothKebbit = { creature: "Sabre-toothed kebbit", hunterRequirement: hunterLevel(51), method: HuntingMethod.Deadfall, locations: ["Rellekka Hunter area"], requirements: [], }; const greyChinchompa = { creature: "Grey chinchompa", hunterRequirement: hunterLevel(53), method: HuntingMethod.BoxTrap, locations: ["Piscatoris Hunter area", "Kourend Woodland", "Isle of Souls"], requirements: [new QuestRequirement("Eagles' Peak")], }; const sabreToothKyatt = { creature: "Sabre-toothed kyatt", hunterRequirement: hunterLevel(55), method: HuntingMethod.SpikedPit, locations: ["Rellekka Hunter area"], requirements: [], }; const darkKebbit = { creature: "Dark kebbit", hunterRequirement: hunterLevel(57), method: HuntingMethod.Falconry, locations: ["Piscatoris falconry area"], requirements: [], }; const pyreFox = { creature: "Pyre fox", hunterRequirement: hunterLevel(57), method: HuntingMethod.Deadfall, locations: ["Avium Savannah"], requirements: [], }; const redSalamander = { creature: "Red salamander", hunterRequirement: hunterLevel(59), method: HuntingMethod.NetTrap, locations: ["Ourania Hunter area", "Charred Island"], requirements: [], }; const redChinchompa = { creature: "Red chinchompa", hunterRequirement: hunterLevel(63), method: HuntingMethod.BoxTrap, locations: ["Chinchompa Island", "Feldip Hunter area", "The Great Conch", "Gwenith Hunter area", "Red chinchompa hunting ground", "Tlati Rainforest"], requirements: [new QuestRequirement("Eagles' Peak")], }; const dashingKebbit = { creature: "Dashing kebbit", hunterRequirement: hunterLevel(69), method: HuntingMethod.Falconry, locations: ["Piscatoris falconry area"], requirements: [], }; const sunlightAntelope = { creature: "Sunlight antelope", hunterRequirement: hunterLevel(72), method: HuntingMethod.SpikedPit, locations: ["Avium Savannah"], requirements: [], }; const sunlightMoth = { creature: "Sunlight moth", hunterRequirement: hunterLevel(75), method: HuntingMethod.ButterflyNet, locations: ["Avium Savannah", "Neypotzli"], requirements: [], }; const tecuSalamander = { creature: "Tecu salamander", hunterRequirement: hunterLevel(79), method: HuntingMethod.NetTrap, locations: ["Ralos' Rise"], requirements: [], }; const herbiboar = { creature: "Herbiboar", hunterRequirement: hunterLevel(80), method: HuntingMethod.TrackingHerbiboar, locations: ["Mushroom Forest on Fossil Island"], requirements: [new QuestRequirement("Bone Voyage"), new LevelRequirement(Skill.Herblore, 31, false)], }; const moonlightMoth = { creature: "Moonlight moth", hunterRequirement: hunterLevel(85), method: HuntingMethod.ButterflyNet, locations: ["The Burrow", "Neypotzli", "Ruins of Tapoyauik", "Tonali Cavern"], requirements: [], }; const moonlightAntelope = { creature: "Moonlight antelope", hunterRequirement: hunterLevel(91), method: HuntingMethod.SpikedPit, locations: ["The Burrow"], requirements: [], }; // ========== All Rumours ========== /** All hunter rumours sorted by Hunter level */ export const ALL_RUMOURS = [ tropicalWagtail, wildKebbit, sapphireGlacialis, swampLizard, spinedLarupia, barbTailedKebbit, snowyKnight, pricklyKebbit, embertailedJerboa, hornedGraahk, spottedKebbit, blackWarlock, orangeSalamander, razorBackedKebbit, sabreToothKebbit, greyChinchompa, sabreToothKyatt, darkKebbit, pyreFox, redSalamander, redChinchompa, dashingKebbit, sunlightAntelope, sunlightMoth, tecuSalamander, herbiboar, moonlightMoth, moonlightAntelope, ]; // ========== Guild Hunter Definitions ========== /** * Huntmaster Gilman (Novice) - Can assign all rumours. */ export const Gilman = { name: GuildHunterName.Gilman, tier: RumourTier.Novice, levelRequired: hunterLevel(46), rumours: [...ALL_RUMOURS], }; /** * Guild Hunter Cervus (Adept) - Has a distinct adept rumour list. */ export const Cervus = { name: GuildHunterName.Cervus, tier: RumourTier.Adept, levelRequired: hunterLevel(57), rumours: [swampLizard, hornedGraahk, spottedKebbit, blackWarlock, orangeSalamander, razorBackedKebbit, sabreToothKebbit, greyChinchompa, darkKebbit, pyreFox, redChinchompa, sunlightMoth], }; /** * Guild Hunter Ornus (Adept) - Has a distinct adept rumour list. */ export const Ornus = { name: GuildHunterName.Ornus, tier: RumourTier.Adept, levelRequired: hunterLevel(57), rumours: [spinedLarupia, snowyKnight, embertailedJerboa, spottedKebbit, orangeSalamander, sabreToothKebbit, sabreToothKyatt, pyreFox, redSalamander, redChinchompa], }; /** * Guild Hunter Aco (Expert) - Has a distinct expert rumour list. */ export const Aco = { name: GuildHunterName.Aco, tier: RumourTier.Expert, levelRequired: hunterLevel(72), rumours: [orangeSalamander, sabreToothKebbit, greyChinchompa, sabreToothKyatt, darkKebbit, redSalamander, redChinchompa, dashingKebbit, sunlightAntelope, tecuSalamander, moonlightMoth], }; /** * Guild Hunter Teco (Expert) - Has a distinct expert rumour list. */ export const Teco = { name: GuildHunterName.Teco, tier: RumourTier.Expert, levelRequired: hunterLevel(72), rumours: [sabreToothKebbit, greyChinchompa, sabreToothKyatt, darkKebbit, redSalamander, redChinchompa, dashingKebbit, sunlightAntelope, sunlightMoth, herbiboar], }; /** * Guild Hunter Wolf (Master) - Requires completion of At First Light. */ export const Wolf = { name: GuildHunterName.Wolf, tier: RumourTier.Master, levelRequired: hunterLevel(91), questRequired: "At First Light", rumours: [redSalamander, redChinchompa, dashingKebbit, sunlightAntelope, tecuSalamander, herbiboar, moonlightMoth, moonlightAntelope], }; /** All guild hunters */ export const ALL_GUILD_HUNTERS = [Gilman, Cervus, Ornus, Aco, Teco, Wolf]; // ========== Utility Functions ========== /** * Get a guild hunter by name. * @param name - The guild hunter's name (enum or string) * @returns The guild hunter, or undefined if not found */ export function getGuildHunterByName(name) { return ALL_GUILD_HUNTERS.find((h) => h.name === name); } /** * Get all guild hunters for a specific tier. * @param tier - The rumour tier * @returns Array of guild hunters for that tier */ export function getGuildHuntersByTier(tier) { return ALL_GUILD_HUNTERS.filter((h) => h.tier === tier); } /** * Get the available rumours for a guild hunter, excluding any creatures * already assigned as active rumours from other hunters. * * This implements the "blocking" mechanic: players cannot receive the same * task from multiple guild hunters at once. By obtaining a task from one * hunter first, it is blocked from appearing with another. * * Example: If Gilman assigns "Swamp lizard", Cervus cannot assign "Swamp lizard" * until the Gilman assignment is completed or reset. * * @param hunter - The guild hunter to get available rumours for * @param activeRumours - Rumours currently assigned from other guild hunters * @returns Rumours the hunter can assign, excluding blocked ones */ export function getAvailableRumours(hunter, activeRumours = []) { const blockedCreatures = new Set(activeRumours.map((r) => r.creature)); return hunter.rumours.filter((r) => !blockedCreatures.has(r.creature)); } /** * Find a rumour by creature name. * @param creature - The creature name to search for (case-insensitive) * @returns The matching rumour, or undefined if not found */ export function getRumourByCreature(creature) { const lower = creature.toLowerCase(); return ALL_RUMOURS.find((r) => r.creature.toLowerCase() === lower); } /** * Get all guild hunters that can assign a specific rumour. * @param rumour - The rumour to check * @returns Array of guild hunters who include this rumour in their list */ export function getHuntersForRumour(rumour) { return ALL_GUILD_HUNTERS.filter((h) => h.rumours.some((r) => r.creature === rumour.creature)); }