@abextm/cache2
Version:
Utilities for reading OSRS "caches"
284 lines (278 loc) • 7.29 kB
text/typescript
import { PerFileLoadable } from "../Loadable.js";
import { Reader } from "../Reader.js";
import { Typed } from "../reflect.js";
import {
AnimationID,
CategoryID,
HSL,
ModelID,
NPCID,
Params,
SpriteID,
TextureID,
VarbitID,
VarPID,
} from "../types.js";
export class NPC extends PerFileLoadable {
constructor(public id: NPCID) {
super();
}
declare public [Typed.type]: Typed.Any;
public static readonly index = 2;
public static readonly archive = 9;
public static readonly gameval = 1;
public models: ModelID[] = <ModelID[]> [];
public name = "null";
public size = 1;
public standingAnimation = <AnimationID> -1;
public walkingAnimation = <AnimationID> -1;
public idleRotateLeftAnimation = <AnimationID> -1;
public idleRotateRightAnimation = <AnimationID> -1;
public rotate180Animation = <AnimationID> -1;
public rotateLeftAnimation = <AnimationID> -1;
public rotateRightAnimation = <AnimationID> -1;
public category = <CategoryID> -1;
public actions: (string | null)[] = [null, null, null, null, null];
public recolorFrom: HSL[] = <HSL[]> [];
public recolorTo: HSL[] = <HSL[]> [];
public retextureFrom: TextureID[] = <TextureID[]> [];
public retextureTo: TextureID[] = <TextureID[]> [];
public chatheadModels: ModelID[] = <ModelID[]> [];
public isMinimapVisible = true;
public combatLevel = -1;
public widthScale = 128;
public heightScale = 128;
public isVisible = false;
public ambient = 0;
public contrast = 0;
public headIconArchive: SpriteID[] = [];
public headIconSpriteIndex: number[] = [];
public rotationSpeed = 32;
public varbit = <VarbitID> -1;
public varp = <VarPID> -1;
public multiChildren: NPCID[] = <NPCID[]> [];
public oobChild = <NPCID> -1;
public isInteractible = true;
public isClickable = true;
public isFollower = false;
public lowPriorityOps = false;
public runAnimation = <AnimationID> -1;
public runRotate180Animation = <AnimationID> -1;
public runRotateLeftAnimation = <AnimationID> -1;
public runRotateRightAnimation = <AnimationID> -1;
public crawlAnimation = <AnimationID> -1;
public crawlRotate180Animation = <AnimationID> -1;
public crawlRotateLeftAnimation = <AnimationID> -1;
public crawlRotateRightAnimation = <AnimationID> -1;
public attack = 1;
public defence = 1;
public strength = 1;
public hitpoints = 1;
public ranged = 1;
public magic = 1;
public height = -1;
public params = new Params();
public static decode(r: Reader, id: NPCID): NPC {
const v = new NPC(id);
for (let opcode: number; (opcode = r.u8()) != 0;) {
switch (opcode) {
case 1: {
let len = r.u8();
v.models = new Array(len);
for (let i = 0; i < len; i++) {
v.models[i] = <ModelID> r.u16();
}
break;
}
case 2:
v.name = r.string();
break;
case 12:
v.size = r.u8();
break;
case 13:
v.standingAnimation = <AnimationID> r.u16();
break;
case 14:
v.walkingAnimation = <AnimationID> r.u16();
break;
case 15:
v.idleRotateLeftAnimation = <AnimationID> r.u16();
break;
case 16:
v.idleRotateRightAnimation = <AnimationID> r.u16();
break;
case 17:
v.walkingAnimation = <AnimationID> r.u16();
v.rotate180Animation = <AnimationID> r.u16();
v.rotateLeftAnimation = <AnimationID> r.u16();
v.rotateRightAnimation = <AnimationID> r.u16();
break;
case 18:
v.category = <CategoryID> r.u16();
break;
case 30:
case 31:
case 32:
case 33:
case 34:
v.actions[opcode - 30] = r.stringNullHidden();
break;
case 40: {
let len = r.u8();
v.recolorFrom = new Array(len);
v.recolorTo = new Array(len);
for (let i = 0; i < len; i++) {
v.recolorFrom[i] = <HSL> r.u16();
v.recolorTo[i] = <HSL> r.u16();
}
break;
}
case 41: {
let len = r.u8();
v.retextureFrom = new Array(len);
v.retextureTo = new Array(len);
for (let i = 0; i < len; i++) {
v.retextureFrom[i] = <TextureID> r.u16();
v.retextureTo[i] = <TextureID> r.u16();
}
break;
}
case 60: {
let len = r.u8();
v.chatheadModels = new Array(len);
for (let i = 0; i < len; i++) {
v.chatheadModels[i] = <ModelID> r.u16();
}
break;
}
case 74:
v.attack = r.u16();
break;
case 75:
v.defence = r.u16();
break;
case 76:
v.strength = r.u16();
break;
case 77:
v.hitpoints = r.u16();
break;
case 78:
v.ranged = r.u16();
break;
case 79:
v.magic = r.u16();
break;
case 93:
v.isMinimapVisible = false;
break;
case 95:
v.combatLevel = r.u16();
break;
case 97:
v.widthScale = r.u16();
break;
case 98:
v.heightScale = r.u16();
break;
case 99:
v.isVisible = true;
break;
case 100:
v.ambient = r.i8();
break;
case 101:
v.contrast = r.i8();
break;
case 102:
if (!r.isAfter({ era: "osrs", indexRevision: 3642 })) {
v.headIconArchive = [-1 as SpriteID];
v.headIconSpriteIndex = [r.u16()];
} else {
let bitfield = r.u8();
v.headIconArchive = [];
v.headIconSpriteIndex = [];
for (let bits = bitfield; bits != 0; bits >>= 1) {
if ((bits & 1) == 0) {
v.headIconArchive.push(-1 as SpriteID);
v.headIconSpriteIndex.push(-1);
} else {
v.headIconArchive.push(r.s2o4n() as SpriteID);
v.headIconSpriteIndex.push(r.u8o16m1());
}
}
}
break;
case 103:
v.rotationSpeed = r.u16();
break;
case 106: {
v.varbit = <VarbitID> r.u16n();
v.varp = <VarPID> r.u16n();
let len = r.u8p1();
v.multiChildren = new Array(len);
for (let i = 0; i < len; i++) {
v.multiChildren[i] = <NPCID> r.u16n();
}
break;
}
case 107:
v.isInteractible = false;
break;
case 109:
v.isClickable = false;
break;
case 111:
// removed in 220
v.isFollower = true;
v.lowPriorityOps = true;
break;
case 114:
v.runAnimation = <AnimationID> r.u16();
break;
case 115:
v.runAnimation = <AnimationID> r.u16();
v.runRotate180Animation = <AnimationID> r.u16();
v.runRotateLeftAnimation = <AnimationID> r.u16();
v.runRotateRightAnimation = <AnimationID> r.u16();
break;
case 116:
v.crawlAnimation = <AnimationID> r.u16();
break;
case 117:
v.crawlAnimation = <AnimationID> r.u16();
v.crawlRotate180Animation = <AnimationID> r.u16();
v.crawlRotateLeftAnimation = <AnimationID> r.u16();
v.crawlRotateRightAnimation = <AnimationID> r.u16();
break;
case 118: {
v.varbit = <VarbitID> r.u16n();
v.varp = <VarPID> r.u16n();
v.oobChild = <NPCID> r.u16n();
let len = r.u8p1();
v.multiChildren = new Array(len);
for (let i = 0; i < len; i++) {
v.multiChildren[i] = <NPCID> r.u16n();
}
break;
}
case 122:
v.isFollower = true;
break;
case 123:
v.lowPriorityOps = true;
break;
case 124:
v.height = r.u16();
break;
case 249:
v.params = r.params();
break;
default:
throw new Error(`unknown opcode ${opcode}`);
}
}
return v;
}
}