Skip to content

Content drop: music for the whole map, quests, skilling, combat and world plugins - #216

Closed
Blade9766 wants to merge 46 commits into
OpenRune:mainfrom
Blade9766:Content-Drop
Closed

Content drop: music for the whole map, quests, skilling, combat and world plugins#216
Blade9766 wants to merge 46 commits into
OpenRune:mainfrom
Blade9766:Content-Drop

Conversation

@Blade9766

Copy link
Copy Markdown

Summary

Content drop from the Content-Drop branch: 45 commits on top of main. The headline change is music for the whole game map; the rest is quests, skilling, combat and player-facing plugins that landed on this branch over the last weeks.

Music for the whole map (latest commit)

  • 539 new modern music areas traced from the OSRS wiki "Map:Music tracks" polygons: every surface region, dungeon and instance region the wiki lists (sailing ocean areas excluded). Each area is a rectangle toml under .data/raw-cache/map/area with an area gameval, a music_modern dbrow and a track list in or-cache/.../impl/Music.kt.
  • The 40 pre-existing music areas are reconciled with the wiki footprints: 26 regenerated so wiki sub-areas (Mage Arena, the Enclave, Dwarf Theme, Knightmare, Temple of Light, Clock Tower dungeon, Fairy Queen's hideout, Cave Background, ...) own their tiles, 14 extended, and the Wilderness, Catherby, Seers' Village, Al Kharid and Fishing Guild shuffles gain the tracks the wiki lists.
  • Engine fix: MapAreaEncoder/MapAreaDecoder stored the per-map-square zone count in a byte. A square split between region-aligned areas on all four levels has 256 zone entries, which wrapped to zero and crashed GameMapDecoder at boot. The count is now a short, so the cache must be rebuilt (./gradlew :or-cache:buildCache).

Also on this branch

  • Quests: The Restless Ghost, Witch's Potion, Demon Slayer, Gertrude's Cat; quest completion jingles.
  • Skilling: agility (nine rooftop courses, shortcuts, underwall tunnels, cross-level glides), thieving (pickpocketing, stalls, chests, rogue equipment, Rocky), fairy rings, teleport jewellery with charges, looting bag and rune pouch.
  • Combat: all four spellbooks' combat spells, dark wizard spells and transformation rings, special attacks for 33 more weapons, stun effect, npc combat animation families and sounds, npc aggression data with tolerance timer, several death/queue/prayer/special-attack fixes.
  • World: Grand Exchange (offers, collection, history), Emir's Arena (legacy duels, stakes, ranked duels), pet cats, generic passages (doors, gates, ladders, stairs, wilderness ditch), music player tab.
  • Player systems: level-up jingles and fireworks, admin cheat menu, xp rates, playtime, persisted appearance, embedded database account tooling, plugin authoring guide.

Verification

  • ./gradlew :or-cache:buildCache succeeds with the new areas and the widened zone count.
  • ./gradlew :server:app:run loads the map, all 585 music areas and 356 plugin scripts cleanly (startup was then stopped by an unrelated port clash with another local instance).
  • Music areas were generated by rasterising the wiki GeoJSON and checking every tile against the server's own polygon fill rules; overlaps between areas were resolved so no tile belongs to two music areas, which the music plugin requires.

🤖 Generated with Claude Code

Blade9766 and others added 30 commits September 5, 2026 00:09
Adds `::cheat`, an administrator menu covering item spawning, teleports,
stat and experience editing, appearance editing, and the god mode /
one-hit-kill / no-rune-cost / no-clip toggles. Shortcuts `::ohk`,
`::norunes`, `::noclip` and `::heal` skip the menu.

The menu uses the chatbox option dialogue (`ifChoice`) rather than
`ProtectedAccess.menu`, which opens a main modal over the middle of the
screen. That dialogue holds five options, so screens are grouped into
four plus a navigation entry, the long lists (skills, 75 teleport
destinations) are reached by typing a name, and appearance styles and
colours are cycled with next/previous rather than entered as ids.

Four cheats had no existing hook, so each is backed by an attribute in
`org.rsmod.api.player.cheat` and read where it takes effect:

- `MagicRuneManager.validateSpell` treats obj requirements as an
  unlimited source, so nothing is consumed. Level and spellbook
  requirements still apply.
- `StandardNpcHitModifier` raises a hit to the npc's remaining
  hitpoints, applied after style immunity and flat armour so neither can
  undo it. Player-vs-player hits are deliberately untouched.
- `PlayerMovementProcessor` walks a straight line through collision, but
  only once pathfinding reports it cannot reach the destination, so loc
  and npc interactions still resolve at their proper approach tile.

`Appearance.setIdentKit` now accepts -1. The backing array already
initialised to -1 and the appearance encoder passes the value straight
to a protocol that reads it as "no model", so the setter's lower bound
contradicted both. Body type B needs it: every id in the jaw slot is a
real beard model, so clean-shaven is the absence of a model rather than
a blank one.

The ident-kit tables in `CheatAppearance` were read out of the revision
240 client cache (config index 2, IDENTKIT archive 3) and grouped by
`bodyPartId`. They cannot be read back at runtime because the server
cache does not decode ident-kit definitions, so a test cross-checks them
against the engine's own default appearance to catch drift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds the content/other/level-up plugin, which listens to the AdvanceStat
engine queue and plays the skill's level-up jingle, the fireworks
spotanim and the levelup_display chatbox box.

Jingles are sent by archive 11 group id rather than RSCM id, since the
client does not understand the gameval id the RSCM table resolves to.
Each released skill maps to its jingle pair following the wiki rules
(unlock levels, Hitpoints/Strength at 50, Hunter odd/even, Construction
every tenth, Sailing at max, Smithing always unlock).

Includes ::testlevelup and ::jingle admin commands for verifying by ear.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fill in `param.defend_anim` at game startup for items the cache leaves
it off: every shield, defender, book, tome and ward, plus the scimitars,
blade of Saeldor, bone dagger, Verac's flail and other weapons with no
block animation. The combat api's existing resolver then plays the
right animation when a player is hit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Npc-versus-player combat plays one `param.attack_anim` per npc,
defaulting to the bare-handed punch, and only a few hundred npcs
declare one. Add `tools/combat-anims`, which identifies each humanoid
npc's weapon and shield by matching its models against item wear
models, classes casters and rangers, and derives monster attack, block
and death animations from their animation family. Its output ships in
`content/other/npc-combat-anims`, which applies it to the cached npc
types at game startup, with a hand-maintained overrides file on top.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Surfaces the varp.playtime counter that the mapclock plugin increments
each cycle: a greeting on login showing total time played, and a
::playtime [name] command to look up any online player.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Puts experience gain on a configurable multiplier read from
xp-rates.yml next to game.yml, defaulting to authentic 1.0x. The
bundled development realm seeds new characters at 150x, so the rate is
re-applied on login to correct existing characters.

Adds ::xprate, ::setxprate, ::globalxprate, ::reloadxprates, and the
confirmed ::resetxp / ::resetxpall commands, plus an opt-in one-time
level reset for characters levelled at an old inflated rate.

xp-rates.yml is generated on first boot and per-server, so it is
gitignored alongside game.yml.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
account_characters has no appearance columns and its schema lives in an
external module, so body type, pronoun, ident kit and colours are stored
in character_attrs, the key/json store the save already writes. They
are encoded from player.appearance on save and restored before the
player is registered on login, with out-of-range values falling back to
engine defaults instead of failing the login.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Walks a player into a solid wall with and without adminNoClip set and
checks the destination is only reached when no clip is on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Weapon attack, spell cast and npc attack sounds were sent as a per-player
synth packet; they now play as area sounds around the attacker, as they
do officially, so nearby players hear them too. Gives the wrench blunt
attack animations and sounds; it had no attack params at all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The generator only recognised weapons whose model matches an item, so
barbarians, Gunthor and skeleton heavies holding npc-only giant axes,
great hammers and two-handed swords punched. Those models and the
two-handed, ice-warrior and staff stances now map to weapon animations,
casters are also recognised by gameval name, and the family matcher
handles orks, Olaf's undead and Dharok. Spear and halberd npcs use the
lunge, axe npcs the chop, each with that stance's sound. Overrides cover
the Barrows brothers and the dark wizards' spell elements.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Dark wizards cast Water Strike and Confuse (levels 7-11) or Earth Strike
and Weaken (level 20+) with the spells' own graphics, sounds and stat
drains instead of the generic caster attack.

The Ring of stone, coins and nature transmogrify the wearer into the
rock, coin pile or bush until they move; the Ring of stone unequips
itself when the disguise ends.

Poison in combat: poisonous npcs (data-driven list) poison the players
they hit, poisoned weapons and ammunition poison players and npcs, and
npcs take poison ticks through a new npc var and timer. Adds an unkeyed
npc hit impact event for mechanics that apply to every npc.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Dragon dagger, mace, scimitar, sword, 2h, halberd, spear, battleaxe and
claws; Zamorakian spear and hasta; the godswords and ornament kits;
Saradomin and blessed swords; whips, tentacle, abyssal dagger and
bludgeon; dragon warhammer, elder maul, granite maul and hammer,
barrelchest anchor, ancient mace; Darklight, Arclight, Excalibur, bone
dagger, brine sabre, Voidwaker, Osmumten's fang; magic shortbow, magic
longbow and comp bow, Seercull, Dorgeshuun, dragon and Armadyl
crossbows, ballistas, dragon knife and thrownaxe.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Implements the Ancient Magicks, the standard curses, binds, Crumble
Undead, Iban Blast, Magic Dart and god spells, the Arceuus grasps and
demonbanes, and Lunar Vengeance and Vengeance Other. Npcs can now be
held in place by binds, grasps and ice spells.

Spells are no longer locked behind quests: the server no longer enforces
teleport quest requirements, and a spellbook plugin pack overrides the
client's per-spell quest check so nothing is greyed out for a quest.

The cheat menu gains a spellbook switch and a ::spellbook command.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Death was a normal queue, which can never launch while the player is
busy, and a player who has just been killed is always fighting back.
Death is now a strong queue, and strong queues interrupt the current
interaction and route so they can launch - without cancelling a script
that is already mid-way, since the death sequence's own pause would
otherwise be cut short by the hits still landing.

Plays the death sound as an area sound and the death jingle by its
archive group, which is the id the client actually plays.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds content/skills/agility: Draynor, Al Kharid, Varrock, Canifis, Falador,
Seers' Village, Pollnivneach, Rellekka and Ardougne rooftop courses with
wiki experience values, lap tracking, failure damage and marks of grace,
plus 42 two-way agility shortcuts.

Every start, landing and fall tile was verified against the cache map and
collision; balance obstacles move the player tile by tile with teleport
steps so the route finder can never knock them off course, and an
interrupted walk always lands on the far side. Adds a rooftop course
teleport group to the cheat menu.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds modern music areas for East Ardougne, West Ardougne, the Ardougne
Sewers, south Ardougne (Clock Tower, Monastery), the Legends' Guild and
the Mourner Tunnels, with their polygons and gameval ids, alongside the
earlier city area tomls the packed music table already referenced.

Adds content/interfaces/music-tab, the server side of the music player
side panel: track play/unlock hint, Area/Shuffle/Single modes, Skip
Track, and the three custom playlists. The handlers follow the cache's
client scripts: varp.musicplay is 0 Area / 1 Shuffle / 2 Single (the
old enum values were wrong), jukebox comsubs index the non-hidden rows
by ascending row id, and playlist slots store varp-index*100+bit.
MusicPlayer now highlights the playing row via varp.music_current_track,
loops in Single mode and draws Shuffle picks from the selected playlist.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds content/travel/fairy-rings: the ring locs' Zanaris, Configure,
Last-destination and Favourites ops, the dial interface with rotation and
confirm, and the travel log with visited codes and up to ten favourites.

Codes and destinations come from the cache's dbtable.fairyring, whose id
column fixes the dial order as ADCB / ILKJ / PSRQ. The travel log only
draws entries whose text the server sets, so visited codes and favourites
are written into their components before the pair opens. Requires a
wielded dramen or lunar staff; codes that go nowhere give the official
"hardly moved at all" line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A cast paid for entirely from a rune pouch or divine rune pouch passed
the rune check but was rejected when consuming: the inventory delete
transaction ran with nothing to delete and an empty transaction counts
as a failure. Skip it when there are no inventory runes to remove so
the pouch quantities are decremented instead.

Every character now logs in as a member. The client only counts rune
pouch and combination runes, and draws member spells as castable, when
the login response flags the player as a member.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… music

Adds content/other/emirs-arena: the Al Kharid arena as a safe PvP minigame.
Inside area.emirs_arena the attack option reads Challenge; two players
challenging each other (right-click or the clickable chat request, which
the client sends as option 1) get the cache's legacy duel options screen,
driven through varp.dueloptions exactly as clientscripts 6169/6174 read
it, with all twelve rules, per-slot worn restrictions and the presets.

Stakes reuse the trade screens (trademain + partydrop_side + tradeconfirm)
since the cache has no Duel Arena stake window; each stake sits in a new
persisted inv.emirs_arena_stake shown to the client under inv.tradeoffer,
mirrored to the opponent, refunded on cancel or logout, handed to the
winner, and returned at login after an interrupted duel.

Duellists are placed in one of the four walled combat areas for a 3-2-1
countdown with the Commence The Fight! jingle; death keeps every item and
respawns in the hospital, trapdoors forfeit, the winner gets You Are
Victorious!. Recruitment boards run ranked matchmaking with rank and
reward points (varbits pvpa_rank_points / pvpa_points_currency), which
Mubariz's reward shop spends through a varbit shop currency. Scoreboards,
hospital healing and the arena NPCs' dialogues are included, and The
Emir's Arena / Shine music areas are added.

Engine additions: PlayerRestrictionHook (walk/prayer/food/drink/equip),
PvPAttackRestrictionHook (attack style and specials), PlayerRespawnHook,
a Silent PvP attack validation result, ifSetPosition and mirrored
inventory helpers, and player option 3 only follows when labelled Follow.
Also fixes MiscOutput.setPlayerOp inserting instead of replacing the slot.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd jingle

Adds content/other/grand-exchange: the cache's ge_offers, ge_collect and
ge_history screens driven from the server, an order book that matches new
buy offers against the cheapest sells (refunding the difference) and new
sells against the highest buys, the 2% seller fee with the wiki's cap and
exemptions, four-hour buy limits, per-slot collect boxes at any bank,
trade history, Repeat Offer, pricing experts, and an ironman bonds-only
rule. Guide prices and limits for every tradeable item ship in a TSV.
The world book persists in .data/grand-exchange.json.

The Trade Parade plays in a new area.grand_exchange music area carved out
of the Varrock polygon, and the Grand Transaction jingle (index 11 group
86, matched by decoding the cache's jingles against the track) plays when
an offer completes. Grand Exchange staff no longer wander from their desks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds the Demon Slayer quest to the quest module: Aris starts it with a
crystal-ball reading and an instanced vision of Wally banishing Delrith,
Sir Prysin holds Silverlight behind three keys (Captain Rovin, the palace
drain and sewer, and Wizard Traiborn in exchange for 25 bones), and the
stone circle south of Varrock becomes a private instance where Denath and
his dark wizards summon Delrith. Reducing Delrith to zero hitpoints leaves
him weakened; the player must speak their randomised five-word incantation
to banish him, with wrong words restoring him and idling letting him slip
away.

Quest sub-state lives in persisted quest attributes and is mirrored to the
cache varbits, because the quest manager writes the whole quest varp (which
those varbits share) on login and stage changes. Both cutscenes run inside
the instance helper with guaranteed cleanup, exempt teleports and a dialogue
fallback for the vision.

Also adds the quest-wide completion jingle, the Wally the Hero and Delrith
music tracks (the latter looping through the fight), quest sound effects,
Silverlight-only attack validation for Delrith, and the ::resetquest,
::queststage and ::testloc admin commands used to test it. Registers the
stone circle area and the weakened-Delrith timeout queue as gamevals.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds content/other/pets: kittens, cats, overgrown cats and lazy cats in all
colours follow their owner when dropped. Kittens need fish or milk and
stroking or a ball of wool or they run away; they grow into cats after three
hours and into overgrown cats after another five and a half. Cats can chase
rats, talk with a catspeak amulet, and meow, purr and hiss. The follower varp
is set so the client shows the pet's options, and a cat that is out respawns
on login and runs away on death.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds Gertrude's Cat to the quest module. Gertrude asks for help finding
Fluffs; Shilop and Wilough sell the location of the lumber yard for 100
coins; Fluffs, up the shed ladder, hisses until she is given a bucket of
milk and then a doogle sardine (raw sardine seasoned with doogle leaves);
one of the mewing crates around the yard, fixed per player, holds her
kitten, and returning it sends Fluffs and the kitten home. Gertrude then
hands over a random-colour kitten, chocolate cake and stew with 1,525
Cooking XP, and sells further kittens for 100 coins to anyone without a cat.

The kitten is the pets plugin's kitten obj so it drops, follows, feeds and
grows as usual, and the cat sounds are the ids that plugin declares. The
broken fence, yard ladders and doogle leaf spawns already worked generically.

Gertrude's options are registered on the base multi-npc: the engine looks
for a handler under the transformed form but dispatches the event with the
base id, so hooks on the transformed names never fire. The mewing crate
npcs get a server timer entry so their ambient "Mew!" runs, and are pinned
to their crates so the Search option stays where the sound is.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ld, Yanille and Castle Wars

Adds modern music areas and track lists for Mudskipper Point (Mudskipper
Melody), the Fishing Guild (Mellow), the Tree Gnome Stronghold (Gnome King,
Gnome Village, Gnome Village 2, with Gnomeball confined to the ball field),
Yanille (Big Chords, Magic Dance), the Yanille Chain (Long Ago), the Yanille
Agility Dungeon (Cavern) and Castle Wars (Castle Wars above ground, Ready for
Battle in the waiting rooms and tunnels). Extends Port Sarim south to meet
Mudskipper Point and includes the pending Wizards Tower (Vision) area.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds The Restless Ghost to the quest module. Father Aereck asks for the
graveyard ghost to be dealt with; Father Urhney in the swamp hands over the
Amulet of Ghostspeak (with the lost-amulet flow that checks pack, worn slot
and bank before giving a spare); the ghost in the graveyard is only
intelligible with the amulet on and explains that a warlock stole his skull;
searching the altar in the Wizards' Tower basement yields the skull and
raises the skeleton in the corner; putting the skull in the opened coffin
releases the ghost and completes the quest for 1,125 Prayer XP.

The coffin opens and closes as a shared loc swap, and the coffin, altar and
skeleton use the cache multilocs on varp.restless_ghost_control. The skull
has its Inspect text and a destroy-on-drop confirmation. Coffin, skeleton
and ghost sound ids are declared in the quest module's gamevals.toml.

Quest completion jingles now play for every quest: the client plays a
jingle by its js5 archive group (the "Cache ID" on the wiki's jingle
pages), not the jingle gameval id, so Quest.completedQuest sends group 154
(Quest Complete 3) by default with 152/153 available to quest scripts.

Gives the Restless Ghost's skeleton a combat animation override with the
updated skeleton set every other skeleton uses, since its definition
carries human idle animations and the generator skipped it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds Witch's Potion to the quest module. Hetty in Rimmington asks for an
eye of newt, a rat's tail, an onion and a piece of burnt meat; her report of
what the player is carrying reads back exactly as in the original; with all
four she turns to her cauldron, casts her charm while it bubbles, and the
potion is drunk straight from the cauldron for 325 Magic XP.

Ordinary rats drop a rat's tail as a guaranteed drop, gated to the quest
being in progress, through a new rat drop table. Betty's Magic Emporium had
a shop config but no keeper, so Betty now talks and trades, which is where
the eye of newt comes from. The drink and cauldron sound ids join the quest
module's gamevals.

Attaches "Faerie" and "Crystal Cave" to the existing Zanaris area in the
modern music table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ear shove

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Blade9766 and others added 16 commits September 8, 2026 11:13
…ged defend waits for the projectile

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… end on death

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d annihilate hit npcs across zones

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…points run out

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…sts and spiders

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…el glides

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ess ditch

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…lderness level rule

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ath hooks

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
# Conflicts:
#	.data/gamevals/varn.rscm
#	.data/raw-cache/server/npcs.toml
…sic map

Adds 539 modern music areas traced from the wiki "Map:Music tracks" polygons:
every surface region, dungeon and instance region the wiki lists, except the
sailing ocean areas. Each area is a rectangle toml under .data/raw-cache/map/area
with an area gameval, a music_modern dbrow and a track list in Music.kt.

Reconciles the 40 existing music areas with the wiki footprints: 26 are
regenerated so the sub-areas the wiki lists separately (Mage Arena, the Enclave,
Dwarf Theme, Knightmare, Temple of Light, Clock Tower dungeon, Fairy Queen's
hideout, Cave Background, ...) own their tiles, 14 are extended where the old
rectangles stopped short, and the Wilderness, Catherby, Seers' Village,
Al Kharid and Fishing Guild shuffles gain the tracks the wiki lists.

The map area encoder stored the per-square zone count in a byte; a square split
between region-aligned areas on all four levels has 256 zone entries, which
wrapped to zero and crashed the map decoder at boot. The count is now a short.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…and Zanaris shed

Adds the Lost City quest plugin: the swamp camp adventurers' dialogue, Shamus popping
out of his tree when it is chopped, the Monks of Entrana ship with the weapon and
armour search and its gangplanks, the cave monk and one-way ladder into the Entrana
dungeon (prayer drained, magic door to the Wilderness), the Tree spirit fight at the
Dramen tree with branch cutting afterwards, and the shed door that carries a staff
wielder into Zanaris and completes the quest.

Fairy ring teleports and the shed portal now play the vanish pose, the flower ring
spotanim and the fairy ring chime (sound 1098). The Entrana dungeon zombies get their
drop table so the bronze axe can be found on the island. Shamus' static map spawn is
removed since the script spawns him.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fun roll(player: Player, random: GameRandom, layout: CourseLayout): Boolean {
val course = layout.course
var denominator = course.markDenominator
if (player.baseAgilityLvl >= course.level + OVERLEVEL_THRESHOLD) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Canifis course does not decrease the mark of grace chance at level 60, as it would here. Although the wiki states its because of a bug, I still think we should aim for accurate behavior when possible.

https://oldschool.runescape.wiki/w/Canifis_Rooftop_Course

Disclaimer: I'm not doing any full review nor have I really looked at much of what's in this PR, this part just jumped out to me as I skimmed through some things.

@Mark7625 Mark7625 closed this Sep 9, 2026
@Mark7625

Mark7625 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Closing as i need to sort through their is a lot of content on same pr, feel free to re pr with smaller drops

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants