2019-11-20 16:21:32 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
|
|
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
|
|
|
This file is part of PCExhumed.
|
|
|
|
PCExhumed is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License version 2
|
|
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-11-22 23:11:37 +00:00
|
|
|
#include "ns.h"
|
2020-08-18 07:52:08 +00:00
|
|
|
#include "aistuff.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include "player.h"
|
|
|
|
#include "engine.h"
|
|
|
|
#include "exhumed.h"
|
|
|
|
#include "sound.h"
|
2020-11-26 17:29:20 +00:00
|
|
|
#include "interpolate.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
BEGIN_PS_NS
|
|
|
|
|
2020-10-11 11:14:32 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
kMaxFlashes = 2000,
|
|
|
|
kMaxFlickerMask = 25,
|
|
|
|
kMaxGlows = 50,
|
|
|
|
kMaxFlickers = 100,
|
|
|
|
kMaxFlows = 375,
|
|
|
|
};
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
struct Flash
|
|
|
|
{
|
2021-10-27 17:35:08 +00:00
|
|
|
int8_t nType;
|
2019-08-31 07:47:15 +00:00
|
|
|
int8_t shade;
|
2021-10-21 08:55:16 +00:00
|
|
|
DExhumedActor* pActor;
|
|
|
|
int nIndex;
|
2020-11-30 00:05:17 +00:00
|
|
|
int next;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Glow
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
short field_0;
|
|
|
|
short field_2;
|
2021-11-09 16:27:54 +00:00
|
|
|
int nSector;
|
2019-08-31 07:47:15 +00:00
|
|
|
short field_6;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Flicker
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
short field_0;
|
2021-11-09 16:27:54 +00:00
|
|
|
int nSector;
|
2019-08-31 07:47:15 +00:00
|
|
|
unsigned int field_4;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Flow
|
|
|
|
{
|
2021-11-09 16:32:50 +00:00
|
|
|
int objindex;
|
|
|
|
int type;
|
2020-11-26 17:29:20 +00:00
|
|
|
int xdelta;
|
|
|
|
int ydelta;
|
2021-10-20 22:01:21 +00:00
|
|
|
int angcos;
|
|
|
|
int angsin;
|
2020-11-26 17:29:20 +00:00
|
|
|
int xacc;
|
|
|
|
int yacc;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
2020-11-30 00:05:17 +00:00
|
|
|
|
|
|
|
FreeListArray<Flash, kMaxFlashes> sFlash;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
Glow sGlow[kMaxGlows];
|
|
|
|
Flicker sFlicker[kMaxFlickers];
|
|
|
|
Flow sFlowInfo[kMaxFlows];
|
|
|
|
int flickermask[kMaxFlickerMask];
|
|
|
|
|
|
|
|
short bTorch = 0;
|
|
|
|
short nFirstFlash = -1;
|
|
|
|
short nLastFlash = -1;
|
|
|
|
short nFlashDepth = 2;
|
|
|
|
short nFlowCount;
|
|
|
|
short nFlickerCount;
|
|
|
|
short nGlowCount;
|
|
|
|
|
|
|
|
int bDoFlicks = 0;
|
|
|
|
int bDoGlows = 0;
|
|
|
|
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2020-11-30 00:05:17 +00:00
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Flash& w, Flash* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
2021-10-27 17:35:08 +00:00
|
|
|
arc("at0", w.nType)
|
2020-11-30 00:05:17 +00:00
|
|
|
("shade", w.shade)
|
2021-10-27 17:35:08 +00:00
|
|
|
("at1", w.nIndex)
|
2020-11-30 00:05:17 +00:00
|
|
|
("next", w.next)
|
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
|
|
|
|
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Glow& w, Glow* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("at0", w.field_0)
|
|
|
|
("at2", w.field_2)
|
|
|
|
("sector", w.nSector)
|
|
|
|
("at6", w.field_6)
|
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
|
|
|
|
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Flicker& w, Flicker* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("at0", w.field_0)
|
|
|
|
("sector", w.nSector)
|
|
|
|
("at4", w.field_4)
|
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
|
|
|
|
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Flow& w, Flow* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("objindex", w.objindex)
|
|
|
|
("type", w.type)
|
|
|
|
("xdelta", w.xdelta)
|
|
|
|
("ydelta", w.ydelta)
|
2021-10-20 22:01:21 +00:00
|
|
|
("atc", w.angcos)
|
|
|
|
("at10", w.angsin)
|
2020-11-30 00:05:17 +00:00
|
|
|
("xacc", w.xacc)
|
|
|
|
("yacc", w.yacc)
|
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2020-11-30 00:05:17 +00:00
|
|
|
void SerializeLighting(FSerializer& arc)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject("lighting"))
|
|
|
|
{
|
|
|
|
arc("flash", sFlash)
|
|
|
|
("glowcount", nGlowCount)
|
|
|
|
.Array("glow", sGlow, nGlowCount)
|
|
|
|
("flickercount", nFlickerCount)
|
|
|
|
.Array("flicker", sFlicker, nFlickerCount)
|
|
|
|
("flowcount", nFlowCount)
|
|
|
|
.Array("flow", sFlowInfo, nFlowCount)
|
|
|
|
.Array("flickermask", flickermask, countof(flickermask))
|
|
|
|
("torch", bTorch)
|
|
|
|
("firstflash", nFirstFlash)
|
|
|
|
("lastflash", nLastFlash)
|
|
|
|
("flashdepth", nFlashDepth)
|
|
|
|
("doflicks", bDoFlicks)
|
|
|
|
("doglows", bDoGlows)
|
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2019-08-26 03:59:14 +00:00
|
|
|
// done
|
|
|
|
int GrabFlash()
|
|
|
|
{
|
2020-11-30 00:05:17 +00:00
|
|
|
int nFlash = sFlash.Get();
|
|
|
|
if (nFlash < 0) {
|
2019-08-31 07:47:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-11-30 00:05:17 +00:00
|
|
|
sFlash[nFlash].next = -1;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nLastFlash <= -1)
|
|
|
|
{
|
|
|
|
nFirstFlash = nFlash;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-30 00:05:17 +00:00
|
|
|
sFlash[nLastFlash].next = nFlash;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nLastFlash = nFlash;
|
|
|
|
return nLastFlash;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void InitLights()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
int i;
|
|
|
|
nFlickerCount = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 0; i < kMaxFlickerMask; i++) {
|
|
|
|
flickermask[i] = RandomSize(0x1F) * 2;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nGlowCount = 0;
|
|
|
|
nFlowCount = 0;
|
2020-08-18 08:28:19 +00:00
|
|
|
bDoFlicks = false;
|
|
|
|
bDoGlows = false;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-11-30 00:05:17 +00:00
|
|
|
sFlash.Clear();
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nFirstFlash = -1;
|
|
|
|
nLastFlash = -1;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-09 16:27:54 +00:00
|
|
|
void AddFlash(int nSector, int x, int y, int z, int val)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
assert(nSector >= 0 && nSector < kMaxSectors);
|
2021-11-07 22:52:45 +00:00
|
|
|
auto sectp = §or[nSector];
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
int var_28 = 0;
|
2021-05-12 15:09:07 +00:00
|
|
|
int var_1C = val >> 8;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
if (var_1C >= nFlashDepth) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int var_20 = val & 0x80;
|
|
|
|
unsigned int var_18 = val & 0x40;
|
|
|
|
|
2021-05-12 15:09:07 +00:00
|
|
|
val = ((var_1C + 1) << 8) | (val & 0xff);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
int var_14 = 0;
|
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
int startwall = sectp->wallptr;
|
|
|
|
int endwall = sectp->wallptr + sectp->wallnum;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
sectortype *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)
|
|
|
|
{
|
2021-11-07 22:52:45 +00:00
|
|
|
if (!pNextSector || pNextSector->floorz < sectp->floorz)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
short nFlash = GrabFlash();
|
|
|
|
if (nFlash < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-27 17:35:08 +00:00
|
|
|
sFlash[nFlash].nType = var_20 | 2;
|
2019-08-31 07:47:15 +00:00
|
|
|
sFlash[nFlash].shade = wall[i].shade;
|
2021-10-27 17:35:08 +00:00
|
|
|
sFlash[nFlash].nIndex = i;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
wall[i].pal += 7;
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
ebx += wall[i].shade;
|
|
|
|
int eax = ebx;
|
|
|
|
|
|
|
|
if (ebx < -127) {
|
|
|
|
eax = -127;
|
|
|
|
}
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
wall[i].shade = eax;
|
|
|
|
|
|
|
|
if (!var_1C && !wall[i].overpicnum && pNextSector)
|
|
|
|
{
|
|
|
|
AddFlash(wall[i].nextsector, x, y, z, val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
if (var_14 && sectp->floorpal < 4)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
short nFlash = GrabFlash();
|
|
|
|
if (nFlash < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-27 17:35:08 +00:00
|
|
|
sFlash[nFlash].nType = var_20 | 1;
|
|
|
|
sFlash[nFlash].nIndex = nSector;
|
2021-11-07 22:52:45 +00:00
|
|
|
sFlash[nFlash].shade = sectp->floorshade;
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
sectp->floorpal += 7;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
int edx = sectp->floorshade + var_28;
|
2019-08-31 07:47:15 +00:00
|
|
|
int eax = edx;
|
|
|
|
|
|
|
|
if (edx < -127) {
|
|
|
|
eax = -127;
|
|
|
|
}
|
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
sectp->floorshade = eax;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
if (!(sectp->ceilingstat & 1))
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-11-07 22:52:45 +00:00
|
|
|
if (sectp->ceilingpal < 4)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
short nFlash2 = GrabFlash();
|
|
|
|
if (nFlash2 >= 0)
|
|
|
|
{
|
2021-10-27 17:35:08 +00:00
|
|
|
sFlash[nFlash2].nType = var_20 | 3;
|
|
|
|
sFlash[nFlash2].nIndex = nSector;
|
2021-11-07 22:52:45 +00:00
|
|
|
sFlash[nFlash2].shade = sectp->ceilingshade;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
sectp->ceilingpal += 7;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
int edx = sectp->ceilingshade + var_28;
|
2019-08-31 07:47:15 +00:00
|
|
|
int eax = edx;
|
|
|
|
|
|
|
|
if (edx < -127) {
|
|
|
|
eax = -127;
|
|
|
|
}
|
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
sectp->ceilingshade = eax;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-20 20:27:16 +00:00
|
|
|
ExhumedSectIterator it(nSector);
|
|
|
|
while (auto pActor = it.Next())
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-20 20:27:16 +00:00
|
|
|
auto pSprite = &pActor->s();
|
2021-09-06 06:33:02 +00:00
|
|
|
if (pSprite->pal < 4)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
short nFlash3 = GrabFlash();
|
|
|
|
if (nFlash3 >= 0)
|
|
|
|
{
|
2021-10-27 17:35:08 +00:00
|
|
|
sFlash[nFlash3].nType = var_20 | 4;
|
2021-09-06 06:33:02 +00:00
|
|
|
sFlash[nFlash3].shade = pSprite->shade;
|
2021-10-21 08:55:16 +00:00
|
|
|
sFlash[nFlash3].nIndex = -1;
|
|
|
|
sFlash[nFlash3].pActor = pActor;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-09-06 06:33:02 +00:00
|
|
|
pSprite->pal += 7;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
int eax = -255;
|
|
|
|
|
|
|
|
if (!var_18)
|
|
|
|
{
|
2021-09-06 06:33:02 +00:00
|
|
|
int xDiff = x - pSprite->x;
|
2019-08-31 07:47:15 +00:00
|
|
|
if (xDiff < 0) {
|
|
|
|
xDiff = -xDiff;
|
|
|
|
}
|
|
|
|
|
2021-09-06 06:33:02 +00:00
|
|
|
int yDiff = y - pSprite->y;
|
2019-08-31 07:47:15 +00:00
|
|
|
if (yDiff < 0) {
|
|
|
|
yDiff = -yDiff;
|
|
|
|
}
|
|
|
|
|
|
|
|
eax = ((xDiff + yDiff) >> 4) - 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eax < 0)
|
|
|
|
{
|
2021-09-06 06:33:02 +00:00
|
|
|
short shade = pSprite->shade + eax;
|
2019-08-31 07:47:15 +00:00
|
|
|
if (shade < -127) {
|
|
|
|
shade = -127;
|
|
|
|
}
|
|
|
|
|
2021-09-06 06:33:02 +00:00
|
|
|
pSprite->shade = (int8_t)shade;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void UndoFlashes()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
int var_24 = 0; // CHECKME - Watcom error "initializer for variable var_24 may not execute
|
|
|
|
|
|
|
|
int edi = -1;
|
|
|
|
|
2021-11-09 16:32:50 +00:00
|
|
|
for (int nFlash = nFirstFlash; nFlash >= 0; nFlash = sFlash[nFlash].next)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
assert(nFlash < 2000 && nFlash >= 0);
|
|
|
|
|
2021-10-27 17:35:08 +00:00
|
|
|
uint8_t type = sFlash[nFlash].nType & 0x3F;
|
2021-11-09 16:32:50 +00:00
|
|
|
int nIndex = sFlash[nFlash].nIndex;
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2021-10-27 17:35:08 +00:00
|
|
|
if (sFlash[nFlash].nType & 0x80)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-27 17:35:08 +00:00
|
|
|
int flashtype = type - 1;
|
|
|
|
assert(flashtype >= 0);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
int8_t *pShade = NULL;
|
|
|
|
|
2021-10-27 17:35:08 +00:00
|
|
|
switch (flashtype)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
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:
|
|
|
|
{
|
2021-10-21 08:55:16 +00:00
|
|
|
auto ac = sFlash[nFlash].pActor;
|
|
|
|
if (!ac) continue;
|
|
|
|
auto sp = &ac->s();
|
|
|
|
if (sp->pal >= 7)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-21 08:55:16 +00:00
|
|
|
pShade = &sp->shade;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
goto loc_1868A;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(pShade != NULL);
|
|
|
|
|
2021-05-12 15:09:07 +00:00
|
|
|
int thisshade = (*pShade) + 6;
|
|
|
|
int maxshade = sFlash[nFlash].shade;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-05-12 15:09:07 +00:00
|
|
|
if (thisshade < maxshade)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-05-12 15:09:07 +00:00
|
|
|
*pShade = (int8_t)thisshade;
|
2019-08-31 07:47:15 +00:00
|
|
|
edi = nFlash;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// loc_185FE
|
2021-10-27 17:35:08 +00:00
|
|
|
var_24 = type - 1; // CHECKME - Watcom error "initializer for variable var_24 may not execute
|
2019-08-31 07:47:15 +00:00
|
|
|
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:
|
|
|
|
{
|
2021-10-21 08:55:16 +00:00
|
|
|
auto ac = sFlash[nFlash].pActor;
|
|
|
|
auto sp = &ac->s();
|
|
|
|
if (sp->pal >= 7)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-21 08:55:16 +00:00
|
|
|
sp->pal -= 7;
|
|
|
|
sp->shade = sFlash[nFlash].shade;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
loc_1868A:
|
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (edi != -1)
|
|
|
|
{
|
2020-11-30 00:05:17 +00:00
|
|
|
sFlash[edi].next = sFlash[nFlash].next;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nFlash == nFirstFlash)
|
|
|
|
{
|
2020-11-30 00:05:17 +00:00
|
|
|
nFirstFlash = sFlash[nFirstFlash].next;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nFlash == nLastFlash)
|
|
|
|
{
|
|
|
|
nLastFlash = edi;
|
|
|
|
}
|
2020-11-30 00:05:17 +00:00
|
|
|
sFlash.Release(nFlash);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-09 16:27:54 +00:00
|
|
|
void AddGlow(int nSector, int nVal)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nGlowCount >= kMaxGlows) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
sGlow[nGlowCount].field_6 = nVal;
|
|
|
|
sGlow[nGlowCount].nSector = nSector;
|
|
|
|
sGlow[nGlowCount].field_0 = -1;
|
|
|
|
sGlow[nGlowCount].field_2 = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nGlowCount++;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ok
|
2021-11-09 16:27:54 +00:00
|
|
|
void AddFlicker(int nSector, int nVal)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nFlickerCount >= kMaxFlickers) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
sFlicker[nFlickerCount].field_0 = nVal;
|
|
|
|
sFlicker[nFlickerCount].nSector = nSector;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nVal >= 25) {
|
|
|
|
nVal = 24;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
sFlicker[nFlickerCount].field_4 = flickermask[nVal];
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nFlickerCount++;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DoGlows()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
bDoGlows++;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (bDoGlows < 3) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
bDoGlows = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < nGlowCount; i++)
|
|
|
|
{
|
|
|
|
sGlow[i].field_2++;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-11-09 16:27:54 +00:00
|
|
|
int nSector =sGlow[i].nSector;
|
2021-11-07 22:52:45 +00:00
|
|
|
auto sectp = §or[nSector];
|
2019-08-31 07:47:15 +00:00
|
|
|
short nShade = sGlow[i].field_0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (sGlow[i].field_2 >= sGlow[i].field_6)
|
|
|
|
{
|
|
|
|
sGlow[i].field_2 = 0;
|
|
|
|
sGlow[i].field_0 = -sGlow[i].field_0;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
sectp->ceilingshade += nShade;
|
|
|
|
sectp->floorshade += nShade;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
int startwall = sectp->wallptr;
|
|
|
|
int endwall = startwall + sectp->wallnum - 1;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int nWall = startwall; nWall <= endwall; nWall++)
|
|
|
|
{
|
|
|
|
wall[nWall].shade += nShade;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
// CHECKME - ASM has edx decreasing here. why?
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DoFlickers()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
bDoFlicks ^= 1;
|
|
|
|
if (!bDoFlicks) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < nFlickerCount; i++)
|
|
|
|
{
|
2021-11-09 16:27:54 +00:00
|
|
|
int nSector =sFlicker[i].nSector;
|
2021-11-07 22:52:45 +00:00
|
|
|
auto sectp = §or[nSector];
|
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
sectp->ceilingshade += shade;
|
|
|
|
sectp->floorshade += shade;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-07 22:52:45 +00:00
|
|
|
int startwall = sectp->wallptr;
|
|
|
|
int endwall = startwall + sectp->wallnum - 1;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
for (int nWall = endwall; nWall >= startwall; nWall--)
|
|
|
|
{
|
|
|
|
wall[nWall].shade += shade;
|
|
|
|
|
|
|
|
// CHECKME - ASM has edx decreasing here. why?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// nWall can also be passed in here via nSprite parameter - TODO - rename nSprite parameter :)
|
2021-10-21 09:26:47 +00:00
|
|
|
void AddFlow(int nIndex, int nSpeed, int b, int nAngle)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nFlowCount >= kMaxFlows)
|
|
|
|
return;
|
|
|
|
|
|
|
|
short nFlow = nFlowCount;
|
|
|
|
nFlowCount++;
|
|
|
|
|
|
|
|
|
|
|
|
if (b < 2)
|
|
|
|
{
|
2021-10-21 09:26:47 +00:00
|
|
|
short nPic = sector[nIndex].floorpicnum;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[nFlow].xacc = (tileWidth(nPic) << 14) - 1;
|
|
|
|
sFlowInfo[nFlow].yacc = (tileHeight(nPic) << 14) - 1;
|
2021-10-20 22:01:21 +00:00
|
|
|
sFlowInfo[nFlow].angcos = -bcos(nAngle) * nSpeed;
|
|
|
|
sFlowInfo[nFlow].angsin = bsin(nAngle) * nSpeed;
|
2021-10-21 09:26:47 +00:00
|
|
|
sFlowInfo[nFlow].objindex = nIndex;
|
2020-11-26 17:29:20 +00:00
|
|
|
|
2021-10-21 09:26:47 +00:00
|
|
|
StartInterpolation(nIndex, b ? Interp_Sect_CeilingPanX : Interp_Sect_FloorPanX);
|
|
|
|
StartInterpolation(nIndex, b ? Interp_Sect_CeilingPanY : Interp_Sect_FloorPanY);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-26 17:29:20 +00:00
|
|
|
StartInterpolation(nIndex, Interp_Wall_PanX);
|
|
|
|
StartInterpolation(nIndex, Interp_Wall_PanY);
|
|
|
|
|
2021-11-16 17:41:34 +00:00
|
|
|
int nAngle;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
if (b == 2) {
|
|
|
|
nAngle = 512;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nAngle = 1536;
|
|
|
|
}
|
|
|
|
|
2021-10-20 22:01:21 +00:00
|
|
|
short nPic = wall[nIndex].picnum;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-20 22:01:21 +00:00
|
|
|
sFlowInfo[nFlow].xacc = (tileWidth(nPic) * wall[nIndex].xrepeat) << 8;
|
|
|
|
sFlowInfo[nFlow].yacc = (tileHeight(nPic) * wall[nIndex].yrepeat) << 8;
|
|
|
|
sFlowInfo[nFlow].angcos = -bcos(nAngle) * nSpeed;
|
|
|
|
sFlowInfo[nFlow].angsin = bsin(nAngle) * nSpeed;
|
|
|
|
sFlowInfo[nFlow].objindex = nIndex;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[nFlow].ydelta = 0;
|
|
|
|
sFlowInfo[nFlow].xdelta = 0;
|
|
|
|
sFlowInfo[nFlow].type = b;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DoFlows()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < nFlowCount; i++)
|
|
|
|
{
|
2021-10-20 22:01:21 +00:00
|
|
|
sFlowInfo[i].xdelta += sFlowInfo[i].angcos;
|
|
|
|
sFlowInfo[i].ydelta += sFlowInfo[i].angsin;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
switch (sFlowInfo[i].type)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[i].xdelta &= sFlowInfo[i].xacc;
|
|
|
|
sFlowInfo[i].ydelta &= sFlowInfo[i].yacc;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-09 16:27:54 +00:00
|
|
|
int nSector =sFlowInfo[i].objindex;
|
2021-01-10 16:13:48 +00:00
|
|
|
sector[nSector].setfloorxpan(sFlowInfo[i].xdelta / 16384.f);
|
|
|
|
sector[nSector].setfloorypan(sFlowInfo[i].ydelta / 16384.f);
|
2019-08-31 07:47:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
{
|
2021-11-09 16:27:54 +00:00
|
|
|
int nSector =sFlowInfo[i].objindex;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-01-10 16:13:48 +00:00
|
|
|
sector[nSector].setceilingxpan(sFlowInfo[i].xdelta / 16384.f);
|
|
|
|
sector[nSector].setceilingypan(sFlowInfo[i].ydelta / 16384.f);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[i].xdelta &= sFlowInfo[i].xacc;
|
|
|
|
sFlowInfo[i].ydelta &= sFlowInfo[i].yacc;
|
2019-08-31 07:47:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
{
|
2021-11-09 16:32:50 +00:00
|
|
|
int nWall = sFlowInfo[i].objindex;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-01-14 22:55:45 +00:00
|
|
|
wall[nWall].setxpan(sFlowInfo[i].xdelta / 16384.f);
|
|
|
|
wall[nWall].setypan(sFlowInfo[i].ydelta / 16384.f);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
if (sFlowInfo[i].xdelta < 0)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[i].xdelta += sFlowInfo[i].xacc;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
if (sFlowInfo[i].ydelta < 0)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[i].ydelta += sFlowInfo[i].yacc;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
{
|
2021-11-09 16:32:50 +00:00
|
|
|
int nWall = sFlowInfo[i].objindex;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-01-14 22:55:45 +00:00
|
|
|
wall[nWall].setxpan(sFlowInfo[i].xdelta / 16384.f);
|
|
|
|
wall[nWall].setypan(sFlowInfo[i].ydelta / 16384.f);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
if (sFlowInfo[i].xdelta >= sFlowInfo[i].xacc)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[i].xdelta -= sFlowInfo[i].xacc;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2020-11-26 17:29:20 +00:00
|
|
|
if (sFlowInfo[i].ydelta >= sFlowInfo[i].yacc)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2020-11-26 17:29:20 +00:00
|
|
|
sFlowInfo[i].ydelta -= sFlowInfo[i].yacc;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DoLights()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
DoFlickers();
|
|
|
|
DoGlows();
|
|
|
|
DoFlows();
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetTorch(int nPlayer, int bTorchOnOff)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (bTorchOnOff == bTorch) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nPlayer != nLocalPlayer) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (bTorchOnOff == 2) {
|
2019-10-27 13:53:20 +00:00
|
|
|
bTorch = !bTorch;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
bTorch = bTorchOnOff;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (bTorch) {
|
2020-02-23 19:40:45 +00:00
|
|
|
PlayLocalSound(StaticSound[kSoundTorchOn], 0);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-19 18:16:25 +00:00
|
|
|
const char* buf = bTorch ? "TXT_EX_TORCHLIT" : "TXT_EX_TORCHOUT";
|
|
|
|
StatusMessage(150, GStrings(buf));
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-09 16:27:54 +00:00
|
|
|
void BuildFlash(int nPlayer, int nVal)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nPlayer == nLocalPlayer)
|
|
|
|
{
|
|
|
|
flash = nVal;
|
|
|
|
flash = -nVal; // ???
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
2019-11-22 23:11:37 +00:00
|
|
|
|
|
|
|
END_PS_NS
|