2020-07-04 21:40:54 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
|
|
|
|
|
|
|
|
Duke Nukem 3D is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
Original Source: 1996 - Todd Replogle
|
|
|
|
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|
|
|
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "ns.h"
|
|
|
|
#include "duke3d.h"
|
2020-07-05 14:49:00 +00:00
|
|
|
#include "build.h"
|
|
|
|
#include "v_video.h"
|
2020-07-06 09:39:39 +00:00
|
|
|
#include "prediction.h"
|
2020-09-06 18:49:43 +00:00
|
|
|
#include "automap.h"
|
2020-11-04 06:01:25 +00:00
|
|
|
#include "dukeactor.h"
|
2020-11-26 15:03:40 +00:00
|
|
|
#include "interpolate.h"
|
2020-07-04 21:40:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Floor Over Floor
|
|
|
|
|
|
|
|
// If standing in sector with SE42
|
|
|
|
// then draw viewing to SE41 and raise all =hi SE43 cielings.
|
|
|
|
|
|
|
|
// If standing in sector with SE43
|
|
|
|
// then draw viewing to SE40 and lower all =hi SE42 floors.
|
|
|
|
|
|
|
|
// If standing in sector with SE44
|
|
|
|
// then draw viewing to SE40.
|
|
|
|
|
|
|
|
// If standing in sector with SE45
|
|
|
|
// then draw viewing to SE41.
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
static int tempsectorz[MAXSECTORS];
|
|
|
|
static int tempsectorpicnum[MAXSECTORS];
|
|
|
|
//short tempcursectnum;
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
void SE40_Draw(int tag, spritetype *spr, int x, int y, int z, binangle a, fixedhoriz h, int smoothratio)
|
2020-07-04 21:40:54 +00:00
|
|
|
{
|
2020-07-05 14:49:00 +00:00
|
|
|
int i, j = 0, k = 0;
|
2020-11-02 17:41:01 +00:00
|
|
|
int ok = 0, fofmode = 0;
|
2020-07-05 14:49:00 +00:00
|
|
|
int offx, offy;
|
2020-11-02 17:41:01 +00:00
|
|
|
spritetype* floor1, *floor2 = nullptr;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
if (spr->ang != 512) return;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
i = FOF; //Effect TILE
|
|
|
|
tileDelete(FOF);
|
|
|
|
if (!(gotpic[i >> 3] & (1 << (i & 7)))) return;
|
|
|
|
gotpic[i >> 3] &= ~(1 << (i & 7));
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
floor1 = spr;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
if (spr->lotag == tag + 2) fofmode = tag + 0;
|
|
|
|
if (spr->lotag == tag + 3) fofmode = tag + 1;
|
|
|
|
if (spr->lotag == tag + 4) fofmode = tag + 0;
|
|
|
|
if (spr->lotag == tag + 5) fofmode = tag + 1;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
ok++;
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
DukeStatIterator it(STAT_RAROR);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
auto spr = &act->s;
|
2020-07-05 14:49:00 +00:00
|
|
|
if (
|
2020-11-02 17:41:01 +00:00
|
|
|
spr->picnum == SECTOREFFECTOR &&
|
|
|
|
spr->lotag == fofmode &&
|
|
|
|
spr->hitag == floor1->hitag
|
|
|
|
)
|
|
|
|
{
|
|
|
|
floor1 = spr;
|
|
|
|
fofmode = spr->lotag;
|
|
|
|
ok++;
|
|
|
|
break;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// if(ok==1) { Message("no floor1",RED); return; }
|
|
|
|
|
|
|
|
if (fofmode == tag + 0) k = tag + 1; else k = tag + 0;
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
it.Reset(STAT_RAROR);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
auto spr = &act->s;
|
2020-07-05 14:49:00 +00:00
|
|
|
if (
|
2020-11-02 17:41:01 +00:00
|
|
|
spr->picnum == SECTOREFFECTOR &&
|
|
|
|
spr->lotag == k &&
|
|
|
|
spr->hitag == floor1->hitag
|
|
|
|
)
|
|
|
|
{
|
|
|
|
floor2 = spr;
|
|
|
|
ok++;
|
|
|
|
break;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if(ok==2) { Message("no floor2",RED); return; }
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
it.Reset(STAT_RAROR);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
auto spr = &act->s;
|
|
|
|
if (spr->picnum == SECTOREFFECTOR &&
|
|
|
|
spr->lotag == k + 2 &&
|
|
|
|
spr->hitag == floor1->hitag
|
2020-07-05 14:49:00 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
if (k == tag + 0)
|
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
tempsectorz[spr->sectnum] = sector[spr->sectnum].floorz;
|
|
|
|
sector[spr->sectnum].floorz += (((z - sector[spr->sectnum].floorz) / 32768) + 1) * 32768;
|
|
|
|
tempsectorpicnum[spr->sectnum] = sector[spr->sectnum].floorpicnum;
|
|
|
|
sector[spr->sectnum].floorpicnum = 13;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
if (k == tag + 1)
|
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
tempsectorz[spr->sectnum] = sector[spr->sectnum].ceilingz;
|
|
|
|
sector[spr->sectnum].ceilingz += (((z - sector[spr->sectnum].ceilingz) / 32768) - 1) * 32768;
|
|
|
|
tempsectorpicnum[spr->sectnum] = sector[spr->sectnum].ceilingpicnum;
|
|
|
|
sector[spr->sectnum].ceilingpicnum = 13;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
offx = x - floor1->x;
|
|
|
|
offy = y - floor1->y;
|
2020-07-04 21:40:54 +00:00
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
renderDrawRoomsQ16(floor2->x + offx, floor2->y + offy, z, a.asq16(), h.asq16(), floor2->sectnum);
|
|
|
|
fi.animatesprites(offx + floor2->x, offy + floor2->y, a.asbuild(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
renderDrawMasks();
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
it.Reset(STAT_RAROR);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
auto spr = &act->s;
|
|
|
|
if (spr->picnum == 1 &&
|
|
|
|
spr->lotag == k + 2 &&
|
|
|
|
spr->hitag == floor1->hitag
|
2020-07-05 14:49:00 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
if (k == tag + 0)
|
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
sector[spr->sectnum].floorz = tempsectorz[spr->sectnum];
|
|
|
|
sector[spr->sectnum].floorpicnum = tempsectorpicnum[spr->sectnum];
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
if (k == tag + 1)
|
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
sector[spr->sectnum].ceilingz = tempsectorz[spr->sectnum];
|
|
|
|
sector[spr->sectnum].ceilingpicnum = tempsectorpicnum[spr->sectnum];
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}// end if
|
|
|
|
}// end for
|
2020-07-04 21:40:54 +00:00
|
|
|
|
|
|
|
} // end SE40
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-07-23 15:01:37 +00:00
|
|
|
void se40code(int x, int y, int z, binangle a, fixedhoriz h, int smoothratio)
|
2020-07-04 21:40:54 +00:00
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
int tag;
|
2020-07-05 14:49:00 +00:00
|
|
|
if (!isRR()) tag = 40;
|
|
|
|
else if (isRRRA()) tag = 150;
|
|
|
|
else return;
|
|
|
|
|
2020-11-02 17:41:01 +00:00
|
|
|
DukeStatIterator it(STAT_RAROR);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 17:41:01 +00:00
|
|
|
switch (act->s.lotag - tag + 40)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
|
|
|
// case 40:
|
|
|
|
// case 41:
|
|
|
|
// SE40_Draw(i,x,y,a,smoothratio);
|
|
|
|
// break;
|
|
|
|
case 42:
|
|
|
|
case 43:
|
|
|
|
case 44:
|
|
|
|
case 45:
|
2020-11-02 17:41:01 +00:00
|
|
|
if (ps[screenpeek].cursectnum == act->s.sectnum)
|
|
|
|
SE40_Draw(tag, &act->s, x, y, z, a, h, smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-07-04 21:40:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-05 14:49:00 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// split out so it can also be applied to camera views
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-07-23 15:01:37 +00:00
|
|
|
void renderMirror(int cposx, int cposy, int cposz, binangle cang, fixedhoriz choriz, int smoothratio)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
|
|
|
if ((gotpic[TILE_MIRROR >> 3] & (1 << (TILE_MIRROR & 7))) > 0)
|
|
|
|
{
|
|
|
|
int dst = 0x7fffffff, i = 0;
|
|
|
|
for (int k = 0; k < mirrorcnt; k++)
|
|
|
|
{
|
|
|
|
int j = abs(wall[mirrorwall[k]].x - cposx) + abs(wall[mirrorwall[k]].y - cposy);
|
|
|
|
if (j < dst) dst = j, i = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wall[mirrorwall[i]].overpicnum == TILE_MIRROR)
|
|
|
|
{
|
2020-07-23 15:01:37 +00:00
|
|
|
int tposx, tposy;
|
2020-09-01 13:00:35 +00:00
|
|
|
fixed_t tang;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-07-23 15:01:37 +00:00
|
|
|
renderPrepareMirror(cposx, cposy, cposz, cang.asq16(), choriz.asq16(), mirrorwall[i], &tposx, &tposy, &tang);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
int j = g_visibility;
|
|
|
|
g_visibility = (j >> 1) + (j >> 2);
|
|
|
|
|
2020-07-23 15:01:37 +00:00
|
|
|
renderDrawRoomsQ16(tposx, tposy, cposz, tang, choriz.asq16(), mirrorsector[i] + MAXSECTORS);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
display_mirror = 1;
|
|
|
|
fi.animatesprites(tposx, tposy, tang, smoothratio);
|
|
|
|
display_mirror = 0;
|
|
|
|
|
|
|
|
renderDrawMasks();
|
|
|
|
renderCompleteMirror(); //Reverse screen x-wise in this function
|
|
|
|
g_visibility = j;
|
|
|
|
}
|
|
|
|
gotpic[TILE_MIRROR >> 3] &= ~(1 << (TILE_MIRROR & 7));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 23:20:51 +00:00
|
|
|
static inline int16_t getcamspriteang(DDukeActor* newOwner, double const smoothratio)
|
2020-09-23 05:34:03 +00:00
|
|
|
{
|
2020-11-02 23:20:51 +00:00
|
|
|
return newOwner->tempang + xs_CRoundToInt(fmulscale16(((newOwner->s.ang - newOwner->tempang + 1024) & 2047) - 1024, smoothratio));
|
2020-09-23 05:34:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-09-23 04:42:33 +00:00
|
|
|
void animatecamsprite(double smoothratio)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-07-06 20:23:18 +00:00
|
|
|
const int VIEWSCREEN_ACTIVE_DISTANCE = 8192;
|
|
|
|
|
2020-11-04 18:25:49 +00:00
|
|
|
if (camsprite == nullptr)
|
2020-07-05 14:49:00 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
auto p = &ps[screenpeek];
|
2020-11-04 18:25:49 +00:00
|
|
|
auto sp = &camsprite->s;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-04 18:25:49 +00:00
|
|
|
if (p->newOwner != nullptr) camsprite->SetOwner(p->newOwner);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-04 18:25:49 +00:00
|
|
|
if (camsprite->GetOwner() && dist(p->GetActor(), camsprite) < VIEWSCREEN_ACTIVE_DISTANCE)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
|
|
|
auto tex = tileGetTexture(sp->picnum);
|
|
|
|
TileFiles.MakeCanvas(TILE_VIEWSCR, tex->GetDisplayWidth(), tex->GetDisplayHeight());
|
|
|
|
|
|
|
|
auto canvas = renderSetTarget(TILE_VIEWSCR);
|
|
|
|
if (!canvas) return;
|
|
|
|
|
|
|
|
screen->RenderTextureView(canvas, [=](IntRect& rect)
|
|
|
|
{
|
2020-11-04 18:25:49 +00:00
|
|
|
auto camera = &camsprite->GetOwner()->s;
|
|
|
|
auto ang = getcamspriteang(camsprite->GetOwner(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
// Note: no ROR or camera here for now - the current setup has no means to detect these things before rendering the scene itself.
|
2020-09-23 04:42:33 +00:00
|
|
|
drawrooms(camera->x, camera->y, camera->z, ang, 100 + camera->shade, camera->sectnum); // why 'shade'...?
|
2020-07-05 14:49:00 +00:00
|
|
|
display_mirror = 1; // should really be 'display external view'.
|
2020-09-23 04:42:33 +00:00
|
|
|
fi.animatesprites(camera->x, camera->y, ang, smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
display_mirror = 0;
|
|
|
|
renderDrawMasks();
|
|
|
|
});
|
|
|
|
renderRestoreTarget();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2020-07-05 19:21:39 +00:00
|
|
|
// RRRA's drug distortion effect
|
2020-07-05 14:49:00 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-11-05 06:25:44 +00:00
|
|
|
int DrugTimer;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-06 09:52:43 +00:00
|
|
|
static int getdrugmode(player_struct *p, int oyrepeat)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-05 06:25:44 +00:00
|
|
|
int now = I_GetBuildTime() >> 1; // this function works on a 60 fps setup.
|
|
|
|
if (playrunning() && p->DrugMode > 0)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-05 06:25:44 +00:00
|
|
|
if (now - DrugTimer > 4 || now - DrugTimer < 0) DrugTimer = now - 1;
|
|
|
|
while (DrugTimer < now)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-05 06:25:44 +00:00
|
|
|
DrugTimer++;
|
2020-07-05 14:49:00 +00:00
|
|
|
int var_8c;
|
|
|
|
if (p->drug_stat[0] == 0)
|
|
|
|
{
|
|
|
|
p->drug_stat[1]++;
|
|
|
|
var_8c = oyrepeat + p->drug_stat[1] * 5000;
|
|
|
|
if (oyrepeat * 3 < var_8c)
|
|
|
|
{
|
|
|
|
p->drug_aspect = oyrepeat * 3;
|
|
|
|
p->drug_stat[0] = 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->drug_aspect = var_8c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (p->drug_stat[0] == 3)
|
|
|
|
{
|
|
|
|
p->drug_stat[1]--;
|
|
|
|
var_8c = oyrepeat + p->drug_stat[1] * 5000;
|
|
|
|
if (var_8c < oyrepeat)
|
|
|
|
{
|
|
|
|
p->DrugMode = 0;
|
|
|
|
p->drug_stat[0] = 0;
|
|
|
|
p->drug_stat[2] = 0;
|
|
|
|
p->drug_stat[1] = 0;
|
2020-11-06 09:52:43 +00:00
|
|
|
p->drug_aspect = oyrepeat;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->drug_aspect = var_8c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (p->drug_stat[0] == 2)
|
|
|
|
{
|
|
|
|
if (p->drug_stat[2] > 30)
|
|
|
|
{
|
|
|
|
p->drug_stat[0] = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->drug_stat[2]++;
|
|
|
|
p->drug_aspect = oyrepeat * 3 + p->drug_stat[2] * 500;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (p->drug_stat[2] < 1)
|
|
|
|
{
|
|
|
|
p->drug_stat[0] = 2;
|
|
|
|
p->DrugMode--;
|
|
|
|
if (p->DrugMode == 1)
|
|
|
|
p->drug_stat[0] = 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->drug_stat[2]--;
|
|
|
|
p->drug_aspect = oyrepeat * 3 + p->drug_stat[2] * 500;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-06 09:52:43 +00:00
|
|
|
return p->drug_aspect;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
2020-11-06 09:52:43 +00:00
|
|
|
else
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-06 09:52:43 +00:00
|
|
|
DrugTimer = now;
|
|
|
|
return oyrepeat;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2020-07-05 19:21:39 +00:00
|
|
|
// used by RR to inject some external geometry into a scene.
|
2020-07-05 14:49:00 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-07-23 15:01:37 +00:00
|
|
|
static void geometryEffect(int cposx, int cposy, int cposz, binangle cang, fixedhoriz choriz, int sect, int smoothratio)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-10-14 19:40:15 +00:00
|
|
|
short gs, tgsect, geosect, geoid = 0;
|
2020-07-23 15:01:37 +00:00
|
|
|
renderDrawRoomsQ16(cposx, cposy, cposz, cang.asq16(), choriz.asq16(), sect);
|
|
|
|
fi.animatesprites(cposx, cposy, cang.asbuild(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
renderDrawMasks();
|
|
|
|
for (gs = 0; gs < geocnt; gs++)
|
|
|
|
{
|
|
|
|
tgsect = geosector[gs];
|
2020-10-14 19:40:15 +00:00
|
|
|
|
2020-11-02 18:23:15 +00:00
|
|
|
DukeSectIterator it(tgsect);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 18:23:15 +00:00
|
|
|
changespritesect(act, geosectorwarp[gs]);
|
|
|
|
setsprite(act, act->s.x -= geox[gs], act->s.y -= geoy[gs], act->s.z);
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
if (geosector[gs] == sect)
|
|
|
|
{
|
|
|
|
geosect = geosectorwarp[gs];
|
|
|
|
geoid = gs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cposx -= geox[geoid];
|
|
|
|
cposy -= geoy[geoid];
|
2020-07-23 15:01:37 +00:00
|
|
|
renderDrawRoomsQ16(cposx, cposy, cposz, cang.asq16(), choriz.asq16(), sect);
|
2020-07-05 14:49:00 +00:00
|
|
|
cposx += geox[geoid];
|
|
|
|
cposy += geoy[geoid];
|
|
|
|
for (gs = 0; gs < geocnt; gs++)
|
|
|
|
{
|
|
|
|
tgsect = geosectorwarp[gs];
|
2020-11-02 18:23:15 +00:00
|
|
|
DukeSectIterator it(tgsect);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 18:23:15 +00:00
|
|
|
changespritesect(act, geosector[gs]);
|
|
|
|
setsprite(act, act->s.x += geox[gs], act->s.y += geoy[gs], act->s.z);
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-23 15:01:37 +00:00
|
|
|
fi.animatesprites(cposx, cposy, cang.asbuild(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
renderDrawMasks();
|
|
|
|
for (gs = 0; gs < geocnt; gs++)
|
|
|
|
{
|
|
|
|
tgsect = geosector[gs];
|
2020-11-02 18:23:15 +00:00
|
|
|
DukeSectIterator it(tgsect);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 18:23:15 +00:00
|
|
|
changespritesect(act, geosectorwarp2[gs]);
|
|
|
|
setsprite(act, act->s.x -= geox2[gs], act->s.y -= geoy2[gs], act->s.z);
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
if (geosector[gs] == sect)
|
|
|
|
{
|
|
|
|
geosect = geosectorwarp2[gs];
|
|
|
|
geoid = gs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cposx -= geox2[geoid];
|
|
|
|
cposy -= geoy2[geoid];
|
2020-07-23 15:01:37 +00:00
|
|
|
renderDrawRoomsQ16(cposx, cposy, cposz, cang.asq16(), choriz.asq16(), sect);
|
2020-07-05 14:49:00 +00:00
|
|
|
cposx += geox2[geoid];
|
|
|
|
cposy += geoy2[geoid];
|
|
|
|
for (gs = 0; gs < geocnt; gs++)
|
|
|
|
{
|
|
|
|
tgsect = geosectorwarp2[gs];
|
2020-11-02 18:23:15 +00:00
|
|
|
DukeSectIterator it(tgsect);
|
|
|
|
while (auto act = it.Next())
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 18:23:15 +00:00
|
|
|
changespritesect(act, geosector[gs]);
|
|
|
|
setsprite(act, act->s.x += geox2[gs], act->s.y += geoy2[gs], act->s.z);
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-23 15:01:37 +00:00
|
|
|
fi.animatesprites(cposx, cposy, cang.asbuild(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
renderDrawMasks();
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-08-25 10:04:29 +00:00
|
|
|
void displayrooms(int snum, double smoothratio)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-07-05 19:24:55 +00:00
|
|
|
int cposx, cposy, cposz, fz, cz;
|
2020-07-23 15:01:37 +00:00
|
|
|
short sect;
|
|
|
|
binangle cang;
|
2020-10-07 12:13:21 +00:00
|
|
|
lookangle rotscrnang;
|
2020-07-23 15:01:37 +00:00
|
|
|
fixedhoriz choriz;
|
2020-07-05 14:49:00 +00:00
|
|
|
struct player_struct* p;
|
2020-07-05 19:24:55 +00:00
|
|
|
int tiltcs = 0; // JBF 20030807
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
p = &ps[snum];
|
|
|
|
|
2020-08-24 17:31:43 +00:00
|
|
|
if (automapMode == am_full || p->cursectnum == -1)
|
2020-07-05 14:49:00 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Do not light up the fog in RRRA's E2L1. Ideally this should apply to all foggy levels but all others use lookup table hacks for their fog.
|
|
|
|
if (isRRRA() && fogactive)
|
|
|
|
{
|
|
|
|
p->visibility = ud.const_visibility;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_visibility = p->visibility;
|
|
|
|
|
2020-07-05 19:21:39 +00:00
|
|
|
videoSetCorrectedAspect();
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
sect = p->cursectnum;
|
|
|
|
if (sect < 0 || sect >= MAXSECTORS) return;
|
|
|
|
|
2020-07-20 21:07:44 +00:00
|
|
|
GLInterface.SetMapFog(fogactive != 0);
|
2020-11-26 15:03:40 +00:00
|
|
|
DoInterpolations(smoothratio / 65536.);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-07-07 02:54:12 +00:00
|
|
|
setgamepalette(BASEPAL);
|
2020-07-05 14:49:00 +00:00
|
|
|
animatecamsprite(smoothratio);
|
|
|
|
|
2020-11-02 22:53:55 +00:00
|
|
|
if (ud.cameraactor)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
|
|
|
spritetype* s;
|
|
|
|
|
2020-11-02 22:53:55 +00:00
|
|
|
s = &ud.cameraactor->s;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
if (s->yvel < 0) s->yvel = -100;
|
|
|
|
else if (s->yvel > 199) s->yvel = 300;
|
|
|
|
|
2020-11-02 22:53:55 +00:00
|
|
|
cang = buildang(ud.cameraactor->tempang + xs_CRoundToInt(fmulscale16(((s->ang + 1024 - ud.cameraactor->tempang) & 2047) - 1024, smoothratio)));
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-07-23 15:01:37 +00:00
|
|
|
auto bh = buildhoriz(s->yvel);
|
|
|
|
se40code(s->x, s->y, s->z, cang, bh, smoothratio);
|
|
|
|
renderMirror(s->x, s->y, s->z, cang, bh, smoothratio);
|
|
|
|
renderDrawRoomsQ16(s->x, s->y, s->z - (4 << 8), cang.asq16(), bh.asq16(), s->sectnum);
|
|
|
|
fi.animatesprites(s->x, s->y, cang.asbuild(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
renderDrawMasks();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-06 09:52:43 +00:00
|
|
|
// Fixme: This should get the aspect ratio from the backend, not the current viewport size.
|
2020-10-23 19:40:49 +00:00
|
|
|
int i = divscale22(1, isRR() ? 64 : p->GetActor()->s.yrepeat + 28);
|
2020-11-06 09:52:43 +00:00
|
|
|
int viewingaspect = !isRRRA() || !p->DrugMode ? xs_CRoundToInt(double(i) * tan(r_fov * (pi::pi() / 360.))) : getdrugmode(p, i);
|
|
|
|
renderSetAspect(mulscale16(viewingaspect, viewingrange), yxaspect);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-05 06:25:44 +00:00
|
|
|
// The camera texture must be rendered with the base palette, so this is the only place where the current global palette can be set.
|
|
|
|
// The setting here will be carried over to the rendering of the weapon sprites, but other 2D content will always default to the main palette.
|
|
|
|
setgamepalette(setpal(p));
|
|
|
|
|
2020-09-23 05:34:03 +00:00
|
|
|
// set screen rotation.
|
2020-10-07 12:13:21 +00:00
|
|
|
rotscrnang = !cl_syncinput ? p->angle.rotscrnang : p->angle.interpolatedrotscrn(smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
if ((snum == myconnectindex) && (numplayers > 1))
|
|
|
|
{
|
2020-08-25 10:04:29 +00:00
|
|
|
cposx = omyx + xs_CRoundToInt(fmulscale16(myx - omyx, smoothratio));
|
|
|
|
cposy = omyy + xs_CRoundToInt(fmulscale16(myy - omyy, smoothratio));
|
|
|
|
cposz = omyz + xs_CRoundToInt(fmulscale16(myz - omyz, smoothratio));
|
2020-07-28 11:38:20 +00:00
|
|
|
if (cl_syncinput)
|
2020-07-16 15:59:25 +00:00
|
|
|
{
|
2020-11-22 13:17:07 +00:00
|
|
|
fixed_t ohorz = (omyhoriz + omyhorizoff).asq16();
|
|
|
|
fixed_t horz = (myhoriz + myhorizoff).asq16();
|
2020-08-25 10:04:29 +00:00
|
|
|
choriz = q16horiz(ohorz + xs_CRoundToInt(fmulscale16(horz - ohorz, smoothratio)));
|
2020-11-22 13:17:07 +00:00
|
|
|
cang = bamang(xs_CRoundToUInt(omyang.asbam() + fmulscale16((myang - omyang).asbam(), smoothratio)));
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-07 12:13:21 +00:00
|
|
|
cang = myang;
|
|
|
|
choriz = myhoriz + myhorizoff;
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
2020-07-05 14:49:00 +00:00
|
|
|
sect = mycursectnum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-08-25 10:04:29 +00:00
|
|
|
cposx = p->oposx + xs_CRoundToInt(fmulscale16(p->posx - p->oposx, smoothratio));
|
|
|
|
cposy = p->oposy + xs_CRoundToInt(fmulscale16(p->posy - p->oposy, smoothratio));
|
|
|
|
cposz = p->oposz + xs_CRoundToInt(fmulscale16(p->posz - p->oposz, smoothratio));
|
2020-07-28 21:10:28 +00:00
|
|
|
if (cl_syncinput)
|
2020-07-16 15:59:25 +00:00
|
|
|
{
|
|
|
|
// Original code for when the values are passed through the sync struct
|
2020-10-07 06:12:37 +00:00
|
|
|
choriz = p->horizon.interpolatedsum(smoothratio);
|
2020-10-07 12:13:21 +00:00
|
|
|
cang = p->angle.interpolatedsum(smoothratio);
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// This is for real time updating of the view direction.
|
2020-10-07 12:13:21 +00:00
|
|
|
cang = p->angle.sum();
|
2020-10-07 06:12:37 +00:00
|
|
|
choriz = p->horizon.sum();
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
|
2020-11-02 23:20:51 +00:00
|
|
|
if (p->newOwner != nullptr)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
2020-11-02 23:20:51 +00:00
|
|
|
auto spr = &p->newOwner->s;
|
|
|
|
cang = buildang(getcamspriteang(p->newOwner, smoothratio));
|
2020-11-02 18:23:15 +00:00
|
|
|
choriz = buildhoriz(spr->shade);
|
|
|
|
cposx = spr->pos.x;
|
|
|
|
cposy = spr->pos.y;
|
|
|
|
cposz = spr->pos.z;
|
|
|
|
sect = spr->sectnum;
|
2020-10-07 12:13:21 +00:00
|
|
|
rotscrnang = buildlook(0);
|
2020-07-31 00:35:24 +00:00
|
|
|
smoothratio = MaxSmoothRatio;
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
else if (p->over_shoulder_on == 0)
|
|
|
|
{
|
2020-08-25 10:04:29 +00:00
|
|
|
if (cl_viewbob) cposz += p->opyoff + xs_CRoundToInt(fmulscale16(p->pyoff - p->opyoff, smoothratio));
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
2020-09-25 07:52:00 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cposz -= isRR() ? 3840 : 3072;
|
|
|
|
|
|
|
|
if (!view(p, &cposx, &cposy, &cposz, §, cang.asbuild(), choriz.asq16(), smoothratio))
|
|
|
|
{
|
|
|
|
cposz += isRR() ? 3840 : 3072;
|
|
|
|
view(p, &cposx, &cposy, &cposz, §, cang.asbuild(), choriz.asq16(), smoothratio);
|
|
|
|
}
|
|
|
|
}
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-09-23 05:34:03 +00:00
|
|
|
// do screen rotation.
|
2020-11-22 13:17:07 +00:00
|
|
|
renderSetRollAngle(rotscrnang.asbuildf());
|
2020-09-23 05:34:03 +00:00
|
|
|
|
2020-11-02 19:23:05 +00:00
|
|
|
cz = p->GetActor()->ceilingz;
|
|
|
|
fz = p->GetActor()->floorz;
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
if (earthquaketime > 0 && p->on_ground == 1)
|
|
|
|
{
|
|
|
|
cposz += 256 - (((earthquaketime) & 1) << 9);
|
2020-07-23 15:01:37 +00:00
|
|
|
cang += buildang((2 - ((earthquaketime) & 2)) << 2);
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
|
2020-10-23 19:40:49 +00:00
|
|
|
if (p->GetActor()->s.pal == 1) cposz -= (18 << 8);
|
2020-07-05 14:49:00 +00:00
|
|
|
|
2020-11-02 23:20:51 +00:00
|
|
|
else if (p->spritebridge == 0 && p->newOwner == nullptr)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
|
|
|
if (cposz < (p->truecz + (4 << 8))) cposz = cz + (4 << 8);
|
|
|
|
else if (cposz > (p->truefz - (4 << 8))) cposz = fz - (4 << 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sect >= 0)
|
|
|
|
{
|
|
|
|
getzsofslope(sect, cposx, cposy, &cz, &fz);
|
|
|
|
if (cposz < cz + (4 << 8)) cposz = cz + (4 << 8);
|
|
|
|
if (cposz > fz - (4 << 8)) cposz = fz - (4 << 8);
|
|
|
|
}
|
|
|
|
|
2020-10-07 02:28:38 +00:00
|
|
|
choriz = clamp(choriz, q16horiz(gi->playerHorizMin()), q16horiz(gi->playerHorizMax()));
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
if (isRR() && sector[sect].lotag == 848)
|
|
|
|
{
|
2020-07-05 19:21:39 +00:00
|
|
|
geometryEffect(cposx, cposy, cposz, cang, choriz, sect, smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
se40code(cposx, cposy, cposz, cang, choriz, smoothratio);
|
|
|
|
renderMirror(cposx, cposy, cposz, cang, choriz, smoothratio);
|
2020-07-23 15:01:37 +00:00
|
|
|
renderDrawRoomsQ16(cposx, cposy, cposz, cang.asq16(), choriz.asq16(), sect);
|
|
|
|
fi.animatesprites(cposx, cposy, cang.asbuild(), smoothratio);
|
2020-07-05 14:49:00 +00:00
|
|
|
renderDrawMasks();
|
|
|
|
}
|
|
|
|
}
|
2020-09-05 21:20:48 +00:00
|
|
|
//GLInterface.SetMapFog(false);
|
2020-11-26 15:03:40 +00:00
|
|
|
RestoreInterpolations();
|
2020-07-05 14:49:00 +00:00
|
|
|
|
|
|
|
if (!isRRRA() || !fogactive)
|
|
|
|
{
|
2020-08-30 22:33:41 +00:00
|
|
|
if (ud.levelclock < lastvisinc)
|
2020-07-05 14:49:00 +00:00
|
|
|
{
|
|
|
|
if (abs(p->visibility - ud.const_visibility) > 8)
|
|
|
|
p->visibility += (ud.const_visibility - p->visibility) >> 2;
|
|
|
|
}
|
|
|
|
else p->visibility = ud.const_visibility;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-05 19:21:39 +00:00
|
|
|
bool GameInterface::GenerateSavePic()
|
|
|
|
{
|
2020-07-31 00:35:24 +00:00
|
|
|
displayrooms(myconnectindex, MaxSmoothRatio);
|
2020-07-05 19:21:39 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-04 21:40:54 +00:00
|
|
|
END_DUKE_NS
|