hostile-takeover/game/fogmap.cpp
2016-08-31 23:55:30 -04:00

805 lines
20 KiB
C++

#include "ht.h"
namespace wi {
FogMap::FogMap()
{
m_pbMap = NULL;
m_panidWalls = NULL;
memset(m_aptbm, 0, sizeof(m_aptbm));
memset(m_aptbmGalax, 0, sizeof(m_aptbmGalax));
// Each tile holds 4 bits. 0 is right most, 1 is top most, 2 is bottom most,
// 3 is left most
//
// Init the pattern results. The only reason a table exists
// (rather than using mask exclusively) is to disallow
// unwanted results. 1001 and 0110 are the only two illegal
// results with the current scheme.
for (byte bSrc = 0; bSrc < 16; bSrc++) {
for (byte bDst = 0; bDst < 16; bDst++) {
byte bRes = ~(~bDst & ~bSrc) & 0xf;
if (bRes == 9 || bRes == 6)
bRes = 0;
m_mpSrcDstResult[(((~bSrc) & 0xf) << 4) | bDst] = bRes;
}
}
}
FogMap::~FogMap()
{
delete m_panidWalls;
delete[] m_pbMap;
int n;
for (n = 0; n < 16; n++)
delete m_aptbm[n];
for (n = 0; n < 9; n++)
delete m_aptbmGalax[n];
}
bool FogMap::Init(Size *psizTile, Size *psizMap)
{
m_cxTile = psizTile->cx;
m_cyTile = psizTile->cy;
m_ctxMap = psizMap->cx / m_cxTile;
m_ctyMap = psizMap->cy / m_cyTile;
// Alloc the map and make it all "fogged" and Galaxite-free
int cb = m_ctxMap * m_ctyMap;
m_pbMap = new byte[cb];
Assert(m_pbMap != NULL, "out of memory!");
if (m_pbMap == NULL)
return false;
memset(m_pbMap, kbOpaque, cb);
// Load the edges
m_aptbm[15] = NULL;
m_aptbm[14] = LoadTBitmap("fog0001.tbm");
m_aptbm[13] = LoadTBitmap("fog0010.tbm");
m_aptbm[12] = LoadTBitmap("fog0011.tbm");
m_aptbm[11] = LoadTBitmap("fog0100.tbm");
m_aptbm[10] = LoadTBitmap("fog0101.tbm");
m_aptbm[9] = NULL;
m_aptbm[8] = LoadTBitmap("fog0111.tbm");
m_aptbm[7] = LoadTBitmap("fog1000.tbm");
m_aptbm[6] = NULL;
m_aptbm[5] = LoadTBitmap("fog1010.tbm");
m_aptbm[4] = LoadTBitmap("fog1011.tbm");
m_aptbm[3] = LoadTBitmap("fog1100.tbm");
m_aptbm[2] = LoadTBitmap("fog1101.tbm");
m_aptbm[1] = LoadTBitmap("fog1110.tbm");
m_aptbm[0] = LoadTBitmap("fog1111.tbm");
int c = 0;
int n;
for (n = 0; n < 16; n++) {
if (m_aptbm[n] == NULL)
c++;
}
if (c != 3)
return false;
m_aptbmGalax[0] = LoadTBitmap("galax1a.tbm");
m_aptbmGalax[1] = LoadTBitmap("galax1b.tbm");
m_aptbmGalax[2] = LoadTBitmap("galax1c.tbm");
m_aptbmGalax[3] = LoadTBitmap("galax2a.tbm");
m_aptbmGalax[4] = LoadTBitmap("galax2b.tbm");
m_aptbmGalax[5] = LoadTBitmap("galax2c.tbm");
m_aptbmGalax[6] = LoadTBitmap("galax3a.tbm");
m_aptbmGalax[7] = LoadTBitmap("galax3b.tbm");
m_aptbmGalax[8] = LoadTBitmap("galax3c.tbm");
for (n = 0; n < 9; n++) {
if (m_aptbmGalax[n] == NULL) {
Assert("Failed to load one of the Galaxite bitmaps");
return false;
}
}
// Load the wall bitmaps
m_panidWalls = LoadAnimationData("walls.anir");
if (m_panidWalls == NULL) {
Assert("Failed to load wall.anir");
return false;
}
return true;
}
#define knVerFogMapState 4
bool FogMap::LoadState(Stream *pstm)
{
// Note at this point the fogmap has already been "initialized" from
// level constants so we just need to load in the contents of the map
// which includes both fog and galaxite state
byte nVer = pstm->ReadByte();
if (nVer != knVerFogMapState)
return false;
pstm->ReadBytesRLE(m_pbMap, m_ctxMap * m_ctyMap);
return pstm->IsSuccess();
}
bool FogMap::SaveState(Stream *pstm)
{
pstm->WriteByte(knVerFogMapState);
pstm->WriteBytesRLE(m_pbMap, m_ctxMap * m_ctyMap);
return pstm->IsSuccess();
}
bool FogMap::IsCovered(TRect *ptrc)
{
TRect trcMap;
trcMap.left = 0;
trcMap.top = 0;
trcMap.right = m_ctxMap;
trcMap.bottom = m_ctyMap;
TRect trcT = *ptrc;
if (!trcT.Intersect(&trcT, &trcMap)) {
return false;
}
for (int ty = trcT.top; ty < trcT.bottom; ty++) {
for (int tx = trcT.left; tx < trcT.right; tx++) {
byte bFog = m_pbMap[ty * m_ctxMap + tx] & kbfFogMask;
if (bFog != 0) {
return false;
}
}
}
return true;
}
void FogMap::RevealAll(UpdateMap *pupd)
{
byte *pbT = m_pbMap;
byte *pbEnd = m_pbMap + (m_ctxMap * m_ctyMap);
while (pbT < pbEnd) {
// *pbT++ = (*pbT & ~kbfFogMask) | kbEmpty;
// BUGBUG: if we post-increment pbT as above the CodeWarrior ARM compiler
// screws it up such that the RHS pbT is one byte ahead of the LHS pbT,
// the end result being that all the Galaxite in the map gets shifted one
// tile to the left!
*pbT = (*pbT & ~kbfFogMask) | kbEmpty;
pbT++;
}
// Invalidate the whole update map
pupd->InvalidateRect();
// Redraw the whole minimap
gpmm->Redraw();
}
void FogMap::Reveal(TRect *ptrc, UpdateMap *pupd, WCoord wxView, WCoord wyView)
{
int ctxT = ptrc->Width();
// Top row and corners
byte *pbDst = &m_pbMap[(ptrc->top * m_ctxMap) + ptrc->left];
int ctx = ctxT - 2;
*pbDst = *pbDst | (15 - 10);
pbDst++;
while (ctx-- > 0) {
// *pbDst++ = *pbDst | (15 - 2);
// BUGBUG: if we post-increment pbDst as above the CodeWarrior ARM compiler
// screws it up such that the RHS pbDst is one byte ahead of the LHS pbDst,
// the end result being that defog pattern isn't applied properly.
*pbDst = *pbDst | (15 - 2);
pbDst++;
}
*pbDst = *pbDst | (15 - 3);
// Bottom row and corners
pbDst = &m_pbMap[((ptrc->bottom - 1) * m_ctxMap) + ptrc->left];
ctx = ctxT - 2;
*pbDst = *pbDst | (15 - 12);
pbDst++;
while (ctx-- > 0) {
// *pbDst++ = *pbDst | (15 - 4);
// BUGBUG: if we post-increment pbDst as above the CodeWarrior ARM compiler
// screws it up such that the RHS pbDst is one byte ahead of the LHS pbDst,
// the end result being that defog pattern isn't applied properly.
*pbDst = *pbDst | (15 - 4);
pbDst++;
}
*pbDst = *pbDst | (15 - 5);
// Left column
pbDst = &m_pbMap[((ptrc->top + 1) * m_ctxMap) + ptrc->left];
ctx = ptrc->Height() - 2;
while (ctx-- > 0) {
// *pbDst++ = *pbDst | (15 - 8);
// BUGBUG: if we post-increment pbDst as above the CodeWarrior ARM compiler
// screws it up such that the RHS pbDst is one byte ahead of the LHS pbDst,
// the end result being that defog pattern isn't applied properly.
*pbDst = *pbDst | (15 - 8);
pbDst += m_ctxMap;
}
// Right column
pbDst = &m_pbMap[((ptrc->top + 1) * m_ctxMap) + ptrc->right - 1];
ctx = ptrc->Height() - 2;
while (ctx-- > 0) {
// *pbDst++ = *pbDst | (15 - 1);
// BUGBUG: if we post-increment pbDst as above the CodeWarrior ARM compiler
// screws it up such that the RHS pbDst is one byte ahead of the LHS pbDst,
// the end result being that defog pattern isn't applied properly.
*pbDst = *pbDst | (15 - 1);
pbDst += m_ctxMap;
}
// Interior
TRect trcT;
trcT = *ptrc;
trcT.Inflate(-1, -1);
ctxT = trcT.Width();
pbDst = &m_pbMap[(trcT.top * m_ctxMap) + trcT.left];
int cty = trcT.Height();
while (cty-- > 0) {
ctx = ctxT;
while (ctx-- > 0) {
*pbDst = *pbDst | kbEmpty;
pbDst++;
}
pbDst += m_ctxMap - ctxT;
}
// Invalidate
gpmm->RedrawTRect(ptrc);
Rect rcT;
rcT.FromTileRect(ptrc);
int xView = PcFromWc(wxView) & 0xfffe;
int yView = PcFromWc(wyView) & 0xfffe;
rcT.Offset(-xView, -yView);
pupd->InvalidateRect(&rcT);
}
void FogMap::Reveal(TCoord txMap, TCoord tyMap, RevealPattern *prvlp, UpdateMap *pupd, WCoord wxView, WCoord wyView)
{
Assert(txMap >= 0 && txMap < m_ctxMap && tyMap >= 0 && tyMap < m_ctyMap);
// RevealPattern is centered around txMap and tyMap
int ctx = prvlp->ctx;
int cty = prvlp->cty;
int tx = txMap - ctx / 2;
int ty = tyMap - cty / 2;
// Clip to map edges
int txPattern = 0;
int tyPattern = 0;
if (tx < 0) {
ctx = tx + ctx;
txPattern = -tx;
tx = 0;
}
if (ty < 0) {
cty = ty + cty;
tyPattern = -ty;
ty = 0;
}
if (tx + ctx > m_ctxMap)
ctx = m_ctxMap - tx;
if (ty + cty > m_ctyMap)
cty = m_ctyMap - ty;
Assert(ctx > 0 && ctx <= prvlp->ctx && cty > 0 && cty <= prvlp->cty);
// Reveal
int cbNextSrc = prvlp->ctx - ctx;
int cbNextDst = m_ctxMap - ctx;
byte *pbDst = &m_pbMap[ty * m_ctxMap + tx];
byte *pbSrc = &prvlp->ab[tyPattern * prvlp->ctx + txPattern];
bool fChanged = false;
for (int tyT = ty; tyT < ty + cty; tyT++) {
for (int txT = tx; txT < tx + ctx; txT++) {
byte bDst = *pbDst;
byte bDstNew = (*pbDst & ~kbfFogMask) | m_mpSrcDstResult[((*pbSrc) << 4) | (*pbDst & kbfFogMask)];
if (bDst != bDstNew) {
*pbDst = bDstNew;
pupd->InvalidateTile(txT, tyT);
gpmm->RedrawTile(txT, tyT);
}
pbDst++;
pbSrc++;
}
pbSrc += cbNextSrc;
pbDst += cbNextDst;
}
}
void FogMap::Draw(DibBitmap *pbm, int xMap, int yMap, UpdateMap *pupd)
{
Size siz;
pbm->GetSize(&siz);
Rect rcDib;
rcDib.left = 0;
rcDib.top = 0;
rcDib.right = siz.cx;
rcDib.bottom = siz.cy;
int tx = xMap / gcxTile;
int ty = yMap / gcyTile;
int ctx = (siz.cx + (gcxTile - 1)) / gcxTile + 1;
if (tx + ctx > m_ctxMap)
ctx = m_ctxMap - tx;
int cty = (siz.cy + (gcyTile - 1)) / gcyTile + 1;
if (ty + cty > m_ctyMap)
cty = m_ctyMap - ty;
Color clrBlack = GetColor(kiclrBlack);
bool *pfInvalid = pupd->GetInvalidMap();
Size sizMap;
pupd->GetMapSize(&sizMap);
int cfInvalidNextScan = sizMap.cx - ctx;
Assert(sizMap.cx >= ctx && sizMap.cy >= cty);
byte *pbDib = pbm->GetBits();
byte *pbMapT = &m_pbMap[ty * m_ctxMap + tx];
int cbNextScan = m_ctxMap - ctx;
int xTile = tx * gcxTile - xMap;
int yTile = ty * gcyTile - yMap;
int xTileStart = xTile;
for (int tyT = ty; tyT < ty + cty; tyT++) {
int cEmpty = 0;
int xStart;
for (int txT = tx; txT < tx + ctx; txT++) {
byte bFog = *pbMapT++ & kbfFogMask;
if (*pfInvalid++ == false)
bFog = kbEmpty;
// Opaque?
if (bFog == kbOpaque) {
if (cEmpty == 0)
xStart = xTile;
cEmpty++;
xTile += gcxTile;
continue;
}
// Not opaque; fill block if there is one
if (cEmpty != 0) {
pbm->Fill(xStart, yTile, cEmpty * gcxTile, gcyTile, clrBlack);
cEmpty = 0;
#ifdef PIL
if (gfOS5Pa1Device)
HostSoundServiceProc();
#endif
}
// Not opaque; draw unique tile
TBitmap *ptbm = m_aptbm[bFog];
if (ptbm == NULL) {
xTile += gcxTile;
continue;
}
ptbm->BltTo(pbm, xTile, yTile);
xTile += gcxTile;
}
if (cEmpty != 0) {
pbm->Fill(xStart, yTile, cEmpty * gcxTile, gcyTile, clrBlack);
cEmpty = 0;
#ifdef PIL
if (gfOS5Pa1Device)
HostSoundServiceProc();
#endif
}
pbMapT += cbNextScan;
pfInvalid += cfInvalidNextScan;
yTile += gcxTile;
xTile = xTileStart;
}
}
byte s_abGxTranslate[] = { 0, 2, 1, 1, 0, 0, 5, 4, 4, 3, 3, 8, 7, 7, 6, 6 };
byte s_abGxInc[] = { 0, 2, 3, 4, 5, 5, 7, 8, 9, 10, 10, 12, 13, 14, 15, 15 };
byte s_abGxDec[] = { 0, 0, 1, 2, 3, 4, 0, 6, 7, 8, 9, 0, 11, 12, 13, 14 };
void FogMap::DrawGalaxite(DibBitmap *pbm, int xMap, int yMap, UpdateMap *pupd, byte *pbTrMap)
{
Size siz;
pbm->GetSize(&siz);
Rect rcDib;
rcDib.left = 0;
rcDib.top = 0;
rcDib.right = siz.cx;
rcDib.bottom = siz.cy;
int tx = xMap / gcxTile;
int ty = yMap / gcyTile;
int ctx = (siz.cx + (gcxTile - 1)) / gcxTile + 1;
if (tx + ctx > m_ctxMap)
ctx = m_ctxMap - tx;
int cty = (siz.cy + (gcyTile - 1)) / gcyTile + 1;
if (ty + cty > m_ctyMap)
cty = m_ctyMap - ty;
byte *pbDib = pbm->GetBits();
byte *pbMapT = &m_pbMap[ty * m_ctxMap + tx];
int cbNextScan = m_ctxMap - ctx;
int xTile = tx * gcxTile - xMap;
int yTile = ty * gcyTile - yMap;
int xTileStart = xTile;
bool *pfInvalid = pupd->GetInvalidMap();
Size sizMap;
pupd->GetMapSize(&sizMap);
int cfInvalidNextScan = sizMap.cx - ctx;
Assert(sizMap.cx >= ctx && sizMap.cy >= cty);
int nServiceSfx = 0;
for (int tyT = ty; tyT < ty + cty; tyT++) {
for (int txT = tx; txT < tx + ctx; txT++, pbMapT++) {
byte b = *pbMapT;
if (*pfInvalid++ == false) {
xTile += gcxTile;
continue;
}
// Is no Galaxite/Wall present or is this tile completely obscured by fog?
byte *ptt = &pbTrMap[pbMapT - m_pbMap];
if (((b & kbfGalaxiteMask) == 0 && *ptt != kttWall) || IsFogOpaque(b)) {
xTile += gcxTile;
continue;
}
// Galaxite?
if (HasGalaxite(b)) {
// Galaxite
TBitmap *ptbm = m_aptbmGalax[s_abGxTranslate[(b & kbfGalaxiteMask) >> kcGalaxiteShift]];
ptbm->BltTo(pbm, xTile, yTile);
#ifdef PIL
if (gfOS5Pa1Device) {
nServiceSfx++;
if ((nServiceSfx & 31) == 0)
HostSoundServiceProc();
}
#endif
}
// Wall?
if (*ptt == kttWall) {
#define HasWall(tt) ((tt) == kttWall)
// Check neighbor cells for walls to decide what shape this
// segment should take.
int ifrm = 0;
if (tyT > 0) {
if (HasWall(*(ptt - m_ctxMap)))
ifrm |= 1;
}
if (txT < m_ctxMap - 1) {
if (HasWall(*(ptt + 1)))
ifrm |= 2;
}
if (tyT < m_ctyMap - 1) {
if (HasWall(*(ptt + m_ctxMap)))
ifrm |= 4;
}
if (txT > 0) {
if (HasWall(*(ptt - 1)))
ifrm |= 8;
}
// The kwfWallMask >> 1 test makes walls with less than half their health
// draw from the 'damaged' strip.
// m_panidWalls->DrawFrame(w <= (kwfWallMask >> 1) ? 1 : 0, ifrm, pbm, xTile, yTile, ksideNeutral);
m_panidWalls->DrawFrame(0, ifrm, pbm, xTile, yTile, ksideNeutral);
#ifdef PIL
if (gfOS5Pa1Device) {
nServiceSfx++;
if ((nServiceSfx & 31) == 0)
HostSoundServiceProc();
}
#endif
}
xTile += gcxTile;
}
pfInvalid += cfInvalidNextScan;
pbMapT += cbNextScan;
yTile += gcxTile;
xTile = xTileStart;
}
}
void FogMap::SetGalaxite(int nGx, TCoord tx, TCoord ty)
{
Assert(tx >= 0 && ty >= 0 && tx < m_ctxMap && ty < m_ctyMap);
byte *pb = &m_pbMap[(ty * m_ctxMap) + tx];
*pb = (*pb & ~kbfGalaxiteMask) | (nGx << kcGalaxiteShift);
}
int FogMap::GetGalaxite(TCoord tx, TCoord ty)
{
// Any attempt to look for Galaxite off the edge of the map returns none
if (tx < 0 || ty < 0 || tx >= m_ctxMap || ty >= m_ctyMap)
return 0;
byte *pb = &m_pbMap[(ty * m_ctxMap) + tx];
int nGx = (*pb & kbfGalaxiteMask) >> kcGalaxiteShift;
#ifdef MP_DEBUG
// MpTrace("GetGalaxite:%d,%d amount %d", tx, ty, nGx);
#endif
return nGx;
}
void FogMap::IncGalaxite(TCoord tx, TCoord ty)
{
Assert(tx >= 0 && ty >= 0 && tx < m_ctxMap && ty < m_ctyMap);
byte *pb = &m_pbMap[(ty * m_ctxMap) + tx];
*pb = (*pb & ~kbfGalaxiteMask) | (s_abGxInc[(*pb & kbfGalaxiteMask) >> kcGalaxiteShift] << kcGalaxiteShift);
// Cause this tile to redraw
if (gptrcMapOpaque == NULL || !gptrcMapOpaque->PtIn(tx, ty))
gpupdSim->InvalidateTile(tx, ty);
if (gpmm != NULL)
gpmm->RedrawTile(tx, ty);
}
bool FogMap::DecGalaxite(TCoord tx, TCoord ty)
{
Assert(tx >= 0 && ty >= 0 && tx < m_ctxMap && ty < m_ctyMap);
byte *pb = &m_pbMap[(ty * m_ctxMap) + tx];
byte bNew = s_abGxDec[(*pb & kbfGalaxiteMask) >> kcGalaxiteShift] << kcGalaxiteShift;
*pb = (*pb & ~kbfGalaxiteMask) | bNew;
#ifdef MP_DEBUG
// MpTrace("DecGalaxite:%d,%d now %d", tx, ty, bNew >> kcGalaxiteShift);
#endif
// Cause this tile to redraw
if (gptrcMapOpaque == NULL || !gptrcMapOpaque->PtIn(tx, ty))
gpupdSim->InvalidateTile(tx, ty);
if (gpmm != NULL)
gpmm->RedrawTile(tx, ty);
return bNew != 0;
}
bool FogMap::FindNearestGalaxite(TCoord txOrigin, TCoord tyOrigin, TPoint *ptpt, bool fIgnoreFog)
{
Assert(txOrigin >= 0 && tyOrigin >= 0 && txOrigin < m_ctxMap && tyOrigin < m_ctyMap);
#if 1
TPoint *atptGx = (TPoint *)gpbScratch;
#else
TPoint atptT[sizeof(TPoint) * ktcMax * 4]; // 1024 bytes, these days
TPoint *atptGx = atptT;
#endif
TPoint *ptptGx = atptGx;
int ctptGx;
int nMax1 = _max((int)txOrigin, m_ctxMap - txOrigin);
int nMax2 = _max((int)tyOrigin, m_ctyMap - tyOrigin);
int nRadiusMax = _max(nMax1, nMax2);
for (int nRadius = 1; nRadius < nRadiusMax; nRadius++) {
// We treat Galaxite directly under the Miner as being
// the equivalent of 2.5 tiles away.
if (nRadius == 3) {
byte *pb = &m_pbMap[(tyOrigin * m_ctxMap) + txOrigin];
if (HasGalaxite(*pb)) {
ptpt->tx = txOrigin;
ptpt->ty = tyOrigin;
// MpTrace(" -- found %d, %d", txOrigin, tyOrigin);
return true;
}
}
// look for galaxite across the top
TCoord txMin = txOrigin - nRadius;
if (txMin < 0)
txMin = 0;
TCoord txMax = txOrigin + nRadius;
if (txMax > m_ctxMap)
txMax = m_ctxMap;
TCoord tx, ty;
ty = tyOrigin - nRadius;
if (ty >= 0) {
byte *pb = &m_pbMap[(ty * m_ctxMap) + txMin];
for (tx = txMin; tx < txMax; tx++, pb++) {
if (!HasGalaxite(*pb)) // Galaxite?
continue; // no
if (IsFogOpaque(*pb) && !fIgnoreFog) // Fogged?
continue; // yes
// MpTrace(" t %d, %d, 0x%lx", tx, ty, ptptGx);
ptptGx->tx = tx;
ptptGx->ty = ty;
ptptGx++;
}
}
// look for galaxite across the bottom
txMax += 1;
if (txMax > m_ctxMap)
txMax = m_ctxMap;
txMin = txOrigin - nRadius + 1;
if (txMin < 0)
txMin = 0;
ty = tyOrigin + nRadius;
if (ty < m_ctyMap) {
byte *pb = &m_pbMap[(ty * m_ctxMap) + txMin];
for (tx = txMin; tx < txMax; tx++, pb++) {
if (!HasGalaxite(*pb))
continue;
if (IsFogOpaque(*pb) && !fIgnoreFog)
continue;
// MpTrace(" b %d, %d, 0x%lx", tx, ty, ptptGx);
ptptGx->tx = tx;
ptptGx->ty = ty;
ptptGx++;
}
}
// look for galaxite down the right side
TCoord tyMin = tyOrigin - nRadius;
if (tyMin < 0)
tyMin = 0;
TCoord tyMax = tyOrigin + nRadius;
if (tyMax > m_ctyMap)
tyMax = m_ctyMap;
tx = txOrigin + nRadius;
if (tx < m_ctxMap) {
byte *pb = &m_pbMap[(tyMin * m_ctxMap) + tx];
for (ty = tyMin; ty < tyMax; ty++, pb += m_ctxMap) {
if (!HasGalaxite(*pb))
continue;
if (IsFogOpaque(*pb) && !fIgnoreFog)
continue;
// MpTrace(" r %d, %d, 0x%lx", tx, ty, ptptGx);
ptptGx->tx = tx;
ptptGx->ty = ty;
ptptGx++;
}
}
// look for galaxite down the left side
tyMin = tyOrigin - nRadius + 1;
if (tyMin < 0)
tyMin = 0;
tyMax += 1;
if (tyMax > m_ctyMap)
tyMax = m_ctyMap;
tx = txOrigin - nRadius;
if (tx >= 0) {
byte *pb = &m_pbMap[(tyMin * m_ctxMap) + tx];
for (ty = tyMin; ty < tyMax; ty++, pb += m_ctxMap) {
if (!HasGalaxite(*pb))
continue;
if (IsFogOpaque(*pb) && !fIgnoreFog)
continue;
// MpTrace(" l %d, %d, 0x%lx", tx, ty, ptptGx);
ptptGx->tx = tx;
ptptGx->ty = ty;
ptptGx++;
}
}
// If Galaxite has been found at this radius randomly pick one
// of the found locations and return it.
if (ptptGx != atptGx) {
ctptGx = (int)(ptptGx - atptGx);
int i = GetRandom() % ctptGx;
*ptpt = atptGx[i];
// MpTrace(" -- found %d, %d, 0x%lx [%d of %d]", ptpt->tx, ptpt->ty, &atptGx[i], i, ctptGx);
return true;
}
}
// MpTrace(" -- found none");
return false;
}
//
// Wall methods
//
#if 0
int FogMap::GetWallHealth(TCoord tx, TCoord ty)
{
// Any attempt to look for wall off the edge of the map returns none
if (tx < 0 || ty < 0 || tx >= m_ctxMap || ty >= m_ctyMap)
return 0;
word *pw = &m_pwMap[(ty * m_ctxMap) + tx];
return (*pw & kwfWallMask) >> kcWallShift;
}
void FogMap::SetWallHealth(int nHealth, TCoord tx, TCoord ty)
{
// If state changes between existing and not existing then the N/S/E/W
// neighbor cells need to be invalidated if they also contain a wall
// segment.
Assert(tx >= 0 && ty >= 0 && tx < m_ctxMap && ty < m_ctyMap);
word *pw = &m_pwMap[(ty * m_ctxMap) + tx];
word wOld = *pw;
word wNew = (wOld & ~kwfWallMask) | (word)(nHealth << kcWallShift);
if (wNew != wOld) {
*pw = wNew;
// UNDONE: whoa! Spaghetti! FogMap should not be reaching out to sim/level/etc
TerrainMap *ptrmap = gsim.GetLevel()->GetTerrainMap();
if (nHealth == 0)
ptrmap->ClearFlags(tx, ty, 1, 1, kbfStructure);
else
ptrmap->SetFlags(tx, ty, 1, 1, kbfStructure);
#if 0
// UNDONE: right now there is no dynamic changing of a wall's health so we don't
// need this stuff. If we allow damaging/destroying walls or give the player the
// ability to create walls we'll need to deal with this.
// Cause this tile to redraw
if (gptrcMapOpaque == NULL || !gptrcMapOpaque->PtIn(tx, ty))
gpupdSim->InvalidateTile(tx, ty);
if (gpmm != NULL)
gpmm->RedrawTile(tx, ty);
// UNDONE: deal with neighbors
#endif
}
}
#endif
} // namespace wi