mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 06:41:41 +00:00
- added a function which collects all portal group an actor would touch if standing in a given position.
This commit is contained in:
parent
0dce22ce85
commit
405db83393
4 changed files with 167 additions and 18 deletions
|
@ -524,6 +524,7 @@ void P_SerializeWorld (FArchive &arc)
|
|||
{
|
||||
linePortals.Clear();
|
||||
}
|
||||
P_CollectLinkedPortals();
|
||||
}
|
||||
|
||||
void extsector_t::Serialize(FArchive &arc)
|
||||
|
|
|
@ -18,6 +18,7 @@ CVAR(Int, sv_portal_recursions, 4, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
|||
FDisplacementTable Displacements;
|
||||
|
||||
TArray<FLinePortal> linePortals;
|
||||
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
|
||||
|
||||
|
||||
FArchive &operator<< (FArchive &arc, FLinePortal &port)
|
||||
|
@ -168,6 +169,19 @@ void P_UpdatePortal(FLinePortal *port)
|
|||
}
|
||||
}
|
||||
|
||||
void P_CollectLinkedPortals()
|
||||
{
|
||||
linkedPortals.Clear();
|
||||
for (unsigned i = 0; i < linePortals.Size(); i++)
|
||||
{
|
||||
FLinePortal * port = &linePortals[i];
|
||||
if (port->mType == PORTT_LINKED)
|
||||
{
|
||||
linkedPortals.Push(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P_FinalizePortals()
|
||||
{
|
||||
for (unsigned i = 0; i < linePortals.Size(); i++)
|
||||
|
@ -175,6 +189,7 @@ void P_FinalizePortals()
|
|||
FLinePortal * port = &linePortals[i];
|
||||
P_UpdatePortal(port);
|
||||
}
|
||||
P_CollectLinkedPortals();
|
||||
}
|
||||
|
||||
static bool ChangePortalLine(line_t *line, int destid)
|
||||
|
@ -839,6 +854,88 @@ void P_CreateLinkedPortals()
|
|||
//BuildBlockmap();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Collect all portal groups this actor would occupy at the given position
|
||||
// This is used to determine which parts of the map need to be checked.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortalGroupTable &out)
|
||||
{
|
||||
TArray<FLinePortal*> foundPortals;
|
||||
bool retval = false;
|
||||
if (linePortals.Size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
out.setSize(Displacements.size);
|
||||
out.setBit(actor->Sector->PortalGroup);
|
||||
//FBoundingBox box(newx, newy, actor->radius);
|
||||
int thisgroup = actor->Sector->PortalGroup;
|
||||
for (unsigned i = 0; i < linePortals.Size(); i++)
|
||||
{
|
||||
if (linePortals[i].mType != PORTT_LINKED) continue; // not a linked portal
|
||||
line_t *ld = linePortals[i].mOrigin;
|
||||
int othergroup = ld->frontsector->PortalGroup;
|
||||
FDisplacement &disp = Displacements(thisgroup, othergroup);
|
||||
if (!disp.isSet) continue; // no connection.
|
||||
|
||||
FBoundingBox box(newx + disp.x, newy + disp.y, actor->radius);
|
||||
|
||||
if (box.Right() <= ld->bbox[BOXLEFT]
|
||||
|| box.Left() >= ld->bbox[BOXRIGHT]
|
||||
|| box.Top() <= ld->bbox[BOXBOTTOM]
|
||||
|| box.Bottom() >= ld->bbox[BOXTOP])
|
||||
continue; // not touched
|
||||
|
||||
if (box.BoxOnLineSide(linePortals[i].mOrigin) != -1) continue; // not touched
|
||||
foundPortals.Push(&linePortals[i]);
|
||||
}
|
||||
bool foundone = true;
|
||||
while (foundone)
|
||||
{
|
||||
foundone = false;
|
||||
for (int i = foundPortals.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (out.getBit(foundPortals[i]->mOrigin->frontsector->PortalGroup) &&
|
||||
!out.getBit(foundPortals[i]->mDestination->frontsector->PortalGroup))
|
||||
{
|
||||
out.setBit(foundPortals[i]->mDestination->frontsector->PortalGroup);
|
||||
foundone = true;
|
||||
retval = true;
|
||||
foundPortals.Delete(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
sector_t *sec = P_PointInSector(newx, newy);
|
||||
sector_t *wsec = sec;
|
||||
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && actor->Top() > wsec->SkyBoxes[sector_t::ceiling]->threshold)
|
||||
{
|
||||
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
|
||||
FDisplacement &disp = Displacements(actor->Sector->PortalGroup, othersec->PortalGroup);
|
||||
fixed_t dx = newx + disp.x;
|
||||
fixed_t dy = newx + disp.y;
|
||||
out.setBit(othersec->PortalGroup);
|
||||
wsec = P_PointInSector(dx, dy); // get upper sector at the exact spot we want to check and repeat,
|
||||
retval = true;
|
||||
}
|
||||
wsec = sec;
|
||||
while (!wsec->PortalBlocksMovement(sector_t::floor) && actor->Z() < wsec->SkyBoxes[sector_t::floor]->threshold)
|
||||
{
|
||||
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
|
||||
FDisplacement &disp = Displacements(actor->Sector->PortalGroup, othersec->PortalGroup);
|
||||
fixed_t dx = newx + disp.x;
|
||||
fixed_t dy = newx + disp.y;
|
||||
out.setBit(othersec->PortalGroup);
|
||||
wsec = P_PointInSector(dx, dy); // get lower sector at the exact spot we want to check and repeat,
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
CCMD(dumplinktable)
|
||||
{
|
||||
for (int x = 1; x < Displacements.size; x++)
|
||||
|
@ -854,3 +951,4 @@ CCMD(dumplinktable)
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
65
src/portal.h
65
src/portal.h
|
@ -7,6 +7,7 @@
|
|||
#include "actor.h"
|
||||
#include "p_local.h"
|
||||
#include "m_bbox.h"
|
||||
#include "a_sharedglobal.h"
|
||||
|
||||
struct FDisplacement
|
||||
{
|
||||
|
@ -33,6 +34,40 @@ struct FDisplacementTable
|
|||
}
|
||||
};
|
||||
|
||||
extern FDisplacementTable Displacements;
|
||||
|
||||
struct FPortalGroupTable
|
||||
{
|
||||
TArray<DWORD> data;
|
||||
TArray<int> touchingGroups;
|
||||
|
||||
void setSize(int num)
|
||||
{
|
||||
data.Resize((num + 31) / 32);
|
||||
memset(&data[0], 0, data.Size()*sizeof(DWORD));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
data.Clear();
|
||||
touchingGroups.Clear();
|
||||
}
|
||||
|
||||
void setBit(int group)
|
||||
{
|
||||
if (!getBit(group))
|
||||
{
|
||||
data[group >> 5] |= (1 << (group & 31));
|
||||
touchingGroups.Push(group);
|
||||
}
|
||||
}
|
||||
|
||||
int getBit(int group)
|
||||
{
|
||||
return data[group >> 5] & (1 << (group & 31));
|
||||
}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PORTF_VISIBLE = 1,
|
||||
|
@ -60,6 +95,12 @@ enum
|
|||
PORG_CEILING,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PCOLL_NOTLINKED = 1,
|
||||
PCOLL_LINKED = 2
|
||||
};
|
||||
|
||||
struct FLinePortal
|
||||
{
|
||||
line_t *mOrigin;
|
||||
|
@ -78,6 +119,12 @@ void P_SpawnLinePortal(line_t* line);
|
|||
void P_FinalizePortals();
|
||||
bool P_ChangePortal(line_t *ln, int thisid, int destid);
|
||||
void P_CreateLinkedPortals();
|
||||
bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortalGroupTable &out);
|
||||
void P_CollectLinkedPortals();
|
||||
inline int P_NumPortalGroups()
|
||||
{
|
||||
return Displacements.size;
|
||||
}
|
||||
|
||||
|
||||
/* code ported from prototype */
|
||||
|
@ -145,4 +192,22 @@ inline int line_t::getPortalAlignment() const
|
|||
return portalindex >= linePortals.Size() ? 0 : linePortals[portalindex].mAlign;
|
||||
}
|
||||
|
||||
inline bool sector_t::PortalBlocksView(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
|
||||
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
inline bool sector_t::PortalBlocksMovement(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
|
||||
return !!(planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
inline bool sector_t::PortalBlocksSound(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
|
||||
return !!(planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
#endif
|
21
src/r_defs.h
21
src/r_defs.h
|
@ -739,24 +739,9 @@ struct sector_t
|
|||
Flags &= ~SECF_SPECIALFLAGS;
|
||||
}
|
||||
|
||||
inline bool PortalBlocksView(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
|
||||
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
inline bool PortalBlocksMovement(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
|
||||
return !!(planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
inline bool PortalBlocksSound(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
|
||||
return !!(planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
bool PortalBlocksView(int plane);
|
||||
bool PortalBlocksMovement(int plane);
|
||||
bool PortalBlocksSound(int plane);
|
||||
|
||||
int GetTerrain(int pos) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue