- use a TArrayView to store the wall references in a sector.

This is a lot more scripting friendly than hacking around the indices.
This commit is contained in:
Christoph Oelckers 2022-11-15 14:53:39 +01:00
parent 9a676ffba6
commit bfae5ce1bc
10 changed files with 113 additions and 124 deletions

View file

@ -95,8 +95,9 @@ void sectortype::allocX()
static void ReadSectorV7(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadInt16();
sect.wallnum = fr.ReadInt16();
int wallptr = fr.ReadInt16();
int wallnum = fr.ReadInt16();
sect.walls.Set(&wall[wallptr], wallnum);
int c = fr.ReadInt32();
int f = fr.ReadInt32();
sect.setzfrommap(c, f);
@ -123,8 +124,9 @@ static void ReadSectorV7(FileReader& fr, sectortype& sect)
static void ReadSectorV6(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadUInt16();
sect.wallnum = fr.ReadUInt16();
int wallptr = fr.ReadInt16();
int wallnum = fr.ReadInt16();
sect.walls.Set(&wall[wallptr], wallnum);
sect.ceilingpicnum = fr.ReadUInt16();
sect.floorpicnum = fr.ReadUInt16();
sect.ceilingheinum = clamp(fr.ReadInt16() << 5, -32768, 32767);
@ -151,8 +153,9 @@ static void ReadSectorV6(FileReader& fr, sectortype& sect)
static void ReadSectorV5(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadInt16();
sect.wallnum = fr.ReadInt16();
int wallptr = fr.ReadInt16();
int wallnum = fr.ReadInt16();
sect.walls.Set(&wall[wallptr], wallnum);
sect.ceilingpicnum = fr.ReadUInt16();
sect.floorpicnum = fr.ReadUInt16();
sect.ceilingheinum = clamp(fr.ReadInt16() << 5, -32768, 32767);
@ -426,8 +429,7 @@ void fixSectors()
// Note: we do not have the 'sector' index initialized here, it would not be helpful anyway for this fix.
while (wp != wall.Data() && wp[-1].twoSided() && wp[-1].nextWall()->nextWall() == &wp[-1] && wp[-1].nextWall()->nextSector() == &sect)
{
sect.wallptr--;
sect.wallnum++;
sect.walls.Set(sect.walls.Data() - 1, sect.walls.Size() + 1);
wp--;
}
}
@ -755,8 +757,8 @@ void setWallSectors()
auto sect = &sector[i];
auto nextsect = &sector[i + 1];
int sectstart = sect->wall_index();
int nextsectstart = nextsect->wall_index();
int sectstart = wallindex(sect->firstWall());
int nextsectstart = wallindex(sect->firstWall());
if (sectstart < nextsectstart && sectstart + sect->wall_count() > nextsectstart)
{
@ -765,8 +767,8 @@ void setWallSectors()
int checkend = sectstart + sect->wall_count();
// for now assign the walls to the first sector. Final decisions are made below.
nextsect->wallnum -= checkend - checkstart;
nextsect->wallptr = checkend;
nextsectstart = checkend;
nextsect->walls.Set(&wall[nextsectstart], nextsect->walls.Size() - (checkend - checkstart));
auto belongs = [](int wal, int first, int last, int firstwal)
{
@ -782,19 +784,20 @@ void setWallSectors()
while (checkstart < checkend && belongs(checkstart, sectstart, checkstart, checkstart))
checkstart++;
sect->wallnum = checkstart - sectstart;
sect->walls.Set(sect->firstWall(), checkstart - sectstart);
while (checkstart < checkend && belongs(checkend - 1, checkend, nextsectstart + nextsect->wall_count(), checkstart))
checkend--;
nextsect->wallnum += nextsectstart - checkend;
nextsect->wallptr = nextsectstart = checkend;
int cnt = nextsect->walls.Size() - (nextsectstart - checkend);
nextsectstart = checkend;
nextsect->walls.Set(&wall[nextsectstart], cnt);
if (nextsectstart > sectstart + sect->wall_count())
{
// If there's a gap, assign to the first sector. In this case we may only guess.
Printf("Wall range %d - %d referenced by sectors %d and %d\n", sectstart + sect->wall_count(), nextsectstart - 1, i, i + 1);
sect->wallnum = nextsectstart - sectstart;
sect->walls.Set(sect->firstWall(), nextsectstart - sectstart);
}
}
}

View file

@ -210,7 +210,86 @@ BEGIN_BLD_NS
END_BLD_NS
class DCoreActor;
struct walltype;
struct sectortype;
//=============================================================================
//
// internal wall struct - no longer identical with on-disk format
//
//=============================================================================
struct walltype
{
DVector2 pos;
vec2_t wall_int_pos() const { return vec2_t(int(pos.X * worldtoint), int(pos.Y * worldtoint)); };
vec2_t int_delta() const { return point2Wall()->wall_int_pos() - wall_int_pos(); }
void setPosFromMap(int x, int y) { pos = { x * maptoworld, y * maptoworld }; }
int32_t point2;
int32_t nextwall;
int32_t sector; // Build never had this...
int32_t nextsector;
// Again, panning fields extended for interpolation.
float xpan_;
float ypan_;
EWallFlags cstat;
int16_t picnum;
int16_t overpicnum;
union { int16_t lotag, type; }; // type is for Blood
int16_t hitag;
int16_t extra;
int8_t shade;
uint8_t pal;
uint8_t xrepeat;
uint8_t yrepeat;
// extensions not from the binary map format.
angle_t clipangle;
double length; // cached value to avoid calling sqrt repeatedly.
uint16_t portalnum;
uint8_t portalflags;
uint8_t lengthflags;
// Blood is the only game which extends the wall struct.
Blood::XWALL* _xw;
DVector2 baseWall;
int xpan() const { return int(xpan_); }
int ypan() const { return int(ypan_); }
void setxpan(float add) { xpan_ = fmodf(add + 512, 256); } // +512 is for handling negative offsets
void setypan(float add) { ypan_ = fmodf(add + 512, 256); } // +512 is for handling negative offsets
void addxpan(float add) { xpan_ = fmodf(xpan_ + add + 512, 256); } // +512 is for handling negative offsets
void addypan(float add) { ypan_ = fmodf(ypan_ + add + 512, 256); } // +512 is for handling negative offsets
sectortype* nextSector() const;
sectortype* sectorp() const;
walltype* nextWall() const;
walltype* lastWall(bool fast = true) const;
walltype* point2Wall() const;
DVector2 delta() const { return point2Wall()->pos - pos; }
DVector2 center() const { return(point2Wall()->pos + pos) / 2; }
DAngle normalAngle() const { return delta().Angle() + DAngle90; }
bool twoSided() const { return nextsector >= 0; }
double Length();
void calcLength(); // this is deliberately not inlined and stored in a file where it can't be found at compile time.
void move(const DVector2& vec)
{
pos = vec;
moved();
}
void moved();
Blood::XWALL& xw() const { return *_xw; }
bool hasX() const { return _xw != nullptr; }
void allocX();
};
// enable for running a compile-check to ensure that renderer-critical variables are not being written to directly.
//#define SECTOR_HACKJOB
@ -227,7 +306,8 @@ struct sectortype
// Fields were reordered by size, some also enlarged.
DCoreActor* firstEntry, * lastEntry;
int32_t wallptr;
TArrayView<walltype> walls;
#ifdef SECTOR_HACKJOB
// Debug hack job for finding all places where ceilingz and floorz get written to.
// If the engine does not compile with this block on, we got a problem.
@ -259,7 +339,6 @@ struct sectortype
float floorxpan_;
float floorypan_;
int16_t wallnum;
ESectorFlags ceilingstat;
ESectorFlags floorstat;
int16_t ceilingpicnum;
@ -348,10 +427,9 @@ struct sectortype
void setfloorslope(int heinum) { floorheinum = heinum; if (heinum) floorstat |= CSTAT_SECTOR_SLOPE; else floorstat &= ~CSTAT_SECTOR_SLOPE; }
int getfloorslope() const { return floorstat & CSTAT_SECTOR_SLOPE ? floorheinum : 0; }
int getceilingslope() const { return ceilingstat & CSTAT_SECTOR_SLOPE ? ceilingheinum : 0; }
walltype* firstWall() const;
walltype* lastWall() const;
int wall_index() const { return wallptr; }
int wall_count() const { return wallnum; }
walltype* firstWall() const { return walls.Data(); }
walltype* lastWall() const { return &walls.Last(); }
int wall_count() const { return walls.Size(); }
Blood::XSECTOR& xs() const { return *_xs; }
@ -362,84 +440,6 @@ struct sectortype
bool hasU() const { return u_defined; }
};
//=============================================================================
//
// internal wall struct - no longer identical with on-disk format
//
//=============================================================================
struct walltype
{
DVector2 pos;
vec2_t wall_int_pos() const { return vec2_t(int(pos.X * worldtoint), int(pos.Y * worldtoint)); };
vec2_t int_delta() const { return point2Wall()->wall_int_pos() - wall_int_pos(); }
void setPosFromMap(int x, int y) { pos = { x * maptoworld, y * maptoworld }; }
int32_t point2;
int32_t nextwall;
int32_t sector; // Build never had this...
int32_t nextsector;
// Again, panning fields extended for interpolation.
float xpan_;
float ypan_;
EWallFlags cstat;
int16_t picnum;
int16_t overpicnum;
union { int16_t lotag, type; }; // type is for Blood
int16_t hitag;
int16_t extra;
int8_t shade;
uint8_t pal;
uint8_t xrepeat;
uint8_t yrepeat;
// extensions not from the binary map format.
angle_t clipangle;
double length; // cached value to avoid calling sqrt repeatedly.
uint16_t portalnum;
uint8_t portalflags;
uint8_t lengthflags;
// Blood is the only game which extends the wall struct.
Blood::XWALL* _xw;
DVector2 baseWall;
int xpan() const { return int(xpan_); }
int ypan() const { return int(ypan_); }
void setxpan(float add) { xpan_ = fmodf(add + 512, 256); } // +512 is for handling negative offsets
void setypan(float add) { ypan_ = fmodf(add + 512, 256); } // +512 is for handling negative offsets
void addxpan(float add) { xpan_ = fmodf(xpan_ + add + 512, 256); } // +512 is for handling negative offsets
void addypan(float add) { ypan_ = fmodf(ypan_ + add + 512, 256); } // +512 is for handling negative offsets
sectortype* nextSector() const;
sectortype* sectorp() const;
walltype* nextWall() const;
walltype* lastWall(bool fast = true) const;
walltype* point2Wall() const;
DVector2 delta() const { return point2Wall()->pos - pos; }
DVector2 center() const { return(point2Wall()->pos + pos) / 2; }
DAngle normalAngle() const { return delta().Angle() + DAngle90; }
bool twoSided() const { return nextsector >= 0; }
double Length();
void calcLength(); // this is deliberately not inlined and stored in a file where it can't be found at compile time.
void move(const DVector2& vec)
{
pos = vec;
moved();
}
void moved();
Blood::XWALL& xw() const { return *_xw; }
bool hasX() const { return _xw != nullptr; }
void allocX();
};
//=============================================================================
//
// internal sprite struct - no longer identical with on-disk format
@ -597,16 +597,6 @@ inline walltype* walltype::point2Wall() const
return &::wall[point2]; // cannot be -1 in a proper map.
}
inline walltype* sectortype::firstWall() const
{
return &wall[wallptr]; // cannot be -1 in a proper map
}
inline walltype* sectortype::lastWall() const
{
return &wall[wallptr + wallnum - 1]; // cannot be -1 in a proper map
}
inline void walltype::moved()
{
lengthflags = 3;

View file

@ -40,6 +40,7 @@
#include "maptypes.h"
#include "hw_sections.h"
#include "mapinfo.h"
#include "gamefuncs.h"
//==========================================================================
//
@ -124,7 +125,7 @@ DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SplitSector)
if (sectornum < sector.Size())
{
int sectstart = sector[sectornum].wall_index();
int sectstart = wallindex(sector[sectornum].firstWall());
if (firstwall >= sectstart && firstwall < sectstart + sector[sectornum].wall_count() &&
secondwall >= sectstart && secondwall < sectstart + sector[sectornum].wall_count())

View file

@ -223,7 +223,7 @@ static void CollectLoops(TArray<loopcollect>& sectors)
int count = 0;
for (unsigned i = 0; i < sector.Size(); i++)
{
int first = sector[i].wall_index();
int first = wallindex(sector[i].firstWall());
int last = first + sector[i].wall_count();
sectors.Reserve(1);
sectors.Last().bugged = 0;

View file

@ -458,8 +458,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sectortype &c, sectort
{
arc("firstentry", c.firstEntry)
("lastentry", c.lastEntry)
("wallptr", c.wallptr, def->wallptr)
("wallnum", c.wallnum, def->wallnum)
#ifndef SECTOR_HACKJOB // can't save these in test mode...
("ceilingz", c.ceilingz, def->ceilingz)
("floorz", c.floorz, def->floorz)

View file

@ -47,8 +47,7 @@ DEFINE_FIELD_NAMED_X(sectortype, sectortype, ceilingxpan_, ceilingxpan)
DEFINE_FIELD_NAMED_X(sectortype, sectortype, ceilingypan_, ceilingypan)
DEFINE_FIELD_NAMED_X(sectortype, sectortype, floorxpan_, floorxpan)
DEFINE_FIELD_NAMED_X(sectortype, sectortype, floorypan_, floorypan)
DEFINE_FIELD_X(sectortype, sectortype, wallptr)
DEFINE_FIELD_X(sectortype, sectortype, wallnum)
DEFINE_FIELD_UNSIZED(sectortype, sectortype, walls)
DEFINE_FIELD_X(sectortype, sectortype, ceilingstat)
DEFINE_FIELD_X(sectortype, sectortype, floorstat)
DEFINE_FIELD_X(sectortype, sectortype, lotag)

View file

@ -253,8 +253,7 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur
{
dbCrypt((char*)&load, sizeof(sectortypedisk), gMapRev * sizeof(sectortypedisk));
}
pSector->wallptr = LittleShort(load.wallptr);
pSector->wallnum = LittleShort(load.wallnum);
pSector->walls.Set(&wall[LittleShort(load.wallptr)], LittleShort(load.wallnum));
pSector->setzfrommap(LittleLong(load.ceilingz), LittleLong(load.floorz));
pSector->ceilingstat = ESectorFlags::FromInt(LittleShort(load.ceilingstat));
pSector->floorstat = ESectorFlags::FromInt(LittleShort(load.floorstat));

View file

@ -1052,7 +1052,7 @@ void DoSector(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor,
switch (lLabelID)
{
case SECTOR_WALLPTR:
if (!bSet) SetGameVarID(lVar2, sectp->wall_index(), sActor, sPlayer);
if (!bSet) SetGameVarID(lVar2, wallindex(sectp->firstWall()), sActor, sPlayer);
break;
case SECTOR_WALLNUM:
if (!bSet) SetGameVarID(lVar2, sectp->wall_count(), sActor, sPlayer);

View file

@ -128,7 +128,7 @@ void feebtag(const DVector3& pos, sectortype* pSector, DExhumedActor **nSprite,
{
*nSprite = nullptr;
int startwall = pSector->wall_index();
auto startwall = pSector->firstWall();
int nWalls = pSector->wall_count();
@ -166,7 +166,7 @@ void feebtag(const DVector3& pos, sectortype* pSector, DExhumedActor **nSprite,
if (nWalls < -1)
return;
pSector = wall[startwall].nextSector();
pSector = startwall->nextSector();
startwall++;
}
}

View file

@ -123,8 +123,7 @@ struct sectortype native
native readonly float floorypan;
native readonly double ceilingz, floorz;
native readonly int wallptr;
native readonly int16 wallnum;
native Array<@walltype> walls;
native int16 ceilingstat;
native int16 floorstat;
//int16 ceilingpicnum;