Commit 5ffe0d7e authored by Dino Bollinger's avatar Dino Bollinger Committed by Richard Gobeille
Browse files

Duke3D: Support for multiple simultaneously active Viewscreens

parent 278ba013
......@@ -91,8 +91,8 @@ enum rendmode_t {
#define MAXWALLSB ((MAXWALLS>>2)+(MAXWALLS>>3))
#define MAXTILES 30720
#define MAXUSERTILES (MAXTILES-16) // reserve 16 tiles at the end
#define MAXTILES 30976
#define MAXUSERTILES (MAXTILES-256) // reserve 256 tiles at the end, most of them for VIEWSCREEN space
#define MAXVOXELS 1024
#define MAXSTATUS 1024
......
......@@ -2636,6 +2636,8 @@ DETONATE:
{
int32_t playerDist;
// T2(spriteNum) contains index of viewscreen in g_activeViewscreenSprite
int const curVscrIndex = T2(spriteNum);
int const p = A_FindPlayer(pSprite, &playerDist);
auto const ps = g_player[p].ps;
......@@ -2645,39 +2647,61 @@ DETONATE:
if (dist(&sprite[ps->i], pSprite) < activeDist)
{
// DOS behavior: yvel of 1 activates screen if player approaches
if (g_curViewscreen == -1 && pSprite->yvel & 1)
if (curVscrIndex == -1 && pSprite->yvel & 1)
{
g_curViewscreen = spriteNum;
int newVscrIndex = 0;
while (newVscrIndex < MAX_ACTIVE_VIEWSCREENS && g_activeVscrSprite[newVscrIndex] >= 0)
newVscrIndex++;
// EDuke32 extension: for remote activation, check for connected camera and display its image
if (sprite[spriteNum].hitag)
T2(spriteNum) = newVscrIndex;
if (newVscrIndex < MAX_ACTIVE_VIEWSCREENS)
{
for (bssize_t SPRITES_OF(STAT_ACTOR, otherSprite))
g_activeVscrSprite[newVscrIndex] = spriteNum;
// EDuke32 extension: for remote activation, check for connected camera and display its image
if (sprite[spriteNum].hitag)
{
if (PN(otherSprite) == CAMERA1 && sprite[spriteNum].hitag == SLT(otherSprite))
for (bssize_t SPRITES_OF(STAT_ACTOR, otherSprite))
{
sprite[spriteNum].owner = otherSprite;
break;
if (PN(otherSprite) == CAMERA1 && sprite[spriteNum].hitag == SLT(otherSprite))
{
sprite[spriteNum].owner = otherSprite;
break;
}
}
}
}
} // deactivate viewscreen in valid range if yvel is 0
else if (g_curViewscreen == spriteNum && !(pSprite->yvel & 3))
}
// deactivate viewscreen in valid range if yvel is set to 0
else if (curVscrIndex != -1 && !(pSprite->yvel & 3))
{
g_curViewscreen = -1;
T1(spriteNum) = 0;
for (bssize_t ii = 0; ii < VIEWSCREENFACTOR; ii++)
walock[TILE_VIEWSCR - ii] = CACHE1D_UNLOCKED;
T1(spriteNum) = 0;
T2(spriteNum) = -1;
if (curVscrIndex < MAX_ACTIVE_VIEWSCREENS)
{
if (g_activeVscrTile[curVscrIndex] >= 0)
walock[g_activeVscrTile[curVscrIndex]] = CACHE1D_UNLOCKED;
g_activeVscrSprite[curVscrIndex] = -1;
g_activeVscrTile[curVscrIndex] = -1;
}
}
}
else if (g_curViewscreen == spriteNum /*&& T1 == 1*/)
else if (curVscrIndex != -1)
{
g_curViewscreen = -1;
pSprite->yvel &= ~2; // VIEWSCREEN YVEL
T1(spriteNum) = 0;
T1(spriteNum) = 0;
T2(spriteNum) = -1;
pSprite->yvel &= ~2; // yvel bit 2 is temp activation
for (bssize_t ii = 0; ii < VIEWSCREENFACTOR; ii++)
walock[TILE_VIEWSCR - ii] = CACHE1D_UNLOCKED;
if (curVscrIndex < MAX_ACTIVE_VIEWSCREENS)
{
if (g_activeVscrTile[curVscrIndex] >= 0)
walock[g_activeVscrTile[curVscrIndex]] = CACHE1D_UNLOCKED;
g_activeVscrSprite[curVscrIndex] = -1;
g_activeVscrTile[curVscrIndex] = -1;
}
}
}
......
......@@ -72,6 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define MAXVOLUMES 7
#define MAXLEVELS 64
#define MAXGAMETYPES 16
#define MAX_ACTIVE_VIEWSCREENS 64
enum {
MUS_FIRST_SPECIAL = MAXVOLUMES*MAXLEVELS,
......@@ -106,7 +107,8 @@ enum {
#define TILE_VIEWSCR (MAXTILES-5)
// Reserved: TILE_VIEWSCR_1 (MAXTILES-6)
// Reserved: TILE_VIEWSCR_2 (MAXTILES-7)
EDUKE32_STATIC_ASSERT(7 <= MAXTILES-MAXUSERTILES);
// Reserved: (MAXTILES-8) to (MAXTILES-196) for additional Viewscreen tilespace
EDUKE32_STATIC_ASSERT(4 + (3 * MAX_ACTIVE_VIEWSCREENS) <= MAXTILES-MAXUSERTILES);
// sprites with these statnums should be considered for fixing
#define ROTFIXSPR_STATNUMP(k) ((k)==STAT_DEFAULT || (k)==STAT_STANDABLE || (k)==STAT_FX || \
......
......@@ -3959,17 +3959,21 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t ourz, int32_t oura
case VIEWSCREEN__:
case VIEWSCREEN2__:
{
// invalid index, skip applying a tile
if (T2(i) < 0 || T2(i) >= MAX_ACTIVE_VIEWSCREENS)
break;
int const viewscrTile = g_activeVscrTile[T2(i)];
int const viewscrShift = G_GetViewscreenSizeShift(t);
int const viewscrTile = TILE_VIEWSCR-viewscrShift;
if (g_curViewscreen >= 0 && actor[OW(i)].t_data[0] == 1)
if (actor[OW(i)].t_data[0] == 1)
{
t->picnum = STATIC;
t->cstat |= (wrand()&12);
t->xrepeat += 10;
t->yrepeat += 9;
}
else if (g_curViewscreen == i && display_mirror != 3 && waloff[viewscrTile])
else if (viewscrTile > 0 && display_mirror != 3 && waloff[viewscrTile])
{
// this exposes a sprite sorting issue which needs to be debugged further...
#if 0
......
......@@ -87,10 +87,12 @@ G_EXTERN char typebuf[TYPEBUFSIZE];
G_EXTERN input_t localInput;
G_EXTERN input_t recsync[RECSYNCBUFSIZ];
G_EXTERN int32_t g_activeVscrSprite[MAX_ACTIVE_VIEWSCREENS];
G_EXTERN int32_t g_activeVscrTile[MAX_ACTIVE_VIEWSCREENS];
G_EXTERN int32_t g_animWallCnt;
G_EXTERN int32_t g_animateCnt;
G_EXTERN int32_t g_cloudCnt;
G_EXTERN int32_t g_curViewscreen;
G_EXTERN int32_t g_curViewscreen; // unused, kept for savegame purposes
G_EXTERN int32_t g_frameRate;
G_EXTERN int32_t g_cyclerCnt;
G_EXTERN int32_t g_damageCameras;
......
......@@ -5325,8 +5325,11 @@ void Menu_Close(uint8_t playerID)
// Reset next-viewscreen-redraw counter.
// XXX: are there any other cases like that in need of handling?
if (g_curViewscreen >= 0)
actor[g_curViewscreen].t_data[0] = (int32_t) totalclock;
for (int vscrIndex = 0; vscrIndex < MAX_ACTIVE_VIEWSCREENS; vscrIndex++)
{
if (g_activeVscrSprite[vscrIndex] >= 0)
actor[g_activeVscrSprite[vscrIndex]].t_data[0] = (int32_t) totalclock;
}
}
walock[TILE_SAVESHOT] = CACHE1D_FREE;
......
......@@ -924,11 +924,13 @@ static void P_PrepForNewLevel(int playerNum, int gameMode)
g_animWallCnt = 0;
g_animateCnt = 0;
g_curViewscreen = -1;
g_cyclerCnt = 0;
g_earthquakeTime = 0;
g_interpolationCnt = 0;
for (int vscrIndex = 0; vscrIndex < MAX_ACTIVE_VIEWSCREENS; vscrIndex++)
g_activeVscrSprite[vscrIndex] = -1;
randomseed = 1996;
screenpeek = myconnectindex;
tempwallptr = 0;
......@@ -1704,8 +1706,11 @@ void G_ResetTimers(bool saveMoveCnt)
if (!saveMoveCnt)
g_moveThingsCount = 0;
if (g_curViewscreen >= 0)
actor[g_curViewscreen].t_data[0] = 0;
for (int vscrIndex = 0; vscrIndex < MAX_ACTIVE_VIEWSCREENS; vscrIndex++)
{
if (g_activeVscrSprite[vscrIndex] >= 0)
actor[g_activeVscrSprite[vscrIndex]].t_data[0] = 0;
}
}
void G_ClearFIFO(void)
......
......@@ -1555,7 +1555,7 @@ static const dataspec_t svgm_anmisc[] =
{ DS_SAVEFN, (void *)&sv_preanimateptrsave, 0, 1 },
{ 0, &g_animatePtr[0], sizeof(g_animatePtr[0]), MAXANIMATES },
{ DS_SAVEFN|DS_LOADFN , (void *)&sv_postanimateptr, 0, 1 },
{ 0, &g_curViewscreen, sizeof(g_curViewscreen), 1 },
{ 0, &g_curViewscreen, sizeof(g_curViewscreen), 1 }, // unused
{ 0, &g_origins[0], sizeof(g_origins[0]), ARRAY_SIZE(g_origins) },
{ 0, &g_spriteDeleteQueuePos, sizeof(g_spriteDeleteQueuePos), 1 },
{ DS_NOCHK, &g_deleteQueueSize, sizeof(g_deleteQueueSize), 1 },
......
......@@ -415,40 +415,69 @@ void G_AnimateCamSprite(int smoothRatio)
return;
#endif
if (g_curViewscreen < 0)
return;
int const spriteNum = g_curViewscreen;
int viewscreenOwners[MAX_ACTIVE_VIEWSCREENS];
int viewscreenSizeX[MAX_ACTIVE_VIEWSCREENS];
int viewscreenSizeY[MAX_ACTIVE_VIEWSCREENS];
if (totalclock >= T1(spriteNum) + ud.camera_time)
for (int vscrIndex = 0; vscrIndex < MAX_ACTIVE_VIEWSCREENS; vscrIndex++)
{
auto const pPlayer = g_player[screenpeek].ps;
if (pPlayer->newowner >= 0)
OW(spriteNum) = pPlayer->newowner;
int const spriteNum = g_activeVscrSprite[vscrIndex];
// EDuke32 extension: xvel of viewscreen determines active distance
int const activeDist = sprite[spriteNum].xvel > 0 ? sprite[spriteNum].xvel : VIEWSCREEN_ACTIVE_DISTANCE;
if (spriteNum < 0)
{
viewscreenOwners[vscrIndex] = -1;
continue;
}
if (OW(spriteNum) >= 0 && dist(&sprite[pPlayer->i], &sprite[spriteNum]) < activeDist)
if (totalclock >= T1(spriteNum) + ud.camera_time)
{
int const viewscrShift = G_GetViewscreenSizeShift((uspriteptr_t)&sprite[spriteNum]);
int const viewscrTile = TILE_VIEWSCR - viewscrShift;
auto const pPlayer = g_player[screenpeek].ps;
if (waloff[viewscrTile] == 0)
tileCreate(viewscrTile, tilesiz[PN(spriteNum)].x << viewscrShift, tilesiz[PN(spriteNum)].y << viewscrShift);
else
walock[viewscrTile] = CACHE1D_UNLOCKED;
// EDuke32 extension: xvel of viewscreen determines active distance
int const activeDist = sprite[spriteNum].xvel > 0 ? sprite[spriteNum].xvel : VIEWSCREEN_ACTIVE_DISTANCE;
if (OW(spriteNum) >= 0 && dist(&sprite[pPlayer->i], &sprite[spriteNum]) < activeDist)
{
int const viewscrShift = G_GetViewscreenSizeShift((uspriteptr_t)&sprite[spriteNum]);
int const viewscrTile = TILE_VIEWSCR - viewscrShift - (3*vscrIndex);
int const tilesizx = tilesiz[PN(spriteNum)].x << viewscrShift;
int const tilesizy = tilesiz[PN(spriteNum)].y << viewscrShift;
viewscreenOwners[vscrIndex] = OW(spriteNum);
viewscreenSizeX[vscrIndex] = tilesizx;
viewscreenSizeY[vscrIndex] = tilesizy;
bool tileRef = false;
for (int j = 0; j < vscrIndex; j++)
{
if (OW(spriteNum) == viewscreenOwners[j] && tilesizx == viewscreenSizeX[j] && tilesizy == viewscreenSizeY[j])
{
g_activeVscrTile[vscrIndex] = g_activeVscrTile[j];
tileRef = true;
break;
}
}
if (!tileRef)
{
g_activeVscrTile[vscrIndex] = viewscrTile;
if (waloff[viewscrTile] == 0)
tileCreate(viewscrTile, tilesizx, tilesizy);
else
walock[viewscrTile] = CACHE1D_UNLOCKED;
G_SetupCamTile(OW(spriteNum), viewscrTile, smoothRatio);
G_SetupCamTile(OW(spriteNum), viewscrTile, smoothRatio);
}
#ifdef POLYMER
// Force texture update on viewscreen sprite in Polymer!
if (videoGetRenderMode() == REND_POLYMER)
polymer_invalidatesprite(spriteNum);
// Force texture update on viewscreen sprite in Polymer!
if (videoGetRenderMode() == REND_POLYMER)
polymer_invalidatesprite(spriteNum);
#endif
}
}
T1(spriteNum) = (int32_t) totalclock;
T1(spriteNum) = (int32_t) totalclock;
}
}
}
......@@ -3495,13 +3524,22 @@ void P_CheckSectors(int playerNum)
A_PlaySound(MONITOR_ACTIVE, pPlayer->i);
sprite[nearSprite].owner = spriteNum;
sprite[nearSprite].yvel |= 2; // VIEWSCREEN_YVEL
g_curViewscreen = nearSprite;
if (T2(nearSprite) == -1)
{
int newVscrIndex = 0;
while (newVscrIndex < MAX_ACTIVE_VIEWSCREENS && g_activeVscrSprite[newVscrIndex] != -1)
newVscrIndex++;
T2(nearSprite) = newVscrIndex;
if (newVscrIndex < MAX_ACTIVE_VIEWSCREENS)
g_activeVscrSprite[newVscrIndex] = nearSprite;
}
int const playerSectnum = pPlayer->cursectnum;
pPlayer->cursectnum = SECT(spriteNum);
P_UpdateScreenPal(pPlayer);
pPlayer->cursectnum = playerSectnum;
pPlayer->newowner = spriteNum;
OW(nearSprite) = pPlayer->newowner = spriteNum;
P_UpdatePosWhenViewingCam(pPlayer);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment