@2003scape/rsc-client
Version:
runescape classic web client
1,830 lines (1,559 loc) • 138 kB
JavaScript
const Long = require('long');
const Polygon = require('./polygon');
const Scanline = require('./scanline');
const COLOUR_TRANSPARENT = 12345678;
/*function polygonDepthSort(a, b) {
if (a.depth === 0) {
return 1;
}
if (a.depth === b.depth) {
return 0;
}
return a.depth < b.depth ? 1 : -1;
}*/
class Scene {
constructor(surface, maxModelCount, polygonCount, spriteCount) {
this.lastVisiblePolygonsCount = 0;
this.anIntArray377 = null;
this.textureCount = 0;
this.textureColoursUsed = null;
this.textureColourList = null;
this.textureDimension = null;
this.textureLoadedNumber = null;
this.texturePixels = null;
this.textureBackTransparent = null;
this.textureColours64 = null;
this.textureColours128 = null;
this.scanlines = null;
this.minY = 0;
this.maxY = 0;
this.interlace = false;
this.mouseX = 0;
this.mouseY = 0;
this.mousePickedCount = 0;
this.newStart = 0;
this.newEnd = 0;
this.cameraX = 0;
this.cameraY = 0;
this.cameraZ = 0;
this.cameraYaw = 0;
this.cameraPitch = 0;
this.cameraRoll = 0;
this.rampCount = 50;
this.gradientBase = new Int32Array(this.rampCount);
this.gradientRamps = [];
for (let i = 0; i < this.rampCount; i += 1) {
this.gradientRamps.push(new Int32Array(256));
}
this.clipNear = 5;
this.clipFar3d = 1000;
this.clipFar2d = 1000;
this.fogZFalloff = 20;
this.fogZDistance = 10;
this.wideBand = false;
this.mousePickingActive = false;
this.mousePickedMax = 100;
this.mousePickedModels = [];
this.mousePickedModels.length = this.mousePickedMax;
this.mousePickedModels.fill(null);
this.mousePickedFaces = new Int32Array(this.mousePickedMax);
this.width = 512;
this.clipX = 256;
this.clipY = 192;
this.baseX = 256;
this.baseY = 256;
this.viewDistance = 8;
this.normalMagnitude = 4;
this.planeX = new Int32Array(40);
this.planeY = new Int32Array(40);
this.vertexShade = new Int32Array(40);
this.vertexX = new Int32Array(40);
this.vertexY = new Int32Array(40);
this.vertexZ = new Int32Array(40);
this.interlace = false;
this.surface = surface;
this.clipX = (surface.width2 / 2) | 0;
this.clipY = (surface.height2 / 2) | 0;
this.raster = surface.pixels;
this.modelCount = 0;
this.maxModelCount = maxModelCount;
this.models = [];
this.models.length = this.maxModelCount;
this.models.fill(null);
this.visiblePolygonsCount = 0;
this.visiblePolygons = [];
for (let i = 0; i < polygonCount; i++) {
this.visiblePolygons.push(new Polygon());
}
this.spriteCount = 0;
//this.view = new GameModel(k * 2, k);
this.spriteId = new Int32Array(spriteCount);
this.spriteWidth = new Int32Array(spriteCount);
this.spriteHeight = new Int32Array(spriteCount);
this.spriteX = new Int32Array(spriteCount);
this.spriteZ = new Int32Array(spriteCount);
this.spriteY = new Int32Array(spriteCount);
this.spriteTranslateX = new Int32Array(spriteCount);
/*if (this.aByteArray434 === null) {
this.aByteArray434 = new Int8Array(17691);
}*/
this.cameraX = 0;
this.cameraY = 0;
this.cameraZ = 0;
this.cameraYaw = 0;
this.cameraPitch = 0;
this.cameraRoll = 0;
for (let i = 0; i < 256; i++) {
Scene.sin512Cache[i] = (Math.sin(i * 0.02454369) * 32768) | 0;
Scene.sin512Cache[i + 256] = (Math.cos(i * 0.02454369) * 32768) | 0;
}
for (let i = 0; i < 1024; i++) {
Scene.sinCosCache[i] = (Math.sin(i * 0.00613592315) * 32768) | 0;
Scene.sinCosCache[i + 1024] =
(Math.cos(i * 0.00613592315) * 32768) | 0;
}
}
static textureScanline(
ai,
ai1,
i,
j,
k,
l,
i1,
j1,
k1,
l1,
i2,
j2,
k2,
l2
) {
if (i2 <= 0) {
return;
}
let i3 = 0;
let j3 = 0;
let i4 = 0;
if (i1 !== 0) {
i = (k / i1) << 7;
j = (l / i1) << 7;
}
if (i < 0) {
i = 0;
} else if (i > 16256) {
i = 16256;
}
k += j1;
l += k1;
i1 += l1;
if (i1 !== 0) {
i3 = (k / i1) << 7;
j3 = (l / i1) << 7;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 16256) {
i3 = 16256;
}
let k3 = (i3 - i) >> 4;
let l3 = (j3 - j) >> 4;
for (let j4 = i2 >> 4; j4 > 0; j4--) {
i += k2 & 0x600000;
i4 = k2 >> 23;
k2 += l2;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i = i3;
j = j3;
k += j1;
l += k1;
i1 += l1;
if (i1 !== 0) {
i3 = (k / i1) << 7;
j3 = (l / i1) << 7;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 16256) {
i3 = 16256;
}
k3 = (i3 - i) >> 4;
l3 = (j3 - j) >> 4;
}
for (let k4 = 0; k4 < (i2 & 0xf); k4++) {
if ((k4 & 3) === 0) {
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
}
ai[j2++] = ai1[(j & 0x3f80) + (i >> 7)] >>> i4;
i += k3;
j += l3;
}
}
static textureTranslucentScanline(
ai,
ai1,
i,
j,
k,
l,
i1,
j1,
k1,
l1,
i2,
j2,
k2,
l2
) {
if (i2 <= 0) {
return;
}
let i3 = 0;
let j3 = 0;
let i4 = 0;
if (i1 !== 0) {
i = (k / i1) << 7;
j = (l / i1) << 7;
}
if (i < 0) {
i = 0;
} else if (i > 16256) {
i = 16256;
}
k += j1;
l += k1;
i1 += l1;
if (i1 !== 0) {
i3 = (k / i1) << 7;
j3 = (l / i1) << 7;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 16256) {
i3 = 16256;
}
let k3 = (i3 - i) >> 4;
let l3 = (j3 - j) >> 4;
for (let j4 = i2 >> 4; j4 > 0; j4--) {
i += k2 & 0x600000;
i4 = k2 >> 23;
k2 += l2;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i = i3;
j = j3;
k += j1;
l += k1;
i1 += l1;
if (i1 !== 0) {
i3 = (k / i1) << 7;
j3 = (l / i1) << 7;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 16256) {
i3 = 16256;
}
k3 = (i3 - i) >> 4;
l3 = (j3 - j) >> 4;
}
for (let k4 = 0; k4 < (i2 & 0xf); k4++) {
if ((k4 & 3) === 0) {
i = (i & 0x3fff) + (k2 & 0x600000);
i4 = k2 >> 23;
k2 += l2;
}
ai[j2++] =
(ai1[(j & 0x3f80) + (i >> 7)] >>> i4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
}
}
static textureBackTranslucentScanline(
ai,
i,
j,
k,
ai1,
l,
i1,
j1,
k1,
l1,
i2,
j2,
k2,
l2,
i3
) {
if (j2 <= 0) {
return;
}
let j3 = 0;
let k3 = 0;
i3 <<= 2;
if (j1 !== 0) {
j3 = (l / j1) << 7;
k3 = (i1 / j1) << 7;
}
if (j3 < 0) {
j3 = 0;
} else if (j3 > 16256) {
j3 = 16256;
}
for (let j4 = j2; j4 > 0; j4 -= 16) {
l += k1;
i1 += l1;
j1 += i2;
j = j3;
k = k3;
if (j1 !== 0) {
j3 = (l / j1) << 7;
k3 = (i1 / j1) << 7;
}
if (j3 < 0) {
j3 = 0;
} else if (j3 > 16256) {
j3 = 16256;
}
let l3 = (j3 - j) >> 4;
let i4 = (k3 - k) >> 4;
let k4 = l2 >> 23;
j += l2 & 0x600000;
l2 += i3;
if (j4 < 16) {
for (let l4 = 0; l4 < j4; l4++) {
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((l4 & 3) === 3) {
j = (j & 0x3fff) + (l2 & 0x600000);
k4 = l2 >> 23;
l2 += i3;
}
}
} else {
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
j = (j & 0x3fff) + (l2 & 0x600000);
k4 = l2 >> 23;
l2 += i3;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
j = (j & 0x3fff) + (l2 & 0x600000);
k4 = l2 >> 23;
l2 += i3;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
j = (j & 0x3fff) + (l2 & 0x600000);
k4 = l2 >> 23;
l2 += i3;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0x3f80) + (j >> 7)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
}
}
}
static textureScanline2(
ai,
ai1,
i,
j,
k,
l,
i1,
j1,
k1,
l1,
i2,
j2,
k2,
l2
) {
if (i2 <= 0) {
return;
}
let i3 = 0;
let j3 = 0;
l2 <<= 2;
if (i1 !== 0) {
i3 = (k / i1) << 6;
j3 = (l / i1) << 6;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 4032) {
i3 = 4032;
}
for (let i4 = i2; i4 > 0; i4 -= 16) {
k += j1;
l += k1;
i1 += l1;
i = i3;
j = j3;
if (i1 !== 0) {
i3 = (k / i1) << 6;
j3 = (l / i1) << 6;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 4032) {
i3 = 4032;
}
let k3 = (i3 - i) >> 4;
let l3 = (j3 - j) >> 4;
let j4 = k2 >> 20;
i += k2 & 0xc0000;
k2 += l2;
if (i4 < 16) {
for (let k4 = 0; k4 < i4; k4++) {
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
if ((k4 & 3) === 3) {
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
}
}
} else {
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
i += k3;
j += l3;
ai[j2++] = ai1[(j & 0xfc0) + (i >> 6)] >>> j4;
}
}
}
static textureTranslucentScanline2(
ai,
ai1,
i,
j,
k,
l,
i1,
j1,
k1,
l1,
i2,
j2,
k2,
l2
) {
if (i2 <= 0) {
return;
}
let i3 = 0;
let j3 = 0;
l2 <<= 2;
if (i1 !== 0) {
i3 = (k / i1) << 6;
j3 = (l / i1) << 6;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 4032) {
i3 = 4032;
}
for (let i4 = i2; i4 > 0; i4 -= 16) {
k += j1;
l += k1;
i1 += l1;
i = i3;
j = j3;
if (i1 !== 0) {
i3 = (k / i1) << 6;
j3 = (l / i1) << 6;
}
if (i3 < 0) {
i3 = 0;
} else if (i3 > 4032) {
i3 = 4032;
}
let k3 = (i3 - i) >> 4;
let l3 = (j3 - j) >> 4;
let j4 = k2 >> 20;
i += k2 & 0xc0000;
k2 += l2;
if (i4 < 16) {
for (let k4 = 0; k4 < i4; k4++) {
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
if ((k4 & 3) === 3) {
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
}
}
} else {
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
i = (i & 0xfff) + (k2 & 0xc0000);
j4 = k2 >> 20;
k2 += l2;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
i += k3;
j += l3;
ai[j2++] =
(ai1[(j & 0xfc0) + (i >> 6)] >>> j4) +
((ai[j2] >> 1) & 0x7f7f7f);
}
}
}
static textureBackTranslucentScanline2(
ai,
i,
j,
k,
ai1,
l,
i1,
j1,
k1,
l1,
i2,
j2,
k2,
l2,
i3
) {
if (j2 <= 0) {
return;
}
let j3 = 0;
let k3 = 0;
i3 <<= 2;
if (j1 !== 0) {
j3 = (l / j1) << 6;
k3 = (i1 / j1) << 6;
}
if (j3 < 0) {
j3 = 0;
} else if (j3 > 4032) {
j3 = 4032;
}
for (let j4 = j2; j4 > 0; j4 -= 16) {
l += k1;
i1 += l1;
j1 += i2;
j = j3;
k = k3;
if (j1 !== 0) {
j3 = (l / j1) << 6;
k3 = (i1 / j1) << 6;
}
if (j3 < 0) {
j3 = 0;
} else if (j3 > 4032) {
j3 = 4032;
}
let l3 = (j3 - j) >> 4;
let i4 = (k3 - k) >> 4;
let k4 = l2 >> 20;
j += l2 & 0xc0000;
l2 += i3;
if (j4 < 16) {
for (let l4 = 0; l4 < j4; l4++) {
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((l4 & 3) === 3) {
j = (j & 0xfff) + (l2 & 0xc0000);
k4 = l2 >> 20;
l2 += i3;
}
}
} else {
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
j = (j & 0xfff) + (l2 & 0xc0000);
k4 = l2 >> 20;
l2 += i3;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
j = (j & 0xfff) + (l2 & 0xc0000);
k4 = l2 >> 20;
l2 += i3;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
j = (j & 0xfff) + (l2 & 0xc0000);
k4 = l2 >> 20;
l2 += i3;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
j += l3;
k += i4;
if ((i = ai1[(k & 0xfc0) + (j >> 6)] >>> k4) !== 0) {
ai[k2] = i;
}
k2++;
}
}
}
static gradientScanline(ai, i, j, k, ai1, l, i1) {
if (i >= 0) {
return;
}
i1 <<= 1;
k = ai1[(l >> 8) & 0xff];
l += i1;
let j1 = (i / 8) | 0;
for (let k1 = j1; k1 < 0; k1++) {
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
}
j1 = -(i % 8);
for (let l1 = 0; l1 < j1; l1++) {
ai[j++] = k;
if ((l1 & 1) === 1) {
k = ai1[(l >> 8) & 0xff];
l += i1;
}
}
}
static textureGradientScanline(ai, i, j, k, ai1, l, i1) {
if (i >= 0) {
return;
}
i1 <<= 2;
k = ai1[(l >> 8) & 0xff];
l += i1;
let j1 = (i / 16) | 0;
for (let k1 = j1; k1 < 0; k1++) {
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
k = ai1[(l >> 8) & 0xff];
l += i1;
}
j1 = -(i % 16);
for (let l1 = 0; l1 < j1; l1++) {
ai[j++] = k + ((ai[j] >> 1) & 0x7f7f7f);
if ((l1 & 3) === 3) {
k = ai1[(l >> 8) & 0xff];
l += i1;
l += i1;
}
}
}
static gradientScanline2(ai, i, j, k, ai1, l, i1) {
if (i >= 0) {
return;
}
i1 <<= 2;
k = ai1[(l >> 8) & 0xff];
l += i1;
let j1 = (i / 16) | 0;
for (let k1 = j1; k1 < 0; k1++) {
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
ai[j++] = k;
k = ai1[(l >> 8) & 0xff];
l += i1;
}
j1 = -(i % 16);
for (let l1 = 0; l1 < j1; l1++) {
ai[j++] = k;
if ((l1 & 3) === 3) {
k = ai1[(l >> 8) & 0xff];
l += i1;
}
}
}
static rgb(i, j, k) {
return -1 - ((i / 8) | 0) * 1024 - ((j / 8) | 0) * 32 - ((k / 8) | 0);
}
addModel(model) {
if (model === null) {
console.log('Warning tried to add null object!');
}
if (this.modelCount < this.maxModelCount) {
this.models[this.modelCount++] = model;
}
}
removeModel(gameModel) {
for (let i = 0; i < this.modelCount; i++) {
if (this.models[i] === gameModel) {
this.modelCount--;
for (let j = i; j < this.modelCount; j++) {
this.models[j] = this.models[j + 1];
}
}
}
}
dispose() {
this.clear();
for (let i = 0; i < this.modelCount; i++) {
this.models[i] = null;
}
this.modelCount = 0;
}
clear() {
this.spriteCount = 0;
this.view.clear();
}
reduceSprites(i) {
this.spriteCount -= i;
this.view.reduce(i, i * 2);
if (this.spriteCount < 0) {
this.spriteCount = 0;
}
}
addSprite(n, x, z, y, w, h, tag) {
this.spriteId[this.spriteCount] = n;
this.spriteX[this.spriteCount] = x;
this.spriteZ[this.spriteCount] = z;
this.spriteY[this.spriteCount] = y;
this.spriteWidth[this.spriteCount] = w;
this.spriteHeight[this.spriteCount] = h;
this.spriteTranslateX[this.spriteCount] = 0;
const bottomVert = this.view.createVertex(x, z, y);
const topVert = this.view.createVertex(x, z - h, y);
const vertexes = new Int32Array([bottomVert, topVert]);
this.view.createFace(2, vertexes, 0, 0);
this.view.faceTag[this.spriteCount] = tag;
this.view.isLocalPlayer[this.spriteCount++] = 0;
return this.spriteCount - 1;
}
setLocalPlayer(i) {
this.view.isLocalPlayer[i] = 1;
}
setSpriteTranslateX(i, n) {
this.spriteTranslateX[i] = n;
}
setMouseLoc(x, y) {
this.mouseX = x - this.baseX;
this.mouseY = y;
this.mousePickedCount = 0;
this.mousePickingActive = true;
}
// TODO remove these getters
getMousePickedCount() {
return this.mousePickedCount;
}
getMousePickedFaces() {
return this.mousePickedFaces;
}
getMousePickedModels() {
return this.mousePickedModels;
}
setBounds(baseX, baseY, clipX, clipY, width, viewDistance) {
this.clipX = clipX;
this.clipY = clipY;
this.baseX = baseX;
this.baseY = baseY;
this.width = width;
this.viewDistance = viewDistance;
this.scanlines = [];
for (let k1 = 0; k1 < clipY + baseY; k1++) {
this.scanlines.push(new Scanline());
}
}
polygonsQSort(polygons, low, high) {
if (low < high) {
let min = low - 1;
let max = high + 1;
let mid = ((low + high) / 2) | 0;
let polygon = polygons[mid];
polygons[mid] = polygons[low];
polygons[low] = polygon;
let j1 = polygon.depth;
while (min < max) {
do {
max--;
} while (polygons[max].depth < j1);
do {
min++;
} while (polygons[min].depth > j1);
if (min < max) {
let polygon_1 = polygons[min];
polygons[min] = polygons[max];
polygons[max] = polygon_1;
}
}
this.polygonsQSort(polygons, low, max);
this.polygonsQSort(polygons, max + 1, high);
}
}
polygonsIntersectSort(step, polygons, count) {
for (let i = 0; i <= count; i++) {
polygons[i].skipSomething = false;
polygons[i].index = i;
polygons[i].index2 = -1;
}
let l = 0;
do {
while (polygons[l].skipSomething) {
l++;
}
if (l === count) {
return;
}
let polygon = polygons[l];
polygon.skipSomething = true;
let i1 = l;
let j1 = l + step;
if (j1 >= count) {
j1 = count - 1;
}
for (let k1 = j1; k1 >= i1 + 1; k1--) {
let other = polygons[k1];
if (
polygon.minPlaneX < other.maxPlaneX &&
other.minPlaneX < polygon.maxPlaneX &&
polygon.minPlaneY < other.maxPlaneY &&
other.minPlaneY < polygon.maxPlaneY &&
polygon.index !== other.index2 &&
!this.separatePolygon(polygon, other) &&
this.heuristicPolygon(other, polygon)
) {
this.polygonsOrder(polygons, i1, k1);
if (polygons[k1] !== other) {
k1++;
}
i1 = this.newStart;
other.index2 = polygon.index;
}
}
} while (true);
}
polygonsOrder(polygons, start, end) {
do {
let polygon = polygons[start];
for (let k = start + 1; k <= end; k++) {
let polygon_1 = polygons[k];
if (!this.separatePolygon(polygon_1, polygon)) {
break;
}
polygons[start] = polygon_1;
polygons[k] = polygon;
start = k;
if (start === end) {
this.newStart = start;
this.newEnd = start - 1;
return true;
}
}
let polygon_2 = polygons[end];
for (let l = end - 1; l >= start; l--) {
let polygon_3 = polygons[l];
if (!this.separatePolygon(polygon_2, polygon_3)) {
break;
}
polygons[end] = polygon_3;
polygons[l] = polygon_2;
end = l;
if (start === end) {
this.newStart = end + 1;
this.newEnd = end;
return true;
}
}
if (start + 1 >= end) {
this.newStart = start;
this.newEnd = end;
return false;
}
if (!this.polygonsOrder(polygons, start + 1, end)) {
this.newStart = start;
return false;
}
end = this.newEnd;
} while (true);
}
setFrustum(i, j, k) {
let l = (-this.cameraYaw + 1024) & 0x3ff;
let i1 = (-this.cameraPitch + 1024) & 0x3ff;
let j1 = (-this.cameraRoll + 1024) & 0x3ff;
if (j1 !== 0) {
let k1 = Scene.sinCosCache[j1];
let j2 = Scene.sinCosCache[j1 + 1024];
let i3 = (j * k1 + i * j2) >> 15;
j = (j * j2 - i * k1) >> 15;
i = i3;
}
if (l !== 0) {
let l1 = Scene.sinCosCache[l];
let k2 = Scene.sinCosCache[l + 1024];
let j3 = (j * k2 - k * l1) >> 15;
k = (j * l1 + k * k2) >> 15;
j = j3;
}
if (i1 !== 0) {
let i2 = Scene.sinCosCache[i1];
let l2 = Scene.sinCosCache[i1 + 1024];
let k3 = (k * i2 + i * l2) >> 15;
k = (k * l2 - i * i2) >> 15;
i = k3;
}
if (i < Scene.frustumMaxX) {
Scene.frustumMaxX = i;
}
if (i > Scene.frustumMinX) {
Scene.frustumMinX = i;
}
if (j < Scene.frustumMaxY) {
Scene.frustumMaxY = j;
}
if (j > Scene.frustumMinY) {
Scene.frustumMinY = j;
}
if (k < Scene.frustumFarZ) {
Scene.frustumFarZ = k;
}
if (k > Scene.frustumNearZ) {
Scene.frustumNearZ = k;
}
}
render() {
this.interlace = this.surface.interlace;
let i3 = (this.clipX * this.clipFar3d) >> this.viewDistance;
let j3 = (this.clipY * this.clipFar3d) >> this.viewDistance;
Scene.frustumMaxX = 0;
Scene.frustumMinX = 0;
Scene.frustumMaxY = 0;
Scene.frustumMinY = 0;
Scene.frustumFarZ = 0;
Scene.frustumNearZ = 0;
this.setFrustum(-i3, -j3, this.clipFar3d);
this.setFrustum(-i3, j3, this.clipFar3d);
this.setFrustum(i3, -j3, this.clipFar3d);
this.setFrustum(i3, j3, this.clipFar3d);
this.setFrustum(-this.clipX, -this.clipY, 0);
this.setFrustum(-this.clipX, this.clipY, 0);
this.setFrustum(this.clipX, -this.clipY, 0);
this.setFrustum(this.clipX, this.clipY, 0);
Scene.frustumMaxX += this.cameraX;
Scene.frustumMinX += this.cameraX;
Scene.frustumMaxY += this.cameraY;
Scene.frustumMinY += this.cameraY;
Scene.frustumFarZ += this.cameraZ;
Scene.frustumNearZ += this.cameraZ;
this.models[this.modelCount] = this.view;
this.view.transformState = 2;
for (let i = 0; i < this.modelCount; i++) {
this.models[i].project(
this.cameraX,
this.cameraY,
this.cameraZ,
this.cameraYaw,
this.cameraPitch,
this.cameraRoll,
this.viewDistance,
this.clipNear
);
}
this.models[this.modelCount].project(
this.cameraX,
this.cameraY,
this.cameraZ,
this.cameraYaw,
this.cameraPitch,
this.cameraRoll,
this.viewDistance,
this.clipNear
);
this.visiblePolygonsCount = 0;
for (let count = 0; count < this.modelCount; count++) {
let gameModel = this.models[count];
if (gameModel.visible) {
for (let face = 0; face < gameModel.numFaces; face++) {
let num_vertices = gameModel.faceNumVertices[face];
let vertices = gameModel.faceVertices[face];
let visible = false;
for (let vertex = 0; vertex < num_vertices; vertex++) {
let z = gameModel.projectVertexZ[vertices[vertex]];
if (z <= this.clipNear || z >= this.clipFar3d) {
continue;
}
visible = true;
break;
}
if (visible) {
let viewXCount = 0;
for (let vertex = 0; vertex < num_vertices; vertex++) {
let x = gameModel.vertexViewX[vertices[vertex]];
if (x > -this.clipX) {
viewXCount |= 1;
}
if (x < this.clipX) {
viewXCount |= 2;
}
if (viewXCount === 3) {
break;
}
}
if (viewXCount === 3) {
let viewYCount = 0;
for (
let vertex = 0;
vertex < num_vertices;
vertex++
) {
let k1 =
gameModel.vertexViewY[vertices[vertex]];
if (k1 > -this.clipY) {
viewYCount |= 1;
}
if (k1 < this.clipY) {
viewYCount |= 2;
}
if (viewYCount === 3) {
break;
}
}
if (viewYCount === 3) {
let polygon_1 = this.visiblePolygons[
this.visiblePolygonsCount
];
polygon_1.model = gameModel;
polygon_1.face = face;
this.initialisePolygon3D(
this.visiblePolygonsCount
);
let faceFill = 0;
if (polygon_1.visibility < 0) {
faceFill = gameModel.faceFillFront[face];
} else {
faceFill = gameModel.faceFillBack[face];
}
if (faceFill !== COLOUR_TRANSPARENT) {
let h = 0;
for (
let vertex = 0;
vertex < num_vertices;
vertex++
) {
h +=
gameModel.projectVertexZ[
vertices[vertex]
];
}
polygon_1.depth =
((h / num_vertices) | 0) +
gameModel.depth;
polygon_1.facefill = faceFill;
this.visiblePolygonsCount++;
}
}
}
}
}
}
}
let model_2d = this.view;
if (model_2d.visible) {
for (let face = 0; face < model_2d.numFaces; face++) {
let faceVertices = model_2d.faceVertices[face];
let vertex0 = faceVertices[0];
let vx = model_2d.vertexViewX[vertex0];
let vy = model_2d.vertexViewY[vertex0];
let vz = model_2d.projectVertexZ[vertex0];
if (vz > this.clipNear && vz < this.clipFar2d) {
let vw =
((this.spriteWidth[face] << this.viewDistance) / vz) |
0;
let vh =
((this.spriteHeight[face] << this.viewDistance) / vz) |
0;
if (
vx - ((vw / 2) | 0) <= this.clipX &&
vx + ((vw / 2) | 0) >= -this.clipX &&
vy - vh <= this.clipY &&
vy >= -this.clipY
) {