UNPKG

@abextm/cache2

Version:

Utilities for reading OSRS "caches"

196 lines (195 loc) 6.41 kB
import { PerFileLoadable } from "../Loadable.js"; import { Typed } from "../reflect.js"; import { AnimRestartMode, PreAnimMoveMode, } from "../types.js"; export class FrameSound { id; weight; loops; retain; constructor(id, weight, loops, location, retain) { this.id = id; this.weight = weight; this.loops = loops; this.retain = retain; this.offsetX = (location >> 16) & 0xFF; this.offsetY = (location >> 8) & 0xFF; this.maxDistance = location & 0xFF; this.isAreaSound = location === 0; } offsetX; offsetY; isAreaSound; maxDistance; } export class Animation extends PerFileLoadable { id; constructor(id) { super(); this.id = id; } static index = 2; static archive = 12; static gameval = 7; frameLengths = undefined; frameIDs = undefined; chatheadFrameIDs = undefined; animMayaID = undefined; animMayaStart = 0; animMayaEnd = 0; masks = undefined; debugName; verticalOffset = 0; frameStep = -1; interleaveLeave = undefined; stretches = true; priority = 5; leftHandItem = undefined; rightHandItem = undefined; maxLoops = undefined; preAnimMove; postAnimMove; restartMode = AnimRestartMode.ResetLoops; sounds = new Map(); static decode(r, id) { const v = new Animation(id); let [legacyFrameSounds, animMayaID, frameSounds, animMayaBounds, verticalOffset] = r.isAfter({ era: "osrs", indexRevision: 4470 }) ? [-1, 13, 14, 15, 16] : [13, 14, 15, 16, -1]; for (let opcode; (opcode = r.u8()) != 0;) { switch (opcode) { case 1: { let len = r.u16(); v.frameLengths = new Array(len); v.frameIDs = new Array(len); for (let i = 0; i < len; i++) { v.frameLengths[i] = r.u16(); } for (let i = 0; i < len; i++) { v.frameIDs[i] = [0, r.u16()]; } for (let i = 0; i < len; i++) { v.frameIDs[i][0] = r.u16(); } break; } case 2: v.frameStep = r.u16(); break; case 3: { let len = r.u8(); v.interleaveLeave = new Array(len + 1); for (let i = 0; i < len; i++) { v.interleaveLeave[i] = r.u8(); } v.interleaveLeave[len] = 9999999; break; } case 4: v.stretches = true; break; case 5: v.priority = r.u8(); break; case 6: v.leftHandItem = r.kit(); break; case 7: v.rightHandItem = r.kit(); break; case 8: v.maxLoops = r.u8(); break; case 9: v.preAnimMove = r.u8(); break; case 10: v.postAnimMove = r.u8(); break; case 11: v.restartMode = r.u8(); break; case 12: { let len = r.u8(); v.chatheadFrameIDs = new Array(len); for (let i = 0; i < len; i++) { v.chatheadFrameIDs[i] = [0, r.u16()]; } for (let i = 0; i < len; i++) { v.chatheadFrameIDs[i][0] = r.u16(); } break; } case legacyFrameSounds: { let len = r.u8(); for (let i = 0; i < len; i++) { readFrameSound(v, r, i); } break; } case animMayaID: v.animMayaID = r.i32(); break; case frameSounds: { let len = r.u16(); for (let i = 0; i < len; i++) { let frame = r.u16(); readFrameSound(v, r, frame); } break; } case animMayaBounds: v.animMayaStart = r.u16(); v.animMayaEnd = r.u16(); break; case verticalOffset: v.verticalOffset = r.i8(); break; case 17: { v.masks = new Array(256); v.masks.fill(false); let len = r.u8(); for (let i = 0; i < len; i++) { v.masks[r.u8()] = true; } break; } case 18: v.debugName = r.string(); break; default: throw new Error(`unknown animation opcode ${opcode}`); } } let defaultAnimMode = v.interleaveLeave === undefined && v.masks == undefined ? PreAnimMoveMode.DelayMove : PreAnimMoveMode.Merge; v.preAnimMove ??= defaultAnimMode; v.postAnimMove ??= defaultAnimMode; return v; } } function readFrameSound(v, r, frame) { let sound; if (r.isAfter({ era: "osrs", indexRevision: 4106 })) { let id = r.u16(); let weight = r.isAfter({ era: "osrs", indexRevision: 4470 }) ? r.u8() : -1; let loops = r.u8(); let location = r.u8(); let retain = r.u8(); sound = new FrameSound(id, weight, loops, location, retain); } else { let bits = r.u24(); sound = new FrameSound((bits >> 8), -1, (bits >> 4) & 7, bits & 15, 0); } if (sound.id >= 1 && sound.loops >= 1) { let list = v.sounds.get(frame); if (!list) { list = []; v.sounds.set(frame, list); } list.push(sound); } }