UNPKG

@2003scape/rsc-client

Version:
1,465 lines (1,256 loc) 88.1 kB
const GameData = require('./game-data'); const Scene = require('./scene'); const GameModel = require('./game-model'); const Utility = require('./utility'); const ndarray = require('ndarray'); class World { constructor(scene, surface) { this.regionWidth = 96; this.regionHeight = 96; this.anInt585 = 128; this.parentModel = null; // Int8Arrays this.landscapePack = null; this.mapPack = null; this.memberLandscapePack = null; this.memberMapPack = null; this.worldInitialised = true; this.objectAdjacency = ndarray( new Int32Array(this.regionWidth * this.regionHeight), [this.regionWidth, this.regionHeight] ); this.tileDirection = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.wallModels = []; this.roofModels = []; for (let i = 0; i < 4; i += 1) { this.wallModels.push([]); this.roofModels.push([]); for (let j = 0; j < 64; j += 1) { this.wallModels[i].push(null); this.roofModels[i].push(null); } } this.terrainColours = new Int32Array(256); this.wallsNorthSouth = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.wallsRoof = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.terrainHeight = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.terrainColour = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.localY = new Int32Array(18432); this.tileDecoration = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.routeVia = ndarray( new Int32Array(this.regionWidth * this.regionHeight), [this.regionWidth, this.regionHeight] ); this.wallsDiagonal = ndarray(new Int32Array(4 * 2304), [4, 2304]); this.wallsEastWest = ndarray(new Int8Array(4 * 2304), [4, 2304]); this.aBoolean592 = false; this.playerAlive = false; this.terrainHeightLocal = ndarray( new Int32Array(this.regionWidth * this.regionHeight), [this.regionWidth, this.regionHeight] ); this.terrainModels = []; this.terrainModels.length = 64; this.terrainModels.fill(null); this.localX = new Int32Array(18432); this.baseMediaSprite = 750; this.scene = scene; this.surface = surface; for (let i = 0; i < 64; i++) { this.terrainColours[i] = Scene.rgb( 255 - i * 4, 255 - ((i * 1.75) | 0), 255 - i * 4 ); } for (let j = 0; j < 64; j++) { this.terrainColours[j + 64] = Scene.rgb(j * 3, 144, 0); } for (let k = 0; k < 64; k++) { this.terrainColours[k + 128] = Scene.rgb( 192 - ((k * 1.5) | 0), 144 - ((k * 1.5) | 0), 0 ); } for (let l = 0; l < 64; l++) { this.terrainColours[l + 192] = Scene.rgb( 96 - ((l * 1.5) | 0), 48 + ((l * 1.5) | 0), 0 ); } } getWallEastWest(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } return this.wallsEastWest.get(h, x * 48 + y) & 0xff; } setTerrainAmbience(x, y, x2, y2, ambience) { let gameModel = this.terrainModels[x + y * 8]; for (let j1 = 0; j1 < gameModel.numVertices; j1++) { if ( gameModel.vertexX[j1] === x2 * this.anInt585 && gameModel.vertexZ[j1] === y2 * this.anInt585 ) { gameModel.setVertexAmbience(j1, ambience); return; } } } getWallRoof(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } return this.wallsRoof.get(h, x * 48 + y); } getElevation(x, y) { let sX = x >> 7; let sY = y >> 7; let aX = x & 0x7f; let aY = y & 0x7f; if (sX < 0 || sY < 0 || sX >= 95 || sY >= 95) { return 0; } let h = 0; let hx = 0; let hy = 0; if (aX <= this.anInt585 - aY) { h = this.getTerrainHeight(sX, sY); hx = this.getTerrainHeight(sX + 1, sY) - h; hy = this.getTerrainHeight(sX, sY + 1) - h; } else { h = this.getTerrainHeight(sX + 1, sY + 1); hx = this.getTerrainHeight(sX, sY + 1) - h; hy = this.getTerrainHeight(sX + 1, sY) - h; aX = this.anInt585 - aX; aY = this.anInt585 - aY; } let elevation = h + (((hx * aX) / this.anInt585) | 0) + (((hy * aY) / this.anInt585) | 0); return elevation; } getWallDiagonal(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } return this.wallsDiagonal.get(h, x * 48 + y); } removeObject2(x, y, id) { if (x < 0 || y < 0 || x >= 95 || y >= 95) { return; } if (GameData.objectType[id] === 1 || GameData.objectType[id] === 2) { let tileDir = this.getTileDirection(x, y); let modelWidth = 0; let modelHeight = 0; if (tileDir === 0 || tileDir === 4) { modelWidth = GameData.objectWidth[id]; modelHeight = GameData.objectHeight[id]; } else { modelHeight = GameData.objectWidth[id]; modelWidth = GameData.objectHeight[id]; } for (let mx = x; mx < x + modelWidth; mx++) { for (let my = y; my < y + modelHeight; my++) { const adjacency = this.objectAdjacency.get(mx, my); if (GameData.objectType[id] === 1) { this.objectAdjacency.set(mx, my, adjacency | 0x40); } else if (tileDir === 0) { this.objectAdjacency.set(mx, my, adjacency | 2); if (mx > 0) { this._setObjectAdjacency_from3(mx - 1, my, 8); } } else if (tileDir === 2) { this.objectAdjacency.set(mx, my, adjacency | 4); if (my < 95) { this._setObjectAdjacency_from3(mx, my + 1, 1); } } else if (tileDir === 4) { this.objectAdjacency.set(mx, my, adjacency | 8); if (mx < 95) { this._setObjectAdjacency_from3(mx + 1, my, 2); } } else if (tileDir === 6) { this.objectAdjacency.set(mx, my, adjacency | 1); if (my > 0) { this._setObjectAdjacency_from3(mx, my - 1, 4); } } } } this.method404(x, y, modelWidth, modelHeight); } } removeWallObject(x, y, k, id) { if (x < 0 || y < 0 || x >= 95 || y >= 95) { return; } if (GameData.wallObjectAdjacent[id] === 1) { const adjacency = this.objectAdjacency.get(x, y); if (k === 0) { this.objectAdjacency.set(x, y, adjacency & 0xfffe); if (y > 0) { this.method407(x, y - 1, 4); } } else if (k === 1) { this.objectAdjacency.set(x, y, adjacency & 0xfffd); if (x > 0) { this.method407(x - 1, y, 8); } } else if (k === 2) { this.objectAdjacency.set(x, y, adjacency & 0xffef); } else if (k === 3) { this.objectAdjacency.set(x, y, adjacency & 0xffdf); } this.method404(x, y, 1, 1); } } method402(i, j, k, l, i1) { let j1 = i * 3; let k1 = j * 3; let l1 = this.scene.method302(l); let i2 = this.scene.method302(i1); l1 = (l1 >> 1) & 0x7f7f7f; i2 = (i2 >> 1) & 0x7f7f7f; if (k === 0) { this.surface.drawLineHoriz(j1, k1, 3, l1); this.surface.drawLineHoriz(j1, k1 + 1, 2, l1); this.surface.drawLineHoriz(j1, k1 + 2, 1, l1); this.surface.drawLineHoriz(j1 + 2, k1 + 1, 1, i2); this.surface.drawLineHoriz(j1 + 1, k1 + 2, 2, i2); return; } if (k === 1) { this.surface.drawLineHoriz(j1, k1, 3, i2); this.surface.drawLineHoriz(j1 + 1, k1 + 1, 2, i2); this.surface.drawLineHoriz(j1 + 2, k1 + 2, 1, i2); this.surface.drawLineHoriz(j1, k1 + 1, 1, l1); this.surface.drawLineHoriz(j1, k1 + 2, 2, l1); } } _loadSection_from4I(x, y, plane, chunk) { const mapName = 'm' + plane + ((x / 10) | 0) + (x % 10) + ((y / 10) | 0) + (y % 10); if (!this.landscapePack) { return; } let mapData = Utility.loadData(mapName + '.hei', 0, this.landscapePack); if (!mapData && this.memberLandscapePack) { mapData = Utility.loadData( mapName + '.hei', 0, this.memberLandscapePack ); } if (mapData && mapData.length) { let off = 0; let lastVal = 0; for (let tile = 0; tile < 2304; ) { let val = mapData[off++] & 0xff; if (val < 128) { this.terrainHeight.set(chunk, tile++, val & 0xff); lastVal = val; } if (val >= 128) { for (let i = 0; i < val - 128; i++) { this.terrainHeight.set(chunk, tile++, lastVal & 0xff); } } } lastVal = 64; for (let tileY = 0; tileY < 48; tileY++) { for (let tileX = 0; tileX < 48; tileX++) { lastVal = (this.terrainHeight.get(chunk, tileX * 48 + tileY) + lastVal) & 0x7f; this.terrainHeight.set( chunk, tileX * 48 + tileY, (lastVal * 2) & 0xff ); } } lastVal = 0; for (let tile = 0; tile < 2304; ) { let val = mapData[off++] & 0xff; if (val < 128) { this.terrainColour.set(chunk, tile++, val & 0xff); lastVal = val; } if (val >= 128) { for (let i = 0; i < val - 128; i++) { this.terrainColour.set(chunk, tile++, lastVal & 0xff); } } } lastVal = 35; for (let tileY = 0; tileY < 48; tileY++) { for (let tileX = 0; tileX < 48; tileX++) { lastVal = (this.terrainColour.get(chunk, tileX * 48 + tileY) + lastVal) & 0x7f; // ??? wat this.terrainColour.set( chunk, tileX * 48 + tileY, (lastVal * 2) & 0xff ); } } } else { for (let tile = 0; tile < 2304; tile++) { this.terrainHeight.set(chunk, tile, 0); this.terrainColour.set(chunk, tile, 0); } } mapData = Utility.loadData(mapName + '.dat', 0, this.mapPack); if (!mapData && this.memberMapPack) { mapData = Utility.loadData(mapName + '.dat', 0, this.memberMapPack); } if (mapData && mapData.length) { let off = 0; for (let tile = 0; tile < 2304; tile++) { this.wallsNorthSouth.set(chunk, tile, mapData[off++]); } for (let tile = 0; tile < 2304; tile++) { this.wallsEastWest.set(chunk, tile, mapData[off++]); } for (let tile = 0; tile < 2304; tile++) { this.wallsDiagonal.set(chunk, tile, mapData[off++] & 0xff); } for (let tile = 0; tile < 2304; tile++) { let val = mapData[off++] & 0xff; if (val > 0) { this.wallsDiagonal.set(chunk, tile, val + 12000); } } for (let tile = 0; tile < 2304; ) { let val = mapData[off++] & 0xff; if (val < 128) { this.wallsRoof.set(chunk, tile++, val & 0xff); } else { for (let i = 0; i < val - 128; i++) { this.wallsRoof.set(chunk, tile++, 0); } } } let lastVal = 0; for (let tile = 0; tile < 2304; ) { let val = mapData[off++] & 0xff; if (val < 128) { this.tileDecoration.set(chunk, tile++, val & 0xff); lastVal = val; } else { for (let i = 0; i < val - 128; i++) { this.tileDecoration.set(chunk, tile++, lastVal); } } } for (let tile = 0; tile < 2304; ) { let val = mapData[off++] & 0xff; if (val < 128) { this.tileDirection.set(chunk, tile++, val & 0xff); } else { for (let i = 0; i < val - 128; i++) { this.tileDirection.set(chunk, tile++, 0); } } } mapData = Utility.loadData(mapName + '.loc', 0, this.mapPack); if (mapData && mapData.length) { off = 0; for (let tile = 0; tile < 2304; ) { let val = mapData[off++] & 0xff; if (val < 128) { this.wallsDiagonal.set(chunk, tile++, val + 48000); } else { tile += val - 128; } } return; } } else { for (let tile = 0; tile < 2304; tile++) { this.terrainHeight.set(chunk, tile, 0); this.terrainColour.set(chunk, tile, 0); this.wallsNorthSouth.set(chunk, tile, 0); this.wallsEastWest.set(chunk, tile, 0); this.wallsDiagonal.set(chunk, tile, 0); this.wallsRoof.set(chunk, tile, 0); this.tileDecoration.set(chunk, tile, 0); if (plane === 0) { this.tileDecoration.set(chunk, tile, -6); } if (plane === 3) { this.tileDecoration.set(chunk, tile, 8); } this.tileDirection.set(chunk, tile, 0); } } } loadSection(...args) { switch (args.length) { case 3: return this._loadSection_from3(...args); case 4: if (typeof args[3] === 'number') { return this._loadSection_from4I(...args); } return this._loadSection_from4(...args); } } method404(x, y, k, l) { if ( x < 1 || y < 1 || x + k >= this.regionWidth || y + l >= this.regionHeight ) { return; } for (let xx = x; xx <= x + k; xx++) { for (let yy = y; yy <= y + l; yy++) { if ( (this.getObjectAdjacency(xx, yy) & 0x63) !== 0 || (this.getObjectAdjacency(xx - 1, yy) & 0x59) !== 0 || (this.getObjectAdjacency(xx, yy - 1) & 0x56) !== 0 || (this.getObjectAdjacency(xx - 1, yy - 1) & 0x6c) !== 0 ) { this.method425(xx, yy, 35); } else { this.method425(xx, yy, 0); } } } } getObjectAdjacency(x, y) { if (x < 0 || y < 0 || x >= this.regionWidth || y >= this.regionHeight) { return 0; } else { return this.objectAdjacency.get(x, y); } } hasRoof(x, y) { return ( this.getWallRoof(x, y) > 0 && this.getWallRoof(x - 1, y) > 0 && this.getWallRoof(x - 1, y - 1) > 0 && this.getWallRoof(x, y - 1) > 0 ); } method407(i, j, k) { const adjacency = this.objectAdjacency.get(i, j); this.objectAdjacency.set(i, j, adjacency & (0xffff - k)); } getTerrainColour(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let byte0 = 0; if (x >= 48 && y < 48) { byte0 = 1; x -= 48; } else if (x < 48 && y >= 48) { byte0 = 2; y -= 48; } else if (x >= 48 && y >= 48) { byte0 = 3; x -= 48; y -= 48; } return this.terrainColour.get(byte0, x * 48 + y) & 0xff; } reset() { if (this.worldInitialised) { this.scene.dispose(); } for (let i = 0; i < 64; i++) { this.terrainModels[i] = null; for (let j = 0; j < 4; j++) { this.wallModels[j][i] = null; } for (let k = 0; k < 4; k++) { this.roofModels[k][i] = null; } } } setTiles() { for (let x = 0; x < this.regionWidth; x++) { for (let y = 0; y < this.regionHeight; y++) { if (this.getTileDecoration(x, y, 0) === 250) { if ( x === 47 && this.getTileDecoration(x + 1, y, 0) !== 250 && this.getTileDecoration(x + 1, y, 0) !== 2 ) { this.setTileDecoration(x, y, 9); } else if ( y === 47 && this.getTileDecoration(x, y + 1, 0) !== 250 && this.getTileDecoration(x, y + 1, 0) !== 2 ) { this.setTileDecoration(x, y, 9); } else { this.setTileDecoration(x, y, 2); } } } } } getWallNorthSouth(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } return this.wallsNorthSouth.get(h, x * 48 + y) & 0xff; } getTileDirection(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } return this.tileDirection.get(h, x * 48 + y); } _getTileDecoration_from4(x, y, unused, def) { const decoration = this._getTileDecoration_from3(x, y); if (decoration === 0) { return def; } else { return GameData.tileDecoration[decoration - 1]; } } _getTileDecoration_from3(x, y) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return 0; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } return this.tileDecoration.get(h, x * 48 + y) & 0xff; } getTileDecoration(...args) { switch (args.length) { case 3: return this._getTileDecoration_from3(...args); case 4: return this._getTileDecoration_from4(...args); } } setTileDecoration(x, y, v) { if (x < 0 || x >= this.regionWidth || y < 0 || y >= this.regionHeight) { return; } let h = 0; if (x >= 48 && y < 48) { h = 1; x -= 48; } else if (x < 48 && y >= 48) { h = 2; y -= 48; } else if (x >= 48 && y >= 48) { h = 3; x -= 48; y -= 48; } this.tileDecoration.set(h, x * 48 + y, v & 0xff); } route(startX, startY, endX1, endY1, endX2, endY2, routeX, routeY, objects) { for (let x = 0; x < this.regionWidth; x++) { for (let y = 0; y < this.regionHeight; y++) { this.routeVia.set(x, y, 0); } } let writePtr = 0; let readPtr = 0; let x = startX; let y = startY; this.routeVia.set(startX, startY, 99); routeX[writePtr] = startX; routeY[writePtr++] = startY; let size = routeX.length; let reached = false; while (readPtr !== writePtr) { x = routeX[readPtr]; y = routeY[readPtr]; readPtr = (readPtr + 1) % size; if (x >= endX1 && x <= endX2 && y >= endY1 && y <= endY2) { reached = true; break; } if (objects) { if ( x > 0 && x - 1 >= endX1 && x - 1 <= endX2 && y >= endY1 && y <= endY2 && (this.objectAdjacency.get(x - 1, y) & 8) === 0 ) { reached = true; break; } if ( x < 95 && x + 1 >= endX1 && x + 1 <= endX2 && y >= endY1 && y <= endY2 && (this.objectAdjacency.get(x + 1, y) & 2) === 0 ) { reached = true; break; } if ( y > 0 && x >= endX1 && x <= endX2 && y - 1 >= endY1 && y - 1 <= endY2 && (this.objectAdjacency.get(x, y - 1) & 4) === 0 ) { reached = true; break; } if ( y < 95 && x >= endX1 && x <= endX2 && y + 1 >= endY1 && y + 1 <= endY2 && (this.objectAdjacency.get(x, y + 1) & 1) === 0 ) { reached = true; break; } } if ( x > 0 && this.routeVia.get(x - 1, y) === 0 && (this.objectAdjacency.get(x - 1, y) & 0x78) === 0 ) { routeX[writePtr] = x - 1; routeY[writePtr] = y; writePtr = (writePtr + 1) % size; this.routeVia.set(x - 1, y, 2); } if ( x < 95 && this.routeVia.get(x + 1, y) === 0 && (this.objectAdjacency.get(x + 1, y) & 0x72) === 0 ) { routeX[writePtr] = x + 1; routeY[writePtr] = y; writePtr = (writePtr + 1) % size; this.routeVia.set(x + 1, y, 8); } if ( y > 0 && this.routeVia.get(x, y - 1) === 0 && (this.objectAdjacency.get(x, y - 1) & 0x74) === 0 ) { routeX[writePtr] = x; routeY[writePtr] = y - 1; writePtr = (writePtr + 1) % size; this.routeVia.set(x, y - 1, 1); } if ( y < 95 && this.routeVia.get(x, y + 1) === 0 && (this.objectAdjacency.get(x, y + 1) & 0x71) === 0 ) { routeX[writePtr] = x; routeY[writePtr] = y + 1; writePtr = (writePtr + 1) % size; this.routeVia.set(x, y + 1, 4); } if ( x > 0 && y > 0 && (this.objectAdjacency.get(x, y - 1) & 0x74) === 0 && (this.objectAdjacency.get(x - 1, y) & 0x78) === 0 && (this.objectAdjacency.get(x - 1, y - 1) & 0x7c) === 0 && this.routeVia.get(x - 1, y - 1) === 0 ) { routeX[writePtr] = x - 1; routeY[writePtr] = y - 1; writePtr = (writePtr + 1) % size; this.routeVia.set(x - 1, y - 1, 3); } if ( x < 95 && y > 0 && (this.objectAdjacency.get(x, y - 1) & 0x74) === 0 && (this.objectAdjacency.get(x + 1, y) & 0x72) === 0 && (this.objectAdjacency.get(x + 1, y - 1) & 0x76) === 0 && this.routeVia.get(x + 1, y - 1) === 0 ) { routeX[writePtr] = x + 1; routeY[writePtr] = y - 1; writePtr = (writePtr + 1) % size; this.routeVia.set(x + 1, y - 1, 9); } if ( x > 0 && y < 95 && (this.objectAdjacency.get(x, y + 1) & 0x71) === 0 && (this.objectAdjacency.get(x - 1, y) & 0x78) === 0 && (this.objectAdjacency.get(x - 1, y + 1) & 0x79) === 0 && this.routeVia.get(x - 1, y + 1) === 0 ) { routeX[writePtr] = x - 1; routeY[writePtr] = y + 1; writePtr = (writePtr + 1) % size; this.routeVia.set(x - 1, y + 1, 6); } if ( x < 95 && y < 95 && (this.objectAdjacency.get(x, y + 1) & 0x71) === 0 && (this.objectAdjacency.get(x + 1, y) & 0x72) === 0 && (this.objectAdjacency.get(x + 1, y + 1) & 0x73) === 0 && this.routeVia.get(x + 1, y + 1) === 0 ) { routeX[writePtr] = x + 1; routeY[writePtr] = y + 1; writePtr = (writePtr + 1) % size; this.routeVia.set(x + 1, y + 1, 12); } } if (!reached) { return -1; } readPtr = 0; routeX[readPtr] = x; routeY[readPtr++] = y; let stride; for ( let step = (stride = this.routeVia.get(x, y)); x !== startX || y !== startY; step = this.routeVia.get(x, y) ) { if (step !== stride) { stride = step; routeX[readPtr] = x; routeY[readPtr++] = y; } if ((step & 2) !== 0) { x++; } else if ((step & 8) !== 0) { x--; } if ((step & 1) !== 0) { y++; } else if ((step & 4) !== 0) { y--; } } return readPtr; } _setObjectAdjacency_from4(x, y, dir, id) { if (x < 0 || y < 0 || x >= 95 || y >= 95) { return; } if (GameData.wallObjectAdjacent[id] === 1) { const adjacency = this.objectAdjacency.get(x, y); if (dir === 0) { this.objectAdjacency.set(x, y, adjacency | 1); if (y > 0) { this._setObjectAdjacency_from3(x, y - 1, 4); } } else if (dir === 1) { this.objectAdjacency.set(x, y, adjacency | 2); if (x > 0) { this._setObjectAdjacency_from3(x - 1, y, 8); } } else if (dir === 2) { this.objectAdjacency.set(x, y, adjacency | 0x10); } else if (dir === 3) { this.objectAdjacency.set(x, y, adjacency | 0x20); } this.method404(x, y, 1, 1); } } setObjectAdjacency(...args) { switch (args.length) { case 4: return this._setObjectAdjacency_from4(...args); case 3: return this._setObjectAdjacency_from3(...args); } } _loadSection_from4(x, y, plane, flag) { let l = ((x + 24) / 48) | 0; let i1 = ((y + 24) / 48) | 0; this._loadSection_from4I(l - 1, i1 - 1, plane, 0); this._loadSection_from4I(l, i1 - 1, plane, 1); this._loadSection_from4I(l - 1, i1, plane, 2); this._loadSection_from4I(l, i1, plane, 3); this.setTiles(); if (this.parentModel === null) { this.parentModel = GameModel._from7( 18688, 18688, true, true, false, false, true ); } if (flag) { this.surface.blackScreen(); for (let j1 = 0; j1 < this.regionWidth; j1++) { for (let l1 = 0; l1 < this.regionHeight; l1++) { this.objectAdjacency.set(j1, l1, 0); } } let gameModel = this.parentModel; gameModel.clear(); for (let j2 = 0; j2 < this.regionWidth; j2++) { for (let i3 = 0; i3 < this.regionHeight; i3++) { let i4 = -this.getTerrainHeight(j2, i3); if ( this.getTileDecoration(j2, i3, plane) > 0 && GameData.tileType[ this.getTileDecoration(j2, i3, plane) - 1 ] === 4 ) { i4 = 0; } if ( this.getTileDecoration(j2 - 1, i3, plane) > 0 && GameData.tileType[ this.getTileDecoration(j2 - 1, i3, plane) - 1 ] === 4 ) { i4 = 0; } if ( this.getTileDecoration(j2, i3 - 1, plane) > 0 && GameData.tileType[ this.getTileDecoration(j2, i3 - 1, plane) - 1 ] === 4 ) { i4 = 0; } if ( this.getTileDecoration(j2 - 1, i3 - 1, plane) > 0 && GameData.tileType[ this.getTileDecoration(j2 - 1, i3 - 1, plane) - 1 ] === 4 ) { i4 = 0; } let j5 = gameModel.vertexAt( j2 * this.anInt585, i4, i3 * this.anInt585 ); let j7 = ((Math.random() * 10) | 0) - 5; gameModel.setVertexAmbience(j5, j7); } } for (let lx = 0; lx < 95; lx++) { for (let ly = 0; ly < 95; ly++) { let colourIndex = this.getTerrainColour(lx, ly); let colour = this.terrainColours[colourIndex]; let colour_1 = colour; let colour_2 = colour; let l14 = 0; if (plane === 1 || plane === 2) { colour = World.colourTransparent; colour_1 = World.colourTransparent; colour_2 = World.colourTransparent; } if (this.getTileDecoration(lx, ly, plane) > 0) { let decorationType = this.getTileDecoration( lx, ly, plane ); let decorationTileType = GameData.tileType[decorationType - 1]; let tileType = this.getTileType(lx, ly, plane); colour = colour_1 = GameData.tileDecoration[decorationType - 1]; if (decorationTileType === 4) { colour = 1; colour_1 = 1; if (decorationType === 12) { colour = 31; colour_1 = 31; } } if (decorationTileType === 5) { if ( this.getWallDiagonal(lx, ly) > 0 && this.getWallDiagonal(lx, ly) < 24000 ) { if ( this.getTileDecoration( lx - 1, ly, plane, colour_2 ) !== World.colourTransparent && this.getTileDecoration( lx, ly - 1, plane, colour_2 ) !== World.colourTransparent ) { colour = this.getTileDecoration( lx - 1, ly, plane, colour_2 ); l14 = 0; } else if ( this.getTileDecoration( lx + 1, ly, plane, colour_2 ) !== World.colourTransparent && this.getTileDecoration( lx, ly + 1, plane, colour_2 ) !== World.colourTransparent ) { colour_1 = this.getTileDecoration( lx + 1, ly, plane, colour_2 ); l14 = 0; } else if ( this.getTileDecoration( lx + 1, ly, plane, colour_2 ) !== World.colourTransparent && this.getTileDecoration( lx, ly - 1, plane, colour_2 ) !== World.colourTransparent ) { colour_1 = this.getTileDecoration( lx + 1, ly, plane, colour_2 ); l14 = 1; } else if ( this.getTileDecoration( lx - 1, ly, plane, colour_2 ) !== World.colourTransparent && this.getTileDecoration( lx, ly + 1, plane, colour_2 ) !== World.colourTransparent ) { colour = this.getTileDecoration( lx - 1, ly, plane, colour_2 ); l14 = 1; } } } else if ( decorationTileType !== 2 || (this.getWallDiagonal(lx, ly) > 0 && this.getWallDiagonal(lx, ly) < 24000) ) { if ( this.getTileType(lx - 1, ly, plane) !== tileType && this.getTileType(lx, ly - 1, plane) !== tileType ) { colour = colour_2; l14 = 0; } else if ( this.getTileType(lx + 1, ly, plane) !== tileType && this.getTileType(lx, ly + 1, plane) !== tileType ) { colour_1 = colour_2; l14 = 0; } else if ( this.getTileType(lx + 1, ly, plane) !== tileType && this.getTileType(lx, ly - 1, plane) !== tileType ) { colour_1 = colour_2; l14 = 1; } else if ( this.getTileType(lx - 1, ly, plane) !== tileType && this.getTileType(lx, ly + 1, plane) !== tileType ) { colour = colour_2; l14 = 1; } } if (GameData.tileAdjacent[decorationType - 1] !== 0) { const adjacency = this.objectAdjacency.get(lx, ly); this.objectAdjacency.set(lx, ly, adjacency | 0x40); } if (GameData.tileType[decorationType - 1] === 2) { const adjacency = this.objectAdjacency.get(lx, ly); this.objectAdjacency.set(lx, ly, adjacency | 0x80); } } this.method402(lx, ly, l14, colour, colour_1); let i17 = this.getTerrainHeight(lx + 1, ly + 1) - this.getTerrainHeight(lx + 1, ly) + this.getTerrainHeight(lx, ly + 1) - this.getTerrainHeight(lx, ly); if (colour !== colour_1 || i17 !== 0) { let ai = new Int32Array(3); let ai7 = new Int32Array(3); if (l14 === 0) { if (colour !== World.colourTransparent) { ai[0] = ly + lx * 96 + 96; ai[1] = ly + lx * 96; ai[2] = ly + lx * 96 + 1; let l21 = gameModel.createFace( 3, ai, World.colourTransparent, colour ); this.localX[l21] = lx; this.localY[l21] = ly; gameModel.faceTag[l21] = 0x30d40 + l21; } if (colour_1 !== World.colourTransparent) { ai7[0] = ly + lx * 96 + 1; ai7[1] = ly + lx * 96 + 96 + 1; ai7[2] = ly + lx * 96 + 96; let i22 = gameModel.createFace( 3, ai7, World.colourTransparent, colour_1 ); this.localX[i22] = lx; this.localY[i22] = ly; gameModel.faceTag[i22] = 0x30d40 + i22; } } else { if (colour !== World.colourTransparent) { ai[0] = ly + lx * 96 + 1; ai[1] = ly + lx * 96 + 96 + 1; ai[2] = ly + lx * 96; let j22 = gameModel.createFace( 3, ai, World.colourTransparent, colour ); this.localX[j22] = lx; this.localY[j22] = ly; gameModel.faceTag[j22] = 0x30d40 + j22; } if (colour_1 !== World.colourTransparent) { ai7[0] = ly + lx * 96 + 96; ai7[1] = ly + lx * 96; ai7[2] = ly + lx * 96 + 96 + 1; let k22 = gameModel.createFace( 3, ai7, World.colourTransparent, colour_1 ); this.localX[k22] = lx; this.localY[k22] = ly; gameModel.faceTag[k22] = 0x30d40 + k22; } } } else if (colour !== World.colourTransparent) { let ai1 = new Int32Array(4); ai1[0] = ly + lx * 96 + 96; ai1[1] = ly + lx * 96; ai1[2] = ly + lx * 96 + 1; ai1[3] = ly + lx * 96 + 96 + 1; let l19 = gameModel.createFace( 4, ai1, World.colourTransparent, colour ); this.localX[l19] = lx; this.localY[l19] = ly; gameModel.faceTag[l19] = 0x30d40 + l19; } } } for (let k4 = 1; k4 < 95; k4++) { for (let i6 = 1; i6 < 95; i6++) { if ( this.getTileDecoration(k4, i6, plane) > 0 && GameData.tileType[ this.getTileDecoration(k4, i6, plane) - 1 ] === 4 ) { let l7 = GameData.tileDecoration[ this.getTileDecoration(k4, i6, plane) - 1 ]; let j10 = gameModel.vertexAt( k4 * this.anInt585, -this.getTerrainHeight(k4, i6), i6 * this.anInt585 ); let l12 = gameModel.vertexAt( (k4 + 1) * this.anInt585, -this.getTerrainHeight(k4 + 1, i6), i6 * this.anInt585 ); let i15 = gameModel.vertexAt( (k4 + 1) * this.anInt585, -this.getTerrainHeight(k4 + 1, i6 + 1), (i6 + 1) * this.anInt585 ); let j17 = gameModel.vertexAt( k4 * this.anInt585, -this.getTerrainHeight(k4, i6 + 1), (i6 + 1) * this.anInt585 ); let ai2 = new Int32Array([j10, l12, i15, j17]); let i20 = gameModel.createFace( 4, ai2, l7, World.colourTransparent ); this.localX[i20] = k4; this.localY[i20] = i6; gameModel.faceTag[i20] = 0x30d40 + i20; this.method402(k4, i6, 0, l7, l7); } else if ( this.getTileDecoration(k4, i6, plane) === 0 || GameData.tileType[ this.getTileDecoration(k4, i6, plane) - 1 ] !== 3 ) { if ( this.getTileDecoration(k4, i6 + 1, plane) > 0 && GameData.tileType[ this.getTileDecoration(k4, i6 + 1, plane) - 1 ] === 4 ) { let i8 = GameData.tileDecoration[ this.getTileDecoration(k4, i6 + 1, plane) - 1 ]; let k10 = gameModel.vertexAt( k4 * this.anInt585, -this.getTerrainHeight(k4, i6), i6 * this.anInt585 ); let i13 = gameModel.vertexAt( (k4 + 1) * this.anInt585, -this.getTerrainHeight(k4 + 1, i6), i6 * this.anInt585 ); let j15 = gameModel.vertexAt( (k4 + 1) * this.anInt585, -this.getTerrainHeight(k4 + 1, i6 + 1), (i6 + 1) * this.anInt585 ); let k17 = gameModel.vertexAt( k4 * this.anInt585, -this.getTerrainHeight(k4, i6 + 1), (i6 + 1) * this.anInt585 );