osrs-tools 2.10.0 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +42 -341
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/runescape/model/slayer/core/Mortifier.d.ts +48 -0
  5. package/dist/runescape/model/slayer/core/Mortifier.js +100 -0
  6. package/dist/runescape/model/slayer/core/MortimerSlayerMaster.d.ts +71 -0
  7. package/dist/runescape/model/slayer/core/MortimerSlayerMaster.js +98 -0
  8. package/dist/runescape/model/slayer/core/SlayerMaster.d.ts +6 -1
  9. package/dist/runescape/model/slayer/core/SlayerMaster.js +10 -1
  10. package/dist/runescape/model/slayer/core/index.d.ts +4 -0
  11. package/dist/runescape/model/slayer/core/index.js +2 -0
  12. package/dist/runescape/model/slayer/core/types.d.ts +2 -0
  13. package/dist/runescape/model/slayer/index.d.ts +3 -3
  14. package/dist/runescape/model/slayer/index.js +2 -2
  15. package/dist/runescape/model/slayer/masters/Chaeldar.js +1 -0
  16. package/dist/runescape/model/slayer/masters/Duradel.js +1 -0
  17. package/dist/runescape/model/slayer/masters/KonarQuoMaten.js +1 -0
  18. package/dist/runescape/model/slayer/masters/Krystilia.js +1 -0
  19. package/dist/runescape/model/slayer/masters/Mazchna.js +1 -0
  20. package/dist/runescape/model/slayer/masters/Mortimer.d.ts +21 -0
  21. package/dist/runescape/model/slayer/masters/Mortimer.js +37 -0
  22. package/dist/runescape/model/slayer/masters/Nieve.js +1 -0
  23. package/dist/runescape/model/slayer/masters/Spria.js +1 -0
  24. package/dist/runescape/model/slayer/masters/Turael.js +1 -0
  25. package/dist/runescape/model/slayer/masters/Vannaka.js +1 -0
  26. package/dist/runescape/model/slayer/masters/index.d.ts +2 -0
  27. package/dist/runescape/model/slayer/masters/index.js +2 -0
  28. package/dist/runescape/model/slayer/masters/registry.d.ts +2 -1
  29. package/dist/runescape/model/slayer/masters/registry.js +1 -0
  30. package/dist/runescape/model/slayer/masters.d.ts +1 -1
  31. package/dist/runescape/model/slayer/masters.js +1 -1
  32. package/dist/runescape/model/slayer/task/MortimerTasks.d.ts +14 -0
  33. package/dist/runescape/model/slayer/task/MortimerTasks.js +227 -0
  34. package/dist/runescape/model/slayer/tasks/index.d.ts +1 -0
  35. package/dist/runescape/model/slayer/tasks/index.js +1 -0
  36. package/package.json +1 -1
package/README.md CHANGED
@@ -1,88 +1,25 @@
1
1
  # OSRS Tools
2
2
 
3
- [![NPM Version](https://img.shields.io/npm/v/osrs-tools.svg?style=for-the-badge)](https://www.npmjs.com/package/osrs-tools)
4
- [![Downloads](https://img.shields.io/npm/dm/osrs-tools.svg?style=for-the-badge)](https://www.npmjs.com/package/osrs-tools)
5
- [![CI](https://img.shields.io/github/actions/workflow/status/jamescer/osrs-tools/ci.yml?branch=master&style=for-the-badge&label=CI)](https://github.com/jamescer/osrs-tools/actions/workflows/ci.yml)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg?style=for-the-badge)](https://www.typescriptlang.org)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)
8
- [![Node Version](https://img.shields.io/node/v/osrs-tools.svg?style=for-the-badge)](https://nodejs.org)
9
- [![Test Coverage](https://img.shields.io/codecov/c/github/jamescer/osrs-tools.svg?style=for-the-badge)](https://codecov.io/gh/jamescer/osrs-tools)
3
+ [![NPM Version](https://img.shields.io/npm/v/osrs-tools.svg?style=flat-square)](https://www.npmjs.com/package/osrs-tools)
4
+ [![Downloads](https://img.shields.io/npm/dm/osrs-tools.svg?style=flat-square)](https://www.npmjs.com/package/osrs-tools)
5
+ [![CI](https://img.shields.io/github/actions/workflow/status/jamescer/osrs-tools/ci.yml?branch=master&style=flat-square&label=CI)](https://github.com/jamescer/osrs-tools/actions/workflows/ci.yml)
6
+ [![Test Coverage](https://img.shields.io/codecov/c/github/jamescer/osrs-tools.svg?style=flat-square)](https://codecov.io/gh/jamescer/osrs-tools)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](./license)
10
8
 
11
- > A comprehensive TypeScript library for Old School RuneScape (OSRS) data, tools, and game modeling.
9
+ A fully-typed TypeScript library of Old School RuneScape game data and logic — quests, accounts, diaries, combat achievements, slayer, clues, items, and more.
12
10
 
13
- **Type-safe**   **Zero runtime dependencies**   **CJS + ESM**   **Tree-shakeable**   **Well-tested**
11
+ Zero runtime dependencies, dual CJS/ESM output, tree-shakeable, Node ≥ 18.
14
12
 
15
- ## Table of Contents
16
-
17
- - [Overview](#overview)
18
- - [Installation](#installation)
19
- - [Features](#features)
20
- - [Usage](#usage)
21
- - [API Reference](#api-reference)
22
- - [Development](#development)
23
- - [Contributing](#contributing)
24
- - [Support](#support)
25
- - [License](#license)
26
-
27
- ## Overview
28
-
29
- `osrs-tools` gives OSRS developers a fully-typed model of the game, covering:
30
-
31
- - full quest and requirement system with 189+ quests and miniquests
32
- - account data modeling for skills, bosses, clues, and progression
33
- - achievement diary lookups for all 10 regions, with a `DiaryTool` for account-based progress checks
34
- - Combat Achievements: all 637 tasks across six tiers, with a `CombatAchievementTool` for points and reward-tier progress
35
- - clue scroll reward simulation with wiki-accurate odds
36
- - item data model with combat stats and clue/quest item registries
37
- - slayer masters, tasks, reward unlocks/extends/buys, and point tables
38
- - hunter guild, rumours, and master progression
39
- - skill metadata, experience tables, and combat helpers
40
- - league support (Demonic Pacts, Raging Echoes)
41
- - custom `ValidationError` for consistent error handling
42
-
43
- This library is built for analytics, web apps, and toolchains that need OSRS game logic and data. It ships as dual CommonJS/ESM with bundled type definitions, has a single runtime dependency (`tslib`), and is marked side-effect free for tree-shaking.
44
-
45
- ## Installation
46
-
47
- ### Prerequisites
48
-
49
- - Node.js 18.x or higher
50
-
51
- TypeScript is not required to consume this package — it ships compiled JavaScript with bundled `.d.ts` type definitions — but is recommended to get full type-checking in your own project.
52
-
53
- ### Install
13
+ ## Install
54
14
 
55
15
  ```bash
56
16
  npm install osrs-tools
57
17
  ```
58
18
 
59
- ## Features
60
-
61
- - Quest system with all OSRS quests and recursive requirement checking
62
- - `OsrsAccount` skill, score, and combat level lookups
63
- - Achievement diaries with full task and requirement breakdowns via `DiaryTool`
64
- - Combat Achievements: all 637 tasks, reward-tier unlocks, and points calculation via `CombatAchievementTool`
65
- - Clue scroll casket simulation with tier-specific tables and mimic handling
66
- - Item model with combat stats, alch values, and quest/clue item flags
67
- - Slayer masters (Turael through Krystilia), task weights, point tables, reward utilities
68
- - Hunter guild rumours, masters, and locations
69
- - League modules for Demonic Pacts and Raging Echoes
70
- - Skill metadata helpers (24 skills including Sailing) and experience tables
71
- - Requirement classes covering levels, quests, items, combat, location, and more
72
- - `ValidationError` for uniform error handling across the library
73
-
74
- ## Usage
75
-
76
- ### Core Import
19
+ ## Quick Start
77
20
 
78
21
  ```typescript
79
- import {
80
- QuestTool,
81
- OsrsAccount,
82
- ClueScrollHelper,
83
- Item,
84
- ValidationError,
85
- } from "osrs-tools";
22
+ import { QuestTool, OsrsAccount } from "osrs-tools";
86
23
 
87
24
  const account = OsrsAccount.fromJson({
88
25
  name: "Player123",
@@ -95,191 +32,35 @@ const account = OsrsAccount.fromJson({
95
32
 
96
33
  const questTool = new QuestTool(account);
97
34
  const dragonSlayer = QuestTool.getQuestByName("Dragon Slayer I");
98
- const canComplete = questTool.canCompleteQuest(dragonSlayer);
99
35
 
100
- console.log("Requirements:", dragonSlayer?.requirements);
101
- console.log("Can complete?", canComplete);
36
+ console.log(questTool.canCompleteQuest(dragonSlayer));
102
37
  ```
103
38
 
104
- ### Subpath Imports
39
+ Import from the root package or from a subpath to keep bundles small:
105
40
 
106
41
  ```typescript
107
- import { QuestTool, DragonSlayerI } from "osrs-tools/quest";
108
42
  import { Duradel, getMasterByName } from "osrs-tools/slayer";
109
- import { OsrsAccount, Skill } from "osrs-tools/account";
110
- import diaries, { getDiaryByName, getAllDiaries, DiaryTool } from "osrs-tools/diary";
111
- import { CombatAchievementTool, ALL_COMBAT_ACHIEVEMENT_TASKS } from "osrs-tools/combat-achievements";
112
- import { getExperienceForLevel, getLevelForExperience } from "osrs-tools/tools";
113
- import { validateSkillLevel, getSkillsByCategory } from "osrs-tools/utils";
114
- ```
115
-
116
- ## API Reference
117
-
118
- ### Quest System (`osrs-tools/quest`)
119
-
120
- - `QuestTool` — account-based quest completion checks and quest registry
121
- - `QuestTool.getQuestByName(name)` — look up a quest by name
122
- - `QuestList`, `MiniQuestList` — full quest and miniquest registries
123
- - `QuestDifficulty`, `QuestLength`, `QuestStatus` — enums for quest metadata
124
- - 189+ individual quest classes (e.g., `DragonSlayerI`, `AKingdomDivided`)
125
- - Requirement classes:
126
- - `LevelRequirement` — skill level with optional boost support
127
- - `SlayerLevelRequirement` — slayer-specific level checks
128
- - `CombatLevelRequirement` — combat level gate
129
- - `QuestRequirement` — quest completion dependency
130
- - `ItemRequirement` — item with quantity, consumption, alternatives, and bankable flags
131
- - `LocationRequirement` — geographic access requirement
132
- - `QuestPointRequirement` — quest point gate
133
- - `SlayerUnlockRequirement` — slayer unlock dependency
134
-
135
- ### Account Modeling (`osrs-tools/account`)
136
-
137
- - `OsrsAccount.fromJson(json)` — parse an account from hiscores-style JSON
138
- - Skill access via `Skill` enum (24 skills: Attack, Defence, Strength, Hitpoints, Ranged, Prayer, Magic, Woodcutting, Fishing, Firemaking, Crafting, Smithing, Mining, Herblore, Agility, Thieving, Slayer, Farming, Runecraft, Hunter, Construction, Cooking, Fletching, Sailing)
139
- - `SKILL_METADATA` — per-skill metadata including category, maxLevel, and isBoostable
140
-
141
- ### Achievement Diaries (`osrs-tools/diary`)
142
-
143
- - `diaries` default export — all diaries
144
- - `getDiaryByName(name)` — look up a diary by region name
145
- - `getAllDiaries()` — array of all 10 regional diaries
146
- - Regions: Ardougne, Desert, Fremennik, Kandarin, Karamja, Kourend & Kebos, Lumbridge & Draynor, Morytania, Varrock, Wilderness
147
- - Each diary includes Easy/Medium/Hard/Elite tasks with full requirement breakdowns
148
- - `DiaryTool` — account-bound task checks:
149
- - `canCompleteTask(task)` / `canCompleteLevel(level)` — checks Level/Quest/CombatLevel/QuestPoint requirements
150
- - `getCompletableTasks(source)` / `getRemainingTasks(source)` — accepts a full `Diary` or a single `DiaryLevel`
151
- - `getDiaryProgress(diary)` — completable/remaining/total breakdown per tier
152
-
153
- ### Combat Achievements (`osrs-tools/combat-achievements`)
154
-
155
- - All 637 tasks across six tiers (Easy 41 / Medium 60 / Hard 85 / Elite 162 / Master 168 / Grandmaster 121), sourced from the OSRS Wiki
156
- - `ALL_COMBAT_ACHIEVEMENT_TASKS`, `EASY_COMBAT_ACHIEVEMENTS` ... `GRANDMASTER_COMBAT_ACHIEVEMENTS` — task lists per tier
157
- - `getCombatAchievementByName(name)`, `getCombatAchievementsByTier(tier)`, `getCombatAchievementsByMonster(monster)`
158
- - `COMBAT_ACHIEVEMENT_REWARD_TIERS` — the 6 cumulative point thresholds (41/161/416/1064/1904/2630) and their reward text
159
- - `CombatAchievementTool`:
160
- - `hasEngagedMonster(task)` — best-effort accessibility signal from the account's boss kill count; task completion itself isn't exposed via hiscores and can't be verified
161
- - `getAccessibleTasks(tasks)` / `getInaccessibleTasks(tasks)`
162
- - `calculatePoints(completedTaskNames)` — points for a caller-supplied list of completed task names
163
- - `getUnlockedRewardTiers(points)` / `getNextRewardTier(points)`
164
- - `getProgress(completedTaskNames)` — full per-tier breakdown plus unlocked/next reward tiers
165
-
166
- ```typescript
43
+ import { DiaryTool, getDiaryByName } from "osrs-tools/diary";
167
44
  import { CombatAchievementTool } from "osrs-tools/combat-achievements";
168
-
169
- const caTool = new CombatAchievementTool(account);
170
- const progress = caTool.getProgress(["Barrows Novice", "Noxious Foe"]);
171
- console.log(progress.totalPoints, progress.nextRewardTier?.tier);
172
45
  ```
173
46
 
174
- ### Clue Scroll Simulation
175
-
176
- Available from the main `osrs-tools` import:
177
-
178
- ```typescript
179
- import { ClueScrollHelper } from "osrs-tools";
180
-
181
- const result = ClueScrollHelper.openCasket("hard");
182
- console.log(result.items, result.mimicTriggered);
183
- ```
184
-
185
- - `ClueScrollHelper.openCasket(tier)` — simulate a casket opening with wiki-accurate odds
186
- - Tiers: `beginner`, `easy`, `medium`, `hard`, `elite`, `master`
187
- - `CasketReward` interface: `{ items, count, masterClue, mimicTriggered, mimicGuaranteed, mimicBonusItem }`
188
-
189
- ### Items
190
-
191
- Available from the main `osrs-tools` import:
192
-
193
- - `Item` — item data model with combat stats (attack/defence stab/slash/crush/magic/ranged, melee/ranged/magic bonuses, prayer), alch values, weight, tradeable/equipable/stackable flags
194
- - `ClueRewards` — item registries for clue scroll reward tables
195
- - `QuestItems` — item registry for quest-related items
47
+ ## What's included
196
48
 
197
- ### Slayer System (`osrs-tools/slayer`)
49
+ | Module | Subpath | Highlights |
50
+ | --- | --- | --- |
51
+ | Quests | `osrs-tools/quest` | `QuestTool`, 189+ quests, requirement classes (level, quest, item, combat, location…) |
52
+ | Accounts | `osrs-tools/account` | `OsrsAccount` (hiscores-compatible), `Skill` enum, skill metadata |
53
+ | Diaries | `osrs-tools/diary` | 10 regional achievement diaries, `DiaryTool` for progress checks |
54
+ | Combat Achievements | `osrs-tools/combat-achievements` | All 637 tasks across six tiers, `CombatAchievementTool` |
55
+ | Slayer | `osrs-tools/slayer` | 9 masters, tasks, points, unlocks/extends/buys |
56
+ | Experience | `osrs-tools/tools` | XP ⇄ level conversion, full XP table |
57
+ | Validation | `osrs-tools/utils` | Skill/level validation, `ValidationError` |
58
+ | Clues, items, guilds, leagues | root `osrs-tools` import | `ClueScrollHelper`, `Item`, `HunterGuild`, league data |
198
59
 
199
- #### Masters
200
-
201
- | Class | `getMasterByName` key |
202
- | --- | --- |
203
- | `Turael` | `"Turael"` |
204
- | `Spria` | `"Spria"` |
205
- | `Mazchna` | `"Mazchna"` |
206
- | `Vannaka` | `"Vannaka"` |
207
- | `Chaeldar` | `"Chaeldar"` |
208
- | `KonarQuoMaten` | `"Konar quo Maten"` |
209
- | `Nieve` | `"Nieve"` |
210
- | `Duradel` | `"Duradel"` |
211
- | `Krystilia` | `"Krystilia"` |
212
-
213
- #### Registry Utilities
214
-
215
- - `getMasterByName(name)` — look up a master by name
216
- - `getAllMasters()` — all slayer masters
217
- - `getMastersByMinimumLevel(level)` — masters accessible at a given combat level
218
- - `getMastersByProgression()` — masters ordered by progression
219
- - `getRandomMasterForLevel(level)` — random master appropriate for a level
220
-
221
- #### Rewards
222
-
223
- - `SlayerUnlock`, `SlayerExtend`, `SlayerBuy` — reward classes
224
- - `SLAYER_UNLOCKS`, `SLAYER_EXTENDS`, `SLAYER_BUYS` — full data sets
225
- - `getUnlockByName`, `getUnlocksByCostRange`, `calculateUnlocksCost`
226
- - `getExtendByName`, `getExtendsForTask`
227
- - `getBuyByItem`, `getBuysByCostRange`, `getBuysByRequirement`, `calculateBuysCost`
228
-
229
- #### Data & Constants
230
-
231
- - `POINTS_TABLE` — point rewards per master and streak
232
- - `SLAYER_EXP_RATES`, `STANDARD_TASK_WEIGHTS`, `TASK_QUANTITY_PRESETS`, `EXTENDED_QUANTITY_PRESETS`
233
- - `SlayerLocation`, `SlayerBoss`, `MonsterType` enums
234
-
235
- ### Experience Tools (`osrs-tools/tools`)
236
-
237
- - `getExperienceForLevel(level: number): number` — XP required to reach a level
238
- - `getLevelForExperience(xp: number): number` — level at a given XP total
239
- - `LEVEL_TO_EXPERIENCE: Record<number, number>` — full XP table (levels 1–99)
240
-
241
- ### Guilds
242
-
243
- Available from the main `osrs-tools` import:
244
-
245
- #### Hunter Guild
246
-
247
- - `HunterGuild` — guild class
248
- - `HunterGuildMaster` — master NPC with progression data
249
- - `HunterGuildMasterName` — enum of master names
250
- - `HunterRumour` — rumour entry with location and loot
251
- - `Rumours` — full rumour registry
252
- - `RumourLocation` — location data for rumours
253
-
254
- ### Leagues
255
-
256
- Available from the main `osrs-tools` import:
257
-
258
- - `League` interface — relics, reward tiers, and relic tiers
259
- - `Relic` — selectable relic with passive bonuses
260
- - `RelicTier` — tier with XP/drop multipliers
261
- - `RewardTier` — milestone reward unlock
262
- - `DemonicPactsLeagueAreas` — area data for Demonic Pacts
263
- - `RagingEchoesLeague` — region and relic data for Raging Echoes
264
- - `LeagueRegion`, `NotableDrop`, `GenericLeagueRegion` enums
265
-
266
- ### Validation & Skill Utilities (`osrs-tools/utils`)
267
-
268
- - `validateSkillLevel(level: number, skillName: string): void` — throws `ValidationError` for invalid levels
269
- - `validateQuestPoints(points: number): void` — throws `ValidationError` for invalid point totals
270
- - `getSkillMetadata(skill: Skill | string): SkillMetadata | undefined`
271
- - `isValidSkill(skillName: string): boolean`
272
- - `isValidLevel(skill: Skill | string, level: number): boolean`
273
- - `getSkillsByCategory(category: "combat" | "gathering" | "production" | "support"): Skill[]`
274
-
275
- ### Error Handling
276
-
277
- - `ValidationError` — extends `Error` with `fieldName: string`, `value: unknown`, and optional `context: Record<string, unknown>`
60
+ For the full API surface and source layout, see [summary.md](./summary.md).
278
61
 
279
62
  ## Development
280
63
 
281
- ### Local Setup
282
-
283
64
  ```bash
284
65
  git clone https://github.com/jamescer/osrs-tools.git
285
66
  cd osrs-tools
@@ -288,110 +69,30 @@ npm run build
288
69
  npm test
289
70
  ```
290
71
 
291
- ### Available Scripts
292
-
293
- | Command | Description |
294
- | ----------------------- | ------------------------------------- |
295
- | `build` | Compile TypeScript to `dist/` |
296
- | `build:npm` | Build with publish tsconfig |
297
- | `clean` | Remove `dist/` output directory |
298
- | `dev` | Watch mode compilation |
299
- | `test` | Run test suite |
300
- | `test:watch` | Run tests in watch mode |
301
- | `test:coverage` | Generate coverage report |
302
- | `coverage` | Run coverage and upload to Codecov |
303
- | `format` | Format source and tests with Prettier |
304
- | `lint` | Lint and auto-fix with ESLint |
305
- | `publish-test` | Dry-run `npm publish` |
306
-
307
- ### Project Structure
308
-
309
- ```text
310
- src/
311
- ├── index.ts # Main entry point
312
- └── runescape/
313
- ├── errors.ts # ValidationError
314
- ├── model/
315
- │ ├── Requirement.ts # All requirement classes and RequirementType enum
316
- │ ├── account/ # OsrsAccount, Skill enum, SKILL_METADATA
317
- │ │ └── skills/unlocks/ # AttackUnlocks, SkillUnlock
318
- │ ├── clue/ # ClueScrollHelper, ClueScrollRewards
319
- │ ├── diaries/ # 10 regional diary modules + DiaryTool
320
- │ ├── combat-achievements/ # 637 tasks (6 tiers), reward tiers, CombatAchievementTool
321
- │ ├── guilds/
322
- │ │ └── hunter/ # HunterGuild, HunterGuildMaster, Rumours, RumourLocation
323
- │ ├── items/ # Item, ClueRewards, QuestItems
324
- │ ├── leagues/ # DemonicPactsLeague, RagingEchoesLeague, League interfaces
325
- │ ├── quest/
326
- │ │ ├── QuestTool.ts
327
- │ │ ├── QuestList.ts
328
- │ │ ├── MiniQuestList.ts
329
- │ │ └── all/ # 189+ individual quest classes
330
- │ ├── skills/ # Skill interface, attack and hunter skill modules
331
- │ └── slayer/
332
- │ ├── core/ # SlayerMaster, Task, Assignment
333
- │ ├── masters/ # 9 master classes + registry
334
- │ ├── rewards/ # SlayerUnlock, SlayerExtend, SlayerBuy + data
335
- │ └── tasks/ # Task constants and weights
336
- ├── tools/
337
- │ └── experience.ts # getExperienceForLevel, getLevelForExperience, LEVEL_TO_EXPERIENCE
338
- └── utils/
339
- ├── validation.ts # validateSkillLevel, validateQuestPoints
340
- └── skillUtils.ts # getSkillMetadata, isValidSkill, getSkillsByCategory, isValidLevel
72
+ | Command | Description |
73
+ | --- | --- |
74
+ | `npm run build` | Compile TypeScript to `dist/` |
75
+ | `npm test` | Run the test suite |
76
+ | `npm run lint` | Lint and auto-fix with ESLint |
77
+ | `npm run format` | Format with Prettier |
78
+ | `npm run changeset` | Record a change for the next release |
341
79
 
342
- test/
343
- └── unit/
344
- ├── account/
345
- ├── diaries/
346
- ├── combat-achievements/
347
- ├── quest/
348
- ├── slayer/
349
- ├── model/
350
- ├── tools/
351
- └── utils/
352
-
353
- dist/ # Compiled output (generated by build)
354
- ```
80
+ See [dev_setup.md](./dev_setup.md) for the full setup and release workflow.
355
81
 
356
82
  ## Contributing
357
83
 
358
- We welcome contributions! We use [Conventional Commits](https://www.conventionalcommits.org/).
359
-
360
- ### Getting Started
361
-
362
- 1. Fork and clone the repository
363
- 2. Create a branch (`feat/amazing-feature`)
364
- 3. Make your changes and add tests
365
- 4. Run `npm test && npm run lint`
366
- 5. Commit with conventional format:
367
-
368
- ```text
369
- feat: add quest requirement validation
370
- fix: correct slayer task weights
371
- docs: update API documentation
372
- ```
84
+ Contributions are welcome. We use [Conventional Commits](https://www.conventionalcommits.org/) and [changesets](https://github.com/changesets/changesets) for releases.
373
85
 
374
- 6. Push and open a Pull Request
86
+ 1. Fork and clone the repo, create a branch
87
+ 2. Make your change and add tests
88
+ 3. `npm test && npm run lint`
89
+ 4. `npm run changeset` to record a changelog entry
90
+ 5. Open a pull request
375
91
 
376
- ### Guidelines
377
-
378
- - Add tests for new features
379
- - Update documentation for public API changes
380
- - Follow existing code style
381
- - Keep changes focused
382
-
383
- ## Support
384
-
385
- - [Report Issues](https://github.com/jamescer/osrs-tools/issues)
386
- - [Request Features](https://github.com/jamescer/osrs-tools/issues)
387
- - [Discussions](https://github.com/jamescer/osrs-tools/discussions)
92
+ Please also review our [Code of Conduct](./code-of-conduct.md) and [Security Policy](./SECURITY.md).
388
93
 
389
94
  ## License
390
95
 
391
- [MIT](./LICENSE) © James Cerniglia
392
-
393
- ## Credits
96
+ [MIT](./license) © [James Cerniglia](mailto:jamesmcerniglia@gmail.com)
394
97
 
395
- - **Author**: [James Cerniglia](mailto:jamesmcerniglia@gmail.com)
396
- - **Contributors**: [View all contributors](https://github.com/jamescer/osrs-tools/graphs/contributors)
397
- - **Data Source**: [Old School RuneScape Wiki](https://oldschool.runescape.wiki/)
98
+ Data sourced from the [Old School RuneScape Wiki](https://oldschool.runescape.wiki/).
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ export * from './runescape/model/diaries';
27
27
  export * from './runescape/model/quest/QuestTool';
28
28
  export * from './runescape/model/items';
29
29
  export * from './runescape/model/leagues';
30
- export { Assignment, Chaeldar, Duradel, getAllMasters, getMasterByName, getMastersByMinimumLevel, getMastersByProgression, KonarQuoMaten, Krystilia, Mazchna, Nieve, POINTS_TABLE, SLAYER_BUYS, SLAYER_EXTENDS, SLAYER_UNLOCKS, SlayerBoss, SlayerBuy, SlayerExtend, SlayerLocation, SlayerMaster, SlayerUnlock, Spria, Task, Turael, Vannaka, } from './runescape/model/slayer';
30
+ export { Assignment, Chaeldar, Duradel, getAllMasters, getMasterByName, getMastersByMinimumLevel, getMastersByProgression, KonarQuoMaten, Krystilia, Mazchna, Mortifier, MORTIFIERS, Mortimer, MortimerSlayerMaster, Nieve, POINTS_TABLE, SLAYER_BUYS, SLAYER_EXTENDS, SLAYER_UNLOCKS, SlayerBoss, SlayerBuy, SlayerExtend, SlayerLocation, SlayerMaster, SlayerUnlock, Spria, Task, Turael, Vannaka, } from './runescape/model/slayer';
31
31
  export * from './runescape/model/guilds';
32
32
  export * from './runescape/model/skills';
33
33
  export * from './runescape/errors';
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ export * from './runescape/model/items';
31
31
  // Leagues
32
32
  export * from './runescape/model/leagues';
33
33
  // Slayer system
34
- export { Assignment, Chaeldar, Duradel, getAllMasters, getMasterByName, getMastersByMinimumLevel, getMastersByProgression, KonarQuoMaten, Krystilia, Mazchna, Nieve, POINTS_TABLE, SLAYER_BUYS, SLAYER_EXTENDS, SLAYER_UNLOCKS, SlayerBoss, SlayerBuy, SlayerExtend, SlayerLocation, SlayerMaster, SlayerUnlock, Spria, Task, Turael, Vannaka, } from './runescape/model/slayer';
34
+ export { Assignment, Chaeldar, Duradel, getAllMasters, getMasterByName, getMastersByMinimumLevel, getMastersByProgression, KonarQuoMaten, Krystilia, Mazchna, Mortifier, MORTIFIERS, Mortimer, MortimerSlayerMaster, Nieve, POINTS_TABLE, SLAYER_BUYS, SLAYER_EXTENDS, SLAYER_UNLOCKS, SlayerBoss, SlayerBuy, SlayerExtend, SlayerLocation, SlayerMaster, SlayerUnlock, Spria, Task, Turael, Vannaka, } from './runescape/model/slayer';
35
35
  // Guilds system
36
36
  export * from './runescape/model/guilds';
37
37
  // Skills system
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Mortifiers - Mortimer's unique task modifier system
3
+ * Reference: https://oldschool.runescape.wiki/w/Mortimer
4
+ *
5
+ * Unlike other Slayer Masters, Mortimer does not reward Slayer points as the primary
6
+ * incentive for completing tasks. Instead his tasks carry a "Mortifier" - a modifier
7
+ * that is unlocked permanently as a player completes more tasks with him, and which
8
+ * is then applied (with a variable magnitude, "X") to a given task offer.
9
+ *
10
+ * NOTE: Mortimer and Wyrmscraig were, at time of writing, planned but not yet
11
+ * released content (Player Designed Island Competition). Names, thresholds and
12
+ * effects may change before/if this is implemented in the live game.
13
+ */
14
+ export interface MortifierConfig {
15
+ id: number;
16
+ name: string;
17
+ /** Number of Slayer tasks completed with Mortimer required to unlock this Mortifier. */
18
+ unlockThreshold: number;
19
+ description: string;
20
+ }
21
+ export declare class Mortifier {
22
+ id: number;
23
+ name: string;
24
+ unlockThreshold: number;
25
+ description: string;
26
+ constructor(config: MortifierConfig);
27
+ /**
28
+ * Get the number of tasks that must be completed with Mortimer to unlock this Mortifier.
29
+ */
30
+ getUnlockThreshold(): number;
31
+ /**
32
+ * Whether this Mortifier is unlocked for a player with the given number of completed tasks.
33
+ */
34
+ isUnlockedAt(completedTasks: number): boolean;
35
+ getDescription(): string;
36
+ }
37
+ /**
38
+ * All Mortifiers, in unlock order.
39
+ */
40
+ export declare const MORTIFIERS: Mortifier[];
41
+ /**
42
+ * Get every Mortifier unlocked for a player with the given number of tasks completed with Mortimer.
43
+ */
44
+ export declare function getAvailableMortifiers(completedTasks: number): Mortifier[];
45
+ /**
46
+ * Get a single Mortifier by its name (case insensitive).
47
+ */
48
+ export declare function getMortifierByName(name: string): Mortifier | undefined;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Mortifiers - Mortimer's unique task modifier system
3
+ * Reference: https://oldschool.runescape.wiki/w/Mortimer
4
+ *
5
+ * Unlike other Slayer Masters, Mortimer does not reward Slayer points as the primary
6
+ * incentive for completing tasks. Instead his tasks carry a "Mortifier" - a modifier
7
+ * that is unlocked permanently as a player completes more tasks with him, and which
8
+ * is then applied (with a variable magnitude, "X") to a given task offer.
9
+ *
10
+ * NOTE: Mortimer and Wyrmscraig were, at time of writing, planned but not yet
11
+ * released content (Player Designed Island Competition). Names, thresholds and
12
+ * effects may change before/if this is implemented in the live game.
13
+ */
14
+ export class Mortifier {
15
+ id;
16
+ name;
17
+ unlockThreshold;
18
+ description;
19
+ constructor(config) {
20
+ this.id = config.id;
21
+ this.name = config.name;
22
+ this.unlockThreshold = config.unlockThreshold;
23
+ this.description = config.description;
24
+ }
25
+ /**
26
+ * Get the number of tasks that must be completed with Mortimer to unlock this Mortifier.
27
+ */
28
+ getUnlockThreshold() {
29
+ return this.unlockThreshold;
30
+ }
31
+ /**
32
+ * Whether this Mortifier is unlocked for a player with the given number of completed tasks.
33
+ */
34
+ isUnlockedAt(completedTasks) {
35
+ return completedTasks >= this.unlockThreshold;
36
+ }
37
+ getDescription() {
38
+ return this.description;
39
+ }
40
+ }
41
+ const BonusSlayerPoints = new Mortifier({
42
+ description: 'Task awards X additional Slayer Points on completion.',
43
+ id: 1,
44
+ name: 'Bonus Slayer Points',
45
+ unlockThreshold: 0,
46
+ });
47
+ const QuantityModifier = new Mortifier({
48
+ description: 'Task quantity modified by X%.',
49
+ id: 2,
50
+ name: 'Quantity Modifier',
51
+ unlockThreshold: 0,
52
+ });
53
+ const ClueScrollBoost = new Mortifier({
54
+ description: 'Clue scroll drop-rates are increased by X%.',
55
+ id: 3,
56
+ name: 'Clue Scroll Boost',
57
+ unlockThreshold: 15,
58
+ });
59
+ const SuperiorUniqueBoost = new Mortifier({
60
+ description: "Slayer creatures' superiors access the superior unique table X% more often.",
61
+ id: 4,
62
+ name: 'Superior Unique Boost',
63
+ unlockThreshold: 25,
64
+ });
65
+ const BonusSlayerExp = new Mortifier({
66
+ description: 'Slayer creatures award X% more Slayer XP.',
67
+ id: 5,
68
+ name: 'Bonus Slayer Exp',
69
+ unlockThreshold: 40,
70
+ });
71
+ const ThirdTaskChoice = new Mortifier({
72
+ description: 'Adds a third task choice to Mortimer task offers.',
73
+ id: 6,
74
+ name: 'Third Task Choice',
75
+ unlockThreshold: 50,
76
+ });
77
+ /**
78
+ * All Mortifiers, in unlock order.
79
+ */
80
+ export const MORTIFIERS = [
81
+ BonusSlayerPoints,
82
+ QuantityModifier,
83
+ ClueScrollBoost,
84
+ SuperiorUniqueBoost,
85
+ BonusSlayerExp,
86
+ ThirdTaskChoice,
87
+ ];
88
+ /**
89
+ * Get every Mortifier unlocked for a player with the given number of tasks completed with Mortimer.
90
+ */
91
+ export function getAvailableMortifiers(completedTasks) {
92
+ return MORTIFIERS.filter(mortifier => mortifier.isUnlockedAt(completedTasks));
93
+ }
94
+ /**
95
+ * Get a single Mortifier by its name (case insensitive).
96
+ */
97
+ export function getMortifierByName(name) {
98
+ const normalized = name.toLowerCase();
99
+ return MORTIFIERS.find(mortifier => mortifier.name.toLowerCase() === normalized);
100
+ }