Configs/LocType: Difference between revisions
From RuneWiki
Line 671: | Line 671: | ||
==== width Property ==== | ==== width Property ==== | ||
Number of tiles a loc takes on the | Number of tiles a loc takes on the east/west axis. | ||
===== 186 ===== | ===== 186 ===== | ||
Line 681: | Line 681: | ||
==== length Property ==== | ==== length Property ==== | ||
Number of tiles a loc takes on the | Number of tiles a loc takes on the north/south axis. | ||
===== 186 ===== | ===== 186 ===== | ||
Line 777: | Line 777: | ||
==== wallwidth Property ==== | ==== wallwidth Property ==== | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java" line="1"> | ||
if (code == 28) { | if (code == 28) { | ||
this.wallwidth = dat.g1(); | this.wallwidth = dat.g1(); | ||
Line 784: | Line 784: | ||
==== ambient Property ==== | ==== ambient Property ==== | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java" line="1"> | ||
if (code == 29) { | if (code == 29) { | ||
this.ambient = dat.g1b(); | this.ambient = dat.g1b(); | ||
Line 791: | Line 791: | ||
==== contrast Property ==== | ==== contrast Property ==== | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java" line="1"> | ||
if (code == 39) { | if (code == 39) { | ||
this.contrast = dat.g1b(); | this.contrast = dat.g1b(); | ||
Line 800: | Line 800: | ||
op1-5 directly correlates to the server-script triggers for oploc1 through oploc5. | op1-5 directly correlates to the server-script triggers for oploc1 through oploc5. | ||
There are options labelled "hidden" which are used for the server-side triggers to repeat oploc interactions.<syntaxhighlight lang="java"> | There are options labelled "hidden" which are used for the server-side triggers to repeat oploc interactions.<syntaxhighlight lang="java" line="1"> | ||
if (code >= 30 && code < 39) { | if (code >= 30 && code < 39) { | ||
if (this.ops == null) { | if (this.ops == null) { | ||
Line 910: | Line 910: | ||
Pathfinder property - allow the pathfinder to route through this loc. | Pathfinder property - allow the pathfinder to route through this loc. | ||
Scenario: interacting with a NPC behind a bank booth from an outside wall, so the player walks around to be within operable range. | Scenario: interacting with a NPC behind a bank booth from an outside wall, so the player walks around to be within operable range.<syntaxhighlight lang="java" line="1"> | ||
if (code === 74) { | |||
this.breakroutefinding = true; | |||
} | |||
</syntaxhighlight> | |||
==== raiseobject Property ==== | ==== raiseobject Property ==== | ||
<syntaxhighlight lang="java" line="1"> | |||
if (code === 75) { | |||
this.raiseobject = buf.g1(); | |||
} | |||
</syntaxhighlight> | |||
==== multiloc Property ==== | ==== multiloc Property ==== | ||
==== bgsound Property ==== | ==== bgsound Property ==== | ||
<syntaxhighlight lang="java" line="1"> | |||
if (code === 78) { | |||
this.bgsound = buf.g2(); | |||
this.bgsoundrange = buf.g1(); | |||
} | |||
</syntaxhighlight> | |||
==== randomsound Property ==== | ==== randomsound Property ==== | ||
<syntaxhighlight lang="java" line="1"> | |||
if (code === 79) { | |||
this.bgsoundmin = buf.g1(); | |||
this.bgsoundmax = bug.g1(); | |||
this.bgsoundrange = buf.g1(); | |||
int count = buf.g1(); | |||
this.bgsounds = new int[count]; | |||
for (int i = 0; i < count; i++) { | |||
this.bgsounds[i] = buf.g2(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
==== hardshadow Property ==== | ==== hardshadow Property ==== | ||
<syntaxhighlight lang="java" line="1"> | |||
if (code === 88) { | |||
this.hardshadow = false; | |||
} | |||
</syntaxhighlight> | |||
==== randseq Property ==== | ==== randseq Property ==== | ||
<syntaxhighlight lang="java" line="1"> | |||
if (code === 89) { | |||
this.randseq = false; | |||
} | |||
</syntaxhighlight> | |||
==== members Property ==== | ==== members Property ==== | ||
<syntaxhighlight lang="java" line="1"> | |||
if (code === 91) { | |||
this.members = true; | |||
} | |||
</syntaxhighlight> | |||
==== mapscenerotates Property ==== | ==== mapscenerotates Property ==== |
Revision as of 13:29, 9 February 2024
Structure
Regardless of the revision, the packing process has some basic rules.
- Loc names must be unique. They can have + symbols in the name.
- Configs are a purely text format with a custom parser. True/false values are written as yes/no.
- Opcodes are written in the order they're read in. This means the packing process is writing immediately as it parses, with a few exceptions for properties that are "collected" and written at the end (typically arrays or complex properties). If you decode to memory or a standard intermediate format, you will lose this information, not that it matters much for the end result. Only bother with this if you care to match the checksum exactly.
Because of #2 you'll also be able to see when they copy-paste lines and/or forget to remove old properties!
[example]
name=Example
desc=This is an example
model=example
length=4
width=2
length=2
recol1s=5
recol1d=1234
RS2
Changes based on decompiling available clients. If a revision is off by a couple, it's because we were missing those clients or they were not auto-decompilable (yet) to narrow the revision down further. I'll refine this again later.
Names are an attempt to be authentic and correct, if you have any more information definitely reach out.
Property | Opcode | History | Notes |
---|---|---|---|
model | 1 | Added 186 (2003-12-02)
Changed 300 (2005-03-07) Changed 581 (2010-01-29) |
Written at the end of a config. |
name | 2 | Added 186 (2003-12-02) | Written at the end of a config. |
desc | 3 | Added 186 (2003-12-02)
Removed 410 (2006-05-25) |
Examine text, written at the end of a config. Later transmitted from the server. |
model | 5 | Added 249 (2004-08-09)
Changed 300 (2005-03-07) Changed 581 (2010-01-29) |
Written at the end of a config. This opcode is used to save bytes in the list of models. |
width | 14 | Added 186 (2003-12-02) | |
length | 15 | Added 186 (2003-12-02) | |
blockwalk=no | 17 | Added 186 (2003-12-02) | |
blockrange=no | 18 | Added 186 (2003-12-02) | |
active | 19 | Added 186 (2003-12-02) | |
hillskew=yes | 21 | Added 186 (2003-12-02) | hillskew mode 1 |
sharelight=yes | 22 | Added 186 (2003-12-02) | |
occlude=yes | 23 | Added 186 (2003-12-02) | |
anim | 24 | Added 186 (2003-12-02) | |
- | 25 | Added 186 (2003-12-02)
Removed 249 (2004-08-09) |
This opcode was used internally for disposing of alpha data between animation frames.
It was not manually defined and comes from a linked anim. |
blockwalk=yes | 27 | Added 454 (2007-03-26) | |
wallwidth | 28 | Added 186 (2003-12-02) | |
ambient | 29 | Added 186 (2003-12-02) | |
contrast | 39 | Added 186 (2003-12-02) | |
op | 30-35 | Added 186 (2003-12-02) | Originally this reserved opcodes >= 30 & < 39 (likely copy-pasted). |
recol | 40 | Added 186 (2003-12-02) | |
retex | 41 | Added 465 (2007-07-19) | |
recoldpalette | 42 | Added 494 (2008-04-15) | |
mapfunction | 60 | Added 186 (2003-12-02) | |
mirror=yes | 62 | Added 186 (2003-12-02) | |
shadow=no | 64 | Added 186 (2003-12-02) | |
resizex | 65 | Added 186 (2003-12-02) | |
resizey | 66 | Added 186 (2003-12-02) | |
resizez | 67 | Added 186 (2003-12-02) | |
mapscene | 68 | Added 186 (2003-12-02)
Removed 530 (2009-01-28) |
|
forceapproach | 69 | Added 186 (2003-12-02) | This is a bitmask, one bit will be unset - the direction. |
offsetx | 70 | Added 194 (2004-01-07) | |
offsety | 71 | Added 194 (2004-01-07) | |
offsetz | 72 | Added 194 (2004-01-07) | |
forcedecor=yes | 73 | Added 194 (2004-01-07) | |
breakroutefinding=yes | 74 | Added 245 (2004-07-13) | |
raiseobject | 75 | Added 249 (2004-08-09) | |
multiloc | 77 | Added 289 (2005-01-17) | |
bgsound | 78 | Added 417 (2006-06-27) | |
randomsound | 79 | Added 417 (2006-06-27) | |
treeskew* | 81 | Added 465 (2007-07-19) | hillskew mode 2 |
82 | Added 487 (2008-02-12) | Related to whether it should render? | |
hardshadow=no* | 88 | Added 487 (2008-02-12) | If this isn't hardshadow, it's something like sceneshadow? |
randseq=no* | 89 | Added 487 (2008-02-12) | Disable randomizing the initial seq frame. |
90 | Added 487 (2008-02-12) | ||
members=yes | 91 | Added 494 (2008-04-15) | |
multiloc | 92 | Added 498 (2008-05-09) | multiloc with a default value. |
rotateskew* | 93 | Added 498 (2008-05-09) | hillskew mode 3 - Same as previous but reads 2-bytes. |
ceilingskew=yes* | 94 | Added 498 (2008-05-09) | hillskew mode 4 |
skewtofit=yes* | 95 | Added 498 (2008-05-09) | hillskew mode 5 |
96 | Added 501 (2008-07-01) | Related to having an animation? | |
mapscenerotates=yes | 97 | Added 506 (2008-07-28) | Map scene icon rotates with the loc. |
98 | Added 530 (2009-01-28) | ||
cursor1 | 99 | Added 530 (2009-01-28) | |
cursor2 | 100 | Added 530 (2009-01-28) | |
mapsceneangle* | 101 | Added 530 (2009-01-28) | Map scene icon angle offset. |
mapscene | 102 | Added 530 (2009-01-28) | Replaces the earlier mapscene. |
occlude=no | 103 | Added 535 (2009-03-16) | |
bgsoundvol | 104 | Added 535 (2009-03-16) | |
mapsceneflipy* | 105 | Added 535 (2009-03-16) | Map scene icon flipped vertically. |
anims | 106 | Added 542 (2009-04-02) | Animation weights? |
mel | 107 | Added 548 (2009-05-27) | Map element. |
memberop* | 150-155 | Added 548 (2009-05-27) | Members-only ops. |
quests* | 160 | Added 555 (2009-09-02) | |
rotateskew* | 162 | Added 581 (2010-01-29) | Same as previous but reads 4-bytes. |
tint | 163 | Added 581 (2010-01-29) | Hue, saturation, luminance, weight values |
postoffsetx | 164 | Added 593 (2010-03-02) | |
postoffsety | 165 | Added 593 (2010-03-02) | |
postoffsetz | 166 | Added 593 (2010-03-02) | |
decorheight* | 167 | Added 595 (2010-03-12) | |
168 | Added 611 (2010-06-08) | ||
169 | Added 611 (2010-06-08) | ||
occludewidth | 170 | Added 618 (2010-09-14) | |
occludeheight | 171 | Added 618 (2010-09-14) | |
bgsoundrate | 173 | Added 623 (2010-10-11) | |
177 | Added 637 (2011-02-07) | ||
bgsounddistance | 178 | Added 637 (2011-02-07) | |
189 | 667+ (todo) | ||
param | 249 | Added 500 (2008-06-05) | Map of params key -> value. |
hillskew Types
enum HillSkewType {
none = 0,
floor_skew = 1,
tree_skew = 2,
rotate = 3,
ceiling_skew = 4,
skew_to_fit = 5
}
shape Names
enum LocShape {
wall_straight = 0,
wall_diagonalcorner = 1,
wall_l = 2,
wall_squarecorner = 3,
wall_diagonal = 9,
walldecor_straight_nooffset = 4,
walldecor_straight_offset = 5,
walldecor_diagonal_nooffset = 6,
walldecor_diagonal_offset = 7,
walldecor_diagonal_both = 8,
centrepiece_straight = 10,
centrepiece_diagonal = 11,
grounddecor = 22,
roof_straight = 12,
roof_diagonal_with_roofedge = 13,
roof_diagonal = 14,
roof_l_concave = 15,
roof_l_convex = 16,
roof_flat = 17,
roofedge_straight = 18,
roofedge_diagonalcorner = 19,
roofedge_l = 20,
roofedge_squarecorner = 21,
}
shape Map Editor Hotkeys
// hotkeys in jagex's map editor are used as the extension for loc models so they know which shape to inherit
enum LocShapeHotkey {
_1 = 0, // 'wall_straight',
_2 = 1, // 'wall_diagonalcorner',
_3 = 2, // 'wall_l',
_4 = 3, // 'wall_squarecorner',
_5 = 9, // 'wall_diagonal',
//
_q = 4, // 'walldecor_straight_nooffset',
_w = 5, // 'walldecor_straight_offset',
_e = 6, // 'walldecor_diagonal_nooffset',
_r = 7, // 'walldecor_diagonal_offset',
_t = 8, // 'walldecor_diagonal_both',
//
_8 = 10, // 'centrepiece_straight',
_9 = 11, // 'centrepiece_diagonal',
_0 = 22, // 'grounddecor',
//
_a = 12, // 'roof_straight',
_s = 13, // 'roof_diagonal_with_roofedge',
_d = 14, // 'roof_diagonal',
_f = 15, // 'roof_l_concave',
_g = 16, // 'roof_l_convex',
_h = 17, // 'roof_flat',
//
_z = 18, // 'roofedge_straight',
_x = 19, // 'roofedge_diagonalcorner',
_c = 20, // 'roofedge_l',
_v = 21, // 'roofedge_squarecorner',
}
model Property
This property is used to render a specific model based on the shape. The shape to use comes from the map data and zone protocol.
This opcode is packed at the end of the config when we receive it in the cache.
Config
[example]
model=example
They only need to define this as a single model=name
, the shape is derived by looking for suffixes on file names in their src/models/
directory. The suffixes are not the shape numbers here but rather their map editor's hotkeys!
Scenario 1: a model example_8.ob3
and they have model=example
in their loc config. It sees _8
and then knows to add shape=10.
Scenario 2: two models, example_8.ob3
and example_0.ob3
and they have model=example
in their loc config. It sees both suffixes and knows to add shape=10 and shape=22 with those model IDs.
Scenario 3: two models, example_8.ob3
and example_0.ob3
again, but this time they have model=example_0
in their loc config. It sees that it's a specific suffix and adds that grounddecor model using shape=10 instead. This is a very particular feature used to override the appearance of the standard centrepiece_straight shape.
186
if (opcode == 1) {
int count = buf.g1();
this.shapes = new int[count];
this.models = new int[count];
for (int i = 0; i < count; i++) {
this.models[i] = buf.g2();
this.shapes[i] = buf.g1();
}
}
249
Opcode 5 was added (in addition to 1) for models that are solely shape 10.
if (opcode == 5) {
int count = buf.g1();
if (this.models == null || lowmem) {
this.shapes = null;
this.models = new int[count];
for (int i = 0; i < count; i++) {
this.models[i] = buf.g2();
}
}
}
300
Locs are able to change their appearance for lowmem (low detail) mode. I have no clue what this looks like on their end -- maybe another key like ldmodel, or maybe it just assumes one of the model= values is lowmem inherently?
if (opcode == 1) {
int count = buf.g1();
if (count > 0) {
// this opcode can be packed twice -- the first instance is the standard models
// the second instance is the low-detail model
if (this.models == null || lowmem) {
this.shapes = new int[count];
this.models = new int[count];
for (int i = 0; i < count; i++) {
this.models[i] = buf.g2();
this.shapes[i] = buf.g1();
}
} else {
buf.pos += count * 2;
}
}
} else if (opcode == 5) {
int count = buf.g1();
if (count > 0) {
// same as above
if (this.models == null || lowmem) {
this.shapes = null;
this.models = new int[count];
for (int i = 0; i < count; i++) {
this.models[i] = buf.g2();
}
} else {
buf.pos += count * 2;
}
}
}
581
Models is now a 2d array so multiple models can be merged when rendering a loc shape.
Opcode 5 is now used to differentiate the lowmem models (not limited to shape 10).
if (opcode == 1 || opcode == 5) {
if (opcode == 5 && LocTypeList.lowmem) {
this.skipModels(buf);
}
int shapeCount = buf.g1();
this.shapes = new byte[shapeCount];
this.models = new int[shapeCount][];
for (int i = 0; i < shapeCount; i++) {
this.shapes[i] = buf.g1();
int modelCount = buf.g1();
this.models[i] = new int[modelCount];
for (int j = 0; j < modelCount; j++) {
this.models[i][j] = buf.g2();
}
}
if (opcode == 5 && !LocTypeList.lowmem) {
this.skipModels(buf);
}
}
void skipModels(Buffer buf) {
int shapeCount = buf.g1();
for (int i = 0; i < shapeCount; i++) {
buf.pos++;
int modelCount = buf.g1();
buf.pos += modelCount * 2;
}
}
name Property
This property is the visible tooltip name. Occasionally, the internal debug name can slip in here, but that isn't visible unless the loc is "active" (based on shape or explicitly defined).
This opcode is packed at the end of the config when we receive it in the cache.
Config
[example]
name=Example
186
if (opcode == 2) {
this.name = buf.gjstr();
}
desc Property
This property is the examine text. After 2006 this was no longer stored in the cache and is transmitted on-demand when a player examines something.
This opcode is packed at the end of the config when we receive it in the cache.
Config
[example]
desc=This is an example
186
if (opcode == 3) {
this.desc = buf.gjstr();
}
width Property
Number of tiles a loc takes on the east/west axis.
186
if (opcode == 14) {
this.width = buf.g1();
}
length Property
Number of tiles a loc takes on the north/south axis.
186
if (opcode == 15) {
this.length = buf.g1();
}
blockwalk Property
Pathfinder property - controls line-of-walk checks through this tile.
186
if (opcode == 17) {
this.blockwalk = false;
}
blockrange Property
Pathfinder property - controls line-of-sight checks through this tile.
186
if (opcode == 18) {
this.blockrange = false;
}
active Property
Overrides if a loc can be examined and/or interacted with. There is a default value based on the available shapes/ops.
Config
[door]
active=yes
op1=Open
This door example is good because doors use wall shapes, so they wouldn't be set to active (able to use) without this.
186
if (opcode == 19) {
active = dat.g1();
if (active == 1) {
this.active = true;
}
}
// after all decoding
if (active == -1) {
this.active = this.shapes.length > 0 && this.shapes[0] == 10;
if (this.ops != null) {
this.active = true;
}
}
hillskew Property
Aligns the loc to the tile's height.
if (opcode == 21) {
this.hillskew = true;
}
Allows vertex lighting to be shared between neighboring locs.
if (opcode == 22) {
this.sharelight = true;
}
occlude Property
if (opcode == 23) {
this.occlude = true;
}
if (opcode == 103) {
this.occlude = false;
}
anim Property
if (opcode == 24) {
this.anim = 65535;
if (this.anim != 65535) {
this.anim = -1;
}
}
wallwidth Property
if (code == 28) {
this.wallwidth = dat.g1();
}
ambient Property
if (code == 29) {
this.ambient = dat.g1b();
}
contrast Property
if (code == 39) {
this.contrast = dat.g1b();
}
op Properties
op1-5 directly correlates to the server-script triggers for oploc1 through oploc5.
There are options labelled "hidden" which are used for the server-side triggers to repeat oploc interactions.
if (code >= 30 && code < 39) {
if (this.ops == null) {
this.ops = new String[5];
}
this.ops[code - 30] = dat.gjstr();
if (this.ops[code - 30].equalsIgnoreCase("hidden")) {
this.ops[code - 30] = null;
}
}
recol Properties
Recolor part of a model.
if (code == 40) {
int count = dat.g1();
this.recol_s = new int[count];
this.recol_d = new int[count];
for (int i = 0; i < count; i++) {
this.recol_s[i] = dat.g2();
this.recol_d[i] = dat.g2();
}
}
retex Properties
Retexture part of a model.
recol_dpalette Properties
mapfunction Property
Draws a mapfunction sprite on the minimap where this loc is.
if (code == 60) {
this.mapfunction = dat.g2();
}
mirror Property
if (code == 62) {
this.mirror = true;
}
shadow Property
if (code == 64) {
this.shadow = false;
}
resize Properties
if (code == 65) {
this.resizex = dat.g2();
} else if (code == 66) {
this.resizey = dat.g2();
} else if (code == 67) {
this.resizez = dat.g2();
}
mapscene Property
Draws a mapscene sprite on the minimap where this loc is.
if (code == 68) {
this.mapscene = dat.g2();
}
forceapproach Property
Pathfinder property - forces the player to approach the loc from a specific side.
if bit 1 == 0: top (north)
if bit 2 == 0: right (east)
if bit 3 == 0: bottom (south)
if bit 4 == 0: left (west)
186
if (code == 69) {
this.forceapproach = dat.g1();
}
offset Properties
if (code == 70) {
this.offsetx = dat.g2s();
} else if (code == 71) {
this.offsety = dat.g2s();
} else if (code == 72) {
this.offsetz = dat.g2s();
}
forcedecor Property
if (code == 73) {
this.forcedecor=true
}
breakroutefinding Property
Pathfinder property - allow the pathfinder to route through this loc.
Scenario: interacting with a NPC behind a bank booth from an outside wall, so the player walks around to be within operable range.
if (code === 74) {
this.breakroutefinding = true;
}
raiseobject Property
if (code === 75) {
this.raiseobject = buf.g1();
}
multiloc Property
bgsound Property
if (code === 78) {
this.bgsound = buf.g2();
this.bgsoundrange = buf.g1();
}
randomsound Property
if (code === 79) {
this.bgsoundmin = buf.g1();
this.bgsoundmax = bug.g1();
this.bgsoundrange = buf.g1();
int count = buf.g1();
this.bgsounds = new int[count];
for (int i = 0; i < count; i++) {
this.bgsounds[i] = buf.g2();
}
}
hardshadow Property
if (code === 88) {
this.hardshadow = false;
}
randseq Property
if (code === 89) {
this.randseq = false;
}
members Property
if (code === 91) {
this.members = true;
}
mapscenerotates Property
cursor Properties
mapsceneangle Property
bgsoundvol Property
mapsceneflipy Property
anims Properties
mel Property
memberop Property
quests Property
tint Property
postoffset Properties
decorheight Property
occludewidth Property
occludeheight Property
bgsoundrate Property
bgsounddistance Property
param Properties
RS3
Very little time spent on RS3 (little-to-no tools). Here's some ones that existed in 2016.
Property | Opcode | History | Notes |
---|---|---|---|
44 | |||
45 | |||
179 | |||
186 | |||
188 | |||
196 | |||
197 | |||
198 | |||
199 | |||
200 | |||
201 | |||
250 | |||
251 | |||
252 | |||
253 | |||
254 | |||
255 |
OSRS
OSRS is pretty similar, it forked from 468 but they can also backport stuff - here's the known additions
Property | Opcode | History | Notes |
---|---|---|---|
category | 61 | Added 197 (2021-06-16) | Originally only server-sided. |
External Credits
* Walied for reviewing the list afterwards and advising on some properties