mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 04:22:34 +00:00
- added a TStaticArray class that allows safe access to resizable static data (like the sectors, linedefs, etc.) for the VM.
- used this to replace the line list in Sector because that gets already used and implemented proper bounds checks for this type of array.
This commit is contained in:
parent
b31b6589e7
commit
1a16f664e4
24 changed files with 456 additions and 233 deletions
|
@ -560,6 +560,7 @@ void PType::StaticInit()
|
|||
RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PClassPointer);
|
||||
RUNTIME_CLASS(PEnum)->TypeTableType = RUNTIME_CLASS(PEnum);
|
||||
RUNTIME_CLASS(PArray)->TypeTableType = RUNTIME_CLASS(PArray);
|
||||
RUNTIME_CLASS(PResizableArray)->TypeTableType = RUNTIME_CLASS(PResizableArray);
|
||||
RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray);
|
||||
RUNTIME_CLASS(PMap)->TypeTableType = RUNTIME_CLASS(PMap);
|
||||
RUNTIME_CLASS(PStruct)->TypeTableType = RUNTIME_CLASS(PStruct);
|
||||
|
@ -2050,6 +2051,80 @@ PArray *NewArray(PType *type, unsigned int count)
|
|||
return (PArray *)atype;
|
||||
}
|
||||
|
||||
/* PArray *****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PResizableArray, false, false)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PArray - Default Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PResizableArray::PResizableArray()
|
||||
{
|
||||
mDescriptiveName = "ResizableArray";
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PArray - Parameterized Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PResizableArray::PResizableArray(PType *etype)
|
||||
: PArray(etype, 0)
|
||||
{
|
||||
mDescriptiveName.Format("ResizableArray<%s>", etype->DescriptiveName());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PArray :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PResizableArray::IsMatch(intptr_t id1, intptr_t id2) const
|
||||
{
|
||||
const PType *elemtype = (const PType *)id1;
|
||||
unsigned int count = (unsigned int)(intptr_t)id2;
|
||||
|
||||
return elemtype == ElementType && count == 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PArray :: GetTypeIDs
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PResizableArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||
{
|
||||
id1 = (intptr_t)ElementType;
|
||||
id2 = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewResizableArray
|
||||
//
|
||||
// Returns a PArray for the given type and size, making sure not to create
|
||||
// duplicates.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PResizableArray *NewResizableArray(PType *type)
|
||||
{
|
||||
size_t bucket;
|
||||
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PResizableArray), (intptr_t)type, 0, &bucket);
|
||||
if (atype == NULL)
|
||||
{
|
||||
atype = new PResizableArray(type);
|
||||
TypeTable.AddType(atype, RUNTIME_CLASS(PResizableArray), (intptr_t)type, 0, bucket);
|
||||
}
|
||||
return (PResizableArray *)atype;
|
||||
}
|
||||
|
||||
/* PDynArray **************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PDynArray, false, true)
|
||||
|
|
|
@ -660,6 +660,20 @@ protected:
|
|||
PArray();
|
||||
};
|
||||
|
||||
class PResizableArray : public PArray
|
||||
{
|
||||
DECLARE_CLASS(PResizableArray, PArray);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PResizableArray(PType *etype);
|
||||
|
||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
|
||||
protected:
|
||||
PResizableArray();
|
||||
};
|
||||
|
||||
class PDynArray : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PDynArray, PCompoundType);
|
||||
|
@ -919,6 +933,7 @@ extern FTypeTable TypeTable;
|
|||
// Returns a type from the TypeTable. Will create one if it isn't present.
|
||||
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||
PArray *NewArray(PType *type, unsigned int count);
|
||||
PResizableArray *NewResizableArray(PType *type);
|
||||
PDynArray *NewDynArray(PType *type);
|
||||
PPointer *NewPointer(PType *type, bool isconst = false);
|
||||
PClassPointer *NewClassPointer(PClass *restrict);
|
||||
|
|
|
@ -305,7 +305,6 @@ static void PrepareTransparentDoors(sector_t * sector)
|
|||
int notextures=0;
|
||||
int nobtextures=0;
|
||||
int selfref=0;
|
||||
int i;
|
||||
sector_t * nextsec=NULL;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -323,15 +322,15 @@ static void PrepareTransparentDoors(sector_t * sector)
|
|||
|
||||
if (sector->transdoor)
|
||||
{
|
||||
for (i=0; i<sector->linecount; i++)
|
||||
for (auto ln : sector->Lines)
|
||||
{
|
||||
if (sector->lines[i]->frontsector==sector->lines[i]->backsector)
|
||||
if (ln->frontsector == ln->backsector)
|
||||
{
|
||||
selfref++;
|
||||
continue;
|
||||
}
|
||||
|
||||
sector_t * sec=getNextSector(sector->lines[i], sector);
|
||||
sector_t * sec=getNextSector(ln, sector);
|
||||
if (sec==NULL)
|
||||
{
|
||||
solidwall=true;
|
||||
|
@ -341,15 +340,15 @@ static void PrepareTransparentDoors(sector_t * sector)
|
|||
{
|
||||
nextsec=sec;
|
||||
|
||||
int side = sector->lines[i]->sidedef[0]->sector == sec;
|
||||
int side = ln->sidedef[0]->sector == sec;
|
||||
|
||||
if (sector->GetPlaneTexZ(sector_t::floor)!=sec->GetPlaneTexZ(sector_t::floor)+1. || sec->floorplane.isSlope())
|
||||
{
|
||||
sector->transdoor=false;
|
||||
return;
|
||||
}
|
||||
if (!sector->lines[i]->sidedef[1-side]->GetTexture(side_t::top).isValid()) notextures++;
|
||||
if (!sector->lines[i]->sidedef[1-side]->GetTexture(side_t::bottom).isValid()) nobtextures++;
|
||||
if (!ln->sidedef[1-side]->GetTexture(side_t::top).isValid()) notextures++;
|
||||
if (!ln->sidedef[1-side]->GetTexture(side_t::bottom).isValid()) nobtextures++;
|
||||
}
|
||||
}
|
||||
if (sector->GetTexture(sector_t::ceiling)==skyflatnum)
|
||||
|
@ -358,19 +357,19 @@ static void PrepareTransparentDoors(sector_t * sector)
|
|||
return;
|
||||
}
|
||||
|
||||
if (selfref+nobtextures!=sector->linecount)
|
||||
if (selfref+nobtextures!=sector->Lines.Size())
|
||||
{
|
||||
sector->transdoor=false;
|
||||
}
|
||||
|
||||
if (selfref+notextures!=sector->linecount)
|
||||
if (selfref+notextures!=sector->Lines.Size())
|
||||
{
|
||||
// This is a crude attempt to fix an incorrect transparent door effect I found in some
|
||||
// WolfenDoom maps but considering the amount of code required to handle it I left it in.
|
||||
// Do this only if the sector only contains one-sided walls or ones with no lower texture.
|
||||
if (solidwall)
|
||||
{
|
||||
if (solidwall+nobtextures+selfref==sector->linecount && nextsec)
|
||||
if (solidwall+nobtextures+selfref==sector->Lines.Size() && nextsec)
|
||||
{
|
||||
sector->heightsec=nextsec;
|
||||
sector->heightsec->MoreFlags=0;
|
||||
|
@ -604,9 +603,8 @@ void gl_PreprocessLevel()
|
|||
PrepareTransparentDoors(§ors[i]);
|
||||
|
||||
// This ignores vertices only used for seg splitting because those aren't needed here
|
||||
for(int j = 0; j < sectors[i].linecount; j++)
|
||||
for(auto l : sectors[i].Lines)
|
||||
{
|
||||
line_t *l = sectors[i].lines[j];
|
||||
if (l->sidedef[0]->Flags & WALLF_POLYOBJ) continue; // don't bother with polyobjects
|
||||
|
||||
int vtnum1 = int(l->v1 - vertexes);
|
||||
|
|
|
@ -320,9 +320,8 @@ void GLFlat::DrawSkyboxSector(int pass, bool processlights)
|
|||
float minx = FLT_MAX, miny = FLT_MAX;
|
||||
float maxx = -FLT_MAX, maxy = -FLT_MAX;
|
||||
|
||||
for (int i = 0; i < sector->linecount; i++)
|
||||
for (auto ln : sector->Lines)
|
||||
{
|
||||
line_t *ln = sector->lines[i];
|
||||
float x = ln->v1->fX();
|
||||
float y = ln->v1->fY();
|
||||
if (x < minx) minx = x;
|
||||
|
|
|
@ -756,6 +756,7 @@ xx(ResolveState)
|
|||
xx(DamageFunction)
|
||||
xx(Length)
|
||||
xx(Unit)
|
||||
xx(Size)
|
||||
xx(StateLabel)
|
||||
xx(SpriteID)
|
||||
xx(TextureID)
|
||||
|
|
|
@ -216,7 +216,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
|
|||
//==========================================================================
|
||||
static int P_Set3DFloor(line_t * line, int param, int param2, int alpha)
|
||||
{
|
||||
int s, i;
|
||||
int s;
|
||||
int flags;
|
||||
int tag = line->args[0];
|
||||
sector_t * sec = line->frontsector, *ss;
|
||||
|
@ -230,10 +230,8 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha)
|
|||
{
|
||||
flags = FF_EXISTS | FF_RENDERALL | FF_SOLID | FF_INVERTSECTOR;
|
||||
alpha = 255;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
for (auto l: sec->Lines)
|
||||
{
|
||||
line_t * l = sec->lines[i];
|
||||
|
||||
if (l->special == Sector_SetContents && l->frontsector == sec)
|
||||
{
|
||||
alpha = clamp<int>(l->args[1], 0, 100);
|
||||
|
|
|
@ -167,10 +167,8 @@ void P_Attach3dMidtexLinesToSector(sector_t *sector, int lineid, int tag, bool c
|
|||
int sec;
|
||||
while ((sec = it.Next()) >= 0)
|
||||
{
|
||||
for (int line = 0; line < sectors[sec].linecount; line ++)
|
||||
for (auto ln : sectors[sec].Lines)
|
||||
{
|
||||
line_t *ln = sectors[sec].lines[line];
|
||||
|
||||
if (lineid != 0 && !tagManager.LineHasID(ln, lineid)) continue;
|
||||
|
||||
if (ln->frontsector == NULL || ln->backsector == NULL || !(ln->flags & ML_3DMIDTEX))
|
||||
|
|
|
@ -242,7 +242,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
|
|||
|
||||
// new door thinker
|
||||
DCeiling *ceiling = new DCeiling (sec, speed, speed2, silent & ~4);
|
||||
vertex_t *spot = sec->lines[0]->v1;
|
||||
vertex_t *spot = sec->Lines[0]->v1;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
|
|
@ -286,10 +286,9 @@ void DDoor::DoorSound(bool raise, DSeqNode *curseq) const
|
|||
|
||||
// Search the front top textures of 2-sided lines on the door sector
|
||||
// for a door sound to use.
|
||||
for (int i = 0; i < m_Sector->linecount; ++i)
|
||||
for (auto line : m_Sector->Lines)
|
||||
{
|
||||
const char *texname;
|
||||
line_t *line = m_Sector->lines[i];
|
||||
|
||||
if (line->backsector == NULL)
|
||||
continue;
|
||||
|
@ -694,14 +693,14 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay,
|
|||
m_Line1 = line;
|
||||
m_Line2 = line;
|
||||
|
||||
for (int i = 0; i < sec->linecount; ++i)
|
||||
for (auto l : sec->Lines)
|
||||
{
|
||||
if (sec->lines[i] == line)
|
||||
if (l == line)
|
||||
continue;
|
||||
|
||||
if (sec->lines[i]->sidedef[0]->GetTexture(side_t::top) == line->sidedef[0]->GetTexture(side_t::top))
|
||||
if (l->sidedef[0]->GetTexture(side_t::top) == line->sidedef[0]->GetTexture(side_t::top))
|
||||
{
|
||||
m_Line2 = sec->lines[i];
|
||||
m_Line2 = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -789,9 +788,8 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay)
|
|||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; tag != 0 && i < sec->linecount; ++i)
|
||||
for (auto line : sec->Lines)
|
||||
{
|
||||
line = sec->lines[i];
|
||||
if (line->backsector == NULL)
|
||||
{
|
||||
continue;
|
||||
|
|
|
@ -161,10 +161,8 @@ static void P_RecursiveSound(sector_t *sec, AActor *soundtarget, bool splash, AA
|
|||
bool checkabove = !sec->PortalBlocksSound(sector_t::ceiling);
|
||||
bool checkbelow = !sec->PortalBlocksSound(sector_t::floor);
|
||||
|
||||
for (int i = 0; i < sec->linecount; i++)
|
||||
for (auto check : sec->Lines)
|
||||
{
|
||||
line_t *check = sec->lines[i];
|
||||
|
||||
// check sector portals
|
||||
// I wish there was a better method to do this than randomly looking through the portal at a few places...
|
||||
if (checkabove)
|
||||
|
|
|
@ -578,7 +578,6 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
|
|||
int osecnum; //jff 3/4/98 save old loop index
|
||||
double height;
|
||||
double stairstep;
|
||||
int i;
|
||||
int newsecnum = -1;
|
||||
FTextureID texture;
|
||||
int ok;
|
||||
|
@ -669,18 +668,18 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
|
|||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
for (auto line : sec->Lines)
|
||||
{
|
||||
if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
|
||||
if ( !(line->flags & ML_TWOSIDED) )
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->frontsector;
|
||||
tsec = line->frontsector;
|
||||
newsecnum = (int)(tsec-sectors);
|
||||
|
||||
if (secnum != newsecnum)
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->backsector;
|
||||
tsec = line->backsector;
|
||||
if (!tsec) continue; //jff 5/7/98 if no backside, continue
|
||||
newsecnum = (int)(tsec - sectors);
|
||||
|
||||
|
@ -765,7 +764,6 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed)
|
|||
sector_t* s3;
|
||||
int secnum;
|
||||
bool rtn;
|
||||
int i;
|
||||
DFloor* floor;
|
||||
vertex_t* spot;
|
||||
double height;
|
||||
|
@ -782,19 +780,19 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed)
|
|||
continue; // safe now, because we check that tag is non-0 in the looping condition [fdari]
|
||||
|
||||
rtn = true;
|
||||
s2 = getNextSector (s1->lines[0], s1); // s2 is pool's sector
|
||||
s2 = getNextSector (s1->Lines[0], s1); // s2 is pool's sector
|
||||
if (!s2) // note lowest numbered line around
|
||||
continue; // pillar must be two-sided
|
||||
|
||||
if (s2->PlaneMoving(sector_t::floor))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < s2->linecount; i++)
|
||||
for (auto ln : s2->Lines)
|
||||
{
|
||||
if (!(s2->lines[i]->flags & ML_TWOSIDED) ||
|
||||
(s2->lines[i]->backsector == s1))
|
||||
if (!(ln->flags & ML_TWOSIDED) ||
|
||||
(ln->backsector == s1))
|
||||
continue;
|
||||
s3 = s2->lines[i]->backsector;
|
||||
s3 = ln->backsector;
|
||||
|
||||
// Spawn rising slime
|
||||
floor = new DFloor (s2);
|
||||
|
|
|
@ -540,9 +540,9 @@ void EV_TurnTagLightsOff (int tag)
|
|||
sector_t *sector = sectors + secnum;
|
||||
int min = sector->lightlevel;
|
||||
|
||||
for (int i = 0; i < sector->linecount; i++)
|
||||
for (auto ln : sector->Lines)
|
||||
{
|
||||
sector_t *tsec = getNextSector (sector->lines[i],sector);
|
||||
sector_t *tsec = getNextSector (ln, sector);
|
||||
if (!tsec)
|
||||
continue;
|
||||
if (tsec->lightlevel < min)
|
||||
|
@ -574,11 +574,9 @@ void EV_LightTurnOn (int tag, int bright)
|
|||
// surrounding sector
|
||||
if (bright < 0)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < sector->linecount; j++)
|
||||
for (auto ln : sector->Lines)
|
||||
{
|
||||
sector_t *temp = getNextSector (sector->lines[j], sector);
|
||||
sector_t *temp = getNextSector(ln, sector);
|
||||
|
||||
if (!temp)
|
||||
continue;
|
||||
|
@ -622,11 +620,11 @@ void EV_LightTurnOnPartway (int tag, double frac)
|
|||
while ((secnum = it.Next()) >= 0)
|
||||
{
|
||||
sector_t *temp, *sector = §ors[secnum];
|
||||
int j, bright = 0, min = sector->lightlevel;
|
||||
int bright = 0, min = sector->lightlevel;
|
||||
|
||||
for (j = 0; j < sector->linecount; ++j)
|
||||
for (auto ln : sector->Lines)
|
||||
{
|
||||
if ((temp = getNextSector (sector->lines[j], sector)) != NULL)
|
||||
if ((temp = getNextSector (ln, sector)) != nullptr)
|
||||
{
|
||||
if (temp->lightlevel > bright)
|
||||
{
|
||||
|
|
|
@ -45,12 +45,8 @@
|
|||
sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const
|
||||
{
|
||||
sector_t *tsec;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto ln : Lines)
|
||||
{
|
||||
line_t *ln = lines[i];
|
||||
|
||||
if (NULL != (tsec = getNextSector (ln, this)) &&
|
||||
tsec != nogood &&
|
||||
tsec->special == type)
|
||||
|
@ -67,21 +63,18 @@ sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const
|
|||
//
|
||||
double sector_t::FindLowestFloorSurrounding (vertex_t **v) const
|
||||
{
|
||||
int i;
|
||||
sector_t *other;
|
||||
line_t *check;
|
||||
double floor;
|
||||
double ofloor;
|
||||
vertex_t *spot;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
floor = floorplane.ZatPoint(spot);
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
ofloor = other->floorplane.ZatPoint (check->v1);
|
||||
|
@ -111,21 +104,18 @@ double sector_t::FindLowestFloorSurrounding (vertex_t **v) const
|
|||
//
|
||||
double sector_t::FindHighestFloorSurrounding (vertex_t **v) const
|
||||
{
|
||||
int i;
|
||||
line_t *check;
|
||||
sector_t *other;
|
||||
double floor;
|
||||
double ofloor;
|
||||
vertex_t *spot;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
floor = -FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
ofloor = other->floorplane.ZatPoint (check->v1);
|
||||
|
@ -166,18 +156,15 @@ double sector_t::FindNextHighestFloor (vertex_t **v) const
|
|||
double ofloor, floor;
|
||||
sector_t *other;
|
||||
vertex_t *spot;
|
||||
line_t *check;
|
||||
int i;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
height = floorplane.ZatPoint(spot);
|
||||
heightdiff = FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
ofloor = other->floorplane.ZatPoint (check->v1);
|
||||
|
@ -221,18 +208,15 @@ double sector_t::FindNextLowestFloor (vertex_t **v) const
|
|||
double ofloor, floor;
|
||||
sector_t *other;
|
||||
vertex_t *spot;
|
||||
line_t *check;
|
||||
int i;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
height = floorplane.ZatPoint (spot);
|
||||
heightdiff = FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
ofloor = other->floorplane.ZatPoint (check->v1);
|
||||
|
@ -275,19 +259,15 @@ double sector_t::FindNextLowestCeiling (vertex_t **v) const
|
|||
double oceil, ceil;
|
||||
sector_t *other;
|
||||
vertex_t *spot;
|
||||
line_t *check;
|
||||
int i;
|
||||
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
height = ceilingplane.ZatPoint(spot);
|
||||
heightdiff = FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
oceil = other->ceilingplane.ZatPoint(check->v1);
|
||||
|
@ -330,18 +310,15 @@ double sector_t::FindNextHighestCeiling (vertex_t **v) const
|
|||
double oceil, ceil;
|
||||
sector_t *other;
|
||||
vertex_t *spot;
|
||||
line_t *check;
|
||||
int i;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
height = ceilingplane.ZatPoint(spot);
|
||||
heightdiff = FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
oceil = other->ceilingplane.ZatPoint(check->v1);
|
||||
|
@ -376,17 +353,14 @@ double sector_t::FindLowestCeilingSurrounding (vertex_t **v) const
|
|||
double oceil;
|
||||
sector_t *other;
|
||||
vertex_t *spot;
|
||||
line_t *check;
|
||||
int i;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
height = FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
oceil = other->ceilingplane.ZatPoint(check->v1);
|
||||
|
@ -418,17 +392,14 @@ double sector_t::FindHighestCeilingSurrounding (vertex_t **v) const
|
|||
double oceil;
|
||||
sector_t *other;
|
||||
vertex_t *spot;
|
||||
line_t *check;
|
||||
int i;
|
||||
|
||||
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
spot = lines[0]->v1;
|
||||
spot = Lines[0]->v1;
|
||||
height = -FLT_MAX;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
check = lines[i];
|
||||
if (NULL != (other = getNextSector (check, this)))
|
||||
{
|
||||
oceil = other->ceilingplane.ZatPoint(check->v1);
|
||||
|
@ -479,12 +450,12 @@ double sector_t::FindShortestTextureAround () const
|
|||
{
|
||||
double minsize = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
if (lines[i]->flags & ML_TWOSIDED)
|
||||
if (check->flags & ML_TWOSIDED)
|
||||
{
|
||||
CheckShortestTex (lines[i]->sidedef[0]->GetTexture(side_t::bottom), minsize);
|
||||
CheckShortestTex (lines[i]->sidedef[1]->GetTexture(side_t::bottom), minsize);
|
||||
CheckShortestTex (check->sidedef[0]->GetTexture(side_t::bottom), minsize);
|
||||
CheckShortestTex (check->sidedef[1]->GetTexture(side_t::bottom), minsize);
|
||||
}
|
||||
}
|
||||
return minsize < FLT_MAX ? minsize : TexMan[0]->GetHeight();
|
||||
|
@ -505,12 +476,12 @@ double sector_t::FindShortestUpperAround () const
|
|||
{
|
||||
double minsize = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
if (lines[i]->flags & ML_TWOSIDED)
|
||||
if (check->flags & ML_TWOSIDED)
|
||||
{
|
||||
CheckShortestTex (lines[i]->sidedef[0]->GetTexture(side_t::top), minsize);
|
||||
CheckShortestTex (lines[i]->sidedef[1]->GetTexture(side_t::top), minsize);
|
||||
CheckShortestTex (check->sidedef[0]->GetTexture(side_t::top), minsize);
|
||||
CheckShortestTex (check->sidedef[1]->GetTexture(side_t::top), minsize);
|
||||
}
|
||||
}
|
||||
return minsize < FLT_MAX ? minsize : TexMan[0]->GetHeight();
|
||||
|
@ -533,17 +504,14 @@ double sector_t::FindShortestUpperAround () const
|
|||
//
|
||||
sector_t *sector_t::FindModelFloorSector (double floordestheight) const
|
||||
{
|
||||
int i;
|
||||
sector_t *sec;
|
||||
|
||||
//jff 5/23/98 don't disturb sec->linecount while searching
|
||||
// but allow early exit in old demos
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
sec = getNextSector (lines[i], this);
|
||||
sec = getNextSector (check, this);
|
||||
if (sec != NULL &&
|
||||
(sec->floorplane.ZatPoint(lines[i]->v1) == floordestheight ||
|
||||
sec->floorplane.ZatPoint(lines[i]->v2) == floordestheight))
|
||||
(sec->floorplane.ZatPoint(check->v1) == floordestheight ||
|
||||
sec->floorplane.ZatPoint(check->v2) == floordestheight))
|
||||
{
|
||||
return sec;
|
||||
}
|
||||
|
@ -569,17 +537,14 @@ sector_t *sector_t::FindModelFloorSector (double floordestheight) const
|
|||
//
|
||||
sector_t *sector_t::FindModelCeilingSector (double floordestheight) const
|
||||
{
|
||||
int i;
|
||||
sector_t *sec;
|
||||
|
||||
//jff 5/23/98 don't disturb sec->linecount while searching
|
||||
// but allow early exit in old demos
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
sec = getNextSector (lines[i], this);
|
||||
sec = getNextSector (check, this);
|
||||
if (sec != NULL &&
|
||||
(sec->ceilingplane.ZatPoint(lines[i]->v1) == floordestheight ||
|
||||
sec->ceilingplane.ZatPoint(lines[i]->v2) == floordestheight))
|
||||
(sec->ceilingplane.ZatPoint(check->v1) == floordestheight ||
|
||||
sec->ceilingplane.ZatPoint(check->v2) == floordestheight))
|
||||
{
|
||||
return sec;
|
||||
}
|
||||
|
@ -592,13 +557,10 @@ sector_t *sector_t::FindModelCeilingSector (double floordestheight) const
|
|||
//
|
||||
int sector_t::FindMinSurroundingLight (int min) const
|
||||
{
|
||||
int i;
|
||||
line_t* line;
|
||||
sector_t* check;
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto line : Lines)
|
||||
{
|
||||
line = lines[i];
|
||||
if (NULL != (check = getNextSector (line, this)) &&
|
||||
check->lightlevel < min)
|
||||
{
|
||||
|
@ -613,8 +575,6 @@ int sector_t::FindMinSurroundingLight (int min) const
|
|||
//
|
||||
double sector_t::FindHighestFloorPoint (vertex_t **v) const
|
||||
{
|
||||
int i;
|
||||
line_t *line;
|
||||
double height = -FLT_MAX;
|
||||
double probeheight;
|
||||
vertex_t *spot = NULL;
|
||||
|
@ -623,15 +583,14 @@ double sector_t::FindHighestFloorPoint (vertex_t **v) const
|
|||
{
|
||||
if (v != NULL)
|
||||
{
|
||||
if (linecount == 0) *v = &vertexes[0];
|
||||
else *v = lines[0]->v1;
|
||||
if (Lines.Size() == 0) *v = &vertexes[0];
|
||||
else *v = Lines[0]->v1;
|
||||
}
|
||||
return -floorplane.fD();
|
||||
}
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto line : Lines)
|
||||
{
|
||||
line = lines[i];
|
||||
probeheight = floorplane.ZatPoint(line->v1);
|
||||
if (probeheight > height)
|
||||
{
|
||||
|
@ -655,8 +614,6 @@ double sector_t::FindHighestFloorPoint (vertex_t **v) const
|
|||
//
|
||||
double sector_t::FindLowestCeilingPoint (vertex_t **v) const
|
||||
{
|
||||
int i;
|
||||
line_t *line;
|
||||
double height = FLT_MAX;
|
||||
double probeheight;
|
||||
vertex_t *spot = NULL;
|
||||
|
@ -665,15 +622,14 @@ double sector_t::FindLowestCeilingPoint (vertex_t **v) const
|
|||
{
|
||||
if (v != NULL)
|
||||
{
|
||||
if (linecount == 0) *v = &vertexes[0];
|
||||
else *v = lines[0]->v1;
|
||||
if (Lines.Size() == 0) *v = &vertexes[0];
|
||||
else *v = Lines[0]->v1;
|
||||
}
|
||||
return ceilingplane.fD();
|
||||
}
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
for (auto line : Lines)
|
||||
{
|
||||
line = lines[i];
|
||||
probeheight = ceilingplane.ZatPoint(line->v1);
|
||||
if (probeheight < height)
|
||||
{
|
||||
|
@ -738,15 +694,14 @@ DEFINE_ACTION_FUNCTION(_Sector, SetFade)
|
|||
|
||||
void sector_t::ClosestPoint(const DVector2 &in, DVector2 &out) const
|
||||
{
|
||||
int i;
|
||||
double x = in.X, y = in.Y;
|
||||
double bestdist = HUGE_VAL;
|
||||
double bestx = 0, besty = 0;
|
||||
|
||||
for (i = 0; i < linecount; ++i)
|
||||
for (auto check : Lines)
|
||||
{
|
||||
vertex_t *v1 = lines[i]->v1;
|
||||
vertex_t *v2 = lines[i]->v2;
|
||||
vertex_t *v1 = check->v1;
|
||||
vertex_t *v2 = check->v2;
|
||||
double a = v2->fX() - v1->fX();
|
||||
double b = v2->fY() - v1->fY();
|
||||
double den = a*a + b*b;
|
||||
|
@ -1133,9 +1088,8 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
|
|||
|
||||
void sector_t::RemoveForceField()
|
||||
{
|
||||
for (int i = 0; i < linecount; ++i)
|
||||
for (auto line : Lines)
|
||||
{
|
||||
line_t *line = lines[i];
|
||||
if (line->backsector != NULL && line->special == ForceField)
|
||||
{
|
||||
line->flags &= ~(ML_BLOCKING | ML_BLOCKEVERYTHING);
|
||||
|
@ -1377,8 +1331,7 @@ DEFINE_FIELD_X(Sector, sector_t, soundtraversed)
|
|||
DEFINE_FIELD_X(Sector, sector_t, stairlock)
|
||||
DEFINE_FIELD_X(Sector, sector_t, prevsec)
|
||||
DEFINE_FIELD_X(Sector, sector_t, nextsec)
|
||||
DEFINE_FIELD_X(Sector, sector_t, linecount)
|
||||
DEFINE_FIELD_X(Sector, sector_t, lines)
|
||||
DEFINE_FIELD_X(Sector, sector_t, Lines)
|
||||
DEFINE_FIELD_X(Sector, sector_t, heightsec)
|
||||
DEFINE_FIELD_X(Sector, sector_t, bottommap)
|
||||
DEFINE_FIELD_X(Sector, sector_t, midmap)
|
||||
|
|
|
@ -775,16 +775,13 @@ static void SetTextureNoErr (side_t *side, int position, DWORD *color, const cha
|
|||
|
||||
void P_FloodZone (sector_t *sec, int zonenum)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sec->ZoneNumber == zonenum)
|
||||
return;
|
||||
|
||||
sec->ZoneNumber = zonenum;
|
||||
|
||||
for (i = 0; i < sec->linecount; ++i)
|
||||
for (auto check : sec->Lines)
|
||||
{
|
||||
line_t *check = sec->lines[i];
|
||||
sector_t *other;
|
||||
|
||||
if (check->sidedef[1] == NULL || (check->flags & ML_ZONEBOUNDARY))
|
||||
|
@ -3093,7 +3090,6 @@ static void P_GroupLines (bool buildmap)
|
|||
cycle_t times[16];
|
||||
int* linesDoneInEachSector;
|
||||
int i;
|
||||
int j;
|
||||
int total;
|
||||
line_t* li;
|
||||
sector_t* sector;
|
||||
|
@ -3140,13 +3136,13 @@ static void P_GroupLines (bool buildmap)
|
|||
}
|
||||
else
|
||||
{
|
||||
li->frontsector->linecount++;
|
||||
li->frontsector->Lines.Count++;
|
||||
total++;
|
||||
}
|
||||
|
||||
if (li->backsector && li->backsector != li->frontsector)
|
||||
{
|
||||
li->backsector->linecount++;
|
||||
li->backsector->Lines.Count++;
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
@ -3165,7 +3161,7 @@ static void P_GroupLines (bool buildmap)
|
|||
|
||||
for (sector = sectors, i = 0; i < numsectors; i++, sector++)
|
||||
{
|
||||
if (sector->linecount == 0)
|
||||
if (sector->Lines.Count == 0)
|
||||
{
|
||||
Printf ("Sector %i (tag %i) has no lines\n", i, tagManager.GetFirstSectorTag(sector));
|
||||
// 0 the sector's tag so that no specials can use it
|
||||
|
@ -3173,8 +3169,8 @@ static void P_GroupLines (bool buildmap)
|
|||
}
|
||||
else
|
||||
{
|
||||
sector->lines = lineb_p;
|
||||
lineb_p += sector->linecount;
|
||||
sector->Lines.Array = lineb_p;
|
||||
lineb_p += sector->Lines.Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3182,26 +3178,25 @@ static void P_GroupLines (bool buildmap)
|
|||
{
|
||||
if (li->frontsector != NULL)
|
||||
{
|
||||
li->frontsector->lines[linesDoneInEachSector[li->frontsector - sectors]++] = li;
|
||||
li->frontsector->Lines[linesDoneInEachSector[li->frontsector - sectors]++] = li;
|
||||
}
|
||||
if (li->backsector != NULL && li->backsector != li->frontsector)
|
||||
{
|
||||
li->backsector->lines[linesDoneInEachSector[li->backsector - sectors]++] = li;
|
||||
li->backsector->Lines[linesDoneInEachSector[li->backsector - sectors]++] = li;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, sector = sectors; i < numsectors; ++i, ++sector)
|
||||
{
|
||||
if (linesDoneInEachSector[i] != sector->linecount)
|
||||
if (linesDoneInEachSector[i] != sector->Lines.Size())
|
||||
{
|
||||
I_Error("P_GroupLines: miscounted");
|
||||
}
|
||||
if (sector->linecount > 3)
|
||||
if (sector->Lines.Size() > 3)
|
||||
{
|
||||
bbox.ClearBox();
|
||||
for (j = 0; j < sector->linecount; ++j)
|
||||
for (auto li : sector->Lines)
|
||||
{
|
||||
li = sector->lines[j];
|
||||
bbox.AddToBox(li->v1->fPos());
|
||||
bbox.AddToBox(li->v2->fPos());
|
||||
}
|
||||
|
@ -3210,15 +3205,15 @@ static void P_GroupLines (bool buildmap)
|
|||
sector->centerspot.X = (bbox.Right() + bbox.Left()) / 2;
|
||||
sector->centerspot.Y = (bbox.Top() + bbox.Bottom()) / 2;
|
||||
}
|
||||
else if (sector->linecount > 0)
|
||||
else if (sector->Lines.Size() > 0)
|
||||
{
|
||||
// For triangular sectors the above does not calculate good points unless the longest of the triangle's lines is perfectly horizontal and vertical
|
||||
DVector2 pos = { 0,0 };
|
||||
for (int i = 0; i < sector->linecount; i++)
|
||||
for (auto ln : sector->Lines)
|
||||
{
|
||||
pos += sector->lines[i]->v1->fPos() + sector->lines[i]->v2->fPos();
|
||||
pos += ln->v1->fPos() + ln->v2->fPos();
|
||||
}
|
||||
sector->centerspot = pos / (2 * sector->linecount);
|
||||
sector->centerspot = pos / (2 * sector->Lines.Size());
|
||||
}
|
||||
}
|
||||
delete[] linesDoneInEachSector;
|
||||
|
|
|
@ -201,10 +201,8 @@ void P_SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi, const D
|
|||
|
||||
void P_VavoomSlope(sector_t * sec, int id, const DVector3 &pos, int which)
|
||||
{
|
||||
for (int i=0;i<sec->linecount;i++)
|
||||
for(auto l : sec->Lines)
|
||||
{
|
||||
line_t * l=sec->lines[i];
|
||||
|
||||
if (l->args[0]==id)
|
||||
{
|
||||
DVector3 v1, v2, cross;
|
||||
|
@ -306,16 +304,16 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
|
|||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
sector_t *sec = §ors[i];
|
||||
if (sec->linecount != 3) continue; // only works with triangular sectors
|
||||
if (sec->Lines.Size() != 3) continue; // only works with triangular sectors
|
||||
|
||||
DVector3 vt1, vt2, vt3, cross;
|
||||
DVector3 vec1, vec2;
|
||||
int vi1, vi2, vi3;
|
||||
|
||||
vi1 = int(sec->lines[0]->v1 - vertexes);
|
||||
vi2 = int(sec->lines[0]->v2 - vertexes);
|
||||
vi3 = (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2)?
|
||||
int(sec->lines[1]->v2 - vertexes) : int(sec->lines[1]->v1 - vertexes);
|
||||
vi1 = int(sec->Lines[0]->v1 - vertexes);
|
||||
vi2 = int(sec->Lines[0]->v2 - vertexes);
|
||||
vi3 = (sec->Lines[1]->v1 == sec->Lines[0]->v1 || sec->Lines[1]->v1 == sec->Lines[0]->v2)?
|
||||
int(sec->Lines[1]->v2 - vertexes) : int(sec->Lines[1]->v1 - vertexes);
|
||||
|
||||
vt1 = DVector3(vertexes[vi1].fPos(), 0);
|
||||
vt2 = DVector3(vertexes[vi2].fPos(), 0);
|
||||
|
@ -332,7 +330,7 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
|
|||
vt2.Z = h2? *h2 : j==0? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
|
||||
vt3.Z = h3? *h3 : j==0? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
if (P_PointOnLineSidePrecise(vertexes[vi3].fX(), vertexes[vi3].fY(), sec->lines[0]) == 0)
|
||||
if (P_PointOnLineSidePrecise(vertexes[vi3].fX(), vertexes[vi3].fY(), sec->Lines[0]) == 0)
|
||||
{
|
||||
vec1 = vt2 - vt3;
|
||||
vec2 = vt1 - vt3;
|
||||
|
@ -451,9 +449,7 @@ static void P_AlignPlane(sector_t *sec, line_t *line, int which)
|
|||
{
|
||||
sector_t *refsec;
|
||||
double bestdist;
|
||||
vertex_t *refvert = (*sec->lines)->v1; // Shut up, GCC
|
||||
int i;
|
||||
line_t **probe;
|
||||
vertex_t *refvert = sec->Lines[0]->v1; // Shut up, GCC
|
||||
|
||||
if (line->backsector == NULL)
|
||||
return;
|
||||
|
@ -461,22 +457,22 @@ static void P_AlignPlane(sector_t *sec, line_t *line, int which)
|
|||
// Find furthest vertex from the reference line. It, along with the two ends
|
||||
// of the line, will define the plane.
|
||||
bestdist = 0;
|
||||
for (i = sec->linecount * 2, probe = sec->lines; i > 0; i--)
|
||||
for (auto ln : sec->Lines)
|
||||
{
|
||||
double dist;
|
||||
vertex_t *vert;
|
||||
|
||||
if (i & 1)
|
||||
vert = (*probe++)->v2;
|
||||
else
|
||||
vert = (*probe)->v1;
|
||||
dist = fabs((line->v1->fY() - vert->fY()) * line->Delta().X -
|
||||
(line->v1->fX() - vert->fX()) * line->Delta().Y);
|
||||
|
||||
if (dist > bestdist)
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
bestdist = dist;
|
||||
refvert = vert;
|
||||
double dist;
|
||||
vertex_t *vert;
|
||||
|
||||
vert = i == 0 ? ln->v1 : ln->v2;
|
||||
dist = fabs((line->v1->fY() - vert->fY()) * line->Delta().X -
|
||||
(line->v1->fX() - vert->fX()) * line->Delta().Y);
|
||||
|
||||
if (dist > bestdist)
|
||||
{
|
||||
bestdist = dist;
|
||||
refvert = vert;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1038,10 +1038,8 @@ void P_SpawnSkybox(ASkyViewpoint *origin)
|
|||
}
|
||||
if (Sector)
|
||||
{
|
||||
line_t * refline = NULL;
|
||||
for (short i = 0; i < Sector->linecount; i++)
|
||||
for(auto refline : Sector->Lines)
|
||||
{
|
||||
refline = Sector->lines[i];
|
||||
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
|
||||
{
|
||||
// We found the setup linedef for this skybox, so let's use it for our init.
|
||||
|
|
|
@ -801,9 +801,8 @@ static bool CollectSectors(int groupid, sector_t *origin)
|
|||
{
|
||||
sector_t *sec = list[i];
|
||||
|
||||
for (int j = 0; j < sec->linecount; j++)
|
||||
for (auto line : sec->Lines)
|
||||
{
|
||||
line_t *line = sec->lines[j];
|
||||
sector_t *other = line->frontsector == sec ? line->backsector : line->frontsector;
|
||||
if (other != NULL && other != sec && other->PortalGroup != groupid)
|
||||
{
|
||||
|
@ -1096,9 +1095,9 @@ void P_CreateLinkedPortals()
|
|||
// set a flag on each line connecting to a plane portal sector. This is used to reduce the amount of checks in P_CheckSight.
|
||||
if (sectors[i].PortalIsLinked(sector_t::floor) || sectors[i].PortalIsLinked(sector_t::ceiling))
|
||||
{
|
||||
for (int j = 0; j < sectors[i].linecount; j++)
|
||||
for(auto ln : sectors[i].Lines)
|
||||
{
|
||||
sectors[i].lines[j]->flags |= ML_PORTALCONNECT;
|
||||
ln->flags |= ML_PORTALCONNECT;
|
||||
}
|
||||
}
|
||||
if (sectors[i].PortalIsLinked(sector_t::ceiling) && sectors[i].PortalIsLinked(sector_t::floor))
|
||||
|
|
|
@ -1037,8 +1037,7 @@ public:
|
|||
// jff 2/26/98 lockout machinery for stairbuilding
|
||||
SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally
|
||||
|
||||
short linecount;
|
||||
struct line_t **lines; // [linecount] size
|
||||
TStaticPointedArray<line_t *> Lines;
|
||||
|
||||
// killough 3/7/98: support flat heights drawn at another sector's heights
|
||||
sector_t *heightsec; // other sector, or NULL if no other sector
|
||||
|
|
|
@ -6620,6 +6620,7 @@ FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index)
|
|||
index = _index;
|
||||
AddressRequested = false;
|
||||
AddressWritable = false;
|
||||
SizeAddr = ~0u;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -6691,10 +6692,31 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
|||
arraytype = static_cast<PArray*>(ptype->PointedType);
|
||||
arrayispointer = true;
|
||||
}
|
||||
if (index->isConstant())
|
||||
|
||||
if (Array->IsResizableArray())
|
||||
{
|
||||
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
|
||||
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
|
||||
{
|
||||
auto parentfield = static_cast<FxStructMember *>(Array)->membervar;
|
||||
SizeAddr = unsigned(parentfield->Offset + parentfield->Type->Align);
|
||||
}
|
||||
else if (Array->ExprType == EFX_GlobalVariable)
|
||||
{
|
||||
auto parentfield = static_cast<FxGlobalVariable *>(Array)->membervar;
|
||||
SizeAddr = unsigned(parentfield->Offset + parentfield->Type->Align);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Invalid resizable array");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (index->isConstant())
|
||||
{
|
||||
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
|
||||
if (indexval >= arraytype->ElementCount)
|
||||
if (indexval >= arraytype->ElementCount && !Array->IsResizableArray())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Array index out of bounds");
|
||||
delete this;
|
||||
|
@ -6767,21 +6789,40 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
|||
arraytype = static_cast<PArray*>(Array->ValueType);
|
||||
}
|
||||
ExpEmit start = Array->Emit(build);
|
||||
ExpEmit bound;
|
||||
|
||||
/* what was this for?
|
||||
if (start.Konst)
|
||||
// For resizable arrays we even need to check the bounds if if the index is constant.
|
||||
if (SizeAddr != ~0u)
|
||||
{
|
||||
ExpEmit tmpstart(build, REGT_POINTER);
|
||||
build->Emit(OP_LKP, tmpstart.RegNum, start.RegNum);
|
||||
start.Free(build);
|
||||
start = tmpstart;
|
||||
auto f = new PField(NAME_None, TypeUInt32, 0, SizeAddr);
|
||||
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
|
||||
{
|
||||
static_cast<FxStructMember *>(Array)->membervar = f;
|
||||
static_cast<FxStructMember *>(Array)->AddressRequested = false;
|
||||
}
|
||||
else if (Array->ExprType == EFX_GlobalVariable)
|
||||
{
|
||||
static_cast<FxGlobalVariable *>(Array)->membervar = f;
|
||||
static_cast<FxGlobalVariable *>(Array)->AddressRequested = false;
|
||||
}
|
||||
|
||||
Array->ValueType = TypeUInt32;
|
||||
bound = Array->Emit(build);
|
||||
}
|
||||
*/
|
||||
|
||||
if (index->isConstant())
|
||||
{
|
||||
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
|
||||
assert(indexval < arraytype->ElementCount && "Array index out of bounds");
|
||||
assert(SizeAddr != ~0u || (indexval < arraytype->ElementCount && "Array index out of bounds"));
|
||||
|
||||
if (SizeAddr != ~0u)
|
||||
{
|
||||
ExpEmit indexreg(build, REGT_INT);
|
||||
build->EmitLoadInt(indexreg.RegNum, indexval);
|
||||
build->Emit(OP_BOUND_R, indexreg.RegNum, bound.RegNum);
|
||||
indexreg.Free(build);
|
||||
bound.Free(build);
|
||||
}
|
||||
if (AddressRequested)
|
||||
{
|
||||
if (indexval != 0)
|
||||
|
@ -6821,9 +6862,12 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
|||
else
|
||||
{
|
||||
ExpEmit indexv(index->Emit(build));
|
||||
// Todo: For dynamically allocated arrays (like global sector and linedef tables) we need to get the bound value in here somehow.
|
||||
// Right now their bounds are not properly checked for.
|
||||
if (arraytype->ElementCount > 65535)
|
||||
if (SizeAddr != ~0u)
|
||||
{
|
||||
build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum);
|
||||
bound.Free(build);
|
||||
}
|
||||
else if (arraytype->ElementCount > 65535)
|
||||
{
|
||||
build->Emit(OP_BOUND_K, indexv.RegNum, build->GetConstantInt(arraytype->ElementCount));
|
||||
}
|
||||
|
@ -7347,7 +7391,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
// Note: These builtins would better be relegated to the actual type objects, instead of polluting this file, but that's a task for later.
|
||||
|
||||
// Texture builtins.
|
||||
if (Self->ValueType == TypeTextureID)
|
||||
else if (Self->ValueType == TypeTextureID)
|
||||
{
|
||||
if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull)
|
||||
{
|
||||
|
@ -7390,7 +7434,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
}
|
||||
|
||||
if (Self->IsVector())
|
||||
else if (Self->IsVector())
|
||||
{
|
||||
// handle builtins: Vectors got 2: Length and Unit.
|
||||
if (MethodName == NAME_Length || MethodName == NAME_Unit)
|
||||
|
@ -7408,11 +7452,63 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
}
|
||||
|
||||
if (Self->ValueType == TypeString)
|
||||
else if (Self->ValueType == TypeString)
|
||||
{
|
||||
// same for String methods. It also uses a hidden struct type to define them.
|
||||
Self->ValueType = TypeStringStruct;
|
||||
}
|
||||
else if (Self->IsArray())
|
||||
{
|
||||
if (MethodName == NAME_Size)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!Self->IsResizableArray())
|
||||
{
|
||||
auto atype = Self->ValueType;
|
||||
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) atype = static_cast<PPointer*>(ValueType)->PointedType;
|
||||
auto size = static_cast<PArray*>(atype)->ElementCount;
|
||||
auto x = new FxConstant(size, ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resizable arrays can only be defined in C code and they can only exist in pointer form to reduce their impact on the code generator.
|
||||
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember)
|
||||
{
|
||||
auto member = static_cast<FxStructMember*>(Self);
|
||||
auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer.
|
||||
member->membervar = newfield;
|
||||
Self = nullptr;
|
||||
delete this;
|
||||
member->ValueType = TypeUInt32;
|
||||
return member;
|
||||
}
|
||||
else if (Self->ExprType == EFX_GlobalVariable)
|
||||
{
|
||||
auto member = static_cast<FxGlobalVariable*>(Self);
|
||||
auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer.
|
||||
member->membervar = newfield;
|
||||
Self = nullptr;
|
||||
delete this;
|
||||
member->ValueType = TypeUInt32;
|
||||
return member;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This should never happen because resizable arrays cannot be defined in scripts.
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot retrieve size of array");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
|
|
|
@ -326,6 +326,8 @@ public:
|
|||
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
|
||||
bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); }
|
||||
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
|
||||
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); }
|
||||
bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PResizableArray))); } // can only exist in pointer form.
|
||||
|
||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitStatement(VMFunctionBuilder *build);
|
||||
|
@ -426,6 +428,13 @@ public:
|
|||
isresolved = true;
|
||||
}
|
||||
|
||||
FxConstant(unsigned int val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos)
|
||||
{
|
||||
ValueType = value.Type = TypeUInt32;
|
||||
value.Int = val;
|
||||
isresolved = true;
|
||||
}
|
||||
|
||||
FxConstant(double val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos)
|
||||
{
|
||||
ValueType = value.Type = TypeFloat64;
|
||||
|
@ -1427,6 +1436,7 @@ class FxArrayElement : public FxExpression
|
|||
public:
|
||||
FxExpression *Array;
|
||||
FxExpression *index;
|
||||
unsigned SizeAddr;
|
||||
bool AddressRequested;
|
||||
bool AddressWritable;
|
||||
bool arrayispointer = false;
|
||||
|
|
|
@ -710,12 +710,8 @@ static int fieldcmp(const void * a, const void * b)
|
|||
|
||||
void InitThingdef()
|
||||
{
|
||||
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
|
||||
// Create all global variables here because this cannot be done on the script side and really isn't worth adding support for.
|
||||
|
||||
PStruct *sstruct = NewNativeStruct("Sector", nullptr);
|
||||
auto sptr = NewPointer(sstruct);
|
||||
sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget));
|
||||
|
||||
// expose the global validcount variable.
|
||||
PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount);
|
||||
GlobalSymbols.AddSymbol(vcf);
|
||||
|
@ -746,7 +742,7 @@ void InitThingdef()
|
|||
// set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well...
|
||||
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
|
||||
pstruct = NewNativeStruct("Sector", nullptr);
|
||||
pstruct->AddNativeField("lines", NewPointer(NewArray(NewPointer(NewNativeStruct("line", nullptr), false), 0x40000), false), myoffsetof(sector_t, lines), VARF_Native);
|
||||
pstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(NewNativeStruct("line", nullptr), false)), false), myoffsetof(sector_t, Lines), VARF_Native);
|
||||
|
||||
parray = NewArray(TypeBool, MAXPLAYERS);
|
||||
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
|
||||
|
|
106
src/tarray.h
106
src/tarray.h
|
@ -467,6 +467,112 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// A non-resizable array
|
||||
// This is meant for data that can be replaced but is otherwise static as long as it exists.
|
||||
// The reason for it is to replace any global pointer/counter pairs with something that can
|
||||
// be reliably accessed by the scripting VM and which can use 'for' iterator syntax.
|
||||
|
||||
// This is split into two, so that it also can be used to wrap arrays that are not directly allocated.
|
||||
// This first class only gets a reference to some data but won't own it.
|
||||
template <class T>
|
||||
class TStaticPointedArray
|
||||
{
|
||||
public:
|
||||
|
||||
typedef TIterator<T> iterator;
|
||||
typedef TIterator<const T> const_iterator;
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return &Array[0];
|
||||
}
|
||||
const_iterator begin() const
|
||||
{
|
||||
return &Array[0];
|
||||
}
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return &Array[0];
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return &Array[Count];
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return &Array[Count];
|
||||
}
|
||||
const_iterator cend() const
|
||||
{
|
||||
return &Array[Count];
|
||||
}
|
||||
|
||||
void Init(T *ptr, unsigned cnt)
|
||||
{
|
||||
Array = ptr;
|
||||
Count = cnt;
|
||||
}
|
||||
// Return a reference to an element
|
||||
T &operator[] (size_t index) const
|
||||
{
|
||||
return Array[index];
|
||||
}
|
||||
unsigned int Size() const
|
||||
{
|
||||
return Count;
|
||||
}
|
||||
// Some code needs to access these directly so they cannot be private.
|
||||
T *Array;
|
||||
unsigned int Count;
|
||||
};
|
||||
|
||||
// This second type owns its data, it can delete and reallocate it, but it cannot
|
||||
// resize the array or repurpose its old contents if new ones are about to be created.
|
||||
template <class T>
|
||||
class TStaticArray : public TStaticPointedArray<T>
|
||||
{
|
||||
public:
|
||||
|
||||
////////
|
||||
// This is a dummy constructor that does nothing. The purpose of this
|
||||
// is so you can create a global TArray in the data segment that gets
|
||||
// used by code before startup without worrying about the constructor
|
||||
// resetting it after it's already been used. You MUST NOT use it for
|
||||
// heap- or stack-allocated TArrays.
|
||||
enum ENoInit
|
||||
{
|
||||
NoInit
|
||||
};
|
||||
TStaticArray(ENoInit dummy)
|
||||
{
|
||||
}
|
||||
////////
|
||||
TStaticArray()
|
||||
{
|
||||
Count = 0;
|
||||
Array = NULL;
|
||||
}
|
||||
// This is not supposed to be copyable.
|
||||
TStaticArray(const TStaticArray<T> &other) = delete;
|
||||
|
||||
~TStaticArray()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
if (Array) delete[] Array;
|
||||
}
|
||||
void Alloc(unsigned int amount)
|
||||
{
|
||||
Clear();
|
||||
Array = new T[amount];
|
||||
Count = Amount;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// TAutoGrowArray -----------------------------------------------------------
|
||||
// An array with accessors that automatically grow the array as needed.
|
||||
// It can still be used as a normal TArray if needed. ACS uses this for
|
||||
|
|
|
@ -273,8 +273,7 @@ struct Sector native
|
|||
native int prevsec;
|
||||
native int nextsec;
|
||||
|
||||
native readonly int16 linecount;
|
||||
//line_t **lines; // this is defined internally to avoid exposing some overly complicated type to the parser
|
||||
//TStaticPointedArray<line_t *> Lines; // this is defined internally to avoid exposing some overly complicated type to the parser
|
||||
|
||||
native readonly Sector heightsec;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class LittleFly : Actor
|
|||
return fallback;
|
||||
}
|
||||
// Try neighboring sectors
|
||||
for (int i = 0; i < sec.linecount; ++i)
|
||||
for (int i = 0; i < sec.lines.Size(); ++i)
|
||||
{
|
||||
line ln = sec.lines[i];
|
||||
sector sec2 = (ln.frontsector == sec) ? ln.backsector : ln.frontsector;
|
||||
|
|
Loading…
Reference in a new issue