mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 20:20:40 +00:00
936ce5a866
# Conflicts: # platform/Windows/exhumed.vcxproj # platform/Windows/exhumed.vcxproj.filters
761 lines
13 KiB
C++
761 lines
13 KiB
C++
|
|
#include "typedefs.h"
|
|
#include "lighting.h"
|
|
#include "player.h"
|
|
#include "engine.h"
|
|
#include "exhumed.h"
|
|
#include "sound.h"
|
|
#include "light.h"
|
|
#include "random.h"
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#define kMaxFlashes 2000
|
|
#define kMaxFlickerMask 25
|
|
#define kMaxGlows 50
|
|
#define kMaxFlickers 100
|
|
#define kMaxFlows 375
|
|
|
|
struct Flash
|
|
{
|
|
char field_0;
|
|
short field_1;
|
|
schar shade;
|
|
};
|
|
|
|
struct Glow
|
|
{
|
|
short field_0;
|
|
short field_2;
|
|
short nSector;
|
|
short field_6;
|
|
};
|
|
|
|
struct Flicker
|
|
{
|
|
short field_0;
|
|
short nSector;
|
|
unsigned int field_4;
|
|
};
|
|
|
|
struct Flow
|
|
{
|
|
short field_0;
|
|
short field_2;
|
|
int field_4;
|
|
int field_8;
|
|
int field_C;
|
|
int field_10;
|
|
int field_14;
|
|
int field_18;
|
|
};
|
|
|
|
Flash sFlash[kMaxFlashes];
|
|
|
|
Glow sGlow[kMaxGlows];
|
|
short nNextFlash[kMaxFlashes];
|
|
Flicker sFlicker[kMaxFlickers];
|
|
short nFreeFlash[kMaxFlashes];
|
|
Flow sFlowInfo[kMaxFlows];
|
|
int flickermask[kMaxFlickerMask];
|
|
|
|
short bTorch = 0;
|
|
short nFirstFlash = -1;
|
|
short nLastFlash = -1;
|
|
short nFlashDepth = 2;
|
|
short nFlashes;
|
|
short nFlowCount;
|
|
short nFlickerCount;
|
|
short nGlowCount;
|
|
|
|
int bDoFlicks = 0;
|
|
int bDoGlows = 0;
|
|
|
|
// done
|
|
int GrabFlash()
|
|
{
|
|
if (nFlashes >= kMaxFlashes) {
|
|
return -1;
|
|
}
|
|
|
|
short nFlash = nFreeFlash[nFlashes];
|
|
nNextFlash[nFlash] = -1;
|
|
|
|
nFlashes++;
|
|
|
|
if (nLastFlash <= -1)
|
|
{
|
|
nFirstFlash = nFlash;
|
|
}
|
|
else
|
|
{
|
|
nNextFlash[nLastFlash] = nFlash;
|
|
}
|
|
|
|
nLastFlash = nFlash;
|
|
|
|
return nLastFlash;
|
|
}
|
|
|
|
void InitLights()
|
|
{
|
|
int i;
|
|
nFlickerCount = 0;
|
|
|
|
for (i = 0; i < kMaxFlickerMask; i++) {
|
|
flickermask[i] = RandomSize(0x1F) * 2;
|
|
}
|
|
|
|
nGlowCount = 0;
|
|
nFlowCount = 0;
|
|
nFlashes = 0;
|
|
bDoFlicks = kFalse;
|
|
bDoGlows = kFalse;
|
|
|
|
for (i = 0; i < kMaxFlashes; i++) {
|
|
nFreeFlash[i] = i;
|
|
}
|
|
|
|
nFirstFlash = -1;
|
|
nLastFlash = -1;
|
|
}
|
|
|
|
void AddFlash(short nSector, int x, int y, int z, int val)
|
|
{
|
|
assert(nSector >= 0 && nSector < kMaxSectors);
|
|
|
|
int var_28 = 0;
|
|
unsigned int var_1C = val >> 8;
|
|
|
|
if (var_1C >= nFlashDepth) {
|
|
return;
|
|
}
|
|
|
|
unsigned int var_20 = val & 0x80;
|
|
unsigned int var_18 = val & 0x40;
|
|
|
|
val = ((var_1C + 1) << 8) | char(val);
|
|
|
|
int var_14 = 0;
|
|
|
|
short startwall = sector[nSector].wallptr;
|
|
short endwall = sector[nSector].wallptr + sector[nSector].wallnum;
|
|
|
|
for (int i = startwall; i < endwall; i++)
|
|
{
|
|
short wall2 = wall[i].point2;
|
|
|
|
int xAverage = (wall[i].x + wall[wall2].x) / 2;
|
|
int yAverage = (wall[i].y + wall[wall2].y) / 2;
|
|
|
|
SECTOR *pNextSector = NULL;
|
|
if (wall[i].nextsector > -1) {
|
|
pNextSector = §or[wall[i].nextsector];
|
|
}
|
|
|
|
int ebx = -255;
|
|
|
|
if (!var_18)
|
|
{
|
|
int x2 = x - xAverage;
|
|
if (x2 < 0) {
|
|
x2 = -x2;
|
|
}
|
|
|
|
ebx = x2;
|
|
|
|
int y2 = y - yAverage;
|
|
if (y2 < 0) {
|
|
y2 = -y2;
|
|
}
|
|
|
|
ebx = ((y2 + ebx) >> 4) - 255;
|
|
}
|
|
|
|
if (ebx < 0)
|
|
{
|
|
var_14++;
|
|
var_28 += ebx;
|
|
|
|
if (wall[i].pal < 5)
|
|
{
|
|
if (!pNextSector || pNextSector->floorz < sector[nSector].floorz)
|
|
{
|
|
short nFlash = GrabFlash();
|
|
if (nFlash < 0) {
|
|
return;
|
|
}
|
|
|
|
sFlash[nFlash].field_0 = var_20 | 2;
|
|
sFlash[nFlash].shade = wall[i].shade;
|
|
sFlash[nFlash].field_1 = i;
|
|
|
|
wall[i].pal += 7;
|
|
|
|
ebx += wall[i].shade;
|
|
int eax = ebx;
|
|
|
|
if (ebx < -127) {
|
|
eax = -127;
|
|
}
|
|
|
|
wall[i].shade = eax;
|
|
|
|
if (!var_1C && !wall[i].overpicnum && pNextSector)
|
|
{
|
|
AddFlash(wall[i].nextsector, x, y, z, val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (var_14 && sector[nSector].floorpal < 4)
|
|
{
|
|
short nFlash = GrabFlash();
|
|
if (nFlash < 0) {
|
|
return;
|
|
}
|
|
|
|
sFlash[nFlash].field_0 = var_20 | 1;
|
|
sFlash[nFlash].field_1 = nSector;
|
|
sFlash[nFlash].shade = sector[nSector].floorshade;
|
|
|
|
sector[nSector].floorpal += 7;
|
|
|
|
int edx = sector[nSector].floorshade + var_28;
|
|
int eax = edx;
|
|
|
|
if (edx < -127) {
|
|
eax = -127;
|
|
}
|
|
|
|
sector[nSector].floorshade = eax;
|
|
|
|
if (!(sector[nSector].ceilingstat & 1))
|
|
{
|
|
if (sector[nSector].ceilingpal < 4)
|
|
{
|
|
short nFlash2 = GrabFlash();
|
|
if (nFlash2 >= 0)
|
|
{
|
|
sFlash[nFlash2].field_0 = var_20 | 3;
|
|
sFlash[nFlash2].field_1 = nSector;
|
|
sFlash[nFlash2].shade = sector[nSector].ceilingshade;
|
|
|
|
sector[nSector].ceilingpal += 7;
|
|
|
|
int edx = sector[nSector].ceilingshade + var_28;
|
|
int eax = edx;
|
|
|
|
if (edx < -127) {
|
|
eax = -127;
|
|
}
|
|
|
|
sector[nSector].ceilingshade = eax;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (short nSprite = headspritesect[nSector]; nSprite >= 0; nSprite = nextspritesect[nSprite])
|
|
{
|
|
if (sprite[nSprite].pal < 4)
|
|
{
|
|
short nFlash3 = GrabFlash();
|
|
if (nFlash3 >= 0)
|
|
{
|
|
sFlash[nFlash3].field_0 = var_20 | 4;
|
|
sFlash[nFlash3].shade = sprite[nSprite].shade;
|
|
sFlash[nFlash3].field_1 = nSprite;
|
|
|
|
sprite[nSprite].pal += 7;
|
|
|
|
int eax = -255;
|
|
|
|
if (!var_18)
|
|
{
|
|
int xDiff = x - sprite[nSprite].x;
|
|
if (xDiff < 0) {
|
|
xDiff = -xDiff;
|
|
}
|
|
|
|
int yDiff = y - sprite[nSprite].y;
|
|
if (yDiff < 0) {
|
|
yDiff = -yDiff;
|
|
}
|
|
|
|
eax = ((xDiff + yDiff) >> 4) - 255;
|
|
}
|
|
|
|
if (eax < 0)
|
|
{
|
|
short shade = sprite[nSprite].shade + eax;
|
|
if (shade < -127) {
|
|
shade = -127;
|
|
}
|
|
|
|
sprite[nSprite].shade = shade;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UndoFlashes()
|
|
{
|
|
if (!nFlashes) {
|
|
return;
|
|
}
|
|
|
|
int var_24 = 0; // CHECKME - Watcom error "initializer for variable var_24 may not execute
|
|
|
|
int edi = -1;
|
|
|
|
for (short nFlash = nFirstFlash; nFlash >= 0; nFlash = nNextFlash[nFlash])
|
|
{
|
|
assert(nFlash < 2000 && nFlash >= 0);
|
|
|
|
uchar var_28 = sFlash[nFlash].field_0 & 0x3F;
|
|
short nIndex = sFlash[nFlash].field_1;
|
|
|
|
if (sFlash[nFlash].field_0 & 0x80)
|
|
{
|
|
int var_20 = var_28 - 1;
|
|
assert(var_20 >= 0);
|
|
|
|
schar *pShade = NULL;
|
|
|
|
switch (var_20)
|
|
{
|
|
case 0:
|
|
{
|
|
assert(nIndex >= 0 && nIndex < kMaxSectors);
|
|
|
|
pShade = §or[nIndex].floorshade;
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
assert(nIndex >= 0 && nIndex < kMaxWalls);
|
|
|
|
pShade = &wall[nIndex].shade;
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
assert(nIndex >= 0 && nIndex < kMaxSectors);
|
|
|
|
pShade = §or[nIndex].ceilingshade;
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
assert(nIndex >= 0 && nIndex < kMaxSprites);
|
|
|
|
if (sprite[nIndex].pal >= 7)
|
|
{
|
|
pShade = &sprite[nIndex].shade;
|
|
}
|
|
else {
|
|
goto loc_1868A;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
assert(pShade != NULL);
|
|
|
|
short var_2C = (*pShade) + 6;
|
|
int var_30 = sFlash[nFlash].shade;
|
|
|
|
if (var_2C < var_30)
|
|
{
|
|
*pShade = var_2C;
|
|
edi = nFlash;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// loc_185FE
|
|
var_24 = var_28 - 1; // CHECKME - Watcom error "initializer for variable var_24 may not execute
|
|
assert(var_24 >= 0);
|
|
|
|
switch (var_24)
|
|
{
|
|
default:
|
|
break;
|
|
|
|
case 0:
|
|
{
|
|
sector[nIndex].floorpal -= 7;
|
|
sector[nIndex].floorshade = sFlash[nFlash].shade;
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
wall[nIndex].pal -= 7;
|
|
wall[nIndex].shade = sFlash[nFlash].shade;
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
sector[nIndex].ceilingpal -= 7;
|
|
sector[nIndex].ceilingshade = sFlash[nFlash].shade;
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
if (sprite[nIndex].pal >= 7)
|
|
{
|
|
sprite[nIndex].pal -= 7;
|
|
sprite[nIndex].shade = sFlash[nFlash].shade;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
loc_1868A:
|
|
|
|
nFlashes--;
|
|
assert(nFlashes >= 0);
|
|
|
|
nFreeFlash[nFlashes] = nFlash;
|
|
|
|
if (edi != -1)
|
|
{
|
|
nNextFlash[edi] = nNextFlash[nFlash];
|
|
}
|
|
|
|
if (nFlash == nFirstFlash)
|
|
{
|
|
nFirstFlash = nNextFlash[nFirstFlash];
|
|
}
|
|
|
|
if (nFlash == nLastFlash)
|
|
{
|
|
nLastFlash = edi;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddGlow(short nSector, int nVal)
|
|
{
|
|
if (nGlowCount >= kMaxGlows) {
|
|
return;
|
|
}
|
|
|
|
sGlow[nGlowCount].field_6 = nVal;
|
|
sGlow[nGlowCount].nSector = nSector;
|
|
sGlow[nGlowCount].field_0 = -1;
|
|
sGlow[nGlowCount].field_2 = 0;
|
|
|
|
nGlowCount++;
|
|
}
|
|
|
|
// ok
|
|
void AddFlicker(short nSector, int nVal)
|
|
{
|
|
if (nFlickerCount >= kMaxFlickers) {
|
|
return;
|
|
}
|
|
|
|
sFlicker[nFlickerCount].field_0 = nVal;
|
|
sFlicker[nFlickerCount].nSector = nSector;
|
|
|
|
if (nVal >= 25) {
|
|
nVal = 24;
|
|
}
|
|
|
|
sFlicker[nFlickerCount].field_4 = flickermask[nVal];
|
|
|
|
nFlickerCount++;
|
|
}
|
|
|
|
void DoGlows()
|
|
{
|
|
bDoGlows++;
|
|
|
|
if (bDoGlows < 3) {
|
|
return;
|
|
}
|
|
|
|
bDoGlows = 0;
|
|
|
|
for (int i = 0; i < nGlowCount; i++)
|
|
{
|
|
sGlow[i].field_2++;
|
|
|
|
short nSector = sGlow[i].nSector;
|
|
short nShade = sGlow[i].field_0;
|
|
|
|
if (sGlow[i].field_2 >= sGlow[i].field_6)
|
|
{
|
|
sGlow[i].field_2 = 0;
|
|
sGlow[i].field_0 = -sGlow[i].field_0;
|
|
}
|
|
|
|
sector[nSector].ceilingshade += nShade;
|
|
sector[nSector].floorshade += nShade;
|
|
|
|
int startwall = sector[nSector].wallptr;
|
|
int endwall = startwall + sector[nSector].wallnum - 1;
|
|
|
|
for (int nWall = startwall; nWall <= endwall; nWall++)
|
|
{
|
|
wall[nWall].shade += nShade;
|
|
|
|
// CHECKME - ASM has edx decreasing here. why?
|
|
}
|
|
}
|
|
}
|
|
|
|
void DoFlickers()
|
|
{
|
|
bDoFlicks ^= 1;
|
|
if (!bDoFlicks) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < nFlickerCount; i++)
|
|
{
|
|
short nSector = sFlicker[i].nSector;
|
|
|
|
unsigned int eax = (sFlicker[i].field_4 & 1);
|
|
unsigned int edx = (sFlicker[i].field_4 & 1) << 31;
|
|
unsigned int ebp = sFlicker[i].field_4 >> 1;
|
|
|
|
ebp |= edx;
|
|
edx = ebp & 1;
|
|
|
|
sFlicker[i].field_4 = ebp;
|
|
|
|
if (edx ^ eax)
|
|
{
|
|
short shade;
|
|
|
|
if (eax)
|
|
{
|
|
shade = sFlicker[i].field_0;
|
|
}
|
|
else
|
|
{
|
|
shade = -sFlicker[i].field_0;
|
|
}
|
|
|
|
sector[nSector].ceilingshade += shade;
|
|
sector[nSector].floorshade += shade;
|
|
|
|
int startwall = sector[nSector].wallptr;
|
|
int endwall = startwall + sector[nSector].wallnum - 1;
|
|
|
|
for (int nWall = endwall; nWall >= startwall; nWall--)
|
|
{
|
|
wall[nWall].shade += shade;
|
|
|
|
// CHECKME - ASM has edx decreasing here. why?
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// nWall can also be passed in here via nSprite parameter - TODO - rename nSprite parameter :)
|
|
void AddFlow(int nSprite, int a, int b)
|
|
{
|
|
if (nFlowCount >= kMaxFlows)
|
|
return;
|
|
|
|
short nFlow = nFlowCount;
|
|
nFlowCount++;
|
|
|
|
short var_18;
|
|
|
|
if (b < 2)
|
|
{
|
|
var_18 = sprite[nSprite].sectnum;
|
|
short nPic = sector[var_18].floorpicnum;
|
|
short nAngle = sprite[nSprite].ang;
|
|
|
|
sFlowInfo[nFlow].field_14 = (tilesizx[nPic] << 14) - 1;
|
|
sFlowInfo[nFlow].field_18 = (tilesizy[nPic] << 14) - 1;
|
|
sFlowInfo[nFlow].field_C = (-Sin(nAngle + 512)) * a;
|
|
sFlowInfo[nFlow].field_10 = (-Sin(nAngle)) * a;
|
|
}
|
|
else
|
|
{
|
|
short nAngle;
|
|
|
|
if (b == 2) {
|
|
nAngle = 512;
|
|
}
|
|
else {
|
|
nAngle = 1536;
|
|
}
|
|
|
|
var_18 = nSprite;
|
|
short nPic = wall[var_18].picnum;
|
|
|
|
sFlowInfo[nFlow].field_14 = (tilesizx[nPic] * wall[var_18].xrepeat) << 8;
|
|
sFlowInfo[nFlow].field_18 = (tilesizy[nPic] * wall[var_18].yrepeat) << 8;
|
|
sFlowInfo[nFlow].field_C = (-Sin(nAngle + 512)) * a;
|
|
sFlowInfo[nFlow].field_10 = (-Sin(nAngle)) * a;
|
|
}
|
|
|
|
sFlowInfo[nFlow].field_8 = 0;
|
|
sFlowInfo[nFlow].field_4 = 0;
|
|
sFlowInfo[nFlow].field_0 = var_18;
|
|
sFlowInfo[nFlow].field_2 = b;
|
|
}
|
|
|
|
void DoFlows()
|
|
{
|
|
for (int i = 0; i < nFlowCount; i++)
|
|
{
|
|
sFlowInfo[i].field_4 += sFlowInfo[i].field_C;
|
|
sFlowInfo[i].field_8 += sFlowInfo[i].field_10;
|
|
|
|
switch (sFlowInfo[i].field_2)
|
|
{
|
|
case 0:
|
|
{
|
|
sFlowInfo[i].field_4 &= sFlowInfo[i].field_14;
|
|
sFlowInfo[i].field_8 &= sFlowInfo[i].field_18;
|
|
|
|
short nSector = sFlowInfo[i].field_0;
|
|
sector[nSector].floorxpanning = sFlowInfo[i].field_4 >> 14;
|
|
sector[nSector].floorypanning = sFlowInfo[i].field_8 >> 14;
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
short nSector = sFlowInfo[i].field_0;
|
|
|
|
sector[nSector].ceilingxpanning = sFlowInfo[i].field_4 >> 14;
|
|
sector[nSector].ceilingypanning = sFlowInfo[i].field_8 >> 14;
|
|
|
|
sFlowInfo[i].field_4 &= sFlowInfo[i].field_14;
|
|
sFlowInfo[i].field_8 &= sFlowInfo[i].field_18;
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
short nWall = sFlowInfo[i].field_0;
|
|
|
|
wall[nWall].xpanning = sFlowInfo[i].field_4 >> 14;
|
|
wall[nWall].ypanning = sFlowInfo[i].field_8 >> 14;
|
|
|
|
if (sFlowInfo[i].field_4 < 0)
|
|
{
|
|
sFlowInfo[i].field_4 += sFlowInfo[i].field_14;
|
|
}
|
|
|
|
if (sFlowInfo[i].field_8 < 0)
|
|
{
|
|
sFlowInfo[i].field_8 += sFlowInfo[i].field_18;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
short nWall = sFlowInfo[i].field_0;
|
|
|
|
wall[nWall].xpanning = sFlowInfo[i].field_4 >> 14;
|
|
wall[nWall].ypanning = sFlowInfo[i].field_8 >> 14;
|
|
|
|
if (sFlowInfo[i].field_4 >= sFlowInfo[i].field_14)
|
|
{
|
|
sFlowInfo[i].field_4 -= sFlowInfo[i].field_14;
|
|
}
|
|
|
|
if (sFlowInfo[i].field_8 >= sFlowInfo[i].field_18)
|
|
{
|
|
sFlowInfo[i].field_8 -= sFlowInfo[i].field_18;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DoLights()
|
|
{
|
|
DoFlickers();
|
|
DoGlows();
|
|
DoFlows();
|
|
}
|
|
|
|
void SetTorch(int nPlayer, int bTorchOnOff)
|
|
{
|
|
char buf[40];
|
|
|
|
if (bTorchOnOff == bTorch) {
|
|
return;
|
|
}
|
|
|
|
if (nPlayer != nLocalPlayer) {
|
|
return;
|
|
}
|
|
|
|
char *pTempPal = origpalookup[kPalTorch];
|
|
palookup[kPalTorch] = palookup[kPalNoTorch];
|
|
palookup[kPalNoTorch] = pTempPal;
|
|
|
|
pTempPal = origpalookup[kPalTorch];
|
|
origpalookup[kPalTorch] = origpalookup[kPalNoTorch];
|
|
origpalookup[kPalNoTorch] = pTempPal;
|
|
|
|
pTempPal = origpalookup[kPalTorch2];
|
|
origpalookup[kPalTorch2] = origpalookup[kPalNoTorch2];
|
|
origpalookup[kPalNoTorch2] = pTempPal;
|
|
|
|
pTempPal = palookup[kPalTorch2];
|
|
palookup[kPalNoTorch2] = palookup[kPalTorch2];
|
|
palookup[kPalTorch2] = pTempPal;
|
|
|
|
if (bTorchOnOff == 2) {
|
|
bTorch = bTorch == 0;
|
|
}
|
|
else {
|
|
bTorch = bTorchOnOff;
|
|
}
|
|
|
|
if (bTorch) {
|
|
PlayLocalSound(kSoundTorchOn, 0);
|
|
}
|
|
|
|
strcpy(buf, "TORCH IS ");
|
|
|
|
if (bTorch) {
|
|
strcat(buf, "LIT");
|
|
}
|
|
else {
|
|
strcat(buf, "OUT");
|
|
}
|
|
|
|
StatusMessage(150, buf);
|
|
}
|
|
|
|
void BuildFlash(short nPlayer, short nSector, int nVal)
|
|
{
|
|
if (nPlayer == nLocalPlayer)
|
|
{
|
|
flash = nVal;
|
|
flash = -nVal; // ???
|
|
}
|
|
}
|