mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 20:20:40 +00:00
- engine-side portal setup for Blood and RRRA.
This commit is contained in:
parent
b91441f849
commit
a36377111c
6 changed files with 212 additions and 16 deletions
|
@ -36,15 +36,13 @@ enum
|
|||
{
|
||||
PORTAL_SECTOR_FLOOR = 1,
|
||||
PORTAL_SECTOR_CEILING = 2,
|
||||
PORTAL_SECTOR_FLOOR_REFLECT = 4,
|
||||
PORTAL_SECTOR_CEILING_REFLECT = 8,
|
||||
PORTAL_SECTOR_FLOOR_REFLECT = 3,
|
||||
PORTAL_SECTOR_CEILING_REFLECT = 4,
|
||||
PORTAL_WALL_VIEW = 5,
|
||||
PORTAL_WALL_MIRROR = 6,
|
||||
PORTAL_SECTOR_GEOMETRY = 7,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PORTAL_WALL_VIEW = 1,
|
||||
PORTAL_WALL_MIRROR = 2,
|
||||
};
|
||||
|
||||
//40 bytes
|
||||
struct sectortype
|
||||
|
@ -68,6 +66,7 @@ struct sectortype
|
|||
uint8_t dirty;
|
||||
float ceilingxpan_, ceilingypan_, floorxpan_, floorypan_;
|
||||
uint8_t portalflags;
|
||||
uint8_t portalnum;
|
||||
|
||||
int ceilingxpan() const { return int(ceilingxpan_); }
|
||||
int ceilingypan() const { return int(ceilingypan_); }
|
||||
|
@ -120,6 +119,7 @@ struct walltype
|
|||
float xpan_, ypan_;
|
||||
angle_t clipangle;
|
||||
uint8_t portalflags;
|
||||
uint8_t portalnum;
|
||||
|
||||
int xpan() const { return int(xpan_); }
|
||||
int ypan() const { return int(ypan_); }
|
||||
|
|
|
@ -54,6 +54,7 @@ EXTERN_CVAR(Bool, cl_capfps)
|
|||
|
||||
PalEntry GlobalMapFog;
|
||||
float GlobalFogDensity;
|
||||
TArray<PortalDesc> allPortals;
|
||||
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -3,3 +3,69 @@
|
|||
|
||||
void render_drawrooms(spritetype* playersprite, const vec3_t& position, int sectnum, fixed_t q16angle, fixed_t q16horizon, float rollang);
|
||||
|
||||
struct PortalDesc
|
||||
{
|
||||
int type;
|
||||
int dx, dy, dz;
|
||||
TArray<int> targets;
|
||||
};
|
||||
|
||||
extern TArray<PortalDesc> allPortals;
|
||||
|
||||
inline void portalClear()
|
||||
{
|
||||
allPortals.Clear();
|
||||
}
|
||||
|
||||
inline int portalAdd(int type, int target, int dx = 0, int dy = 0, int dz = 0)
|
||||
{
|
||||
auto& pt = allPortals[allPortals.Reserve(1)];
|
||||
pt.type = type;
|
||||
pt.targets.Push(target);
|
||||
pt.dx = dx;
|
||||
pt.dy = dy;
|
||||
pt.dz = dz;
|
||||
return allPortals.Size() - 1;
|
||||
}
|
||||
|
||||
// merges portals in adjoining sectors. AFAIK the only one of this kind is in Blood's E4M9, which with the original code is very glitchy.
|
||||
inline void mergePortals()
|
||||
{
|
||||
Printf("Have %d portals\n", allPortals.Size());
|
||||
bool didsomething = true;
|
||||
while (didsomething)
|
||||
{
|
||||
didsomething = false;
|
||||
for (unsigned i = 0; i < allPortals.Size(); i++)
|
||||
{
|
||||
auto& pt1 = allPortals[i];
|
||||
if (pt1.type == PORTAL_SECTOR_CEILING || pt1.type == PORTAL_SECTOR_FLOOR)
|
||||
{
|
||||
for (unsigned j = i + 1; j < allPortals.Size(); j++)
|
||||
{
|
||||
auto& pt2 = allPortals[j];
|
||||
if (pt1.type != pt2.type || pt1.dx != pt2.dx || pt1.dy != pt2.dy || pt1.dz != pt2.dz) continue;
|
||||
for (unsigned s = 0; s < pt1.targets.Size(); s++)
|
||||
{
|
||||
for (unsigned t = 0; t < pt2.targets.Size(); t++)
|
||||
{
|
||||
if (findwallbetweensectors(pt1.targets[s], pt2.targets[t]) >= 0)
|
||||
{
|
||||
pt1.targets.Append(pt2.targets);
|
||||
pt2.targets.Reset();
|
||||
pt2.type = -1;
|
||||
for (int n = 0; n < numsectors; n++)
|
||||
{
|
||||
Printf("Merged %d and %d\n", i, j);
|
||||
if (sector[n].portalnum == j) sector[n].portalnum = i;
|
||||
didsomething = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -555,6 +555,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sectortype &c, sectort
|
|||
("hitag", c.hitag, def->hitag)
|
||||
("extra", c.extra, def->extra)
|
||||
("portalflags", c.portalflags, def->portalflags)
|
||||
("portalnum", c.portalnum, def->portalnum)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
|
@ -582,6 +583,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, walltype &c, walltype
|
|||
("hitag", c.hitag, def->hitag)
|
||||
("extra", c.extra, def->extra)
|
||||
("portalflags", c.portalflags, def->portalflags)
|
||||
("portalnum", c.portalnum, def->portalnum)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
|
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "savegamehelp.h"
|
||||
|
||||
#include "blood.h"
|
||||
#include "render.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
@ -42,6 +43,7 @@ void InitMirrors(void)
|
|||
|
||||
mirrorcnt = 0;
|
||||
tileDelete(504);
|
||||
portalClear();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
|
@ -57,7 +59,7 @@ void InitMirrors(void)
|
|||
if (wall[i].extra > 0 && GetWallType(i) == kWallStack)
|
||||
{
|
||||
wall[i].overpicnum = nTile;
|
||||
wall[i].portalflags = PORTAL_WALL_VIEW;
|
||||
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
mirror[mirrorcnt].type = 0;
|
||||
wall[i].cstat |= 32;
|
||||
|
@ -78,8 +80,15 @@ void InitMirrors(void)
|
|||
}
|
||||
}
|
||||
if (j < 0)
|
||||
I_Error("wall[%d] has no matching wall link! (data=%d)\n", i, tmp);
|
||||
mirrorcnt++;
|
||||
{
|
||||
Printf(PRINT_HIGH, "wall[%d] has no matching wall link! (data=%d)\n", i, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mirrorcnt++;
|
||||
wall[i].portalflags = PORTAL_WALL_VIEW;
|
||||
wall[i].portalnum = portalAdd(PORTAL_WALL_VIEW, j);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -117,6 +126,7 @@ void InitMirrors(void)
|
|||
mirror[mirrorcnt].link = j;
|
||||
sector[i].floorpicnum = 4080+mirrorcnt;
|
||||
sector[i].portalflags = PORTAL_SECTOR_FLOOR;
|
||||
sector[i].portalnum = portalAdd(PORTAL_SECTOR_FLOOR, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
|
||||
mirrorcnt++;
|
||||
mirror[mirrorcnt].type = 1;
|
||||
mirror[mirrorcnt].dx = sprite[nLink].x-sprite[nLink2].x;
|
||||
|
@ -126,10 +136,12 @@ void InitMirrors(void)
|
|||
mirror[mirrorcnt].link = i;
|
||||
sector[j].ceilingpicnum = 4080+mirrorcnt;
|
||||
sector[j].portalflags = PORTAL_SECTOR_CEILING;
|
||||
sector[i].portalnum = portalAdd(PORTAL_SECTOR_CEILING, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
|
||||
mirrorcnt++;
|
||||
}
|
||||
}
|
||||
mirrorsector = numsectors;
|
||||
mergePortals();
|
||||
#if 1 // The new backend won't need this shit anymore.
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|||
#include "automap.h"
|
||||
#include "dukeactor.h"
|
||||
#include "interpolate.h"
|
||||
#include "render.h"
|
||||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
|
@ -838,6 +839,124 @@ void newgame(MapRecord* map, int sk, func completion)
|
|||
else completion1(false);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// the setup here is very, very sloppy, because mappings are not 1:1.
|
||||
// Each portal can have multiple sectors, and even extends to unmarked
|
||||
// neighboring sectors if they got the portal tile as floor or ceiling
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void SpawnPortals()
|
||||
{
|
||||
for (int i = 0; i < numwalls; i++)
|
||||
{
|
||||
if (wall[i].overpicnum == TILE_MIRROR) wall[i].portalflags |= PORTAL_WALL_MIRROR;
|
||||
}
|
||||
|
||||
portalClear();
|
||||
int tag;
|
||||
if (!isRR()) tag = 40;
|
||||
else if (isRRRA()) tag = 150;
|
||||
else return;
|
||||
|
||||
TArray<int> processedTags;
|
||||
DukeStatIterator it(STAT_RAROR);
|
||||
while (auto act = it.Next())
|
||||
{
|
||||
auto spr = &act->s;
|
||||
if (spr->picnum == SECTOREFFECTOR && spr->lotag == tag)
|
||||
{
|
||||
if (processedTags.Find(spr->hitag) == processedTags.Size())
|
||||
{
|
||||
DukeStatIterator it2(STAT_RAROR);
|
||||
while (auto act2 = it2.Next())
|
||||
{
|
||||
auto spr2 = &act2->s;
|
||||
if (spr2->picnum == SECTOREFFECTOR && spr2->lotag == tag + 1 && spr2->hitag == spr->hitag)
|
||||
{
|
||||
if (processedTags.Find(spr->hitag) == processedTags.Size())
|
||||
{
|
||||
int s1 = spr->sectnum, s2 = spr2->sectnum;
|
||||
sector[s1].portalflags = PORTAL_SECTOR_FLOOR;
|
||||
sector[s2].portalflags = PORTAL_SECTOR_CEILING;
|
||||
sector[s1].portalnum = portalAdd(PORTAL_SECTOR_FLOOR, s2, spr2->x - spr->x, spr2->y - spr->y, spr->hitag);
|
||||
sector[s2].portalnum = portalAdd(PORTAL_SECTOR_CEILING, s1, spr->x - spr2->x, spr->y - spr2->y, spr->hitag);
|
||||
processedTags.Push(spr->hitag);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& p : allPortals)
|
||||
{
|
||||
if (p.type == PORTAL_SECTOR_FLOOR && p.dz == spr->hitag)
|
||||
{
|
||||
p.targets.Push(spr2->sectnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& p : allPortals)
|
||||
{
|
||||
if (p.type == PORTAL_SECTOR_CEILING && p.dz == spr->hitag)
|
||||
{
|
||||
p.targets.Push(spr->sectnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unfortunately the above still isn't enough. We got to do one more check to add stuff to the portals.
|
||||
// There is one map where a sector neighboring a portal is not marked as part of the portal itself.
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
if (sector[i].floorpicnum == FOF && sector[i].portalflags != PORTAL_SECTOR_FLOOR)
|
||||
{
|
||||
for (auto& pt : allPortals)
|
||||
{
|
||||
if (pt.type == PORTAL_SECTOR_CEILING)
|
||||
{
|
||||
for (auto& t : pt.targets)
|
||||
{
|
||||
if (findwallbetweensectors(i, t) >= 0)
|
||||
{
|
||||
sector[i].portalflags = PORTAL_SECTOR_FLOOR;
|
||||
sector[i].portalnum = uint8_t(&pt - allPortals.Data());
|
||||
pt.targets.Push(i);
|
||||
goto nexti;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sector[i].ceilingpicnum == FOF && sector[i].portalflags != PORTAL_SECTOR_CEILING)
|
||||
{
|
||||
for (auto& pt : allPortals)
|
||||
{
|
||||
if (pt.type == PORTAL_SECTOR_FLOOR)
|
||||
{
|
||||
for (auto& t : pt.targets)
|
||||
{
|
||||
if (findwallbetweensectors(i, t) >= 0)
|
||||
{
|
||||
sector[i].portalflags = PORTAL_SECTOR_CEILING;
|
||||
sector[i].portalnum = uint8_t(&pt - allPortals.Data());
|
||||
pt.targets.Push(i);
|
||||
goto nexti;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nexti:;
|
||||
}
|
||||
for (auto& p : allPortals) p.dz = 0;
|
||||
mergePortals();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
@ -853,12 +972,6 @@ static int LoadTheMap(MapRecord *mi, struct player_struct *p, int gamemode)
|
|||
}
|
||||
|
||||
engineLoadBoard(mi->fileName, isShareware(), &p->pos, &lbang, &p->cursectnum);
|
||||
for(int i = 0; i < numsectors; i++)
|
||||
{
|
||||
if (sector[i].ceilingpicnum == FOF) sector[i].portalflags |= PORTAL_SECTOR_CEILING;
|
||||
if (sector[i].floorpicnum == FOF) sector[i].portalflags |= PORTAL_SECTOR_FLOOR;
|
||||
if (wall[i].overpicnum == TILE_MIRROR) wall[i].portalflags |= PORTAL_WALL_MIRROR;
|
||||
}
|
||||
|
||||
currentLevel = mi;
|
||||
SECRET_SetMapName(mi->DisplayName(), mi->name);
|
||||
|
@ -877,6 +990,8 @@ static int LoadTheMap(MapRecord *mi, struct player_struct *p, int gamemode)
|
|||
if (isRR()) prelevel_r(gamemode);
|
||||
else prelevel_d(gamemode);
|
||||
|
||||
SpawnPortals();
|
||||
|
||||
if (isRRRA() && mi->levelNumber == levelnum(2, 0))
|
||||
{
|
||||
for (int i = PISTOL_WEAPON; i < MAX_WEAPONS; i++)
|
||||
|
|
Loading…
Reference in a new issue