#include #include "engine.h" #include "sectorfx.h" #include "globals.h" #include "db.h" #include "misc.h" #include "trig.h" #include "debug4g.h" #include #define kPanScale 8 short shadeList[kMaxXSectors]; short panList[kMaxXSectors]; int shadeCount = 0, panCount = 0; short wallPanList[kMaxXSectors]; int wallPanCount = 0; int gDepth[] = { 0, // kDepthWalk 15 << 8, // kDepthTread 30 << 8, // kDepthWade 40 << 8 // kDepthSwim }; // monotonic flicker -- very doom like static char flicker1[] = { 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, }; // organic flicker -- good for torches static char flicker2[] = { 1, 2, 4, 2, 3, 4, 3, 2, 0, 0, 1, 2, 4, 3, 2, 0, 2, 1, 0, 1, 0, 2, 3, 4, 3, 2, 1, 1, 2, 0, 0, 1, 1, 2, 3, 4, 4, 3, 2, 1, 2, 3, 4, 4, 2, 1, 0, 1, 0, 0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, }; // mostly on flicker -- good for flaky fluourescents static char flicker3[] = { 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 2, 4, 3, 4, 4, 4, 4, 2, 1, 3, 3, 3, 4, 3, 4, 4, 4, 4, 4, 2, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 1, 0, 1, 0, 1, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 4, }; // not yet done (same as 2 for now) static char flicker4[] = { 1, 2, 4, 2, 3, 4, 3, 2, 0, 0, 1, 2, 4, 3, 2, 0, 2, 1, 0, 1, 0, 2, 3, 4, 3, 2, 1, 1, 2, 0, 0, 1, 1, 2, 3, 4, 4, 3, 2, 1, 2, 3, 4, 4, 2, 1, 0, 1, 0, 0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, }; static char strobe[] = { 64, 64, 64, 48, 36, 27, 20, 15, 11, 9, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static int GetWaveValue( int nWave, long time, int freq, int amplitude ) { switch (nWave) { case kWaveNone: return amplitude; case kWaveSquare: return ((time * freq >> 11) & 1) * amplitude; case kWaveSaw: return abs(0x80 - ((time * freq >> 4) & 0xFF)) * amplitude >> 7; case kWaveRampup: return ((time * freq >> 4) & 0xFF) * amplitude >> 8; case kWaveRampdown: return (0xFF - ((time * freq >> 4) & 0xFF)) * amplitude >> 8; case kWaveSine: return (amplitude + mulscale30(amplitude, Sin(time * freq >> 1))) >> 1; case kWaveFlicker1: return flicker1[(time * freq >> 6) & 0x3F] * amplitude; case kWaveFlicker2: return flicker2[(time * freq >> 6) & 0x3F] * amplitude >> 2; case kWaveFlicker3: return flicker3[(time * freq >> 6) & 0x3F] * amplitude >> 2; case kWaveFlicker4: return flicker4[(time * freq >> 6) & 0x3F] * amplitude >> 2; case kWaveStrobe: return strobe[(time * freq >> 6) & 0x3F] * amplitude >> 6; case kWaveSearch: { int phi = ((time * freq >> 1) & kAngleMask) << 2; if (phi > kAngle360) return 0; return (amplitude - mulscale30(amplitude, Cos(phi))) >> 1; } } return 0; }; void DoSectorLighting( void ) { int i, nXSector, nSector; int nWave, freq, amplitude, value; int nWall, startwall, endwall; for (i = 0; i < shadeCount; i++) { nXSector = shadeList[i]; XSECTOR *pXSector = &xsector[nXSector]; nSector = pXSector->reference; dassert(sector[nSector].extra == nXSector); // undo previous lighting if ( pXSector->shade != 0 ) { value = pXSector->shade; if ( pXSector->shadeFloor ) sector[nSector].floorshade = (schar)(sector[nSector].floorshade - value); if ( pXSector->shadeCeiling ) sector[nSector].ceilingshade = (schar)(sector[nSector].ceilingshade - value); if ( pXSector->shadeWalls ) { startwall = sector[nSector].wallptr; endwall = startwall + sector[nSector].wallnum-1; for (nWall = startwall; nWall <= endwall; nWall++) wall[nWall].shade = (schar)(wall[nWall].shade - value); } pXSector->shade = 0; } if ( pXSector->shadeAlways || pXSector->busy ) { freq = pXSector->freq; nWave = pXSector->wave; amplitude = pXSector->amplitude; if ( !pXSector->shadeAlways && pXSector->busy ) amplitude = mulscale16(amplitude, pXSector->busy); value = GetWaveValue(nWave, gFrameClock + pXSector->phase, freq, amplitude); if ( pXSector->shadeFloor ) sector[nSector].floorshade = (schar)ClipRange(sector[nSector].floorshade + value, -128, 127); if ( pXSector->shadeCeiling ) sector[nSector].ceilingshade = (schar)ClipRange(sector[nSector].ceilingshade + value, -128, 127); if ( pXSector->shadeWalls ) { startwall = sector[nSector].wallptr; endwall = startwall + sector[nSector].wallnum-1; for (nWall = startwall; nWall <= endwall; nWall++) wall[nWall].shade = (schar)ClipRange(wall[nWall].shade + value, -128, 127); } pXSector->shade = value; } } } void UndoSectorLighting( void ) // should be used only in mapedit { int nXSector, nSector; int value; int nWall, startwall, endwall; for (nSector = 0; nSector < numsectors; nSector++) { nXSector = sector[nSector].extra; if (nXSector <= 0) continue; XSECTOR *pXSector = &xsector[nXSector]; if ( pXSector->shade != 0 ) { value = pXSector->shade; if ( pXSector->shadeFloor ) sector[nSector].floorshade = (schar)(sector[nSector].floorshade - value); if ( pXSector->shadeCeiling ) sector[nSector].ceilingshade = (schar)(sector[nSector].ceilingshade - value); if ( pXSector->shadeWalls ) { startwall = sector[nSector].wallptr; endwall = startwall + sector[nSector].wallnum-1; for (nWall = startwall; nWall <= endwall; nWall++) wall[nWall].shade = (schar)(wall[nWall].shade - value); } pXSector->shade = 0; } } } void DoSectorPanning( void ) { int i; for (i = 0; i < panCount; i++) { int nXSector = panList[i]; XSECTOR *pXSector = &xsector[nXSector]; int nSector = pXSector->reference; dassert(nSector >= 0 && nSector < kMaxSectors); SECTOR *pSector = §or[nSector]; dassert(pSector->extra == nXSector); if ( pXSector->panAlways || pXSector->busy ) { int panAngle = (pXSector->panAngle - kAngle90) & kAngleMask; int panVel = pXSector->panVel << kPanScale; if ( !pXSector->panAlways && (pXSector->busy & kFluxMask) ) panVel = mulscale16(panVel, pXSector->busy); if ( pXSector->panFloor ) { int nTile = pSector->floorpicnum; int panX = (pSector->floorxpanning << 8) + pXSector->floorxpanFrac; int panY = (pSector->floorypanning << 8) + pXSector->floorypanFrac; panX += mulscale30(kFrameTicks * panVel, Cos(panAngle)) >> ((picsiz[nTile] & 0xF) - (pSector->floorstat & kSectorExpand ? 1 : 0)); panY += mulscale30(kFrameTicks * panVel, Sin(panAngle)) >> ((picsiz[nTile] / 16) - (pSector->floorstat & kSectorExpand ? 1 : 0)); pSector->floorxpanning = (char)(panX >> 8); pSector->floorypanning = (char)(panY >> 8); pXSector->floorxpanFrac = panX & 0xFF; pXSector->floorypanFrac = panY & 0xFF; } if ( pXSector->panCeiling ) { int nTile = pSector->ceilingpicnum; int panX = (pSector->ceilingxpanning << 8) + pXSector->ceilxpanFrac; int panY = (pSector->ceilingypanning << 8) + pXSector->ceilypanFrac; panX += mulscale30(kFrameTicks * panVel, Cos(panAngle)) >> ((picsiz[nTile] & 0xF) - (pSector->ceilingstat & kSectorExpand ? 1 : 0)); panY += mulscale30(kFrameTicks * panVel, Sin(panAngle)) >> ((picsiz[nTile] / 16) - (pSector->ceilingstat & kSectorExpand ? 1 : 0)); pSector->ceilingxpanning = (char)(panX >> 8); pSector->ceilingypanning = (char)(panY >> 8); pXSector->ceilxpanFrac = panX & 0xFF; pXSector->ceilypanFrac = panY & 0xFF; } } } for (i = 0; i < wallPanCount; i++) { int nXWall = wallPanList[i]; XWALL *pXWall = &xwall[nXWall]; int nWall = pXWall->reference; dassert(wall[nWall].extra == nXWall); if ( pXWall->panAlways || pXWall->busy ) { int panXVel = pXWall->panXVel << 8; int panYVel = pXWall->panYVel << 8; if ( !pXWall->panAlways && (pXWall->busy & kFluxMask) ) { panXVel = mulscale16(panXVel, pXWall->busy); panYVel = mulscale16(panYVel, pXWall->busy); } int nTile = wall[nWall].picnum; int panX = (wall[nWall].xpanning << 8) + pXWall->xpanFrac; int panY = (wall[nWall].ypanning << 8) + pXWall->ypanFrac; panX += kFrameTicks * panXVel >> (picsiz[nTile] & 0xF); panY += kFrameTicks * panYVel >> (picsiz[nTile] / 16); wall[nWall].xpanning = (char)(panX >> 8); wall[nWall].ypanning = (char)(panY >> 8); pXWall->xpanFrac = panX & 0xFF; pXWall->ypanFrac = panY & 0xFF; } } } void InitSectorFX( void ) { int i; shadeCount = 0; panCount = 0; wallPanCount = 0; for (i = 0; i < numsectors; i++) { short nXSector = sector[i].extra; if ( nXSector > 0 ) { XSECTOR *pXSector = &xsector[nXSector]; if ( pXSector->amplitude != 0 ) shadeList[shadeCount++] = nXSector; if ( pXSector->panVel != 0 ) panList[panCount++] = nXSector; } } for (i = 0; i < numwalls; i++) { short nXWall = wall[i].extra; if ( nXWall > 0 ) { XWALL *pXWall = &xwall[nXWall]; if ( pXWall->panXVel != 0 || pXWall->panYVel != 0) wallPanList[wallPanCount++] = nXWall; } } }