mirror of
https://github.com/ZDoom/gzdoom-last-svn.git
synced 2025-05-31 01:10:52 +00:00
- sync with trunk r1152.
git-svn-id: http://mancubus.net/svn/hosted/gzdoom/branches/voxels@1154 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
commit
b02a00e89c
210 changed files with 5513 additions and 3227 deletions
|
@ -2312,10 +2312,6 @@
|
|||
<Filter
|
||||
Name="Render Sources"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\r_anim.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\r_bsp.cpp"
|
||||
>
|
||||
|
@ -2436,6 +2432,14 @@
|
|||
<Filter
|
||||
Name="Textures"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\textures\anim_switches.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\textures\animations.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\textures\automaptexture.cpp"
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
===============================================================================
|
||||
Universal Doom Map Format ZDoom extensions v1.10 - 25.04.2010
|
||||
Universal Doom Map Format ZDoom extensions v1.15 - 14.12.2010
|
||||
|
||||
|
||||
Copyright (c) 2008 Christoph Oelckers.
|
||||
|
@ -84,6 +84,12 @@ field to 'strifeally', even for the 'Doom' namespace.
|
|||
In addition to the standard fields, ZDoom defines the following:
|
||||
Note: All <bool> fields default to false unless mentioned otherwise.
|
||||
|
||||
vertex
|
||||
{
|
||||
zfloor = <float>; // Floor height at this vertex. Only applies to triangular sectors
|
||||
zceiling = <float>; // Ceiling height at this vertex. Only applies to triangular sectors
|
||||
}
|
||||
|
||||
linedef
|
||||
{
|
||||
alpha = <float>; // Translucency of this line, default is 1.0
|
||||
|
@ -153,6 +159,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
// relative to the owning sector's light level.
|
||||
lightceilingabsolute = <bool>; // true = 'lightceiling' is an absolute value. Default is
|
||||
// relative to the owning sector's light level.
|
||||
alphafloor = <float>; // translucency of floor plane (only has meaning with Sector_SetPortal) Default is 1.0.
|
||||
alphaceiling = <float>; // translucency of ceiling plane (only has meaning with Sector_SetPortal) Default is 1.0.
|
||||
gravity = <float>; // Sector's gravity. Default is 1.0.
|
||||
lightcolor = <integer>; // Sector'S light color as RRGGBB value, default = 0xffffff.
|
||||
fadecolor = <integer>; // Sector'S fog color as RRGGBB value, default = 0x000000.
|
||||
|
@ -281,6 +289,9 @@ Added 'hidden' sector property.
|
|||
1.14 19.09.2010
|
||||
Added 'countsecret' actor property.
|
||||
|
||||
1.15 14.12.2010
|
||||
Added vertex floor and ceiling height properties
|
||||
|
||||
===============================================================================
|
||||
EOF
|
||||
===============================================================================
|
||||
|
|
|
@ -396,8 +396,7 @@ endif( SSE_MATTERS )
|
|||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
if( PROFILE )
|
||||
set( CMAKE_C_FLinclude( FindFluidSynth.cmake )
|
||||
AGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
|
||||
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
|
||||
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" )
|
||||
set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -pg" )
|
||||
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" )
|
||||
|
@ -727,7 +726,6 @@ add_executable( zdoom WIN32
|
|||
p_xlat.cpp
|
||||
parsecontext.cpp
|
||||
po_man.cpp
|
||||
r_anim.cpp
|
||||
r_bsp.cpp
|
||||
r_data.cpp
|
||||
r_draw.cpp
|
||||
|
@ -911,6 +909,8 @@ add_executable( zdoom WIN32
|
|||
sound/music_timidity_mididevice.cpp
|
||||
sound/music_win_mididevice.cpp
|
||||
sound/music_pseudo_mididevice.cpp
|
||||
textures/animations.cpp
|
||||
textures/anim_switches.cpp
|
||||
textures/automaptexture.cpp
|
||||
textures/bitmap.cpp
|
||||
textures/buildtexture.cpp
|
||||
|
|
|
@ -529,7 +529,12 @@ struct FDropItem
|
|||
class FDropItemPtrArray : public TArray<FDropItem *>
|
||||
{
|
||||
public:
|
||||
~FDropItemPtrArray();
|
||||
~FDropItemPtrArray()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
extern FDropItemPtrArray DropItemList;
|
||||
|
|
273
src/am_map.cpp
273
src/am_map.cpp
|
@ -64,6 +64,12 @@
|
|||
#include "po_man.h"
|
||||
#include "a_keys.h"
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Automap colors
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
struct AMColor
|
||||
{
|
||||
int Index;
|
||||
|
@ -85,7 +91,7 @@ struct AMColor
|
|||
static AMColor Background, YourColor, WallColor, TSWallColor,
|
||||
FDWallColor, CDWallColor, ThingColor,
|
||||
ThingColor_Item, ThingColor_CountItem, ThingColor_Monster, ThingColor_Friend,
|
||||
SecretWallColor, GridColor, XHairColor,
|
||||
SpecialWallColor, SecretWallColor, GridColor, XHairColor,
|
||||
NotSeenColor,
|
||||
LockedColor,
|
||||
AlmostBackground,
|
||||
|
@ -119,6 +125,12 @@ static BYTE RavenPaletteVals[11*3] =
|
|||
0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// globals
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#define MAPBITS 12
|
||||
#define MapDiv SafeDivScale12
|
||||
#define MapMul MulScale12
|
||||
|
@ -155,6 +167,7 @@ CVAR (Color, am_backcolor, 0x6c5440, CVAR_ARCHIVE);
|
|||
CVAR (Color, am_yourcolor, 0xfce8d8, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_wallcolor, 0x2c1808, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_secretwallcolor, 0x000000, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_specialwallcolor, 0xffffff, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_tswallcolor, 0x888888, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_fdwallcolor, 0x887058, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_cdwallcolor, 0x4c3820, CVAR_ARCHIVE);
|
||||
|
@ -165,6 +178,7 @@ CVAR (Color, am_notseencolor, 0x6c6c6c, CVAR_ARCHIVE);
|
|||
CVAR (Color, am_lockedcolor, 0x007800, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_ovyourcolor, 0xfce8d8, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_ovwallcolor, 0x00ff00, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_ovspecialwallcolor, 0xffffff, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_ovthingcolor, 0xe88800, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_ovotherwallscolor, 0x008844, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_ovunseencolor, 0x00226e, CVAR_ARCHIVE);
|
||||
|
@ -176,6 +190,7 @@ CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE);
|
|||
CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE);
|
||||
CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE);
|
||||
CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE);
|
||||
CVAR (Bool, am_showtriggerlines, false, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE);
|
||||
|
@ -287,72 +302,28 @@ struct islope_t
|
|||
// A line drawing of the player pointing right,
|
||||
// starting from the middle.
|
||||
//
|
||||
#define R ((8*PLAYERRADIUS)/7)
|
||||
mline_t player_arrow[] = {
|
||||
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
||||
{ { R, 0 }, { R-R/2, R/4 } }, // ----->
|
||||
{ { R, 0 }, { R-R/2, -R/4 } },
|
||||
{ { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
|
||||
{ { -R+R/8, 0 }, { -R-R/8, -R/4 } },
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
|
||||
};
|
||||
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
|
||||
|
||||
mline_t player_arrow_raven[] = {
|
||||
{ { -R+R/4, 0 }, { 0, 0} }, // center line.
|
||||
{ { -R+R/4, R/8 }, { R, 0} }, // blade
|
||||
{ { -R+R/4, -R/8 }, { R, 0 } },
|
||||
{ { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece
|
||||
{ { -R+R/8, -R/4 }, { -R+R/8, R/4 } },
|
||||
{ { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors
|
||||
{ { -R+R/8, R/4 }, { -R+R/4, R/4} },
|
||||
{ { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel
|
||||
{ { -R-R/4, R/8 }, { -R+R/8, R/8 } },
|
||||
{ { -R-R/4, -R/8}, { -R+R/8, -R/8 } }
|
||||
};
|
||||
#define NUMPLYRLINES_RAVEN (sizeof(player_arrow_raven)/sizeof(mline_t))
|
||||
|
||||
mline_t cheat_player_arrow[] = {
|
||||
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
||||
{ { R, 0 }, { R-R/2, R/6 } }, // ----->
|
||||
{ { R, 0 }, { R-R/2, -R/6 } },
|
||||
{ { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
|
||||
{ { -R+R/8, 0 }, { -R-R/8, -R/6 } },
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
|
||||
{ { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
|
||||
{ { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
|
||||
{ { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
|
||||
{ { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
|
||||
{ { -R/6, -R/6 }, { 0, -R/6 } },
|
||||
{ { 0, -R/6 }, { 0, R/4 } },
|
||||
{ { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
|
||||
{ { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
|
||||
{ { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
|
||||
};
|
||||
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
|
||||
|
||||
#undef R
|
||||
static TArray<mline_t> MapArrow;
|
||||
static TArray<mline_t> CheatMapArrow;
|
||||
static TArray<mline_t> CheatKey;
|
||||
|
||||
#define R (MAPUNIT)
|
||||
// [RH] Avoid lots of warnings without compiler-specific #pragmas
|
||||
#define L(a,b,c,d) { {(fixed_t)((a)*R),(fixed_t)((b)*R)}, {(fixed_t)((c)*R),(fixed_t)((d)*R)} }
|
||||
mline_t triangle_guy[] = {
|
||||
static mline_t triangle_guy[] = {
|
||||
L (-.867,-.5, .867,-.5),
|
||||
L (.867,-.5, 0,1),
|
||||
L (0,1, -.867,-.5)
|
||||
};
|
||||
#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
|
||||
|
||||
mline_t thintriangle_guy[] = {
|
||||
static mline_t thintriangle_guy[] = {
|
||||
L (-.5,-.7, 1,0),
|
||||
L (1,0, -.5,.7),
|
||||
L (-.5,.7, -.5,-.7)
|
||||
};
|
||||
#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
|
||||
|
||||
mline_t square_guy[] = {
|
||||
static mline_t square_guy[] = {
|
||||
L (0,1,1,0),
|
||||
L (1,0,0,-1),
|
||||
L (0,-1,-1,0),
|
||||
|
@ -361,26 +332,6 @@ mline_t square_guy[] = {
|
|||
#define NUMSQUAREGUYLINES (sizeof(square_guy)/sizeof(mline_t))
|
||||
|
||||
#undef R
|
||||
#define R (MAPUNIT)
|
||||
|
||||
mline_t key_guy[] = {
|
||||
L (-2, 0, -1.7, -0.5),
|
||||
L (-1.7, -0.5, -1.5, -0.7),
|
||||
L (-1.5, -0.7, -0.8, -0.5),
|
||||
L (-0.8, -0.5, -0.6, 0),
|
||||
L (-0.6, 0, -0.8, 0.5),
|
||||
L (-1.5, 0.7, -0.8, 0.5),
|
||||
L (-1.7, 0.5, -1.5, 0.7),
|
||||
L (-2, 0, -1.7, 0.5),
|
||||
L (-0.6, 0, 2, 0),
|
||||
L (1.7, 0, 1.7, -1),
|
||||
L (1.5, 0, 1.5, -1),
|
||||
L (1.3, 0, 1.3, -1)
|
||||
};
|
||||
#define NUMKEYGUYLINES (sizeof(key_guy)/sizeof(mline_t))
|
||||
|
||||
#undef L
|
||||
#undef R
|
||||
|
||||
|
||||
|
||||
|
@ -396,8 +347,6 @@ CUSTOM_CVAR (Int, am_cheat, 0, 0)
|
|||
|
||||
static int grid = 0;
|
||||
|
||||
static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
|
||||
|
||||
bool automapactive = false;
|
||||
|
||||
// location of window on screen
|
||||
|
@ -449,8 +398,6 @@ static FTextureID marknums[10]; // numbers used for marking by the automap
|
|||
static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
|
||||
static int markpointnum = 0; // next point to be assigned
|
||||
|
||||
static int followplayer = 1; // specifies whether to follow the player around
|
||||
|
||||
static FTextureID mapback; // the automap background
|
||||
static fixed_t mapystart=0; // y-value for the start of the map bitmap...used in the parallax stuff.
|
||||
static fixed_t mapxstart=0; //x-value for the bitmap.
|
||||
|
@ -476,11 +423,14 @@ void AM_restoreScaleAndLoc ();
|
|||
void AM_minOutWindowScale ();
|
||||
|
||||
|
||||
CVAR(Bool, am_followplayer, true, CVAR_ARCHIVE)
|
||||
|
||||
|
||||
CCMD(am_togglefollow)
|
||||
{
|
||||
followplayer = !followplayer;
|
||||
am_followplayer = !am_followplayer;
|
||||
f_oldloc.x = FIXED_MAX;
|
||||
Printf ("%s\n", GStrings(followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF"));
|
||||
Printf ("%s\n", GStrings(am_followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF"));
|
||||
}
|
||||
|
||||
CCMD(am_togglegrid)
|
||||
|
@ -545,6 +495,76 @@ void AM_getIslope (mline_t *ml, islope_t *is)
|
|||
}
|
||||
*/
|
||||
|
||||
|
||||
void AM_ParseArrow(TArray<mline_t> &Arrow, const char *lumpname)
|
||||
{
|
||||
const int R = ((8*PLAYERRADIUS)/7);
|
||||
FScanner sc;
|
||||
int lump = Wads.CheckNumForFullName(lumpname, true);
|
||||
if (lump >= 0)
|
||||
{
|
||||
sc.OpenLumpNum(lump);
|
||||
sc.SetCMode(true);
|
||||
while (sc.GetToken())
|
||||
{
|
||||
mline_t line;
|
||||
sc.TokenMustBe('(');
|
||||
sc.MustGetFloat();
|
||||
line.a.x = xs_RoundToInt(sc.Float*R);
|
||||
sc.MustGetToken(',');
|
||||
sc.MustGetFloat();
|
||||
line.a.y = xs_RoundToInt(sc.Float*R);
|
||||
sc.MustGetToken(')');
|
||||
sc.MustGetToken(',');
|
||||
sc.MustGetToken('(');
|
||||
sc.MustGetFloat();
|
||||
line.b.x = xs_RoundToInt(sc.Float*R);
|
||||
sc.MustGetToken(',');
|
||||
sc.MustGetFloat();
|
||||
line.b.y = xs_RoundToInt(sc.Float*R);
|
||||
sc.MustGetToken(')');
|
||||
Arrow.Push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AM_StaticInit()
|
||||
{
|
||||
MapArrow.Clear();
|
||||
CheatMapArrow.Clear();
|
||||
CheatKey.Clear();
|
||||
|
||||
if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow);
|
||||
if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow);
|
||||
AM_ParseArrow(CheatKey, "maparrows/key.txt");
|
||||
if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined");
|
||||
|
||||
char namebuf[9];
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
mysnprintf (namebuf, countof(namebuf), "AMMNUM%d", i);
|
||||
marknums[i] = TexMan.CheckForTexture (namebuf, FTexture::TEX_MiscPatch);
|
||||
}
|
||||
markpointnum = 0;
|
||||
mapback.SetInvalid();
|
||||
|
||||
static DWORD *lastpal = NULL;
|
||||
//static int lastback = -1;
|
||||
DWORD *palette;
|
||||
|
||||
palette = (DWORD *)GPalette.BaseColors;
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0; i < 11; i++, j += 3)
|
||||
{
|
||||
DoomColors[i].FromRGB(DoomPaletteVals[j], DoomPaletteVals[j+1], DoomPaletteVals[j+2]);
|
||||
StrifeColors[i].FromRGB(StrifePaletteVals[j], StrifePaletteVals[j+1], StrifePaletteVals[j+2]);
|
||||
RavenColors[i].FromRGB(RavenPaletteVals[j], RavenPaletteVals[j+1], RavenPaletteVals[j+2]);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// called by the coordinate drawer
|
||||
|
@ -599,7 +619,7 @@ void AM_restoreScaleAndLoc ()
|
|||
{
|
||||
m_w = old_m_w;
|
||||
m_h = old_m_h;
|
||||
if (!followplayer)
|
||||
if (!am_followplayer)
|
||||
{
|
||||
m_x = old_m_x;
|
||||
m_y = old_m_y;
|
||||
|
@ -796,7 +816,7 @@ void AM_changeWindowLoc ()
|
|||
{
|
||||
if (0 != (m_paninc.x | m_paninc.y))
|
||||
{
|
||||
followplayer = 0;
|
||||
am_followplayer = false;
|
||||
f_oldloc.x = FIXED_MAX;
|
||||
}
|
||||
|
||||
|
@ -876,28 +896,11 @@ void AM_initVariables ()
|
|||
|
||||
static void AM_initColors (bool overlayed)
|
||||
{
|
||||
static DWORD *lastpal = NULL;
|
||||
//static int lastback = -1;
|
||||
DWORD *palette;
|
||||
|
||||
palette = (DWORD *)GPalette.BaseColors;
|
||||
|
||||
if (lastpal != palette)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0; i < 11; i++, j += 3)
|
||||
{
|
||||
DoomColors[i].FromRGB(DoomPaletteVals[j], DoomPaletteVals[j+1], DoomPaletteVals[j+2]);
|
||||
StrifeColors[i].FromRGB(StrifePaletteVals[j], StrifePaletteVals[j+1], StrifePaletteVals[j+2]);
|
||||
RavenColors[i].FromRGB(RavenPaletteVals[j], RavenPaletteVals[j+1], RavenPaletteVals[j+2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayed)
|
||||
{
|
||||
YourColor.FromCVar (am_ovyourcolor);
|
||||
WallColor.FromCVar (am_ovwallcolor);
|
||||
SpecialWallColor.FromCVar(am_ovspecialwallcolor);
|
||||
SecretWallColor = WallColor;
|
||||
SecretSectorColor.FromCVar (am_ovsecretsectorcolor);
|
||||
ThingColor_Item.FromCVar (am_ovthingcolor_item);
|
||||
|
@ -920,6 +923,7 @@ static void AM_initColors (bool overlayed)
|
|||
Background.FromCVar (am_backcolor);
|
||||
YourColor.FromCVar (am_yourcolor);
|
||||
SecretWallColor.FromCVar (am_secretwallcolor);
|
||||
SpecialWallColor.FromCVar (am_specialwallcolor);
|
||||
WallColor.FromCVar (am_wallcolor);
|
||||
TSWallColor.FromCVar (am_tswallcolor);
|
||||
FDWallColor.FromCVar (am_fdwallcolor);
|
||||
|
@ -961,6 +965,7 @@ static void AM_initColors (bool overlayed)
|
|||
AlmostBackground = DoomColors[2];
|
||||
SecretSectorColor =
|
||||
SecretWallColor =
|
||||
SpecialWallColor =
|
||||
WallColor = DoomColors[3];
|
||||
TSWallColor = DoomColors[4];
|
||||
FDWallColor = DoomColors[5];
|
||||
|
@ -982,6 +987,7 @@ static void AM_initColors (bool overlayed)
|
|||
AlmostBackground = DoomColors[2];
|
||||
SecretSectorColor =
|
||||
SecretWallColor =
|
||||
SpecialWallColor =
|
||||
WallColor = StrifeColors[3];
|
||||
TSWallColor = StrifeColors[4];
|
||||
FDWallColor = StrifeColors[5];
|
||||
|
@ -1003,6 +1009,7 @@ static void AM_initColors (bool overlayed)
|
|||
AlmostBackground = DoomColors[2];
|
||||
SecretSectorColor =
|
||||
SecretWallColor =
|
||||
SpecialWallColor =
|
||||
WallColor = RavenColors[3];
|
||||
TSWallColor = RavenColors[4];
|
||||
FDWallColor = RavenColors[5];
|
||||
|
@ -1018,30 +1025,6 @@ static void AM_initColors (bool overlayed)
|
|||
break;
|
||||
|
||||
}
|
||||
|
||||
lastpal = palette;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void AM_loadPics ()
|
||||
{
|
||||
int i;
|
||||
char namebuf[9];
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
mysnprintf (namebuf, countof(namebuf), "AMMNUM%d", i);
|
||||
marknums[i] = TexMan.CheckForTexture (namebuf, FTexture::TEX_MiscPatch);
|
||||
}
|
||||
|
||||
const char *autopage = level.info->mapbg[0] == 0? "AUTOPAGE" : (const char*)&level.info->mapbg[0];
|
||||
|
||||
mapback = TexMan.CheckForTexture(autopage, FTexture::TEX_MiscPatch);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -1066,7 +1049,8 @@ bool AM_clearMarks ()
|
|||
|
||||
void AM_LevelInit ()
|
||||
{
|
||||
leveljuststarted = 0;
|
||||
const char *autopage = level.info->mapbg[0] == 0? "AUTOPAGE" : (const char*)&level.info->mapbg[0];
|
||||
mapback = TexMan.CheckForTexture(autopage, FTexture::TEX_MiscPatch);
|
||||
|
||||
AM_clearMarks();
|
||||
|
||||
|
@ -1104,7 +1088,6 @@ void AM_Start ()
|
|||
if (!stopped) AM_Stop();
|
||||
stopped = false;
|
||||
AM_initVariables();
|
||||
AM_loadPics();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1216,7 +1199,7 @@ bool AM_Responder (event_t *ev, bool last)
|
|||
{
|
||||
if (automapactive && (ev->type == EV_KeyDown || ev->type == EV_KeyUp))
|
||||
{
|
||||
if (followplayer)
|
||||
if (am_followplayer)
|
||||
{
|
||||
// check for am_pan* and ignore in follow mode
|
||||
const char *defbind = AutomapBindings.GetBind(ev->data1);
|
||||
|
@ -1329,7 +1312,7 @@ void AM_Ticker ()
|
|||
|
||||
amclock++;
|
||||
|
||||
if (followplayer)
|
||||
if (am_followplayer)
|
||||
{
|
||||
AM_doFollowPlayer();
|
||||
}
|
||||
|
@ -1549,7 +1532,7 @@ void AM_drawGrid (const AMColor &color)
|
|||
|
||||
// [RH] Calculate a minimum for how long the grid lines should be so that
|
||||
// they cover the screen at any rotation.
|
||||
minlen = (fixed_t)sqrtf ((float)m_w*(float)m_w + (float)m_h*(float)m_h);
|
||||
minlen = (fixed_t)sqrt ((double)m_w*(double)m_w + (double)m_h*(double)m_h);
|
||||
extx = (minlen - m_w) / 2;
|
||||
exty = (minlen - m_h) / 2;
|
||||
|
||||
|
@ -1861,14 +1844,16 @@ void AM_drawWalls (bool allmap)
|
|||
else if (lines[i].special == Door_LockedRaise ||
|
||||
lines[i].special == ACS_LockedExecute ||
|
||||
lines[i].special == ACS_LockedExecuteDoor ||
|
||||
(lines[i].special == Generic_Door && lines[i].args[4] !=0 ))
|
||||
(lines[i].special == Door_Animated && lines[i].args[3] != 0) ||
|
||||
(lines[i].special == Generic_Door && lines[i].args[4] != 0))
|
||||
{
|
||||
if (am_colorset == 0 || am_colorset == 3) // Raven games show door colors
|
||||
{
|
||||
int P_GetMapColorForLock(int lock);
|
||||
int lock;
|
||||
|
||||
if (lines[i].special==Door_LockedRaise) lock=lines[i].args[3];
|
||||
if (lines[i].special==Door_LockedRaise || lines[i].special==Door_Animated)
|
||||
lock=lines[i].args[3];
|
||||
else lock=lines[i].args[4];
|
||||
|
||||
int color = P_GetMapColorForLock(lock);
|
||||
|
@ -1885,6 +1870,17 @@ void AM_drawWalls (bool allmap)
|
|||
AM_drawMline (&l, LockedColor); // locked special
|
||||
}
|
||||
}
|
||||
else if (am_showtriggerlines && am_colorset == 0 && lines[i].special != 0
|
||||
&& lines[i].special != Door_Open
|
||||
&& lines[i].special != Door_Close
|
||||
&& lines[i].special != Door_CloseWaitOpen
|
||||
&& lines[i].special != Door_Raise
|
||||
&& lines[i].special != Door_Animated
|
||||
&& lines[i].special != Generic_Door
|
||||
&& (lines[i].activation & SPAC_PlayerActivate))
|
||||
{
|
||||
AM_drawMline(&l, SpecialWallColor); // wall with special non-door action the player can do
|
||||
}
|
||||
else if (lines[i].backsector == NULL)
|
||||
{
|
||||
AM_drawMline(&l, WallColor); // one-sided wall
|
||||
|
@ -2047,20 +2043,15 @@ void AM_drawPlayers ()
|
|||
angle = players[consoleplayer].camera->angle;
|
||||
}
|
||||
|
||||
if (gameinfo.gametype & GAME_Raven)
|
||||
if (am_cheat != 0 && CheatMapArrow.Size() > 0)
|
||||
{
|
||||
arrow = player_arrow_raven;
|
||||
numarrowlines = NUMPLYRLINES_RAVEN;
|
||||
}
|
||||
else if (am_cheat != 0)
|
||||
{
|
||||
arrow = cheat_player_arrow;
|
||||
numarrowlines = NUMCHEATPLYRLINES;
|
||||
arrow = &CheatMapArrow[0];
|
||||
numarrowlines = CheatMapArrow.Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
arrow = player_arrow;
|
||||
numarrowlines = NUMPLYRLINES;
|
||||
arrow = &MapArrow[0];
|
||||
numarrowlines = MapArrow.Size();
|
||||
}
|
||||
AM_drawLineCharacter(arrow, numarrowlines, 0, angle, YourColor, pt.x, pt.y);
|
||||
return;
|
||||
|
@ -2113,9 +2104,7 @@ void AM_drawPlayers ()
|
|||
angle -= players[consoleplayer].camera->angle - ANG90;
|
||||
}
|
||||
|
||||
AM_drawLineCharacter
|
||||
(player_arrow, NUMPLYRLINES, 0, angle,
|
||||
color, pt.x, pt.y);
|
||||
AM_drawLineCharacter(&MapArrow[0], MapArrow.Size(), 0, angle, color, pt.x, pt.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2171,7 +2160,7 @@ void AM_drawThings ()
|
|||
|
||||
if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c));
|
||||
else color = ThingColor_CountItem;
|
||||
AM_drawLineCharacter(key_guy, NUMKEYGUYLINES, 16<<MAPBITS, 0, color, p.x, p.y);
|
||||
AM_drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0, color, p.x, p.y);
|
||||
color.Index = -1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
struct event_t;
|
||||
class FArchive;
|
||||
|
||||
|
||||
void AM_StaticInit();
|
||||
|
||||
// Called by main loop.
|
||||
bool AM_Responder (event_t* ev, bool last);
|
||||
|
||||
|
|
|
@ -105,11 +105,6 @@ FArchive &operator<< (FArchive &arc, botskill_t &skill)
|
|||
// This is intentionally not in the weapon definition anymore.
|
||||
void InitBotStuff()
|
||||
{
|
||||
static bool done = false;
|
||||
|
||||
if (done) return;
|
||||
done = true;
|
||||
|
||||
static struct BotInit
|
||||
{
|
||||
const char *type;
|
||||
|
|
|
@ -63,8 +63,6 @@ Everything that is changed is marked (maybe commented) with "Added by MC"
|
|||
|
||||
static FRandom pr_botspawn ("BotSpawn");
|
||||
|
||||
void InitBotStuff();
|
||||
|
||||
//Externs
|
||||
FCajunMaster bglobal;
|
||||
|
||||
|
@ -321,7 +319,6 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
|
|||
|
||||
waitingforspawn[playernumber] = true;
|
||||
|
||||
InitBotStuff();
|
||||
Net_WriteByte (DEM_ADDBOT);
|
||||
Net_WriteByte (playernumber);
|
||||
{
|
||||
|
|
120
src/c_cmds.cpp
120
src/c_cmds.cpp
|
@ -68,6 +68,8 @@
|
|||
#include "p_setup.h"
|
||||
#include "cmdlib.h"
|
||||
#include "d_net.h"
|
||||
#include "v_text.h"
|
||||
#include "p_lnspec.h"
|
||||
|
||||
extern FILE *Logfile;
|
||||
extern bool insave;
|
||||
|
@ -929,6 +931,7 @@ CCMD(nextsecret)
|
|||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CCMD(currentpos)
|
||||
{
|
||||
AActor *mo = players[consoleplayer].mo;
|
||||
|
@ -936,4 +939,121 @@ CCMD(currentpos)
|
|||
FIXED2FLOAT(mo->x), FIXED2FLOAT(mo->y), FIXED2FLOAT(mo->z), mo->angle/float(ANGLE_1), FIXED2FLOAT(mo->floorz), mo->Sector->sectornum, mo->Sector->lightlevel);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Print secret info (submitted by Karl Murks)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void PrintSecretString(const char *string, bool thislevel)
|
||||
{
|
||||
const char *colstr = thislevel? TEXTCOLOR_YELLOW : TEXTCOLOR_CYAN;
|
||||
if (string != NULL)
|
||||
{
|
||||
if (*string == '$')
|
||||
{
|
||||
if (string[1] == 'S' || string[1] == 's')
|
||||
{
|
||||
long secnum = strtol(string+2, (char**)&string, 10);
|
||||
if (*string == ';') string++;
|
||||
if (thislevel && secnum >= 0 && secnum < numsectors)
|
||||
{
|
||||
if (sectors[secnum].secretsector)
|
||||
{
|
||||
if ((sectors[secnum].special & SECRET_MASK)) colstr = TEXTCOLOR_RED;
|
||||
else colstr = TEXTCOLOR_GREEN;
|
||||
}
|
||||
else colstr = TEXTCOLOR_ORANGE;
|
||||
}
|
||||
}
|
||||
else if (string[1] == 'T' || string[1] == 't')
|
||||
{
|
||||
long tid = strtol(string+2, (char**)&string, 10);
|
||||
if (*string == ';') string++;
|
||||
FActorIterator it(tid);
|
||||
AActor *actor;
|
||||
bool foundone = false;
|
||||
if (thislevel)
|
||||
{
|
||||
while ((actor = it.Next()))
|
||||
{
|
||||
if (!actor->IsKindOf(PClass::FindClass("SecretTrigger"))) continue;
|
||||
foundone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundone) colstr = TEXTCOLOR_YELLOW;
|
||||
else colstr = TEXTCOLOR_RED;
|
||||
}
|
||||
}
|
||||
FBrokenLines *brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string);
|
||||
|
||||
for (int k = 0; brok[k].Width >= 0; k++)
|
||||
{
|
||||
Printf("%s%s\n", colstr, brok[k].Text.GetChars());
|
||||
}
|
||||
V_FreeBrokenLines(brok);
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Print secret hints
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
CCMD(secret)
|
||||
{
|
||||
const char *mapname = argv.argc() < 2? level.mapname : argv[1];
|
||||
bool thislevel = !stricmp(mapname, level.mapname);
|
||||
bool foundsome = false;
|
||||
|
||||
int lumpno=Wads.CheckNumForName("SECRETS");
|
||||
if (lumpno < 0) return;
|
||||
|
||||
FWadLump lump = Wads.OpenLumpNum(lumpno);
|
||||
FString maphdr;
|
||||
maphdr.Format("[%s]", mapname);
|
||||
|
||||
FString linebuild;
|
||||
char readbuffer[1024];
|
||||
bool inlevel = false;
|
||||
|
||||
while (lump.Gets(readbuffer, 1024))
|
||||
{
|
||||
if (!inlevel)
|
||||
{
|
||||
if (readbuffer[0] == '[')
|
||||
{
|
||||
inlevel = !strnicmp(readbuffer, maphdr, maphdr.Len());
|
||||
if (!foundsome)
|
||||
{
|
||||
FString levelname;
|
||||
level_info_t *info = FindLevelInfo(mapname);
|
||||
levelname.Format("%s - %s\n", mapname, info->LevelName.GetChars());
|
||||
size_t llen = levelname.Len() - 1;
|
||||
for(size_t ii=0; ii<llen; ii++) levelname += '-';
|
||||
Printf(TEXTCOLOR_YELLOW"%s\n", levelname.GetChars());
|
||||
foundsome = true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readbuffer[0] != '[')
|
||||
{
|
||||
linebuild += readbuffer;
|
||||
if (linebuild.Len() < 1023 || linebuild[1022] == '\n')
|
||||
{
|
||||
// line complete so print it.
|
||||
linebuild.Substitute("\r", "");
|
||||
linebuild.StripRight(" \t\n");
|
||||
PrintSecretString(linebuild, thislevel);
|
||||
linebuild = "";
|
||||
}
|
||||
}
|
||||
else inlevel = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -94,7 +94,7 @@ extern FBaseCVar *CVars;
|
|||
extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE];
|
||||
|
||||
int ConCols, PhysRows;
|
||||
bool vidactive = false, gotconback = false;
|
||||
bool vidactive = false;
|
||||
bool cursoron = false;
|
||||
int ConBottom, ConScroll, RowAdjust;
|
||||
int CursorTicker;
|
||||
|
@ -232,7 +232,7 @@ CUSTOM_CVAR (Int, msgmidcolor2, 4, CVAR_ARCHIVE)
|
|||
static void maybedrawnow (bool tick, bool force)
|
||||
{
|
||||
// FIXME: Does not work right with hw2d
|
||||
if (ConsoleDrawing || !gotconback || screen == NULL || screen->IsLocked () || screen->Accel2D)
|
||||
if (ConsoleDrawing || screen == NULL || screen->IsLocked () || screen->Accel2D || ConFont == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -297,32 +297,28 @@ void DequeueConsoleText ()
|
|||
EnqueuedTextTail = &EnqueuedText;
|
||||
}
|
||||
|
||||
void C_InitConback()
|
||||
{
|
||||
conback = TexMan.CheckForTexture ("CONBACK", FTexture::TEX_MiscPatch);
|
||||
|
||||
if (!conback.isValid())
|
||||
{
|
||||
conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch);
|
||||
conshade = MAKEARGB(175,0,0,0);
|
||||
conline = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
conshade = 0;
|
||||
conline = false;
|
||||
}
|
||||
}
|
||||
|
||||
void C_InitConsole (int width, int height, bool ingame)
|
||||
{
|
||||
if ( (vidactive = ingame) )
|
||||
{
|
||||
if (!gotconback)
|
||||
{
|
||||
conback = TexMan.CheckForTexture ("CONBACK", FTexture::TEX_MiscPatch);
|
||||
|
||||
if (!conback.isValid())
|
||||
{
|
||||
conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch);
|
||||
conshade = MAKEARGB(175,0,0,0);
|
||||
conline = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
conshade = 0;
|
||||
conline = false;
|
||||
}
|
||||
|
||||
gotconback = true;
|
||||
}
|
||||
}
|
||||
|
||||
int cwidth, cheight;
|
||||
|
||||
vidactive = ingame;
|
||||
if (ConFont != NULL)
|
||||
{
|
||||
cwidth = ConFont->GetCharWidth ('M');
|
||||
|
|
|
@ -53,6 +53,7 @@ extern int ConBottom;
|
|||
// Initialize the console
|
||||
void C_InitConsole (int width, int height, bool ingame);
|
||||
void C_DeinitConsole ();
|
||||
void C_InitConback();
|
||||
|
||||
// Adjust the console for a new screen mode
|
||||
void C_NewModeAdjust (void);
|
||||
|
|
|
@ -221,7 +221,16 @@ int FBaseCVar::ToInt (UCVarValue value, ECVarType type)
|
|||
#else
|
||||
case CVAR_Float: res = (int)value.Float; break;
|
||||
#endif
|
||||
case CVAR_String: res = strtol (value.String, NULL, 0); break;
|
||||
case CVAR_String:
|
||||
{
|
||||
if (stricmp (value.String, "true") == 0)
|
||||
res = 1;
|
||||
else if (stricmp (value.String, "false") == 0)
|
||||
res = 0;
|
||||
else
|
||||
res = strtol (value.String, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CVAR_GUID: res = 0; break;
|
||||
default: res = 0; break;
|
||||
}
|
||||
|
@ -444,7 +453,12 @@ UCVarValue FBaseCVar::FromString (const char *value, ECVarType type)
|
|||
break;
|
||||
|
||||
case CVAR_Int:
|
||||
ret.Int = strtol (value, NULL, 0);
|
||||
if (stricmp (value, "true") == 0)
|
||||
ret.Int = 1;
|
||||
else if (stricmp (value, "false") == 0)
|
||||
ret.Int = 0;
|
||||
else
|
||||
ret.Int = strtol (value, NULL, 0);
|
||||
break;
|
||||
|
||||
case CVAR_Float:
|
||||
|
@ -600,6 +614,11 @@ void FBaseCVar::EnableCallbacks ()
|
|||
}
|
||||
}
|
||||
|
||||
void FBaseCVar::DisableCallbacks ()
|
||||
{
|
||||
m_UseCallback = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Boolean cvar implementation
|
||||
//
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
|
||||
static void EnableNoSet (); // enable the honoring of CVAR_NOSET
|
||||
static void EnableCallbacks ();
|
||||
static void DisableCallbacks ();
|
||||
static void ResetColors (); // recalc color cvars' indices after screen change
|
||||
|
||||
static void ListVars (const char *filter, bool plain);
|
||||
|
|
|
@ -1211,6 +1211,30 @@ void C_ArchiveAliases (FConfigFile *f)
|
|||
}
|
||||
}
|
||||
|
||||
void C_ClearAliases ()
|
||||
{
|
||||
int bucket;
|
||||
FConsoleCommand *alias;
|
||||
|
||||
for (bucket = 0; bucket < FConsoleCommand::HASH_SIZE; bucket++)
|
||||
{
|
||||
alias = Commands[bucket];
|
||||
while (alias)
|
||||
{
|
||||
FConsoleCommand *next = alias->m_Next;
|
||||
if (alias->IsAlias())
|
||||
static_cast<FConsoleAlias *>(alias)->SafeDelete();
|
||||
alias = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCMD(clearaliases)
|
||||
{
|
||||
C_ClearAliases();
|
||||
}
|
||||
|
||||
|
||||
// This is called only by the ini parser.
|
||||
void C_SetAlias (const char *name, const char *cmd)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,7 @@ int C_ExecFile (const char *cmd, bool usePullin);
|
|||
void C_ArchiveAliases (FConfigFile *f);
|
||||
|
||||
void C_SetAlias (const char *name, const char *cmd);
|
||||
void C_ClearAliases ();
|
||||
|
||||
// build a single string out of multiple strings
|
||||
FString BuildString (int argc, char **argv);
|
||||
|
|
|
@ -89,6 +89,7 @@ static FCompatOption Options[] =
|
|||
{ "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW },
|
||||
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
|
||||
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
|
||||
{ "ignoreteleporttags", 0, BCOMPATF_BADTELEPORTERS },
|
||||
|
||||
// list copied from g_mapinfo.cpp
|
||||
{ "shorttex", COMPATF_SHORTTEX, 0 },
|
||||
|
@ -141,6 +142,9 @@ void ParseCompatibility()
|
|||
int i, x;
|
||||
unsigned int j;
|
||||
|
||||
BCompatMap.Clear();
|
||||
CompatParams.Clear();
|
||||
|
||||
// The contents of this file are not cumulative, as it should not
|
||||
// be present in user-distributed maps.
|
||||
FScanner sc(Wads.GetNumForFullName("compatibility.txt"));
|
||||
|
@ -279,7 +283,6 @@ void CheckCompatibility(MapData *map)
|
|||
ib_compatflags = 0;
|
||||
ii_compatparams = -1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
map->GetChecksum(md5.Bytes);
|
||||
|
|
|
@ -2880,6 +2880,8 @@ void FinishDehPatch ()
|
|||
// Now that all Dehacked patches have been processed, it's okay to free StateMap.
|
||||
StateMap.Clear();
|
||||
StateMap.ShrinkToFit();
|
||||
TouchedActors.Clear();
|
||||
TouchedActors.ShrinkToFit();
|
||||
}
|
||||
|
||||
void ModifyDropAmount(AInventory *inv, int dropamount);
|
||||
|
|
|
@ -227,13 +227,14 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
|
|||
{
|
||||
sc.MustGetString();
|
||||
FString wadname = sc.String;
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__APPLE__) // Turns out Mac OS X is case insensitive.
|
||||
mIWadNames.Push(wadname);
|
||||
#else
|
||||
// check for lowercase, uppercased first letter and full uppercase on Linux etc.
|
||||
wadname.ToLower();
|
||||
mIWadNames.Push(wadname);
|
||||
wadname[0] = toupper(wadname[0]);
|
||||
wadname.LockBuffer()[0] = toupper(wadname[0]);
|
||||
wadname.UnlockBuffer();
|
||||
mIWadNames.Push(wadname);
|
||||
wadname.ToUpper();
|
||||
mIWadNames.Push(wadname);
|
||||
|
@ -331,7 +332,7 @@ int FIWadManager::CheckIWAD (const char *doomwaddir, WadStuff *wads)
|
|||
{
|
||||
FString iwad;
|
||||
|
||||
iwad.Format ("%s%s%s", doomwaddir, slash, mIWadNames[i]);
|
||||
iwad.Format ("%s%s%s", doomwaddir, slash, mIWadNames[i].GetChars());
|
||||
FixPathSeperator (iwad);
|
||||
if (FileExists (iwad))
|
||||
{
|
||||
|
@ -547,6 +548,7 @@ int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad,
|
|||
exit (0);
|
||||
|
||||
// zdoom.pk3 must always be the first file loaded and the IWAD second.
|
||||
wadfiles.Clear();
|
||||
D_AddFile (wadfiles, zdoom_wad);
|
||||
|
||||
if (mIWads[wads[pickwad].Type].preload >= 0)
|
||||
|
|
729
src/d_main.cpp
729
src/d_main.cpp
|
@ -122,6 +122,7 @@ extern void M_SetDefaultMode ();
|
|||
extern void R_ExecuteSetViewSize ();
|
||||
extern void G_NewInit ();
|
||||
extern void SetupPlayerClasses ();
|
||||
extern void HUD_InitHud();
|
||||
const FIWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad);
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
@ -131,6 +132,7 @@ void D_ProcessEvents ();
|
|||
void G_BuildTiccmd (ticcmd_t* cmd);
|
||||
void D_DoAdvanceDemo ();
|
||||
void D_AddWildFile (TArray<FString> &wadfiles, const char *pattern);
|
||||
void D_LoadWadSettings ();
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
|
@ -221,6 +223,8 @@ FTexture *Page;
|
|||
FTexture *Advisory;
|
||||
bool nospriterename;
|
||||
FStartupInfo DoomStartupInfo;
|
||||
FString lastIWAD;
|
||||
int restart = 0;
|
||||
|
||||
cycle_t FrameCycles;
|
||||
|
||||
|
@ -712,10 +716,12 @@ void D_Display ()
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned int nowtime = I_FPSTime();
|
||||
TexMan.UpdateAnimations(nowtime);
|
||||
R_UpdateSky(nowtime);
|
||||
switch (gamestate)
|
||||
{
|
||||
case GS_FULLCONSOLE:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
C_DrawConsole (false);
|
||||
|
@ -780,7 +786,6 @@ void D_Display ()
|
|||
break;
|
||||
|
||||
case GS_INTERMISSION:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
WI_Drawer ();
|
||||
|
@ -788,7 +793,6 @@ void D_Display ()
|
|||
break;
|
||||
|
||||
case GS_FINALE:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
F_Drawer ();
|
||||
|
@ -796,7 +800,6 @@ void D_Display ()
|
|||
break;
|
||||
|
||||
case GS_DEMOSCREEN:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
D_PageDrawer ();
|
||||
|
@ -889,7 +892,7 @@ void D_Display ()
|
|||
//
|
||||
// D_ErrorCleanup ()
|
||||
//
|
||||
// Cleanup after a recoverable error.
|
||||
// Cleanup after a recoverable error or a restart
|
||||
//==========================================================================
|
||||
|
||||
void D_ErrorCleanup ()
|
||||
|
@ -927,6 +930,7 @@ void D_DoomLoop ()
|
|||
|
||||
// Clamp the timer to TICRATE until the playloop has been entered.
|
||||
r_NoInterpolate = true;
|
||||
Page = Advisory = NULL;
|
||||
|
||||
vid_cursor.Callback();
|
||||
|
||||
|
@ -1563,80 +1567,6 @@ bool ConsiderPatches (const char *arg)
|
|||
return argc > 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// D_LoadWadSettings
|
||||
//
|
||||
// Parses any loaded KEYCONF lumps. These are restricted console scripts
|
||||
// that can only execute the alias, defaultbind, addkeysection,
|
||||
// addmenukey, weaponsection, and addslotdefault commands.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void D_LoadWadSettings ()
|
||||
{
|
||||
char cmd[4096];
|
||||
int lump, lastlump = 0;
|
||||
|
||||
ParsingKeyConf = true;
|
||||
|
||||
while ((lump = Wads.FindLump ("KEYCONF", &lastlump)) != -1)
|
||||
{
|
||||
FMemLump data = Wads.ReadLump (lump);
|
||||
const char *eof = (char *)data.GetMem() + Wads.LumpLength (lump);
|
||||
const char *conf = (char *)data.GetMem();
|
||||
|
||||
while (conf < eof)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// Fetch a line to execute
|
||||
for (i = 0; conf + i < eof && conf[i] != '\n'; ++i)
|
||||
{
|
||||
cmd[i] = conf[i];
|
||||
}
|
||||
cmd[i] = 0;
|
||||
conf += i;
|
||||
if (*conf == '\n')
|
||||
{
|
||||
conf++;
|
||||
}
|
||||
|
||||
// Comments begin with //
|
||||
char *stop = cmd + i - 1;
|
||||
char *comment = cmd;
|
||||
int inQuote = 0;
|
||||
|
||||
if (*stop == '\r')
|
||||
*stop-- = 0;
|
||||
|
||||
while (comment < stop)
|
||||
{
|
||||
if (*comment == '\"')
|
||||
{
|
||||
inQuote ^= 1;
|
||||
}
|
||||
else if (!inQuote && *comment == '/' && *(comment + 1) == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
comment++;
|
||||
}
|
||||
if (comment == cmd)
|
||||
{ // Comment at line beginning
|
||||
continue;
|
||||
}
|
||||
else if (comment < stop)
|
||||
{ // Comment in middle of line
|
||||
*comment = 0;
|
||||
}
|
||||
|
||||
AddCommandString (cmd);
|
||||
}
|
||||
}
|
||||
ParsingKeyConf = false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// D_MultiExec
|
||||
|
@ -1723,7 +1653,8 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
|
|||
}
|
||||
else if (!nextKey.CompareNoCase("NOSPRITERENAME"))
|
||||
{
|
||||
nospriterename = true;
|
||||
sc.MustGetString();
|
||||
nospriterename = sc.Compare("true");
|
||||
}
|
||||
else if (!nextKey.CompareNoCase("STARTUPTITLE"))
|
||||
{
|
||||
|
@ -1809,7 +1740,7 @@ static FString CheckGameInfo(TArray<FString> & pwads)
|
|||
|
||||
static void SetMapxxFlag()
|
||||
{
|
||||
int lump_name = Wads.CheckNumForName("MAP01", FWadCollection::IWAD_FILENUM);
|
||||
int lump_name = Wads.CheckNumForName("MAP01", ns_global, FWadCollection::IWAD_FILENUM);
|
||||
int lump_wad = Wads.CheckNumForFullName("maps/map01.wad", FWadCollection::IWAD_FILENUM);
|
||||
int lump_map = Wads.CheckNumForFullName("maps/map01.map", FWadCollection::IWAD_FILENUM);
|
||||
|
||||
|
@ -1818,20 +1749,12 @@ static void SetMapxxFlag()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// D_DoomMain
|
||||
// Initialize
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void D_DoomMain (void)
|
||||
static void D_DoomInit()
|
||||
{
|
||||
int p, flags;
|
||||
const char *v;
|
||||
const char *wad;
|
||||
DArgs *execFiles;
|
||||
TArray<FString> pwads;
|
||||
FString *args;
|
||||
int argcount;
|
||||
|
||||
// Set the FPU precision to 53 significant bits. This is the default
|
||||
// for Visual C++, but not for GCC, so some slight math variances
|
||||
// might crop up if we leave it alone.
|
||||
|
@ -1859,7 +1782,6 @@ void D_DoomMain (void)
|
|||
Args->CollectFiles("-playdemo", ".lmp");
|
||||
Args->CollectFiles("-file", NULL); // anything left goes after -file
|
||||
|
||||
PClass::StaticInit ();
|
||||
atterm (C_DeinitConsole);
|
||||
|
||||
gamestate = GS_STARTUP;
|
||||
|
@ -1872,30 +1794,16 @@ void D_DoomMain (void)
|
|||
Printf ("M_LoadDefaults: Load system defaults.\n");
|
||||
M_LoadDefaults (); // load before initing other systems
|
||||
|
||||
// [RH] Make sure zdoom.pk3 is always loaded,
|
||||
// as it contains magic stuff we need.
|
||||
}
|
||||
|
||||
wad = BaseFileSearch (BASEWAD, NULL, true);
|
||||
if (wad == NULL)
|
||||
{
|
||||
I_FatalError ("Cannot find " BASEWAD);
|
||||
}
|
||||
FString basewad = wad;
|
||||
|
||||
// Load zdoom.pk3 alone so that we can get access to the internal gameinfos before
|
||||
// the IWAD is known.
|
||||
|
||||
GetCmdLineFiles(pwads);
|
||||
FString iwad = CheckGameInfo(pwads);
|
||||
|
||||
FIWadManager *iwad_man = new FIWadManager;
|
||||
const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad);
|
||||
gameinfo.gametype = iwad_info->gametype;
|
||||
gameinfo.flags = iwad_info->flags;
|
||||
gameinfo.ConfigName = iwad_info->Configname;
|
||||
|
||||
GameConfig->DoGameSetup (gameinfo.ConfigName);
|
||||
//==========================================================================
|
||||
//
|
||||
// AddAutoloadFiles
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void AddAutoloadFiles(const char *gamesection)
|
||||
{
|
||||
if (!(gameinfo.flags & GI_SHAREWARE) && !Args->CheckParm("-noautoload"))
|
||||
{
|
||||
FString file;
|
||||
|
@ -1905,7 +1813,7 @@ void D_DoomMain (void)
|
|||
// voices. I never got around to writing the utility to do it, though.
|
||||
// And I probably never will now. But I know at least one person uses
|
||||
// it for something else, so this gets to stay here.
|
||||
wad = BaseFileSearch ("zvox.wad", NULL);
|
||||
const char *wad = BaseFileSearch ("zvox.wad", NULL);
|
||||
if (wad)
|
||||
D_AddFile (allwads, wad);
|
||||
|
||||
|
@ -1932,66 +1840,28 @@ void D_DoomMain (void)
|
|||
D_AddConfigWads (allwads, file);
|
||||
|
||||
// Add IWAD-specific wads
|
||||
if (iwad_info->Autoname != NULL)
|
||||
if (gamesection != NULL)
|
||||
{
|
||||
file = iwad_info->Autoname;
|
||||
file = gamesection;
|
||||
file += ".Autoload";
|
||||
D_AddConfigWads(allwads, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run automatically executed files
|
||||
execFiles = new DArgs;
|
||||
GameConfig->AddAutoexec (execFiles, gameinfo.ConfigName);
|
||||
D_MultiExec (execFiles, true);
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckCmdLine
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// Run .cfg files at the start of the command line.
|
||||
execFiles = Args->GatherFiles ("-exec");
|
||||
D_MultiExec (execFiles, true);
|
||||
static void CheckCmdLine()
|
||||
{
|
||||
int flags = dmflags;
|
||||
int p;
|
||||
const char *v;
|
||||
|
||||
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
|
||||
|
||||
CopyFiles(allwads, pwads);
|
||||
|
||||
// Since this function will never leave we must delete this array here manually.
|
||||
pwads.Clear();
|
||||
pwads.ShrinkToFit();
|
||||
|
||||
Printf ("W_Init: Init WADfiles.\n");
|
||||
Wads.InitMultipleFiles (allwads);
|
||||
allwads.Clear();
|
||||
allwads.ShrinkToFit();
|
||||
SetMapxxFlag();
|
||||
|
||||
// [RH] Initialize localizable strings.
|
||||
GStrings.LoadStrings (false);
|
||||
|
||||
V_InitFontColors ();
|
||||
|
||||
// [RH] Moved these up here so that we can do most of our
|
||||
// startup output in a fullscreen console.
|
||||
|
||||
CT_Init ();
|
||||
|
||||
Printf ("I_Init: Setting up machine state.\n");
|
||||
I_Init ();
|
||||
|
||||
Printf ("V_Init: allocate screen.\n");
|
||||
V_Init ();
|
||||
|
||||
// Base systems have been inited; enable cvar callbacks
|
||||
FBaseCVar::EnableCallbacks ();
|
||||
|
||||
Printf ("S_Init: Setting up sound.\n");
|
||||
S_Init ();
|
||||
|
||||
Printf ("ST_Init: Init startup screen.\n");
|
||||
StartScreen = FStartupScreen::CreateInstance (R_GuesstimateNumTextures() + 5);
|
||||
|
||||
ParseCompatibility();
|
||||
|
||||
Printf ("P_Init: Checking cmd-line parameters...\n");
|
||||
flags = dmflags;
|
||||
Printf ("Checking cmd-line parameters...\n");
|
||||
if (Args->CheckParm ("-nomonsters")) flags |= DF_NO_MONSTERS;
|
||||
if (Args->CheckParm ("-respawn")) flags |= DF_MONSTERS_RESPAWN;
|
||||
if (Args->CheckParm ("-fast")) flags |= DF_FAST_MONSTERS;
|
||||
|
@ -2126,199 +1996,404 @@ void D_DoomMain (void)
|
|||
temp.Format ("Warp to map %s, Skill %d ", startmap.GetChars(), gameskill + 1);
|
||||
StartScreen->AppendStatusLine(temp);
|
||||
}
|
||||
}
|
||||
|
||||
// [RH] Load sound environments
|
||||
S_ParseReverbDef ();
|
||||
//==========================================================================
|
||||
//
|
||||
// D_DoomMain
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// [RH] Parse through all loaded mapinfo lumps
|
||||
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
||||
G_ParseMapInfo (iwad_info->MapInfo);
|
||||
ReadStatistics();
|
||||
void D_DoomMain (void)
|
||||
{
|
||||
int p;
|
||||
const char *v;
|
||||
const char *wad;
|
||||
DArgs *execFiles;
|
||||
TArray<FString> pwads;
|
||||
FString *args;
|
||||
int argcount;
|
||||
|
||||
// [RH] Parse any SNDINFO lumps
|
||||
Printf ("S_InitData: Load sound definitions.\n");
|
||||
S_InitData ();
|
||||
D_DoomInit();
|
||||
PClass::StaticInit ();
|
||||
|
||||
Printf ("Texman.Init: Init texture manager.\n");
|
||||
TexMan.Init();
|
||||
// [RH] Make sure zdoom.pk3 is always loaded,
|
||||
// as it contains magic stuff we need.
|
||||
|
||||
// [CW] Parse any TEAMINFO lumps.
|
||||
Printf ("ParseTeamInfo: Load team definitions.\n");
|
||||
TeamLibrary.ParseTeamInfo ();
|
||||
|
||||
FActorInfo::StaticInit ();
|
||||
|
||||
// [GRB] Initialize player class list
|
||||
SetupPlayerClasses ();
|
||||
|
||||
|
||||
// [RH] Load custom key and weapon settings from WADs
|
||||
D_LoadWadSettings ();
|
||||
|
||||
// [GRB] Check if someone used clearplayerclasses but not addplayerclass
|
||||
if (PlayerClasses.Size () == 0)
|
||||
wad = BaseFileSearch (BASEWAD, NULL, true);
|
||||
if (wad == NULL)
|
||||
{
|
||||
I_FatalError ("No player classes defined");
|
||||
I_FatalError ("Cannot find " BASEWAD);
|
||||
}
|
||||
FString basewad = wad;
|
||||
|
||||
StartScreen->Progress ();
|
||||
|
||||
Printf ("R_Init: Init %s refresh subsystem.\n", gameinfo.ConfigName.GetChars());
|
||||
StartScreen->LoadingStatus ("Loading graphics", 0x3f);
|
||||
R_Init ();
|
||||
// reinit from here
|
||||
|
||||
Printf ("DecalLibrary: Load decals.\n");
|
||||
DecalLibrary.Clear ();
|
||||
DecalLibrary.ReadAllDecals ();
|
||||
|
||||
// [RH] Add any .deh and .bex files on the command line.
|
||||
// If there are none, try adding any in the config file.
|
||||
// Note that the command line overrides defaults from the config.
|
||||
|
||||
if ((ConsiderPatches("-deh") | ConsiderPatches("-bex")) == 0 &&
|
||||
gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked"))
|
||||
do
|
||||
{
|
||||
const char *key;
|
||||
const char *value;
|
||||
|
||||
while (GameConfig->NextInSection (key, value))
|
||||
if (restart)
|
||||
{
|
||||
if (stricmp (key, "Path") == 0 && FileExists (value))
|
||||
{
|
||||
Printf ("Applying patch %s\n", value);
|
||||
D_LoadDehFile(value);
|
||||
}
|
||||
C_InitConsole(SCREENWIDTH, SCREENHEIGHT, false);
|
||||
}
|
||||
}
|
||||
nospriterename = false;
|
||||
|
||||
// Load embedded Dehacked patches
|
||||
D_LoadDehLumps();
|
||||
// Load zdoom.pk3 alone so that we can get access to the internal gameinfos before
|
||||
// the IWAD is known.
|
||||
|
||||
// Create replacements for dehacked pickups
|
||||
FinishDehPatch();
|
||||
GetCmdLineFiles(pwads);
|
||||
FString iwad = CheckGameInfo(pwads);
|
||||
|
||||
FActorInfo::StaticSetActorNums ();
|
||||
// The IWAD selection dialogue dpes not show in fullscreen so if the
|
||||
// restart is initiated without a defined IWAD assume for now that it's not going to change.
|
||||
if (iwad.Len() == 0) iwad = lastIWAD;
|
||||
|
||||
// [RH] User-configurable startup strings. Because BOOM does.
|
||||
static const char *startupString[5] = {
|
||||
"STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5"
|
||||
};
|
||||
for (p = 0; p < 5; ++p)
|
||||
{
|
||||
const char *str = GStrings[startupString[p]];
|
||||
if (str != NULL && str[0] != '\0')
|
||||
{
|
||||
Printf ("%s\n", str);
|
||||
}
|
||||
}
|
||||
FIWadManager *iwad_man = new FIWadManager;
|
||||
const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad);
|
||||
gameinfo.gametype = iwad_info->gametype;
|
||||
gameinfo.flags = iwad_info->flags;
|
||||
gameinfo.ConfigName = iwad_info->Configname;
|
||||
lastIWAD = iwad;
|
||||
|
||||
//Added by MC:
|
||||
argcount = Args->CheckParmList("-bots", &args);
|
||||
for (p = 0; p < argcount; ++p)
|
||||
{
|
||||
bglobal.getspawned.Push(args[p]);
|
||||
}
|
||||
bglobal.spawn_tries = 0;
|
||||
bglobal.wanted_botnum = bglobal.getspawned.Size();
|
||||
FBaseCVar::DisableCallbacks();
|
||||
GameConfig->DoGameSetup (gameinfo.ConfigName);
|
||||
|
||||
Printf ("M_Init: Init menus.\n");
|
||||
M_Init ();
|
||||
AddAutoloadFiles(iwad_info->Autoname);
|
||||
|
||||
Printf ("P_Init: Init Playloop state.\n");
|
||||
StartScreen->LoadingStatus ("Init game engine", 0x3f);
|
||||
P_Init ();
|
||||
// Run automatically executed files
|
||||
execFiles = new DArgs;
|
||||
GameConfig->AddAutoexec (execFiles, gameinfo.ConfigName);
|
||||
D_MultiExec (execFiles, true);
|
||||
|
||||
P_SetupWeapons_ntohton();
|
||||
// Run .cfg files at the start of the command line.
|
||||
execFiles = Args->GatherFiles ("-exec");
|
||||
D_MultiExec (execFiles, true);
|
||||
|
||||
//SBarInfo support.
|
||||
SBarInfo::Load();
|
||||
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
|
||||
|
||||
Printf ("D_CheckNetGame: Checking network game status.\n");
|
||||
StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
|
||||
D_CheckNetGame ();
|
||||
CopyFiles(allwads, pwads);
|
||||
|
||||
// [RH] Lock any cvars that should be locked now that we're
|
||||
// about to begin the game.
|
||||
FBaseCVar::EnableNoSet ();
|
||||
// Since this function will never leave we must delete this array here manually.
|
||||
pwads.Clear();
|
||||
pwads.ShrinkToFit();
|
||||
|
||||
delete iwad_man; // now we won't need this anymore
|
||||
|
||||
// [RH] Run any saved commands from the command line or autoexec.cfg now.
|
||||
gamestate = GS_FULLCONSOLE;
|
||||
Net_NewMakeTic ();
|
||||
DThinker::RunThinkers ();
|
||||
gamestate = GS_STARTUP;
|
||||
|
||||
// start the apropriate game based on parms
|
||||
v = Args->CheckValue ("-record");
|
||||
|
||||
if (v)
|
||||
{
|
||||
G_RecordDemo (v);
|
||||
autostart = true;
|
||||
}
|
||||
|
||||
delete StartScreen;
|
||||
StartScreen = NULL;
|
||||
|
||||
if (Args->CheckParm("-norun"))
|
||||
{
|
||||
throw CNoRunExit();
|
||||
}
|
||||
|
||||
V_Init2();
|
||||
|
||||
v = Args->CheckValue("-playdemo");
|
||||
if (v != NULL)
|
||||
{
|
||||
singledemo = true; // quit after one demo
|
||||
G_DeferedPlayDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
v = Args->CheckValue ("-timedemo");
|
||||
if (v)
|
||||
{
|
||||
G_TimeDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
Printf ("W_Init: Init WADfiles.\n");
|
||||
Wads.InitMultipleFiles (allwads);
|
||||
allwads.Clear();
|
||||
allwads.ShrinkToFit();
|
||||
SetMapxxFlag();
|
||||
|
||||
v = Args->CheckValue ("-loadgame");
|
||||
if (v)
|
||||
{
|
||||
FString file(v);
|
||||
FixPathSeperator (file);
|
||||
DefaultExtension (file, ".zds");
|
||||
G_LoadGame (file);
|
||||
}
|
||||
// [RH] Initialize localizable strings.
|
||||
GStrings.LoadStrings (false);
|
||||
|
||||
if (gameaction != ga_loadgame)
|
||||
{
|
||||
if (autostart || netgame)
|
||||
V_InitFontColors ();
|
||||
|
||||
// [RH] Moved these up here so that we can do most of our
|
||||
// startup output in a fullscreen console.
|
||||
|
||||
CT_Init ();
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
// Do not do any screenwipes when autostarting a game.
|
||||
if (!Args->CheckParm("-warpwipe"))
|
||||
Printf ("I_Init: Setting up machine state.\n");
|
||||
I_Init ();
|
||||
}
|
||||
|
||||
Printf ("V_Init: allocate screen.\n");
|
||||
V_Init (!!restart);
|
||||
|
||||
// Base systems have been inited; enable cvar callbacks
|
||||
FBaseCVar::EnableCallbacks ();
|
||||
|
||||
Printf ("S_Init: Setting up sound.\n");
|
||||
S_Init ();
|
||||
|
||||
Printf ("ST_Init: Init startup screen.\n");
|
||||
if (!restart) StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5);
|
||||
else StartScreen = new FStartupScreen(0);
|
||||
|
||||
ParseCompatibility();
|
||||
|
||||
CheckCmdLine();
|
||||
|
||||
// [RH] Load sound environments
|
||||
S_ParseReverbDef ();
|
||||
|
||||
// [RH] Parse through all loaded mapinfo lumps
|
||||
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
||||
G_ParseMapInfo (iwad_info->MapInfo);
|
||||
ReadStatistics();
|
||||
|
||||
// [RH] Parse any SNDINFO lumps
|
||||
Printf ("S_InitData: Load sound definitions.\n");
|
||||
S_InitData ();
|
||||
|
||||
Printf ("Texman.Init: Init texture manager.\n");
|
||||
TexMan.Init();
|
||||
C_InitConback();
|
||||
|
||||
// [CW] Parse any TEAMINFO lumps.
|
||||
Printf ("ParseTeamInfo: Load team definitions.\n");
|
||||
TeamLibrary.ParseTeamInfo ();
|
||||
|
||||
FActorInfo::StaticInit ();
|
||||
|
||||
// [GRB] Initialize player class list
|
||||
SetupPlayerClasses ();
|
||||
|
||||
|
||||
// [RH] Load custom key and weapon settings from WADs
|
||||
D_LoadWadSettings ();
|
||||
|
||||
// [GRB] Check if someone used clearplayerclasses but not addplayerclass
|
||||
if (PlayerClasses.Size () == 0)
|
||||
{
|
||||
I_FatalError ("No player classes defined");
|
||||
}
|
||||
|
||||
StartScreen->Progress ();
|
||||
|
||||
Printf ("R_Init: Init %s refresh subsystem.\n", gameinfo.ConfigName.GetChars());
|
||||
StartScreen->LoadingStatus ("Loading graphics", 0x3f);
|
||||
R_Init ();
|
||||
|
||||
Printf ("DecalLibrary: Load decals.\n");
|
||||
DecalLibrary.ReadAllDecals ();
|
||||
|
||||
// [RH] Add any .deh and .bex files on the command line.
|
||||
// If there are none, try adding any in the config file.
|
||||
// Note that the command line overrides defaults from the config.
|
||||
|
||||
if ((ConsiderPatches("-deh") | ConsiderPatches("-bex")) == 0 &&
|
||||
gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked"))
|
||||
{
|
||||
const char *key;
|
||||
const char *value;
|
||||
|
||||
while (GameConfig->NextInSection (key, value))
|
||||
{
|
||||
NoWipe = TICRATE;
|
||||
if (stricmp (key, "Path") == 0 && FileExists (value))
|
||||
{
|
||||
Printf ("Applying patch %s\n", value);
|
||||
D_LoadDehFile(value);
|
||||
}
|
||||
}
|
||||
CheckWarpTransMap (startmap, true);
|
||||
if (demorecording)
|
||||
G_BeginRecording (startmap);
|
||||
G_InitNew (startmap, false);
|
||||
}
|
||||
|
||||
// Load embedded Dehacked patches
|
||||
D_LoadDehLumps();
|
||||
|
||||
// Create replacements for dehacked pickups
|
||||
FinishDehPatch();
|
||||
|
||||
FActorInfo::StaticSetActorNums ();
|
||||
|
||||
//Added by MC:
|
||||
bglobal.getspawned.Clear();
|
||||
argcount = Args->CheckParmList("-bots", &args);
|
||||
for (p = 0; p < argcount; ++p)
|
||||
{
|
||||
bglobal.getspawned.Push(args[p]);
|
||||
}
|
||||
bglobal.spawn_tries = 0;
|
||||
bglobal.wanted_botnum = bglobal.getspawned.Size();
|
||||
|
||||
Printf ("M_Init: Init menus.\n");
|
||||
M_Init ();
|
||||
|
||||
Printf ("P_Init: Init Playloop state.\n");
|
||||
StartScreen->LoadingStatus ("Init game engine", 0x3f);
|
||||
AM_StaticInit();
|
||||
P_Init ();
|
||||
|
||||
P_SetupWeapons_ntohton();
|
||||
|
||||
//SBarInfo support.
|
||||
SBarInfo::Load();
|
||||
HUD_InitHud();
|
||||
|
||||
// [RH] User-configurable startup strings. Because BOOM does.
|
||||
static const char *startupString[5] = {
|
||||
"STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5"
|
||||
};
|
||||
for (p = 0; p < 5; ++p)
|
||||
{
|
||||
const char *str = GStrings[startupString[p]];
|
||||
if (str != NULL && str[0] != '\0')
|
||||
{
|
||||
Printf ("%s\n", str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
Printf ("D_CheckNetGame: Checking network game status.\n");
|
||||
StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
|
||||
D_CheckNetGame ();
|
||||
}
|
||||
|
||||
// [RH] Lock any cvars that should be locked now that we're
|
||||
// about to begin the game.
|
||||
FBaseCVar::EnableNoSet ();
|
||||
|
||||
delete iwad_man; // now we won't need this anymore
|
||||
|
||||
// [RH] Run any saved commands from the command line or autoexec.cfg now.
|
||||
gamestate = GS_FULLCONSOLE;
|
||||
Net_NewMakeTic ();
|
||||
DThinker::RunThinkers ();
|
||||
gamestate = GS_STARTUP;
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
// start the apropriate game based on parms
|
||||
v = Args->CheckValue ("-record");
|
||||
|
||||
if (v)
|
||||
{
|
||||
G_RecordDemo (v);
|
||||
autostart = true;
|
||||
}
|
||||
|
||||
delete StartScreen;
|
||||
StartScreen = NULL;
|
||||
|
||||
if (Args->CheckParm("-norun"))
|
||||
{
|
||||
throw CNoRunExit();
|
||||
}
|
||||
|
||||
V_Init2();
|
||||
|
||||
v = Args->CheckValue("-playdemo");
|
||||
if (v != NULL)
|
||||
{
|
||||
singledemo = true; // quit after one demo
|
||||
G_DeferedPlayDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
v = Args->CheckValue ("-timedemo");
|
||||
if (v)
|
||||
{
|
||||
G_TimeDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
v = Args->CheckValue ("-loadgame");
|
||||
if (v)
|
||||
{
|
||||
FString file(v);
|
||||
FixPathSeperator (file);
|
||||
DefaultExtension (file, ".zds");
|
||||
G_LoadGame (file);
|
||||
}
|
||||
|
||||
if (gameaction != ga_loadgame)
|
||||
{
|
||||
if (autostart || netgame)
|
||||
{
|
||||
// Do not do any screenwipes when autostarting a game.
|
||||
if (!Args->CheckParm("-warpwipe"))
|
||||
{
|
||||
NoWipe = TICRATE;
|
||||
}
|
||||
CheckWarpTransMap (startmap, true);
|
||||
if (demorecording)
|
||||
G_BeginRecording (startmap);
|
||||
G_InitNew (startmap, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_StartTitle (); // start up intro loop
|
||||
}
|
||||
}
|
||||
else if (demorecording)
|
||||
{
|
||||
G_BeginRecording (NULL);
|
||||
}
|
||||
|
||||
atterm (D_QuitNetGame); // killough
|
||||
}
|
||||
else
|
||||
{
|
||||
// let the renderer reinitialize some stuff if needed
|
||||
screen->GameRestart();
|
||||
// These calls from inside V_Init2 are still necessary
|
||||
C_NewModeAdjust();
|
||||
M_InitVideoModesMenu();
|
||||
D_StartTitle (); // start up intro loop
|
||||
setmodeneeded = false; // This may be set to true here, but isn't needed for a restart
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
catch (CRestartException &)
|
||||
{
|
||||
// Music and sound should be stopped first
|
||||
S_StopMusic(true);
|
||||
S_StopAllChannels ();
|
||||
|
||||
M_ClearMenus(); // close menu if open
|
||||
F_EndFinale(); // If an intermission is active, end it now
|
||||
|
||||
// clean up game state
|
||||
ST_Clear();
|
||||
D_ErrorCleanup ();
|
||||
P_FreeLevelData();
|
||||
P_FreeExtraLevelData();
|
||||
|
||||
M_SaveDefaults(NULL); // save config before the restart
|
||||
|
||||
// delete all data that cannot be left until reinitialization
|
||||
V_ClearFonts(); // must clear global font pointers
|
||||
R_DeinitTranslationTables(); // some tables are initialized from outside the translation code.
|
||||
gameinfo.~gameinfo_t();
|
||||
new (&gameinfo) gameinfo_t; // Reset gameinfo
|
||||
S_Shutdown(); // free all channels and delete playlist
|
||||
C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here
|
||||
|
||||
GC::FullGC(); // perform one final garbage collection before deleting the class data
|
||||
PClass::ClearRuntimeData(); // clear all runtime generated class data
|
||||
restart++;
|
||||
}
|
||||
}
|
||||
else if (demorecording)
|
||||
{
|
||||
G_BeginRecording (NULL);
|
||||
}
|
||||
|
||||
atterm (D_QuitNetGame); // killough
|
||||
while (1);
|
||||
}
|
||||
|
||||
D_DoomLoop (); // never returns
|
||||
//==========================================================================
|
||||
//
|
||||
// restart the game
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD(restart)
|
||||
{
|
||||
// remove command line args that would get in the way during restart
|
||||
Args->RemoveArgs("-iwad");
|
||||
Args->RemoveArgs("-deh");
|
||||
Args->RemoveArgs("-bex");
|
||||
Args->RemoveArgs("-playdemo");
|
||||
Args->RemoveArgs("-file");
|
||||
Args->RemoveArgs("-altdeath");
|
||||
Args->RemoveArgs("-deathmatch");
|
||||
Args->RemoveArgs("-skill");
|
||||
Args->RemoveArgs("-savedir");
|
||||
Args->RemoveArgs("-xlat");
|
||||
Args->RemoveArgs("-oldsprites");
|
||||
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
for(int i=1;i<argv.argc(); i++)
|
||||
{
|
||||
Args->AppendArg(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// initiate the restart
|
||||
throw CRestartException();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2368,6 +2443,14 @@ void FStartupScreen::AppendStatusLine(const char *status)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
void FStartupScreen::Progress(void) {}
|
||||
void FStartupScreen::NetInit(char const *,int) {}
|
||||
void FStartupScreen::NetProgress(int) {}
|
||||
void FStartupScreen::NetMessage(char const *,...) {}
|
||||
void FStartupScreen::NetDone(void) {}
|
||||
bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; }
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// STAT fps
|
||||
|
|
|
@ -36,6 +36,12 @@ struct event_t;
|
|||
// calls all startup code, parses command line options.
|
||||
// If not overrided by user input, calls N_AdvanceDemo.
|
||||
//
|
||||
|
||||
struct CRestartException
|
||||
{
|
||||
char dummy;
|
||||
};
|
||||
|
||||
void D_DoomMain (void);
|
||||
|
||||
|
||||
|
|
|
@ -835,11 +835,9 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info)
|
|||
{
|
||||
arc.Read (&info.netname, sizeof(info.netname));
|
||||
}
|
||||
arc << info.team << info.aimdist << info.color << info.skin << info.gender << info.neverswitch;
|
||||
if (SaveVersion >= 2193)
|
||||
{
|
||||
arc << info.colorset;
|
||||
}
|
||||
arc << info.team << info.aimdist << info.color
|
||||
<< info.skin << info.gender << info.neverswitch
|
||||
<< info.colorset;
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
|
|
@ -347,6 +347,16 @@ void FDecalLib::ReadAllDecals ()
|
|||
int lump, lastlump = 0;
|
||||
unsigned int i;
|
||||
|
||||
for(unsigned i=0;i<Animators.Size(); i++)
|
||||
{
|
||||
delete Animators[i];
|
||||
}
|
||||
Animators.Clear();
|
||||
FDecalCombinerAnim::AnimatorList.Clear();
|
||||
DecalTranslations.Clear();
|
||||
|
||||
DecalLibrary.Clear();
|
||||
|
||||
while ((lump = Wads.FindLump ("DECALDEF", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump);
|
||||
|
|
|
@ -540,11 +540,6 @@ void DObject::SerializeUserVars(FArchive &arc)
|
|||
DWORD count, j;
|
||||
int *varloc;
|
||||
|
||||
if (SaveVersion < 1933)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
symt = &GetClass()->Symbols;
|
||||
|
||||
if (arc.IsStoring())
|
||||
|
|
|
@ -80,6 +80,24 @@ void PClass::StaticInit ()
|
|||
}
|
||||
}
|
||||
|
||||
void PClass::ClearRuntimeData ()
|
||||
{
|
||||
StaticShutdown();
|
||||
|
||||
m_RuntimeActors.Clear();
|
||||
m_Types.Clear();
|
||||
memset(TypeHash, 0, sizeof(TypeHash));
|
||||
bShutdown = false;
|
||||
|
||||
// Immediately reinitialize the internal classes
|
||||
FAutoSegIterator probe(CRegHead, CRegTail);
|
||||
|
||||
while (*++probe != NULL)
|
||||
{
|
||||
((ClassReg *)*probe)->RegisterClass ();
|
||||
}
|
||||
}
|
||||
|
||||
void PClass::StaticShutdown ()
|
||||
{
|
||||
TArray<size_t *> uniqueFPs(64);
|
||||
|
@ -105,6 +123,8 @@ void PClass::StaticShutdown ()
|
|||
uniqueFPs.Push(const_cast<size_t *>(type->FlatPointers));
|
||||
}
|
||||
}
|
||||
type->FlatPointers = NULL;
|
||||
|
||||
// For runtime classes, this call will also delete the PClass.
|
||||
PClass::StaticFreeData (type);
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ struct PClass
|
|||
static void StaticInit ();
|
||||
static void StaticShutdown ();
|
||||
static void StaticFreeData (PClass *type);
|
||||
static void ClearRuntimeData();
|
||||
|
||||
// Per-class information -------------------------------------
|
||||
FName TypeName; // this class's name
|
||||
|
|
|
@ -341,6 +341,8 @@ enum
|
|||
BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow
|
||||
BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps
|
||||
BCOMPATF_VILEGHOSTS = 1 << 2, // Monsters' radius and height aren't restored properly when resurrected.
|
||||
BCOMPATF_BADTELEPORTERS = 1 << 3, // Ignore tags on Teleport specials
|
||||
BCOMPATF_BADPORTALS = 1 << 4, // Restores the old unstable portal behavior
|
||||
};
|
||||
|
||||
// phares 3/20/98:
|
||||
|
|
|
@ -291,7 +291,11 @@ template<> inline FArchive &operator<< <FFont> (FArchive &arc, FFont* &font)
|
|||
}
|
||||
|
||||
struct FStrifeDialogueNode;
|
||||
struct FSwitchDef;
|
||||
struct FDoorAnimation;
|
||||
template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node);
|
||||
template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &sw);
|
||||
template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &da);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -180,8 +180,6 @@ wbstartstruct_t wminfo; // parms for world map / intermission
|
|||
|
||||
short consistancy[MAXPLAYERS][BACKUPTICS];
|
||||
|
||||
BYTE* savebuffer;
|
||||
|
||||
|
||||
#define MAXPLMOVE (forwardmove[1])
|
||||
|
||||
|
@ -240,9 +238,9 @@ CUSTOM_CVAR (Float, turbo, 100.f, 0)
|
|||
{
|
||||
self = 10.f;
|
||||
}
|
||||
else if (self > 256.f)
|
||||
else if (self > 255.f)
|
||||
{
|
||||
self = 256.f;
|
||||
self = 255.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1906,6 +1904,7 @@ FString G_BuildSaveName (const char *prefix, int slot)
|
|||
}
|
||||
|
||||
CVAR (Int, autosavenum, 0, CVAR_NOSET|CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
static int nextautosave = -1;
|
||||
CVAR (Int, disableautosave, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CUSTOM_CVAR (Int, autosavecount, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
|
@ -1926,10 +1925,25 @@ void G_DoAutoSave ()
|
|||
const char *readableTime;
|
||||
int count = autosavecount != 0 ? autosavecount : 1;
|
||||
|
||||
num.Int = (autosavenum + 1) % count;
|
||||
if (nextautosave == -1)
|
||||
{
|
||||
nextautosave = (autosavenum + 1) % count;
|
||||
}
|
||||
|
||||
num.Int = nextautosave;
|
||||
autosavenum.ForceSet (num, CVAR_Int);
|
||||
|
||||
file = G_BuildSaveName ("auto", num.Int);
|
||||
file = G_BuildSaveName ("auto", nextautosave);
|
||||
|
||||
if (!(level.flags2 & LEVEL2_NOAUTOSAVEHINT))
|
||||
{
|
||||
nextautosave = (nextautosave + 1) % count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This flag can only be used once per level
|
||||
level.flags2 &= ~LEVEL2_NOAUTOSAVEHINT;
|
||||
}
|
||||
|
||||
readableTime = myasctime ();
|
||||
strcpy (description, "Autosave ");
|
||||
|
@ -2575,6 +2589,7 @@ bool G_CheckDemoStatus (void)
|
|||
|
||||
C_RestoreCVars (); // [RH] Restore cvars demo might have changed
|
||||
M_Free (demobuffer);
|
||||
demobuffer = NULL;
|
||||
|
||||
P_SetupWeapons_ntohton();
|
||||
demoplayback = false;
|
||||
|
|
|
@ -85,6 +85,8 @@ void G_AddViewAngle (int yaw);
|
|||
class AActor;
|
||||
extern AActor *bodyque[BODYQUESIZE];
|
||||
extern int bodyqueslot;
|
||||
class AInventory;
|
||||
extern const AInventory *SendItemUse, *SendItemDrop;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -462,8 +462,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check)
|
|||
self->velx = FixedMul(7*FRACUNIT, finecosine[angle]);
|
||||
self->vely = FixedMul(7*FRACUNIT, finesine[angle]);
|
||||
#else
|
||||
double velscale = sqrtf ((float)self->velx * (float)self->velx +
|
||||
(float)self->vely * (float)self->vely);
|
||||
double velscale = sqrt ((double)self->velx * (double)self->velx +
|
||||
(double)self->vely * (double)self->vely);
|
||||
velscale = 458752 / velscale;
|
||||
self->velx = (int)(self->velx * velscale);
|
||||
self->vely = (int)(self->vely * velscale);
|
||||
|
@ -1045,6 +1045,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm)
|
|||
x = self->x + ((pr_storm()&127) - 64) * FRACUNIT;
|
||||
y = self->y + ((pr_storm()&127) - 64) * FRACUNIT;
|
||||
mo = Spawn<ARainPillar> (x, y, ONCEILINGZ, ALLOW_REPLACE);
|
||||
#ifdef _3DFLOORS
|
||||
// We used bouncecount to store the 3D floor index in A_HideInCeiling
|
||||
if (!mo) return;
|
||||
fixed_t newz;
|
||||
if (self->bouncecount >= 0
|
||||
&& (unsigned)self->bouncecount < self->Sector->e->XFloor.ffloors.Size())
|
||||
newz = self->Sector->e->XFloor.ffloors[self->bouncecount]->bottom.plane->ZatPoint(x, y);// - 40 * FRACUNIT;
|
||||
else
|
||||
newz = self->Sector->ceilingplane.ZatPoint(x, y);
|
||||
int moceiling = P_Find3DFloor(NULL, x, y, newz, false, false, newz);
|
||||
if (moceiling >= 0)
|
||||
mo->z = newz - mo->height;
|
||||
#endif
|
||||
mo->Translation = multiplayer ?
|
||||
TRANSLATION(TRANSLATION_PlayersExtra,self->special2) : 0;
|
||||
mo->target = self->target;
|
||||
|
@ -1084,6 +1097,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_RainImpact)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_HideInCeiling)
|
||||
{
|
||||
#ifdef _3DFLOORS
|
||||
// We use bouncecount to store the 3D floor index
|
||||
fixed_t foo;
|
||||
for (unsigned int i=0; i< self->Sector->e->XFloor.ffloors.Size(); i++)
|
||||
{
|
||||
F3DFloor * rover = self->Sector->e->XFloor.ffloors[i];
|
||||
if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
if ((foo = rover->bottom.plane->ZatPoint(self->x, self->y)) >= (self->z + self->height))
|
||||
{
|
||||
self->z = foo + 4*FRACUNIT;
|
||||
self->bouncecount = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
self->bouncecount = -1;
|
||||
#endif
|
||||
self->z = self->ceilingz + 4*FRACUNIT;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ struct FHubInfo
|
|||
};
|
||||
|
||||
|
||||
TArray<FHubInfo> hubdata;
|
||||
static TArray<FHubInfo> hubdata;
|
||||
|
||||
void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
|
||||
{
|
||||
|
@ -182,3 +182,8 @@ void G_ReadHubInfo (PNGHandle *png)
|
|||
G_SerializeHub(arc);
|
||||
}
|
||||
}
|
||||
|
||||
void G_ClearHubInfo()
|
||||
{
|
||||
hubdata.Clear();
|
||||
}
|
|
@ -119,7 +119,6 @@ bool savegamerestore;
|
|||
|
||||
extern int mousex, mousey;
|
||||
extern bool sendpause, sendsave, sendturn180, SendLand;
|
||||
extern const AInventory *SendItemUse, *SendItemDrop;
|
||||
|
||||
void *statcopy; // for statistics driver
|
||||
|
||||
|
@ -309,6 +308,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
|
|||
bool wantFast;
|
||||
int i;
|
||||
|
||||
G_ClearHubInfo();
|
||||
if (!savegamerestore)
|
||||
{
|
||||
G_ClearSnapshots ();
|
||||
|
@ -742,12 +742,7 @@ void G_DoCompleted (void)
|
|||
{ // Reset world variables for the new hub.
|
||||
P_ClearACSVars(false);
|
||||
}
|
||||
// With hub statistics the time should be per hub.
|
||||
// Additionally there is a global time counter now so nothing is missed by changing it
|
||||
//else if (mode == FINISH_NoHub)
|
||||
{ // Reset time to zero if not entering/staying in a hub.
|
||||
level.time = 0;
|
||||
}
|
||||
level.time = 0;
|
||||
level.maptime = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,7 @@ enum ELevelFlags
|
|||
|
||||
LEVEL2_NOSTATISTICS = 0x10000000, // This level should not have statistics collected
|
||||
LEVEL2_ENDGAME = 0x20000000, // This is an epilogue level that cannot be quit.
|
||||
LEVEL2_NOAUTOSAVEHINT = 0x40000000, // tell the game that an autosave for this level does not need to be kept
|
||||
};
|
||||
|
||||
|
||||
|
@ -514,6 +515,7 @@ void G_UnSnapshotLevel (bool keepPlayers);
|
|||
struct PNGHandle;
|
||||
void G_ReadSnapshots (PNGHandle *png);
|
||||
void G_WriteSnapshots (FILE *file);
|
||||
void G_ClearHubInfo();
|
||||
|
||||
enum ESkillProperty
|
||||
{
|
||||
|
|
|
@ -1238,6 +1238,7 @@ MapFlagHandlers[] =
|
|||
{ "resethealth", MITYPE_SETFLAG2, LEVEL2_RESETHEALTH, 0 },
|
||||
{ "endofgame", MITYPE_SETFLAG2, LEVEL2_ENDGAME, 0 },
|
||||
{ "nostatistics", MITYPE_SETFLAG2, LEVEL2_NOSTATISTICS, 0 },
|
||||
{ "noautosavehint", MITYPE_SETFLAG2, LEVEL2_NOAUTOSAVEHINT, 0 },
|
||||
{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2, LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
|
||||
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
|
||||
{ "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX},
|
||||
|
@ -1626,7 +1627,13 @@ void FMapInfoParser::ParseEpisodeInfo ()
|
|||
}
|
||||
else
|
||||
{
|
||||
FEpisode *epi = &AllEpisodes[AllEpisodes.Reserve(1)];
|
||||
// Only allocate a new entry if this doesn't replace an existing episode.
|
||||
if (i >= AllEpisodes.Size())
|
||||
{
|
||||
i = AllEpisodes.Reserve(1);
|
||||
}
|
||||
|
||||
FEpisode *epi = &AllEpisodes[i];
|
||||
|
||||
epi->mEpisodeMap = map;
|
||||
epi->mEpisodeName = name;
|
||||
|
@ -1787,6 +1794,25 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DeinitIntermissions();
|
||||
|
||||
static void ClearMapinfo()
|
||||
{
|
||||
wadclusterinfos.Clear();
|
||||
wadlevelinfos.Clear();
|
||||
ClearEpisodes();
|
||||
AllSkills.Clear();
|
||||
DefaultSkill = -1;
|
||||
DeinitIntermissions();
|
||||
level.info = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// G_ParseMapInfo
|
||||
|
@ -1800,7 +1826,8 @@ void G_ParseMapInfo (const char *basemapinfo)
|
|||
int lump, lastlump = 0;
|
||||
level_info_t gamedefaults;
|
||||
|
||||
atterm(ClearEpisodes);
|
||||
ClearMapinfo();
|
||||
atterm(ClearMapinfo);
|
||||
|
||||
// Parse the default MAPINFO for the current game. This lump *MUST* come from zdoom.pk3.
|
||||
if (basemapinfo != NULL)
|
||||
|
|
|
@ -36,8 +36,6 @@ static FRandom pr_torch ("Torch");
|
|||
#define TIMEFREEZE_TICS ( 12 * TICRATE )
|
||||
*/
|
||||
|
||||
EXTERN_CVAR (Bool, r_drawfuzz);
|
||||
|
||||
IMPLEMENT_CLASS (APowerup)
|
||||
|
||||
// Powerup-Giver -------------------------------------------------------------
|
||||
|
|
|
@ -143,12 +143,21 @@ void AAimingCamera::PostBeginPlay ()
|
|||
tracer = iterator.Next ();
|
||||
if (tracer == NULL)
|
||||
{
|
||||
Printf ("AimingCamera %d: Can't find thing %d\n", tid, args[3]);
|
||||
//Printf ("AimingCamera %d: Can't find TID %d\n", tid, args[3]);
|
||||
}
|
||||
else
|
||||
{ // Don't try for a new target upon losing this one.
|
||||
args[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AAimingCamera::Tick ()
|
||||
{
|
||||
if (tracer == NULL && args[3] != 0)
|
||||
{ // Recheck, in case something with this TID was created since the last time.
|
||||
TActorIterator<AActor> iterator (args[3]);
|
||||
tracer = iterator.Next ();
|
||||
}
|
||||
if (tracer != NULL)
|
||||
{
|
||||
angle_t delta;
|
||||
|
|
|
@ -414,7 +414,7 @@ static void GetWallStuff (side_t *wall, vertex_t *&v1, fixed_t &ldx, fixed_t &ld
|
|||
|
||||
static fixed_t Length (fixed_t dx, fixed_t dy)
|
||||
{
|
||||
return (fixed_t)sqrtf ((float)dx*(float)dx+(float)dy*(float)dy);
|
||||
return (fixed_t)sqrt ((double)dx*(double)dx+(double)dy*(double)dy);
|
||||
}
|
||||
|
||||
static side_t *NextWall (const side_t *wall)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "a_specialspot.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "g_level.h"
|
||||
#include "g_game.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
static FRandom pr_restore ("RestorePos");
|
||||
|
@ -183,6 +184,7 @@ bool P_GiveBody (AActor *actor, int num)
|
|||
int max;
|
||||
player_t *player = actor->player;
|
||||
|
||||
num = clamp(num, -65536, 65536); // prevent overflows for bad values
|
||||
if (player != NULL)
|
||||
{
|
||||
max = static_cast<APlayerPawn*>(actor)->GetMaxHealth() + player->stamina;
|
||||
|
@ -627,7 +629,7 @@ AInventory *AInventory::CreateTossable ()
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
if ((ItemFlags & IF_UNDROPPABLE) || Owner == NULL || Amount <= 0)
|
||||
if ((ItemFlags & (IF_UNDROPPABLE|IF_UNTOSSABLE)) || Owner == NULL || Amount <= 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1033,6 +1035,10 @@ void AInventory::Destroy ()
|
|||
}
|
||||
Inventory = NULL;
|
||||
Super::Destroy ();
|
||||
|
||||
// Although contrived it can theoretically happen that these variables still got a pointer to this item
|
||||
if (SendItemUse == this) SendItemUse = NULL;
|
||||
if (SendItemDrop == this) SendItemDrop = NULL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -116,10 +116,10 @@ enum
|
|||
IF_PICKUPGOOD = 1<<2, // HandlePickup wants normal pickup FX to happen
|
||||
IF_QUIET = 1<<3, // Don't give feedback when picking up
|
||||
IF_AUTOACTIVATE = 1<<4, // Automatically activate item on pickup
|
||||
IF_UNDROPPABLE = 1<<5, // The player cannot manually drop the item
|
||||
IF_UNDROPPABLE = 1<<5, // Item cannot be removed unless done explicitly with RemoveInventory
|
||||
IF_INVBAR = 1<<6, // Item appears in the inventory bar
|
||||
IF_HUBPOWER = 1<<7, // Powerup is kept when moving in a hub
|
||||
// IF_INTERHUBSTRIP = 1<<8, // Item is removed when travelling between hubs
|
||||
IF_UNTOSSABLE = 1<<8, // The player cannot manually drop the item
|
||||
IF_ADDITIVETIME = 1<<9, // when picked up while another item is active, time is added instead of replaced.
|
||||
IF_ALWAYSPICKUP = 1<<10, // For IF_AUTOACTIVATE, MaxAmount=0 items: Always "pick up", even if it doesn't do anything
|
||||
IF_FANCYPICKUPSOUND = 1<<11, // Play pickup sound in "surround" mode
|
||||
|
|
|
@ -55,16 +55,8 @@ void DEarthquake::Serialize (FArchive &arc)
|
|||
{
|
||||
Super::Serialize (arc);
|
||||
arc << m_Spot << m_Intensity << m_Countdown
|
||||
<< m_TremorRadius << m_DamageRadius;
|
||||
|
||||
if (SaveVersion >= 1912)
|
||||
{
|
||||
arc << m_QuakeSFX;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_QuakeSFX = "world/quake";
|
||||
}
|
||||
<< m_TremorRadius << m_DamageRadius
|
||||
<< m_QuakeSFX;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -97,7 +97,6 @@ public:
|
|||
bool bInSkybox;
|
||||
bool bAlways;
|
||||
TObjPtr<ASkyViewpoint> Mate;
|
||||
fixed_t PlaneAlpha;
|
||||
};
|
||||
|
||||
class AStackPoint : public ASkyViewpoint
|
||||
|
|
|
@ -69,7 +69,7 @@ void ASkyViewpoint::BeginPlay ()
|
|||
void ASkyViewpoint::Serialize (FArchive &arc)
|
||||
{
|
||||
Super::Serialize (arc);
|
||||
arc << bInSkybox << bAlways << Mate << PlaneAlpha;
|
||||
arc << bInSkybox << bAlways << Mate;
|
||||
}
|
||||
|
||||
void ASkyViewpoint::Destroy ()
|
||||
|
|
|
@ -381,7 +381,9 @@ DBaseStatusBar *CreateCustomStatusBar(int script=0);
|
|||
|
||||
// Crosshair stuff ----------------------------------------------------------
|
||||
|
||||
void ST_FormatMapName(FString &mapname, const char *mapnamecolor = "");
|
||||
void ST_LoadCrosshair(bool alwaysload=false);
|
||||
void ST_Clear();
|
||||
extern FTexture *CrosshairImage;
|
||||
|
||||
#endif /* __SBAR_H__ */
|
||||
|
|
|
@ -335,6 +335,7 @@ bool FMugShot::SetState(const char *state_name, bool wait_till_done, bool reset)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
CVAR(Bool,st_oldouch,false,CVAR_ARCHIVE)
|
||||
int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
|
||||
{
|
||||
int i;
|
||||
|
@ -357,9 +358,10 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
|
|||
}
|
||||
}
|
||||
|
||||
bool ouch = (!st_oldouch && FaceHealth - player->health > ST_MUCHPAIN) || (st_oldouch && player->health - FaceHealth > ST_MUCHPAIN);
|
||||
if (player->damagecount &&
|
||||
// Now go in if pain is disabled but we think ouch will be shown (and ouch is not disabled!)
|
||||
(!(stateflags & DISABLEPAIN) || (((FaceHealth != -1 && FaceHealth - player->health > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DISABLEOUCH))))
|
||||
(!(stateflags & DISABLEPAIN) || (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH))))
|
||||
{
|
||||
int damage_angle = 1;
|
||||
if (player->attacker && player->attacker != player->mo)
|
||||
|
@ -391,7 +393,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
|
|||
}
|
||||
}
|
||||
bool use_ouch = false;
|
||||
if (((FaceHealth != -1 && FaceHealth - player->health > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DISABLEOUCH))
|
||||
if (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH))
|
||||
{
|
||||
use_ouch = true;
|
||||
full_state_name = "ouch.";
|
||||
|
@ -418,7 +420,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
|
|||
else
|
||||
{
|
||||
bool use_ouch = false;
|
||||
if (((FaceHealth != -1 && player->health - FaceHealth > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DISABLEOUCH))
|
||||
if (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH))
|
||||
{
|
||||
use_ouch = true;
|
||||
full_state_name = "ouch.";
|
||||
|
|
|
@ -423,6 +423,8 @@ static void FreeSBarInfoScript()
|
|||
|
||||
void SBarInfo::Load()
|
||||
{
|
||||
FreeSBarInfoScript();
|
||||
MugShotStates.Clear();
|
||||
if(gameinfo.statusbar.IsNotEmpty())
|
||||
{
|
||||
int lump = Wads.CheckNumForFullName(gameinfo.statusbar, true);
|
||||
|
@ -1153,8 +1155,8 @@ public:
|
|||
|
||||
if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER)
|
||||
{
|
||||
dx -= (texture->GetScaledWidthDouble()/2.0)-texture->LeftOffset;
|
||||
dy -= (texture->GetScaledHeightDouble()/2.0)-texture->TopOffset;
|
||||
dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble();
|
||||
dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble();
|
||||
}
|
||||
|
||||
dx += xOffset;
|
||||
|
@ -1188,7 +1190,7 @@ public:
|
|||
}
|
||||
|
||||
if(clearDontDraw)
|
||||
screen->Clear(static_cast<int>(MAX<double>(dx, dcx)), static_cast<int>(MAX<double>(dy, dcy)), static_cast<int>(dcr), static_cast<int>(dcb), GPalette.BlackIndex, 0);
|
||||
screen->Clear(static_cast<int>(MAX<double>(dx, dcx)), static_cast<int>(MAX<double>(dy, dcy)), static_cast<int>(MIN<double>(dcr,w+MAX<double>(dx, dcx))), static_cast<int>(MIN<double>(dcb,MAX<double>(dy, dcy)+h)), GPalette.BlackIndex, 0);
|
||||
else
|
||||
{
|
||||
if(alphaMap)
|
||||
|
|
|
@ -2660,6 +2660,58 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CommandPlayerType : public SBarInfoCommandFlowControl
|
||||
{
|
||||
public:
|
||||
CommandPlayerType(SBarInfo *script) : SBarInfoCommandFlowControl(script)
|
||||
{
|
||||
}
|
||||
|
||||
void Parse(FScanner &sc, bool fullScreenOffsets)
|
||||
{
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
do
|
||||
{
|
||||
bool foundClass = false;
|
||||
const PClass *cls = PClass::FindClass(sc.String);
|
||||
if (cls != NULL)
|
||||
{
|
||||
foundClass = true;
|
||||
classes.Push(cls);
|
||||
}
|
||||
/*
|
||||
if(!foundClass)
|
||||
sc.ScriptError("Unkown PlayerClass '%s'.", sc.String);
|
||||
*/
|
||||
if(!sc.CheckToken(','))
|
||||
break;
|
||||
}
|
||||
while(sc.CheckToken(TK_Identifier));
|
||||
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
|
||||
}
|
||||
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
|
||||
{
|
||||
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged);
|
||||
|
||||
if(statusBar->CPlayer->cls == NULL)
|
||||
return; //No class so we can not continue
|
||||
|
||||
for(unsigned int i = 0;i < classes.Size();i++)
|
||||
{
|
||||
if (statusBar->CPlayer->cls->IsDescendantOf(classes[i]))
|
||||
{
|
||||
SetTruth(true, block, statusBar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SetTruth(false, block, statusBar);
|
||||
}
|
||||
protected:
|
||||
TArray<const PClass *> classes;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CommandHasWeaponPiece : public SBarInfoCommandFlowControl
|
||||
{
|
||||
public:
|
||||
|
@ -2730,7 +2782,7 @@ class CommandDrawGem : public SBarInfoCommand
|
|||
SBarInfoCoordinate drawY = y;
|
||||
if(wiggle && drawValue != goalValue) // Should only wiggle when the value doesn't equal what is being drawn.
|
||||
drawY += chainWiggle;
|
||||
int chainWidth = chainImg->GetWidth();
|
||||
int chainWidth = chainImg->GetScaledWidth();
|
||||
int offset = (int) (((double) (chainWidth-leftPadding-rightPadding)/100)*drawValue);
|
||||
statusBar->DrawGraphic(chainImg, x+(offset%chainSize), drawY, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets());
|
||||
if(gemImg != NULL)
|
||||
|
@ -3082,7 +3134,7 @@ static const char *SBarInfoCommandNames[] =
|
|||
"drawmugshot", "drawselectedinventory",
|
||||
"drawinventorybar", "drawbar", "drawgem",
|
||||
"drawshader", "drawstring", "drawkeybar",
|
||||
"gamemode", "playerclass", "aspectratio",
|
||||
"gamemode", "playerclass", "playertype", "aspectratio",
|
||||
"isselected", "usesammo", "usessecondaryammo",
|
||||
"hasweaponpiece", "inventorybarnotvisible",
|
||||
"weaponammo", "ininventory", "alpha",
|
||||
|
@ -3095,7 +3147,7 @@ enum SBarInfoCommands
|
|||
SBARINFO_DRAWMUGSHOT, SBARINFO_DRAWSELECTEDINVENTORY,
|
||||
SBARINFO_DRAWINVENTORYBAR, SBARINFO_DRAWBAR, SBARINFO_DRAWGEM,
|
||||
SBARINFO_DRAWSHADER, SBARINFO_DRAWSTRING, SBARINFO_DRAWKEYBAR,
|
||||
SBARINFO_GAMEMODE, SBARINFO_PLAYERCLASS, SBARINFO_ASPECTRATIO,
|
||||
SBARINFO_GAMEMODE, SBARINFO_PLAYERCLASS, SBARINFO_PLAYERTYPE, SBARINFO_ASPECTRATIO,
|
||||
SBARINFO_ISSELECTED, SBARINFO_USESAMMO, SBARINFO_USESSECONDARYAMMO,
|
||||
SBARINFO_HASWEAPONPIECE, SBARINFO_INVENTORYBARNOTVISIBLE,
|
||||
SBARINFO_WEAPONAMMO, SBARINFO_ININVENTORY, SBARINFO_ALPHA,
|
||||
|
@ -3126,6 +3178,7 @@ SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc)
|
|||
case SBARINFO_ASPECTRATIO: return new CommandAspectRatio(script);
|
||||
case SBARINFO_ISSELECTED: return new CommandIsSelected(script);
|
||||
case SBARINFO_PLAYERCLASS: return new CommandPlayerClass(script);
|
||||
case SBARINFO_PLAYERTYPE: return new CommandPlayerType(script);
|
||||
case SBARINFO_HASWEAPONPIECE: return new CommandHasWeaponPiece(script);
|
||||
case SBARINFO_WEAPONAMMO: return new CommandWeaponAmmo(script);
|
||||
case SBARINFO_ININVENTORY: return new CommandInInventory(script);
|
||||
|
|
|
@ -124,16 +124,16 @@ void SetHUDIcon(PClass *cls, FTextureID tex)
|
|||
//---------------------------------------------------------------------------
|
||||
static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans=0xc000)
|
||||
{
|
||||
float scale1, scale2;
|
||||
double scale1, scale2;
|
||||
|
||||
if (tex)
|
||||
{
|
||||
int texwidth=tex->GetWidth();
|
||||
int texheight=tex->GetHeight();
|
||||
|
||||
if (w<texwidth) scale1=(float)w/texwidth;
|
||||
if (w<texwidth) scale1=(double)w/texwidth;
|
||||
else scale1=1.0f;
|
||||
if (h<texheight) scale2=(float)h/texheight;
|
||||
if (h<texheight) scale2=(double)h/texheight;
|
||||
else scale2=1.0f;
|
||||
if (scale2<scale1) scale1=scale2;
|
||||
|
||||
|
@ -170,11 +170,14 @@ static void DrawHudText(FFont *font, int color, char * text, int x, int y, int t
|
|||
FTexture *texc = font->GetChar(text[i], &width);
|
||||
if (texc != NULL)
|
||||
{
|
||||
int offset = texc->TopOffset - tex_zero->TopOffset + tex_zero->GetHeight();
|
||||
double offset = texc->GetScaledTopOffsetDouble()
|
||||
- tex_zero->GetScaledTopOffsetDouble()
|
||||
+ tex_zero->GetScaledHeightDouble();
|
||||
|
||||
screen->DrawChar(font, color, x, y, text[i],
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans,
|
||||
DTA_LeftOffset, width/2, DTA_TopOffset, offset,
|
||||
DTA_LeftOffset, width/2, DTA_TopOffsetF, offset,
|
||||
/*DTA_CenterBottomOffset, 1,*/ TAG_DONE);
|
||||
}
|
||||
x += zerowidth;
|
||||
|
@ -280,16 +283,42 @@ static void DrawHealth(int health, int x, int y)
|
|||
//===========================================================================
|
||||
//
|
||||
// Draw Armor.
|
||||
// very similar to drawhealth.
|
||||
// very similar to drawhealth, but adapted to handle Hexen armor too
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static void DrawArmor(AInventory * armor, int x, int y)
|
||||
static void DrawArmor(ABasicArmor * barmor, AHexenArmor * harmor, int x, int y)
|
||||
{
|
||||
if (armor)
|
||||
{
|
||||
int ap=armor->Amount;
|
||||
int ap = 0;
|
||||
int bestslot = 4;
|
||||
|
||||
if (harmor)
|
||||
{
|
||||
int ac = (harmor->Slots[0] + harmor->Slots[1] + harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]);
|
||||
ac >>= FRACBITS;
|
||||
ap += ac;
|
||||
|
||||
if (ac)
|
||||
{
|
||||
// Find the part of armor that protects the most
|
||||
bestslot = 0;
|
||||
for (int i = 1; i < 4; ++i)
|
||||
{
|
||||
if (harmor->Slots[i] > harmor->Slots[bestslot])
|
||||
{
|
||||
bestslot = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (barmor)
|
||||
{
|
||||
ap += barmor->Amount;
|
||||
}
|
||||
|
||||
if (ap)
|
||||
{
|
||||
// decide on color
|
||||
int fontcolor =
|
||||
ap < hud_armor_red ? CR_RED :
|
||||
|
@ -298,11 +327,23 @@ static void DrawArmor(AInventory * armor, int x, int y)
|
|||
CR_BLUE;
|
||||
|
||||
|
||||
if (ap)
|
||||
// Use the sprite of one of the predefined Hexen armor bonuses.
|
||||
// This is not a very generic approach, but it is not possible
|
||||
// to truly create new types of Hexen armor bonus items anyway.
|
||||
if (harmor && bestslot < 4)
|
||||
{
|
||||
DrawImageToBox(TexMan[armor->Icon], x, y, 31, 17);
|
||||
DrawHudNumber(HudFont, fontcolor, ap, x + 33, y + 17);
|
||||
char icon[] = "AR_1A0";
|
||||
switch (bestslot)
|
||||
{
|
||||
case 1: icon[3] = '2'; break;
|
||||
case 2: icon[3] = '3'; break;
|
||||
case 3: icon[3] = '4'; break;
|
||||
default: break;
|
||||
}
|
||||
DrawImageToBox(TexMan.FindTexture(icon, FTexture::TEX_Sprite), x, y, 31, 17);
|
||||
}
|
||||
else if (barmor) DrawImageToBox(TexMan[barmor->Icon], x, y, 31, 17);
|
||||
DrawHudNumber(HudFont, fontcolor, ap, x + 33, y + 17);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -766,14 +807,11 @@ static void DrawCoordinates(player_t * CPlayer)
|
|||
// draw the overlay
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void HUD_InitHud();
|
||||
|
||||
void DrawHUD()
|
||||
{
|
||||
player_t * CPlayer = StatusBar->CPlayer;
|
||||
|
||||
if (HudFont==NULL) HUD_InitHud();
|
||||
|
||||
players[consoleplayer].inventorytics = 0;
|
||||
if (hud_althudscale && SCREENWIDTH>640)
|
||||
{
|
||||
|
@ -815,9 +853,8 @@ void DrawHUD()
|
|||
DrawFrags(CPlayer, 5, hudheight-70);
|
||||
}
|
||||
DrawHealth(CPlayer->health, 5, hudheight-45);
|
||||
// Yes, that doesn't work properly for Hexen but frankly, I have no
|
||||
// idea how to make a meaningful value out of Hexen's armor system!
|
||||
DrawArmor(CPlayer->mo->FindInventory(RUNTIME_CLASS(ABasicArmor)), 5, hudheight-20);
|
||||
DrawArmor(CPlayer->mo->FindInventory<ABasicArmor>(),
|
||||
CPlayer->mo->FindInventory<AHexenArmor>(), 5, hudheight-20);
|
||||
i=DrawKeys(CPlayer, hudwidth-4, hudheight-10);
|
||||
i=DrawAmmo(CPlayer, hudwidth-5, i);
|
||||
DrawWeapons(CPlayer, hudwidth-5, i);
|
||||
|
@ -830,10 +867,9 @@ void DrawHUD()
|
|||
}
|
||||
else
|
||||
{
|
||||
FString mapname;
|
||||
char printstr[256];
|
||||
int seconds;
|
||||
cluster_info_t *thiscluster = FindClusterInfo (level.cluster);
|
||||
bool hub = !!(thiscluster->flags&CLUSTER_HUB);
|
||||
int length=8*SmallFont->GetCharWidth('0');
|
||||
int fonth=SmallFont->GetHeight()+1;
|
||||
int bottom=hudheight-1;
|
||||
|
@ -862,8 +898,8 @@ void DrawHUD()
|
|||
}
|
||||
}
|
||||
|
||||
mysnprintf(printstr, countof(printstr), "%s: %s", level.mapname, level.LevelName.GetChars());
|
||||
screen->DrawText(SmallFont, hudcolor_titl, 1, hudheight-fonth-1, printstr,
|
||||
ST_FormatMapName(mapname);
|
||||
screen->DrawText(SmallFont, hudcolor_titl, 1, hudheight-fonth-1, mapname,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE);
|
||||
|
||||
|
|
|
@ -95,12 +95,16 @@ CUSTOM_CVAR (Bool, st_scale, true, CVAR_ARCHIVE)
|
|||
}
|
||||
}
|
||||
|
||||
CVAR (Int, crosshair, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, crosshairforce, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
CVAR (Bool, crosshairhealth, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
CVAR (Bool, crosshairscale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
CVAR (Bool, crosshairgrow, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
CVAR (Int, crosshair, 0, CVAR_ARCHIVE)
|
||||
CVAR (Bool, crosshairforce, false, CVAR_ARCHIVE)
|
||||
CVAR (Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE);
|
||||
CVAR (Bool, crosshairhealth, true, CVAR_ARCHIVE);
|
||||
CVAR (Bool, crosshairscale, false, CVAR_ARCHIVE);
|
||||
CVAR (Bool, crosshairgrow, false, CVAR_ARCHIVE);
|
||||
CUSTOM_CVAR(Int, am_showmaplabel, 2, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0 || self > 2) self = 2;
|
||||
}
|
||||
|
||||
CVAR (Bool, idmypos, false, 0);
|
||||
|
||||
|
@ -118,6 +122,30 @@ BYTE DBaseStatusBar::DamageToAlpha[114] =
|
|||
230, 231, 232, 233, 234, 235, 235, 236, 237
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Format the map name, include the map label if wanted
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void ST_FormatMapName(FString &mapname, const char *mapnamecolor)
|
||||
{
|
||||
cluster_info_t *cluster = FindClusterInfo (level.cluster);
|
||||
bool ishub = (cluster != NULL && (cluster->flags & CLUSTER_HUB));
|
||||
|
||||
if (am_showmaplabel == 1 || (am_showmaplabel == 2 && !ishub))
|
||||
{
|
||||
mapname << level.mapname << ": ";
|
||||
}
|
||||
mapname << mapnamecolor << level.LevelName;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Load crosshair definitions
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void ST_LoadCrosshair(bool alwaysload)
|
||||
{
|
||||
int num = 0;
|
||||
|
@ -169,6 +197,23 @@ void ST_LoadCrosshair(bool alwaysload)
|
|||
CrosshairImage = TexMan[TexMan.CheckForTexture(name, FTexture::TEX_MiscPatch)];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ST_Clear
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void ST_Clear()
|
||||
{
|
||||
if (StatusBar != NULL)
|
||||
{
|
||||
StatusBar->Destroy();
|
||||
StatusBar = NULL;
|
||||
}
|
||||
CrosshairImage = NULL;
|
||||
CrosshairNum = 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Constructor
|
||||
|
@ -208,6 +253,7 @@ void DBaseStatusBar::Destroy ()
|
|||
msg->Destroy();
|
||||
msg = next;
|
||||
}
|
||||
Messages = NULL;
|
||||
Super::Destroy();
|
||||
}
|
||||
|
||||
|
@ -1270,18 +1316,9 @@ void DBaseStatusBar::Draw (EHudState state)
|
|||
y -= 8;
|
||||
}
|
||||
}
|
||||
cluster_info_t *cluster = FindClusterInfo (level.cluster);
|
||||
if (cluster == NULL || !(cluster->flags & CLUSTER_HUB))
|
||||
{
|
||||
mysnprintf (line, countof(line), "%s: ", level.mapname);
|
||||
}
|
||||
else
|
||||
{
|
||||
*line = 0;
|
||||
}
|
||||
FString mapname;
|
||||
|
||||
mapname.Format("%s%c%c%s", line, TEXTCOLOR_ESCAPE, CR_GREY + 'A', level.LevelName.GetChars());
|
||||
ST_FormatMapName(mapname, TEXTCOLOR_GREY);
|
||||
screen->DrawText (SmallFont, highlight,
|
||||
(SCREENWIDTH - SmallFont->StringWidth (mapname)*CleanXfac)/2, y, mapname,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
|
42
src/gi.cpp
42
src/gi.cpp
|
@ -77,7 +77,7 @@ static gameborder_t StrifeBorder =
|
|||
|
||||
// Custom GAMEINFO ------------------------------------------------------------
|
||||
|
||||
const char* GameInfoBoarders[] =
|
||||
const char* GameInfoBorders[] =
|
||||
{
|
||||
"DoomBorder",
|
||||
"HereticBorder",
|
||||
|
@ -163,6 +163,28 @@ const char* GameInfoBoarders[] =
|
|||
} \
|
||||
}
|
||||
|
||||
#define GAMEINFOKEY_FONT(key, variable) \
|
||||
else if(nextKey.CompareNoCase(variable) == 0) \
|
||||
{ \
|
||||
sc.MustGetToken(TK_StringConst); \
|
||||
gameinfo.key.fontname = sc.String; \
|
||||
if (sc.CheckToken(',')) { \
|
||||
sc.MustGetToken(TK_StringConst); \
|
||||
gameinfo.key.color = sc.String; \
|
||||
} else { \
|
||||
gameinfo.key.color = NAME_None; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GAMEINFOKEY_PATCH(key, variable) \
|
||||
else if(nextKey.CompareNoCase(variable) == 0) \
|
||||
{ \
|
||||
sc.MustGetToken(TK_StringConst); \
|
||||
gameinfo.key.fontname = sc.String; \
|
||||
gameinfo.key.color = NAME_Null; \
|
||||
}
|
||||
|
||||
|
||||
void FMapInfoParser::ParseGameInfo()
|
||||
{
|
||||
sc.MustGetToken('{');
|
||||
|
@ -197,7 +219,7 @@ void FMapInfoParser::ParseGameInfo()
|
|||
{
|
||||
if(sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
switch(sc.MustMatchString(GameInfoBoarders))
|
||||
switch(sc.MustMatchString(GameInfoBorders))
|
||||
{
|
||||
default:
|
||||
gameinfo.border = &DoomBorder;
|
||||
|
@ -247,6 +269,17 @@ void FMapInfoParser::ParseGameInfo()
|
|||
gameinfo.ArmorIcon2[8] = 0;
|
||||
}
|
||||
}
|
||||
else if(nextKey.CompareNoCase("maparrow") == 0)
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
gameinfo.mMapArrow = sc.String;
|
||||
if (sc.CheckToken(','))
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
gameinfo.mCheatMapArrow = sc.String;
|
||||
}
|
||||
else gameinfo.mCheatMapArrow = "";
|
||||
}
|
||||
// Insert valid keys here.
|
||||
GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8)
|
||||
GAMEINFOKEY_STRINGARRAY(creditPages, "creditPage", 8)
|
||||
|
@ -300,6 +333,11 @@ void FMapInfoParser::ParseGameInfo()
|
|||
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
|
||||
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
|
||||
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
|
||||
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
|
||||
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
|
||||
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
|
||||
GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch")
|
||||
GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch")
|
||||
|
||||
else
|
||||
{
|
||||
|
|
12
src/gi.h
12
src/gi.h
|
@ -46,7 +46,7 @@
|
|||
#define GI_COMPATSTAIRS 0x00000020 // same for stairbuilding
|
||||
#define GI_COMPATPOLY1 0x00000040 // Hexen's MAP36 needs old polyobject drawing
|
||||
#define GI_COMPATPOLY2 0x00000080 // so does HEXDD's MAP47
|
||||
#define GI_NOTEXTCOLOR 0x00000100
|
||||
#define GI_NOTEXTCOLOR 0x00000100 // Chex Quest 3 would have everything green
|
||||
|
||||
#include "gametype.h"
|
||||
|
||||
|
@ -66,6 +66,12 @@ struct gameborder_t
|
|||
char br[8];
|
||||
};
|
||||
|
||||
struct FGIFont
|
||||
{
|
||||
FName fontname;
|
||||
FName color;
|
||||
};
|
||||
|
||||
struct gameinfo_t
|
||||
{
|
||||
int flags;
|
||||
|
@ -129,6 +135,10 @@ struct gameinfo_t
|
|||
int TextScreenX;
|
||||
int TextScreenY;
|
||||
FName DefaultEndSequence;
|
||||
FString mMapArrow, mCheatMapArrow;
|
||||
FGIFont mStatscreenMapNameFont;
|
||||
FGIFont mStatscreenFinishedFont;
|
||||
FGIFont mStatscreenEnteringFont;
|
||||
|
||||
const char *GetFinalePage(unsigned int num) const;
|
||||
};
|
||||
|
|
|
@ -153,8 +153,8 @@ static int LS_Sector_SetPlaneReflection (line_t *ln, AActor *it, bool backSide,
|
|||
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
|
||||
{
|
||||
sector_t * s = §ors[secnum];
|
||||
if (s->floorplane.a==0 && s->floorplane.b==0) s->floor_reflect = arg1/255.f;
|
||||
if (s->ceilingplane.a==0 && s->ceilingplane.b==0) sectors[secnum].ceiling_reflect = arg2/255.f;
|
||||
if (s->floorplane.a==0 && s->floorplane.b==0) s->reflect[sector_t::floor] = arg1/255.f;
|
||||
if (s->ceilingplane.a==0 && s->ceilingplane.b==0) sectors[secnum].reflect[sector_t::ceiling] = arg2/255.f;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -23,30 +23,28 @@ struct GLRenderSettings
|
|||
extern GLRenderSettings glset;
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "a_sharedglobal.h"
|
||||
|
||||
void gl_RecalcVertexHeights(vertex_t * v);
|
||||
FTextureID gl_GetSpriteFrame(unsigned sprite, int frame, int rot, angle_t ang, bool *mirror);
|
||||
|
||||
class AStackPoint;
|
||||
struct GLSectorStackPortal;
|
||||
|
||||
struct FPortal
|
||||
{
|
||||
TArray<vertex_t *> Shape; // forms the smallest convex outline around the portal area
|
||||
TArray<angle_t> ClipAngles;
|
||||
fixed_t xDisplacement;
|
||||
fixed_t yDisplacement;
|
||||
int plane;
|
||||
AStackPoint *origin;
|
||||
GLSectorStackPortal *glportal; // for quick access to the render data. This is only valid during BSP traversal!
|
||||
|
||||
int PointOnShapeLineSide(fixed_t x, fixed_t y, int shapeindex);
|
||||
void AddVertexToShape(vertex_t *vertex);
|
||||
void AddSectorToPortal(sector_t *sector);
|
||||
void UpdateClipAngles();
|
||||
GLSectorStackPortal *GetGLPortal();
|
||||
};
|
||||
|
||||
extern TArray<FPortal> portals;
|
||||
extern TArray<FPortal *> portals;
|
||||
extern TArray<BYTE> currentmapsection;
|
||||
|
||||
void gl_InitPortals();
|
||||
|
||||
void gl_BuildPortalCoverage(FPortalCoverage *coverage, subsector_t *subsector, FPortal *portal);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,25 +57,48 @@
|
|||
#include "gl/data/gl_data.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/scene/gl_clipper.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
#include "gl/dynlights/gl_glow.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/gl_functions.h"
|
||||
|
||||
TArray<FPortal> portals;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FPortal::PointOnShapeLineSide(fixed_t x, fixed_t y, int shapeindex)
|
||||
struct FPortalID
|
||||
{
|
||||
int shapeindex2 = (shapeindex+1)%Shape.Size();
|
||||
fixed_t mXDisplacement;
|
||||
fixed_t mYDisplacement;
|
||||
|
||||
return DMulScale32(y - Shape[shapeindex]->y, Shape[shapeindex2]->x - Shape[shapeindex]->x,
|
||||
Shape[shapeindex]->x - x, Shape[shapeindex2]->y - Shape[shapeindex]->y);
|
||||
// for the hash code
|
||||
operator intptr_t() const { return (mXDisplacement >> 8) + (mYDisplacement << 8); }
|
||||
bool operator != (const FPortalID &other) const
|
||||
{
|
||||
return mXDisplacement != other.mXDisplacement ||
|
||||
mYDisplacement != other.mYDisplacement;
|
||||
}
|
||||
};
|
||||
|
||||
struct FPortalSector
|
||||
{
|
||||
sector_t *mSub;
|
||||
int mPlane;
|
||||
};
|
||||
|
||||
typedef TArray<FPortalSector> FPortalSectors;
|
||||
|
||||
typedef TMap<FPortalID, FPortalSectors> FPortalMap;
|
||||
|
||||
TArray<FPortal *> portals;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
GLSectorStackPortal *FPortal::GetGLPortal()
|
||||
{
|
||||
if (glportal == NULL) glportal = new GLSectorStackPortal(this);
|
||||
return glportal;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -84,123 +107,241 @@ int FPortal::PointOnShapeLineSide(fixed_t x, fixed_t y, int shapeindex)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FPortal::AddVertexToShape(vertex_t *vertex)
|
||||
struct FCoverageVertex
|
||||
{
|
||||
for(unsigned i=0;i<Shape.Size(); i++)
|
||||
fixed_t x, y;
|
||||
|
||||
bool operator !=(FCoverageVertex &other)
|
||||
{
|
||||
if (vertex->x == Shape[i]->x && vertex->y == Shape[i]->y) return;
|
||||
return x != other.x || y != other.y;
|
||||
}
|
||||
};
|
||||
|
||||
struct FCoverageLine
|
||||
{
|
||||
FCoverageVertex v[2];
|
||||
};
|
||||
|
||||
struct FCoverageBuilder
|
||||
{
|
||||
subsector_t *target;
|
||||
FPortal *portal;
|
||||
TArray<int> collect;
|
||||
FCoverageVertex center;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FCoverageBuilder(subsector_t *sub, FPortal *port)
|
||||
{
|
||||
target = sub;
|
||||
portal = port;
|
||||
}
|
||||
|
||||
if (Shape.Size() < 2)
|
||||
//==========================================================================
|
||||
//
|
||||
// GetIntersection
|
||||
//
|
||||
// adapted from P_InterceptVector
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool GetIntersection(FCoverageVertex *v1, FCoverageVertex *v2, node_t *bsp, FCoverageVertex *v)
|
||||
{
|
||||
Shape.Push(vertex);
|
||||
double frac;
|
||||
double num;
|
||||
double den;
|
||||
|
||||
double v2x = (double)v1->x;
|
||||
double v2y = (double)v1->y;
|
||||
double v2dx = (double)(v2->x - v1->x);
|
||||
double v2dy = (double)(v2->y - v1->y);
|
||||
double v1x = (double)bsp->x;
|
||||
double v1y = (double)bsp->y;
|
||||
double v1dx = (double)bsp->dx;
|
||||
double v1dy = (double)bsp->dy;
|
||||
|
||||
den = v1dy*v2dx - v1dx*v2dy;
|
||||
|
||||
if (den == 0)
|
||||
return false; // parallel
|
||||
|
||||
num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
|
||||
frac = num / den;
|
||||
|
||||
if (frac < 0. || frac > 1.) return false;
|
||||
|
||||
v->x = xs_RoundToInt(v2x + frac * v2dx);
|
||||
v->y = xs_RoundToInt(v2y + frac * v2dy);
|
||||
return true;
|
||||
}
|
||||
else if (Shape.Size() == 2)
|
||||
{
|
||||
// Special case: We need to check if the vertex is on an extension of the line between the first two vertices.
|
||||
int pos = PointOnShapeLineSide(vertex->x, vertex->y, 0);
|
||||
|
||||
if (pos == 0)
|
||||
{
|
||||
fixed_t distv1 = P_AproxDistance(vertex->x - Shape[0]->x, vertex->y - Shape[0]->y);
|
||||
fixed_t distv2 = P_AproxDistance(vertex->x - Shape[1]->x, vertex->y - Shape[1]->y);
|
||||
fixed_t distvv = P_AproxDistance(Shape[0]->x - Shape[1]->x, Shape[0]->y - Shape[1]->y);
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
if (distv1 > distvv)
|
||||
{
|
||||
Shape[1] = vertex;
|
||||
}
|
||||
else if (distv2 > distvv)
|
||||
{
|
||||
Shape[0] = vertex;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (pos > 0)
|
||||
{
|
||||
Shape.Insert(1, vertex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Shape.Push(vertex);
|
||||
}
|
||||
double PartitionDistance(FCoverageVertex *vt, node_t *node)
|
||||
{
|
||||
return fabs(double(-node->dy) * (vt->x - node->x) + double(node->dx) * (vt->y - node->y)) / node->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned i=0; i<Shape.Size(); i++)
|
||||
{
|
||||
int startlinepos = PointOnShapeLineSide(vertex->x, vertex->y, i);
|
||||
if (startlinepos >= 0)
|
||||
{
|
||||
int previouslinepos = PointOnShapeLineSide(vertex->x, vertex->y, (i+Shape.Size()-1)%Shape.Size());
|
||||
|
||||
if (previouslinepos < 0) // we found the first line for which the vertex lies in front
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PointOnSide(FCoverageVertex *vt, node_t *node)
|
||||
{
|
||||
return R_PointOnSide(vt->x, vt->y, node);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// adapted from polyobject splitter
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void CollectNode(void *node, TArray<FCoverageVertex> &shape)
|
||||
{
|
||||
static TArray<FCoverageLine> lists[2];
|
||||
const double COVERAGE_EPSILON = 6.; // same epsilon as the node builder
|
||||
|
||||
if (!((size_t)node & 1)) // Keep going until found a subsector
|
||||
{
|
||||
node_t *bsp = (node_t *)node;
|
||||
|
||||
int centerside = R_PointOnSide(center.x, center.y, bsp);
|
||||
|
||||
lists[0].Clear();
|
||||
lists[1].Clear();
|
||||
for(unsigned i=0;i<shape.Size(); i++)
|
||||
{
|
||||
FCoverageVertex *v1 = &shape[i];
|
||||
FCoverageVertex *v2 = &shape[(i+1) % shape.Size()];
|
||||
FCoverageLine vl = { *v1, *v2 };
|
||||
|
||||
double dist_v1 = PartitionDistance(v1, bsp);
|
||||
double dist_v2 = PartitionDistance(v2, bsp);
|
||||
|
||||
if(dist_v1 <= COVERAGE_EPSILON)
|
||||
{
|
||||
unsigned int nextpoint = i;
|
||||
|
||||
do
|
||||
if (dist_v2 <= COVERAGE_EPSILON)
|
||||
{
|
||||
nextpoint = (nextpoint+1) % Shape.Size();
|
||||
}
|
||||
while (PointOnShapeLineSide(vertex->x, vertex->y, nextpoint) >= 0);
|
||||
|
||||
int removecount = (nextpoint - i + Shape.Size()) % Shape.Size() - 1;
|
||||
|
||||
if (removecount == 0)
|
||||
{
|
||||
if (startlinepos > 0)
|
||||
{
|
||||
Shape.Insert(i+1, vertex);
|
||||
}
|
||||
}
|
||||
else if (nextpoint > i || nextpoint == 0)
|
||||
{
|
||||
// The easy case: It doesn't wrap around
|
||||
Shape.Delete(i+1, removecount-1);
|
||||
Shape[i+1] = vertex;
|
||||
lists[centerside].Push(vl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It does wrap around.
|
||||
Shape.Delete(i+1, removecount);
|
||||
Shape.Delete(1, nextpoint-1);
|
||||
Shape[0] = vertex;
|
||||
int side = PointOnSide(v2, bsp);
|
||||
lists[side].Push(vl);
|
||||
}
|
||||
}
|
||||
else if (dist_v2 <= COVERAGE_EPSILON)
|
||||
{
|
||||
int side = PointOnSide(v1, bsp);
|
||||
lists[side].Push(vl);
|
||||
}
|
||||
else
|
||||
{
|
||||
int side1 = PointOnSide(v1, bsp);
|
||||
int side2 = PointOnSide(v2, bsp);
|
||||
|
||||
if(side1 != side2)
|
||||
{
|
||||
// if the partition line crosses this seg, we must split it.
|
||||
|
||||
FCoverageVertex vert;
|
||||
|
||||
if (GetIntersection(v1, v2, bsp, &vert))
|
||||
{
|
||||
lists[0].Push(vl);
|
||||
lists[1].Push(vl);
|
||||
lists[side1].Last().v[1] = vert;
|
||||
lists[side2].Last().v[0] = vert;
|
||||
}
|
||||
else
|
||||
{
|
||||
// should never happen
|
||||
lists[side1].Push(vl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// both points on the same side.
|
||||
lists[side1].Push(vl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (lists[1].Size() == 0)
|
||||
{
|
||||
CollectNode(bsp->children[0], shape);
|
||||
}
|
||||
else if (lists[0].Size() == 0)
|
||||
{
|
||||
CollectNode(bsp->children[1], shape);
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy the static arrays into local ones
|
||||
TArray<FCoverageVertex> locallists[2];
|
||||
|
||||
for(int l=0;l<2;l++)
|
||||
{
|
||||
for (unsigned i=0;i<lists[l].Size(); i++)
|
||||
{
|
||||
locallists[l].Push(lists[l][i].v[0]);
|
||||
unsigned i1= (i+1)%lists[l].Size();
|
||||
if (lists[l][i1].v[0] != lists[l][i].v[1])
|
||||
{
|
||||
locallists[l].Push(lists[l][i].v[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CollectNode(bsp->children[0], locallists[0]);
|
||||
CollectNode(bsp->children[1], locallists[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we reached a subsector so we can link the node with this subsector
|
||||
subsector_t *sub = (subsector_t *)((BYTE *)node - 1);
|
||||
collect.Push(int(sub-subsectors));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
// Calculate portal coverage for a single subsector
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FPortal::AddSectorToPortal(sector_t *sector)
|
||||
void gl_BuildPortalCoverage(FPortalCoverage *coverage, subsector_t *subsector, FPortal *portal)
|
||||
{
|
||||
for(int i=0; i<sector->linecount; i++)
|
||||
{
|
||||
AddVertexToShape(sector->lines[i]->v1);
|
||||
// This is necessary to handle unclosed sectors
|
||||
AddVertexToShape(sector->lines[i]->v2);
|
||||
}
|
||||
}
|
||||
TArray<FCoverageVertex> shape;
|
||||
double centerx=0, centery=0;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FPortal::UpdateClipAngles()
|
||||
{
|
||||
for(unsigned int i=0; i<Shape.Size(); i++)
|
||||
shape.Resize(subsector->numlines);
|
||||
for(unsigned i=0; i<subsector->numlines; i++)
|
||||
{
|
||||
ClipAngles[i] = R_PointToPseudoAngle(viewx, viewy, Shape[i]->x, Shape[i]->y);
|
||||
centerx += (shape[i].x = subsector->firstline[i].v1->x + portal->xDisplacement);
|
||||
centery += (shape[i].y = subsector->firstline[i].v1->y + portal->yDisplacement);
|
||||
}
|
||||
|
||||
FCoverageBuilder build(subsector, portal);
|
||||
build.center.x = xs_CRoundToInt(centerx / subsector->numlines);
|
||||
build.center.y = xs_CRoundToInt(centery / subsector->numlines);
|
||||
|
||||
build.CollectNode(nodes + numnodes - 1, shape);
|
||||
coverage->subsectors = new DWORD[build.collect.Size()];
|
||||
coverage->sscount = build.collect.Size();
|
||||
memcpy(coverage->subsectors, &build.collect[0], build.collect.Size() * sizeof(DWORD));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -209,68 +350,124 @@ void FPortal::UpdateClipAngles()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void gl_InitPortals()
|
||||
static void CollectPortalSectors(FPortalMap &collection)
|
||||
{
|
||||
TThinkerIterator<AStackPoint> it;
|
||||
AStackPoint *pt;
|
||||
|
||||
portals.Clear();
|
||||
while ((pt = it.Next()))
|
||||
for (int i=0;i<numsectors;i++)
|
||||
{
|
||||
FPortal *portal = NULL;
|
||||
int plane;
|
||||
pt->special1 = -1;
|
||||
for(int i=0;i<numsectors;i++)
|
||||
sector_t *sec = §ors[i];
|
||||
if (sec->CeilingSkyBox != NULL && sec->CeilingSkyBox->bAlways && sec->CeilingSkyBox->Mate != NULL)
|
||||
{
|
||||
if (sectors[i].linecount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (sectors[i].FloorSkyBox == pt)
|
||||
{
|
||||
plane = 1;
|
||||
}
|
||||
else if (sectors[i].CeilingSkyBox == pt)
|
||||
{
|
||||
plane = 2;
|
||||
}
|
||||
else continue;
|
||||
FPortalID id = { sec->CeilingSkyBox->x - sec->CeilingSkyBox->Mate->x,
|
||||
sec->CeilingSkyBox->y - sec->CeilingSkyBox->Mate->y};
|
||||
|
||||
// we only process portals that actually are in use.
|
||||
if (portal == NULL)
|
||||
{
|
||||
pt->special1 = portals.Size(); // Link portal thing to render data
|
||||
portal = &portals[portals.Reserve(1)];
|
||||
portal->origin = pt;
|
||||
portal->plane = 0;
|
||||
portal->xDisplacement = pt->x - pt->Mate->x;
|
||||
portal->yDisplacement = pt->y - pt->Mate->y;
|
||||
}
|
||||
portal->AddSectorToPortal(§ors[i]);
|
||||
portal->plane|=plane;
|
||||
FPortalSectors &sss = collection[id];
|
||||
FPortalSector ss = { sec, sector_t::ceiling };
|
||||
sss.Push(ss);
|
||||
}
|
||||
if (portal != NULL)
|
||||
|
||||
if (sec->FloorSkyBox != NULL && sec->FloorSkyBox->bAlways && sec->FloorSkyBox->Mate != NULL)
|
||||
{
|
||||
// if the first vertex is duplicated at the end it'll save time in a time critical function
|
||||
// because that code does not need to check for wraparounds anymire.
|
||||
portal->Shape.Resize(portal->Shape.Size()+1);
|
||||
portal->Shape[portal->Shape.Size()-1] = portal->Shape[0];
|
||||
portal->Shape.ShrinkToFit();
|
||||
portal->ClipAngles.Resize(portal->Shape.Size());
|
||||
FPortalID id = { sec->FloorSkyBox->x - sec->FloorSkyBox->Mate->x,
|
||||
sec->FloorSkyBox->y - sec->FloorSkyBox->Mate->y };
|
||||
|
||||
FPortalSectors &sss = collection[id];
|
||||
FPortalSector ss = { sec, sector_t::floor };
|
||||
sss.Push(ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_InitPortals()
|
||||
{
|
||||
FPortalMap collection;
|
||||
|
||||
if (numnodes == 0) return;
|
||||
|
||||
for(int i=0;i<numnodes;i++)
|
||||
{
|
||||
node_t *no = &nodes[i];
|
||||
double fdx = (double)no->dx;
|
||||
double fdy = (double)no->dy;
|
||||
no->len = (float)sqrt(fdx * fdx + fdy * fdy);
|
||||
}
|
||||
|
||||
CollectPortalSectors(collection);
|
||||
portals.Clear();
|
||||
|
||||
FPortalMap::Iterator it(collection);
|
||||
FPortalMap::Pair *pair;
|
||||
int c = 0;
|
||||
int planeflags = 0;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
for(unsigned i=0;i<pair->Value.Size(); i++)
|
||||
{
|
||||
if (pair->Value[i].mPlane == sector_t::floor) planeflags |= 1;
|
||||
else if (pair->Value[i].mPlane == sector_t::ceiling) planeflags |= 2;
|
||||
}
|
||||
for (int i=1;i<=2;i<<=1)
|
||||
{
|
||||
// For now, add separate portals for floor and ceiling. They can be merged once
|
||||
// proper plane clipping is in.
|
||||
if (planeflags & i)
|
||||
{
|
||||
FPortal *portal = new FPortal;
|
||||
portal->xDisplacement = pair->Key.mXDisplacement;
|
||||
portal->yDisplacement = pair->Key.mYDisplacement;
|
||||
portal->plane = (i==1? sector_t::floor : sector_t::ceiling); /**/
|
||||
portals.Push(portal);
|
||||
for(unsigned j=0;j<pair->Value.Size(); j++)
|
||||
{
|
||||
sector_t *sec = pair->Value[j].mSub;
|
||||
int plane = pair->Value[j].mPlane;
|
||||
if (portal->plane == plane)
|
||||
{
|
||||
for(int k=0;k<sec->subsectorcount; k++)
|
||||
{
|
||||
subsector_t *sub = sec->subsectors[k];
|
||||
gl_BuildPortalCoverage(&sub->portalcoverage[plane], sub, portal);
|
||||
}
|
||||
sec->portals[plane] = portal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCMD(dumpportals)
|
||||
{
|
||||
for(unsigned i=0;i<portals.Size(); i++)
|
||||
{
|
||||
Printf("Portal #%d, plane %d, stackpoint at (%f,%f), displacement = (%f,%f)\n", i, portals[i].plane, portals[i].origin->x/65536., portals[i].origin->y/65536.,
|
||||
portals[i].origin->x/65536. - portals[i].origin->Mate->x/65536., portals[i].origin->y/65536. - portals[i].origin->Mate->y/65536.);
|
||||
for (unsigned j=0;j<portals[i].Shape.Size(); j++)
|
||||
double xdisp = portals[i]->xDisplacement/65536.;
|
||||
double ydisp = portals[i]->yDisplacement/65536.;
|
||||
Printf(PRINT_LOG, "Portal #%d, %s, displacement = (%f,%f)\n", i, portals[i]->plane==0? "floor":"ceiling",
|
||||
xdisp, ydisp);
|
||||
Printf(PRINT_LOG, "Coverage:\n");
|
||||
for(int j=0;j<numsubsectors;j++)
|
||||
{
|
||||
Printf("\t(%f,%f)\n", (portals[i].Shape[j]->x + portals[i].xDisplacement)/65536., (portals[i].Shape[j]->y + portals[i].yDisplacement)/65536.);
|
||||
subsector_t *sub = &subsectors[j];
|
||||
FPortal *port = sub->render_sector->portals[portals[i]->plane];
|
||||
if (port == portals[i])
|
||||
{
|
||||
Printf(PRINT_LOG, "\tSubsector %d (%d):\n\t\t", j, sub->render_sector->sectornum);
|
||||
for(unsigned k = 0;k< sub->numlines; k++)
|
||||
{
|
||||
Printf(PRINT_LOG, "(%.3f,%.3f), ", sub->firstline[k].v1->x/65536. + xdisp, sub->firstline[k].v1->y/65536. + ydisp);
|
||||
}
|
||||
Printf(PRINT_LOG, "\n\t\tCovered by subsectors:\n");
|
||||
FPortalCoverage *cov = &sub->portalcoverage[portals[i]->plane];
|
||||
for(int l = 0;l< cov->sscount; l++)
|
||||
{
|
||||
subsector_t *csub = &subsectors[cov->subsectors[l]];
|
||||
Printf(PRINT_LOG, "\t\t\t%5d (%4d): ", cov->subsectors[l], csub->render_sector->sectornum);
|
||||
for(unsigned m = 0;m< csub->numlines; m++)
|
||||
{
|
||||
Printf(PRINT_LOG, "(%.3f,%.3f), ", csub->firstline[m].v1->x/65536., csub->firstline[m].v1->y/65536.);
|
||||
}
|
||||
Printf(PRINT_LOG, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,153 @@ void gl_InitSegs()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void DoSetMapSection(subsector_t *sub, int num)
|
||||
{
|
||||
sub->mapsection = num;
|
||||
|
||||
for(DWORD i=0;i<sub->numlines;i++)
|
||||
{
|
||||
seg_t * seg = sub->firstline + i;
|
||||
|
||||
if (seg->PartnerSeg)
|
||||
{
|
||||
subsector_t * sub2 = seg->PartnerSeg->Subsector();
|
||||
|
||||
if (sub2->mapsection != num)
|
||||
{
|
||||
assert(sub2->mapsection == 0);
|
||||
DoSetMapSection(sub2, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Merge sections. This is needed in case the map contains errors
|
||||
// like overlapping lines resulting in abnormal subsectors.
|
||||
//
|
||||
// This function ensures that any vertex position can only be in one section.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct cvertex_t
|
||||
{
|
||||
fixed_t x, y;
|
||||
|
||||
operator int () const { return ((x>>16)&0xffff) | y; }
|
||||
bool operator!= (const cvertex_t &other) const { return x != other.x || y != other.y; }
|
||||
cvertex_t& operator =(const vertex_t *v) { x = v->x; y = v->y; return *this; }
|
||||
};
|
||||
|
||||
typedef TMap<cvertex_t, int> FSectionVertexMap;
|
||||
|
||||
static int MergeMapSections(int num)
|
||||
{
|
||||
FSectionVertexMap vmap;
|
||||
FSectionVertexMap::Pair *pair;
|
||||
TArray<int> sectmap;
|
||||
TArray<bool> sectvalid;
|
||||
sectmap.Resize(num);
|
||||
sectvalid.Resize(num);
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
sectmap[i] = -1;
|
||||
sectvalid[i] = true;
|
||||
}
|
||||
int mergecount = 1;
|
||||
|
||||
|
||||
cvertex_t vt;
|
||||
|
||||
// first step: Set mapsection for all vertex positions.
|
||||
for(DWORD i=0;i<numsegs;i++)
|
||||
{
|
||||
seg_t * seg = &segs[i];
|
||||
int section = seg->Subsector()->mapsection;
|
||||
for(int j=0;j<2;j++)
|
||||
{
|
||||
vt = j==0? seg->v1:seg->v2;
|
||||
vmap[vt] = section;
|
||||
}
|
||||
}
|
||||
|
||||
// second step: Check if any seg references more than one mapsection, either by subsector or by vertex
|
||||
for(DWORD i=0;i<numsegs;i++)
|
||||
{
|
||||
seg_t * seg = &segs[i];
|
||||
int section = seg->Subsector()->mapsection;
|
||||
for(int j=0;j<2;j++)
|
||||
{
|
||||
vt = j==0? seg->v1:seg->v2;
|
||||
int vsection = vmap[vt];
|
||||
|
||||
if (vsection != section)
|
||||
{
|
||||
// These 2 sections should be merged
|
||||
for(int k=0;k<numsubsectors;k++)
|
||||
{
|
||||
if (subsectors[k].mapsection == vsection) subsectors[k].mapsection = section;
|
||||
}
|
||||
FSectionVertexMap::Iterator it(vmap);
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
if (pair->Value == vsection) pair->Value = section;
|
||||
}
|
||||
sectvalid[vsection-1] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
if (sectvalid[i]) sectmap[i] = mergecount++;
|
||||
}
|
||||
for(int i=0;i<numsubsectors;i++)
|
||||
{
|
||||
subsectors[i].mapsection = sectmap[subsectors[i].mapsection-1];
|
||||
assert(subsectors[i].mapsection!=-1);
|
||||
}
|
||||
return mergecount-1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void SetMapSections()
|
||||
{
|
||||
bool set;
|
||||
int num = 0;
|
||||
do
|
||||
{
|
||||
set = false;
|
||||
for(int i=0; i<numsubsectors; i++)
|
||||
{
|
||||
if (subsectors[i].mapsection == 0)
|
||||
{
|
||||
num++;
|
||||
DoSetMapSection(&subsectors[i], num);
|
||||
set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (set);
|
||||
num = MergeMapSections(num);
|
||||
currentmapsection.Resize(1 + num/8);
|
||||
#ifdef DEBUG
|
||||
Printf("%d map sections found\n", num);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// prepare subsectors for GL rendering
|
||||
|
@ -112,20 +259,6 @@ void gl_InitSegs()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
inline void M_ClearBox (fixed_t *box)
|
||||
{
|
||||
box[BOXTOP] = box[BOXRIGHT] = INT_MIN;
|
||||
box[BOXBOTTOM] = box[BOXLEFT] = INT_MAX;
|
||||
}
|
||||
|
||||
inline void M_AddToBox(fixed_t* box,fixed_t x,fixed_t y)
|
||||
{
|
||||
if (x<box[BOXLEFT]) box[BOXLEFT] = x;
|
||||
if (x>box[BOXRIGHT]) box[BOXRIGHT] = x;
|
||||
if (y<box[BOXBOTTOM]) box[BOXBOTTOM] = y;
|
||||
if (y>box[BOXTOP]) box[BOXTOP] = y;
|
||||
}
|
||||
|
||||
static void SpreadHackedFlag(subsector_t * sub)
|
||||
{
|
||||
// The subsector pointer hasn't been set yet!
|
||||
|
@ -147,27 +280,18 @@ static void SpreadHackedFlag(subsector_t * sub)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PrepareSectorData()
|
||||
{
|
||||
int i;
|
||||
size_t /*ii,*/ jj;
|
||||
TArray<subsector_t *> undetermined;
|
||||
subsector_t * ss;
|
||||
|
||||
// look up sector number for each subsector
|
||||
for (i = 0; i < numsubsectors; i++)
|
||||
{
|
||||
ss = &subsectors[i];
|
||||
seg_t *seg = ss->firstline;
|
||||
|
||||
M_ClearBox(ss->bbox);
|
||||
for(jj=0; jj<ss->numlines; jj++)
|
||||
{
|
||||
M_AddToBox(ss->bbox,seg->v1->x, seg->v1->y);
|
||||
seg++;
|
||||
}
|
||||
}
|
||||
|
||||
// now group the subsectors by sector
|
||||
subsector_t ** subsectorbuffer = new subsector_t * [numsubsectors];
|
||||
|
||||
|
@ -208,6 +332,7 @@ static void PrepareSectorData()
|
|||
}
|
||||
}
|
||||
}
|
||||
SetMapSections();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -216,6 +341,7 @@ static void PrepareSectorData()
|
|||
// - This will be used to lower the floor of such sectors by one map unit
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PrepareTransparentDoors(sector_t * sector)
|
||||
{
|
||||
bool solidwall=false;
|
||||
|
@ -300,12 +426,12 @@ static void PrepareTransparentDoors(sector_t * sector)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void AddToVertex(const sector_t * sec, TArray<int> & list)
|
||||
{
|
||||
int secno = int(sec-sectors);
|
||||
|
@ -322,6 +448,7 @@ static void AddToVertex(const sector_t * sec, TArray<int> & list)
|
|||
// Attach sectors to vertices - used to generate vertex height lists
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void InitVertexData()
|
||||
{
|
||||
TArray<int> * vt_sectorlists;
|
||||
|
@ -391,7 +518,7 @@ static void InitVertexData()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// Group segs to sidedefs
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
@ -421,6 +548,12 @@ static int STACK_ARGS segcmp(const void *a, const void *b)
|
|||
return xs_RoundToInt(FRACUNIT*(A->sidefrac - B->sidefrac));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Group segs to sidedefs
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PrepareSegs()
|
||||
{
|
||||
int *segcount = new int[numsides];
|
||||
|
@ -503,17 +636,18 @@ static void PrepareSegs()
|
|||
// Initialize the level data for the GL renderer
|
||||
//
|
||||
//==========================================================================
|
||||
extern int restart;
|
||||
|
||||
void gl_PreprocessLevel()
|
||||
{
|
||||
int i;
|
||||
|
||||
static bool datadone=false;
|
||||
static int datadone=-1;
|
||||
|
||||
|
||||
if (!datadone)
|
||||
if (datadone != restart)
|
||||
{
|
||||
datadone=true;
|
||||
datadone = restart;
|
||||
gl_InitData();
|
||||
}
|
||||
|
||||
|
@ -548,6 +682,7 @@ void gl_PreprocessLevel()
|
|||
// Cleans up all the GL data for the last level
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void gl_CleanLevelData()
|
||||
{
|
||||
// Dynamic lights must be destroyed before the sector information here is deleted.
|
||||
|
@ -587,17 +722,42 @@ void gl_CleanLevelData()
|
|||
delete [] sectors[0].subsectors;
|
||||
sectors[0].subsectors = NULL;
|
||||
}
|
||||
if (gamenodes && gamenodes!=nodes)
|
||||
for (int i=0;i<numsubsectors;i++)
|
||||
{
|
||||
delete [] gamenodes;
|
||||
gamenodes = NULL;
|
||||
numgamenodes = 0;
|
||||
for(int j=0;j<2;j++)
|
||||
{
|
||||
if (subsectors[i].portalcoverage[j].subsectors != NULL)
|
||||
{
|
||||
delete [] subsectors[i].portalcoverage[j].subsectors;
|
||||
subsectors[i].portalcoverage[j].subsectors = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gamesubsectors && gamesubsectors!=subsectors)
|
||||
for(unsigned i=0;i<portals.Size(); i++)
|
||||
{
|
||||
delete [] gamesubsectors;
|
||||
gamesubsectors = NULL;
|
||||
numgamesubsectors = 0;
|
||||
delete portals[i];
|
||||
}
|
||||
portals.Clear();
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD(listmapsections)
|
||||
{
|
||||
for(int i=0;i<100;i++)
|
||||
{
|
||||
for (int j=0;j<numsubsectors;j++)
|
||||
{
|
||||
if (subsectors[j].mapsection == i)
|
||||
{
|
||||
Printf("Mapsection %d, sector %d, line %d\n", i, subsectors[j].render_sector->sectornum, int(subsectors[j].firstline->linedef-lines));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@ EXTERN_CVAR (Float, gl_lights_size);
|
|||
int ScriptDepth;
|
||||
void gl_InitGlow(FScanner &sc);
|
||||
void gl_ParseBrightmap(FScanner &sc, int);
|
||||
void gl_DestroyUserShaders();
|
||||
void gl_ParseHardwareShader(FScanner &sc, int deflump);
|
||||
void gl_ParseSkybox(FScanner &sc);
|
||||
void gl_ParseDetailTexture(FScanner &sc);
|
||||
|
@ -1315,6 +1316,8 @@ void gl_ParseDefs()
|
|||
const char *defsLump = NULL;
|
||||
|
||||
atterm( gl_ReleaseLights );
|
||||
gl_ReleaseLights();
|
||||
gl_DestroyUserShaders();
|
||||
switch (gameinfo.gametype)
|
||||
{
|
||||
case GAME_Heretic:
|
||||
|
|
|
@ -258,6 +258,14 @@ void gl_InitModels()
|
|||
|
||||
lastLump = 0;
|
||||
|
||||
for(unsigned i=0;i<Models.Size();i++)
|
||||
{
|
||||
delete Models[i];
|
||||
}
|
||||
Models.Clear();
|
||||
SpriteModelFrames.Clear();
|
||||
DeleteModelHash();
|
||||
|
||||
// First, create models for each voxel
|
||||
for (unsigned i = 0; i < Voxels.Size(); i++)
|
||||
{
|
||||
|
|
|
@ -150,11 +150,12 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend
|
|||
int *tm, int *sb, int *db, int *be)
|
||||
{
|
||||
static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
|
||||
static int renderops[] = { 0, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, -1, -1, -1, -1};
|
||||
static int renderops[] = { 0, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
|
||||
int srcblend = blendstyles[style.SrcAlpha&3];
|
||||
int dstblend = blendstyles[style.DestAlpha&3];
|
||||
int blendequation = renderops[style.BlendOp&7];
|
||||
int blendequation = renderops[style.BlendOp&15];
|
||||
int texturemode = drawopaque? TM_OPAQUE : TM_MODULATE;
|
||||
|
||||
if (style.Flags & STYLEF_ColorIsFixed)
|
||||
|
|
|
@ -538,7 +538,7 @@ void FGLRenderer::Clear(int left, int top, int right, int bottom, int palcolor,
|
|||
{
|
||||
int rt;
|
||||
int offY = 0;
|
||||
PalEntry p = palcolor==-1? (PalEntry)color : GPalette.BaseColors[palcolor];
|
||||
PalEntry p = palcolor==-1 || color != 0? (PalEntry)color : GPalette.BaseColors[palcolor];
|
||||
int width = right-left;
|
||||
int height= bottom-top;
|
||||
|
||||
|
|
|
@ -20,11 +20,12 @@ extern int extralight;
|
|||
enum SectorRenderFlags
|
||||
{
|
||||
// This is used to avoid creating too many drawinfos
|
||||
SSRF_RENDERFLOOR=1,
|
||||
SSRF_RENDERCEILING=2,
|
||||
SSRF_RENDER3DPLANES=4,
|
||||
SSRF_RENDERALL=7,
|
||||
SSRF_PROCESSED=8,
|
||||
SSRF_RENDERFLOOR = 1,
|
||||
SSRF_RENDERCEILING = 2,
|
||||
SSRF_RENDER3DPLANES = 4,
|
||||
SSRF_RENDERALL = 7,
|
||||
SSRF_PROCESSED = 8,
|
||||
SSRF_SEEN = 16,
|
||||
};
|
||||
|
||||
struct GL_IRECT
|
||||
|
@ -105,7 +106,7 @@ public:
|
|||
void DrawScene(bool toscreen = false);
|
||||
void DrawBlend(sector_t * viewsector);
|
||||
|
||||
void DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed_t sy, int cm_index, bool hudModelStep);
|
||||
void DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed_t sy, int cm_index, bool hudModelStep, int OverrideShader);
|
||||
void DrawPlayerSprites(sector_t * viewsector, bool hudModelStep);
|
||||
void DrawTargeterSprites();
|
||||
|
||||
|
|
|
@ -62,6 +62,26 @@ CVAR(Bool, gl_render_things, true, 0)
|
|||
CVAR(Bool, gl_render_walls, true, 0)
|
||||
CVAR(Bool, gl_render_flats, true, 0)
|
||||
|
||||
|
||||
static void UnclipSubsector(subsector_t *sub)
|
||||
{
|
||||
int count = sub->numlines;
|
||||
seg_t * seg = sub->firstline;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
angle_t startAngle = seg->v2->GetClipAngle();
|
||||
angle_t endAngle = seg->v1->GetClipAngle();
|
||||
|
||||
// Back side, i.e. backface culling - read: endAngle >= startAngle!
|
||||
if (startAngle-endAngle >= ANGLE_180)
|
||||
{
|
||||
clipper.SafeRemoveClipRange(startAngle, endAngle);
|
||||
}
|
||||
seg++;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_AddLine
|
||||
|
@ -76,6 +96,13 @@ static sector_t *currentsector;
|
|||
|
||||
static void AddLine (seg_t *seg)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _DEBUG
|
||||
if (seg->linedef-lines==38)
|
||||
__asm nop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
angle_t startAngle, endAngle;
|
||||
sector_t * backsector = NULL;
|
||||
sector_t bs;
|
||||
|
@ -367,6 +394,17 @@ static void DoSubsector(subsector_t * sub)
|
|||
sector=sub->sector;
|
||||
if (!sector) return;
|
||||
|
||||
// If the mapsections differ this subsector can't possibly be visible from the current view point
|
||||
if (!(currentmapsection[sub->mapsection>>3] & (1 << (sub->mapsection & 7)))) return;
|
||||
|
||||
if (gl_drawinfo->ss_renderflags[sub-subsectors] & SSRF_SEEN)
|
||||
{
|
||||
// This means that we have reached a subsector in a portal that has been marked 'seen'
|
||||
// from the other side of the portal. This means we must clear the clipper for the
|
||||
// range this subsector spans before going on.
|
||||
UnclipSubsector(sub);
|
||||
}
|
||||
|
||||
fakesector=gl_FakeFlat(sector, &fake, false);
|
||||
|
||||
if (sector->validcount != validcount)
|
||||
|
@ -426,6 +464,14 @@ static void DoSubsector(subsector_t * sub)
|
|||
// Due to the way a BSP works such a subsector can never be visible
|
||||
if (!sector->heightsec || sector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC || in_area!=area_default)
|
||||
{
|
||||
if (sector != sub->render_sector)
|
||||
{
|
||||
sector = sub->render_sector;
|
||||
// the planes of this subsector are faked to belong to another sector
|
||||
// This means we need the heightsec parts and light info of the render sector, not the actual one.
|
||||
fakesector = gl_FakeFlat(sector, &fake, false);
|
||||
}
|
||||
|
||||
BYTE &srf = gl_drawinfo->sectorrenderflags[sub->render_sector->sectornum];
|
||||
if (!(srf & SSRF_PROCESSED))
|
||||
{
|
||||
|
@ -434,13 +480,6 @@ static void DoSubsector(subsector_t * sub)
|
|||
SetupFlat.Clock();
|
||||
//if (!gl_multithreading)
|
||||
{
|
||||
if (sector != sub->render_sector)
|
||||
{
|
||||
sector = sub->render_sector;
|
||||
// the planes of this subsector are faked to belong to another sector
|
||||
// This means we need the heightsec parts and light info of the render sector, not the actual one!
|
||||
fakesector = gl_FakeFlat(sector, &fake, false);
|
||||
}
|
||||
GLRenderer->ProcessSector(fakesector);
|
||||
}
|
||||
/*
|
||||
|
@ -456,6 +495,22 @@ static void DoSubsector(subsector_t * sub)
|
|||
gl_drawinfo->ss_renderflags[sub-subsectors] =
|
||||
(sub->numlines > 2) ? SSRF_PROCESSED|SSRF_RENDERALL : SSRF_PROCESSED;
|
||||
if (sub->hacked & 1) gl_drawinfo->AddHackedSubsector(sub);
|
||||
|
||||
FPortal *portal;
|
||||
|
||||
portal = fakesector->portals[sector_t::ceiling];
|
||||
if (portal != NULL)
|
||||
{
|
||||
GLSectorStackPortal *glportal = portal->GetGLPortal();
|
||||
glportal->AddSubsector(sub);
|
||||
}
|
||||
|
||||
portal = fakesector->portals[sector_t::floor];
|
||||
if (portal != NULL)
|
||||
{
|
||||
GLSectorStackPortal *glportal = portal->GetGLPortal();
|
||||
glportal->AddSubsector(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -496,7 +551,8 @@ void gl_RenderBSPNode (void *node)
|
|||
// It is not necessary to use the slower precise version here
|
||||
if (!clipper.CheckBox(bsp->bbox[side]))
|
||||
{
|
||||
return;
|
||||
if (!(gl_drawinfo->no_renderflags[bsp-nodes] & SSRF_SEEN))
|
||||
return;
|
||||
}
|
||||
|
||||
node = bsp->children[side];
|
||||
|
|
|
@ -93,6 +93,14 @@ void Clipper::Clear()
|
|||
ClipNode *node = cliphead;
|
||||
ClipNode *temp;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
temp = node;
|
||||
node = node->next;
|
||||
temp->Free();
|
||||
}
|
||||
node = silhouette;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
temp = node;
|
||||
|
@ -101,9 +109,32 @@ void Clipper::Clear()
|
|||
}
|
||||
|
||||
cliphead = NULL;
|
||||
silhouette = NULL;
|
||||
anglecache++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// SetSilhouette
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Clipper::SetSilhouette()
|
||||
{
|
||||
ClipNode *node = cliphead;
|
||||
ClipNode *last = NULL;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ClipNode *snode = ClipNode::NewRange(node->start, node->end);
|
||||
if (silhouette == NULL) silhouette = snode;
|
||||
snode->prev = last;
|
||||
if (last != NULL) last->next = snode;
|
||||
last = snode;
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -243,8 +274,42 @@ void Clipper::AddClipRange(angle_t start, angle_t end)
|
|||
|
||||
void Clipper::RemoveClipRange(angle_t start, angle_t end)
|
||||
{
|
||||
ClipNode *node, *temp;
|
||||
ClipNode *node;
|
||||
|
||||
if (silhouette)
|
||||
{
|
||||
node = silhouette;
|
||||
while (node != NULL && node->end <= start)
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
if (node != NULL && node->start <= start)
|
||||
{
|
||||
if (node->end >= end) return;
|
||||
start = node->end;
|
||||
node = node->next;
|
||||
}
|
||||
while (node != NULL && node->start < end)
|
||||
{
|
||||
DoRemoveClipRange(start, node->start);
|
||||
start = node->end;
|
||||
node = node->next;
|
||||
}
|
||||
if (start >= end) return;
|
||||
}
|
||||
DoRemoveClipRange(start, end);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RemoveClipRange worker function
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Clipper::DoRemoveClipRange(angle_t start, angle_t end)
|
||||
{
|
||||
ClipNode *node, *temp;
|
||||
|
||||
if (cliphead)
|
||||
{
|
||||
//check to see if range contains any old ranges
|
||||
|
|
|
@ -51,12 +51,14 @@ class Clipper
|
|||
{
|
||||
ClipNode * clipnodes;
|
||||
ClipNode * cliphead;
|
||||
ClipNode * silhouette; // will be preserved even when RemoveClipRange is called
|
||||
|
||||
static angle_t AngleToPseudo(angle_t ang);
|
||||
bool IsRangeVisible(angle_t startangle, angle_t endangle);
|
||||
void RemoveRange(ClipNode * cn);
|
||||
void AddClipRange(angle_t startangle, angle_t endangle);
|
||||
void RemoveClipRange(angle_t startangle, angle_t endangle);
|
||||
void DoRemoveClipRange(angle_t start, angle_t end);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -72,6 +74,7 @@ public:
|
|||
void Clear();
|
||||
|
||||
|
||||
void SetSilhouette();
|
||||
|
||||
bool SafeCheckRange(angle_t startAngle, angle_t endAngle)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "r_main.h"
|
||||
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "gl/data/gl_data.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
|
@ -939,9 +940,11 @@ void FDrawInfo::StartScene()
|
|||
|
||||
sectorrenderflags.Resize(numsectors);
|
||||
ss_renderflags.Resize(numsubsectors);
|
||||
no_renderflags.Resize(numsubsectors);
|
||||
|
||||
memset(§orrenderflags[0], 0, numsectors*sizeof(sectorrenderflags[0]));
|
||||
memset(&ss_renderflags[0], 0, numsubsectors*sizeof(ss_renderflags[0]));
|
||||
memset(&no_renderflags[0], 0, numnodes*sizeof(no_renderflags[0]));
|
||||
|
||||
next=gl_drawinfo;
|
||||
gl_drawinfo=this;
|
||||
|
|
|
@ -191,6 +191,7 @@ struct FDrawInfo
|
|||
|
||||
TArray<BYTE> sectorrenderflags;
|
||||
TArray<BYTE> ss_renderflags;
|
||||
TArray<BYTE> no_renderflags;
|
||||
|
||||
TArray<MissingTextureInfo> MissingUpperTextures;
|
||||
TArray<MissingTextureInfo> MissingLowerTextures;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "r_sky.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/scene/gl_clipper.h"
|
||||
#include "gl/data/gl_data.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -70,10 +71,11 @@ bool gl_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsecto
|
|||
|
||||
// Lines with stacked sectors must never block!
|
||||
|
||||
if (backsector->CeilingSkyBox && backsector->CeilingSkyBox->bAlways) return false;
|
||||
if (backsector->FloorSkyBox && backsector->FloorSkyBox->bAlways) return false;
|
||||
if (frontsector->CeilingSkyBox && frontsector->CeilingSkyBox->bAlways) return false;
|
||||
if (frontsector->FloorSkyBox && frontsector->FloorSkyBox->bAlways) return false;
|
||||
if (backsector->portals[sector_t::ceiling] != NULL || backsector->portals[sector_t::floor] != NULL ||
|
||||
frontsector->portals[sector_t::ceiling] != NULL || frontsector->portals[sector_t::floor] != NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// on large levels this distinction can save some time
|
||||
// That's a lot of avoided multiplications if there's a lot to see!
|
||||
|
@ -206,7 +208,23 @@ bool CopyPlaneIfValid (secplane_t *dest, const secplane_t *source, const secplan
|
|||
//==========================================================================
|
||||
sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back)
|
||||
{
|
||||
if (!sec->heightsec || sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC || sec->heightsec==sec) return sec;
|
||||
if (!sec->heightsec || sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC || sec->heightsec==sec)
|
||||
{
|
||||
// check for backsectors with the ceiling lower than the floor. These will create
|
||||
// visual glitches because upper amd lower textures overlap.
|
||||
if (back && sec->planes[sector_t::floor].TexZ > sec->planes[sector_t::ceiling].TexZ)
|
||||
{
|
||||
if (!(sec->floorplane.a | sec->floorplane.b | sec->ceilingplane.a | sec->ceilingplane.b))
|
||||
{
|
||||
*dest = *sec;
|
||||
dest->ceilingplane=sec->floorplane;
|
||||
dest->ceilingplane.FlipVert();
|
||||
dest->planes[sector_t::ceiling].TexZ = dest->planes[sector_t::floor].TexZ;
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _DEBUG
|
||||
|
@ -224,8 +242,13 @@ sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
|
||||
int diffTex = (sec->heightsec->MoreFlags & SECF_CLIPFAKEPLANES);
|
||||
sector_t * s = sec->heightsec;
|
||||
|
||||
*dest=*sec;
|
||||
|
||||
#if 0
|
||||
*dest=*sec; // This will invoke the copy operator which isn't really needed here. Memcpy is faster.
|
||||
#else
|
||||
memcpy(dest, sec, sizeof(sector_t));
|
||||
#endif
|
||||
|
||||
// Replace floor and ceiling height with control sector's heights.
|
||||
if (diffTex)
|
||||
{
|
||||
|
@ -298,6 +321,10 @@ sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
|
||||
dest->vboindex[sector_t::ceiling] = sec->vboindex[sector_t::vbo_fakefloor];
|
||||
dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::floor];
|
||||
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
|
||||
{
|
||||
dest->lightlevel = s->lightlevel;
|
||||
}
|
||||
|
||||
if (!back)
|
||||
{
|
||||
|
@ -323,7 +350,6 @@ sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
|
||||
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
|
||||
{
|
||||
dest->lightlevel = s->lightlevel;
|
||||
dest->SetPlaneLight(sector_t::floor, s->GetPlaneLight(sector_t::floor));
|
||||
dest->SetPlaneLight(sector_t::ceiling, s->GetPlaneLight(sector_t::ceiling));
|
||||
dest->ChangeFlags(sector_t::floor, -1, s->GetFlags(sector_t::floor));
|
||||
|
@ -346,6 +372,11 @@ sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
dest->vboindex[sector_t::ceiling] = sec->vboindex[sector_t::ceiling];
|
||||
dest->vboheight[sector_t::ceiling] = sec->vboheight[sector_t::ceiling];
|
||||
|
||||
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
|
||||
{
|
||||
dest->lightlevel = s->lightlevel;
|
||||
}
|
||||
|
||||
if (!back)
|
||||
{
|
||||
dest->SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false);
|
||||
|
|
|
@ -449,11 +449,6 @@ inline void GLFlat::PutFlat(bool fog)
|
|||
{
|
||||
Colormap.GetFixedColormap();
|
||||
}
|
||||
if ((gl.flags&RFL_NOSTENCIL) && !(renderflags&SSRF_RENDER3DPLANES))
|
||||
{
|
||||
renderstyle=STYLE_Translucent;
|
||||
alpha=1.f;
|
||||
}
|
||||
if (renderstyle!=STYLE_Translucent || alpha < 1.f - FLT_EPSILON || fog)
|
||||
{
|
||||
int list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
||||
|
@ -602,14 +597,20 @@ void GLFlat::ProcessSector(sector_t * frontsector)
|
|||
if (frontsector->floorplane.ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy)) <= FIXED2FLOAT(viewz))
|
||||
{
|
||||
// process the original floor first.
|
||||
if (frontsector->FloorSkyBox && frontsector->FloorSkyBox->bAlways) gl_drawinfo->AddFloorStack(sector);
|
||||
|
||||
srf |= SSRF_RENDERFLOOR;
|
||||
|
||||
lightlevel = GetFloorLight(frontsector);
|
||||
Colormap=frontsector->ColorMap;
|
||||
stack = frontsector->FloorSkyBox && frontsector->FloorSkyBox->bAlways;
|
||||
alpha= stack ? frontsector->FloorSkyBox->PlaneAlpha/65536.0f : 1.0f-frontsector->GetFloorReflect();
|
||||
if ((stack = (frontsector->portals[sector_t::floor] != NULL)))
|
||||
{
|
||||
gl_drawinfo->AddFloorStack(sector);
|
||||
alpha = frontsector->GetAlpha(sector_t::floor)/65536.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 1.0f-frontsector->GetReflect(sector_t::floor);
|
||||
}
|
||||
if (frontsector->VBOHeightcheck(sector_t::floor))
|
||||
{
|
||||
vboindex = frontsector->vboindex[sector_t::floor];
|
||||
|
@ -644,14 +645,21 @@ void GLFlat::ProcessSector(sector_t * frontsector)
|
|||
if (frontsector->ceilingplane.ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy)) >= FIXED2FLOAT(viewz))
|
||||
{
|
||||
// process the original ceiling first.
|
||||
if (frontsector->CeilingSkyBox && frontsector->CeilingSkyBox->bAlways) gl_drawinfo->AddCeilingStack(sector);
|
||||
|
||||
srf |= SSRF_RENDERCEILING;
|
||||
|
||||
lightlevel = GetCeilingLight(frontsector);
|
||||
Colormap=frontsector->ColorMap;
|
||||
stack = frontsector->CeilingSkyBox && frontsector->CeilingSkyBox->bAlways;
|
||||
alpha=stack ? frontsector->CeilingSkyBox->PlaneAlpha/65536.0f : 1.0f-frontsector->GetCeilingReflect();
|
||||
if ((stack = (frontsector->portals[sector_t::ceiling] != NULL)))
|
||||
{
|
||||
gl_drawinfo->AddCeilingStack(sector);
|
||||
alpha = frontsector->GetAlpha(sector_t::ceiling)/65536.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 1.0f-frontsector->GetReflect(sector_t::ceiling);
|
||||
}
|
||||
|
||||
if (frontsector->VBOHeightcheck(sector_t::ceiling))
|
||||
{
|
||||
vboindex = frontsector->vboindex[sector_t::ceiling];
|
||||
|
|
|
@ -83,13 +83,11 @@ int GLPortal::renderdepth;
|
|||
int GLPortal::PlaneMirrorMode;
|
||||
GLuint GLPortal::QueryObject;
|
||||
|
||||
bool GLPortal::inupperstack;
|
||||
bool GLPortal::inlowerstack;
|
||||
int GLPortal::instack[2];
|
||||
bool GLPortal::inskybox;
|
||||
|
||||
UniqueList<GLSkyInfo> UniqueSkies;
|
||||
UniqueList<GLHorizonInfo> UniqueHorizons;
|
||||
UniqueList<GLSectorStackInfo> UniqueStacks;
|
||||
UniqueList<secplane_t> UniquePlaneMirrors;
|
||||
|
||||
|
||||
|
@ -104,7 +102,6 @@ void GLPortal::BeginScene()
|
|||
{
|
||||
UniqueSkies.Clear();
|
||||
UniqueHorizons.Clear();
|
||||
UniqueStacks.Clear();
|
||||
UniquePlaneMirrors.Clear();
|
||||
}
|
||||
|
||||
|
@ -292,6 +289,9 @@ bool GLPortal::Start(bool usestencil, bool doquery)
|
|||
savedviewactor=GLRenderer->mViewActor;
|
||||
savedviewangle=viewangle;
|
||||
savedviewarea=in_area;
|
||||
|
||||
NextPortal = GLRenderer->mCurrentPortal;
|
||||
GLRenderer->mCurrentPortal = NULL; // Portals which need this have to set it themselves
|
||||
PortalAll.Unclock();
|
||||
return true;
|
||||
}
|
||||
|
@ -325,6 +325,8 @@ inline void GLPortal::ClearClipper()
|
|||
angle_t a1 = GLRenderer->FrustumAngle();
|
||||
if (a1<ANGLE_180) clipper.SafeAddClipRangeRealAngles(viewangle+a1, viewangle-a1);
|
||||
|
||||
// lock the parts that have just been clipped out.
|
||||
clipper.SetSilhouette();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -337,6 +339,7 @@ void GLPortal::End(bool usestencil)
|
|||
bool needdepth = NeedDepthBuffer();
|
||||
|
||||
PortalAll.Clock();
|
||||
GLRenderer->mCurrentPortal = NextPortal;
|
||||
if (clipsave) gl.Enable (GL_CLIP_PLANE0+renderdepth-1);
|
||||
if (usestencil)
|
||||
{
|
||||
|
@ -435,7 +438,8 @@ void GLPortal::StartFrame()
|
|||
portals.Push(p);
|
||||
if (renderdepth==0)
|
||||
{
|
||||
inskybox=inupperstack=inlowerstack=false;
|
||||
inskybox=false;
|
||||
instack[sector_t::floor]=instack[sector_t::ceiling]=0;
|
||||
}
|
||||
renderdepth++;
|
||||
}
|
||||
|
@ -466,6 +470,15 @@ void GLPortal::EndFrame()
|
|||
{
|
||||
GLPortal * p;
|
||||
|
||||
if (gl.flags & RFL_NOSTENCIL)
|
||||
{
|
||||
while (portals.Pop(p) && p)
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (gl_portalinfo)
|
||||
{
|
||||
Printf("%s%d portals, depth = %d\n%s{\n", indent.GetChars(), portals.Size(), renderdepth, indent.GetChars());
|
||||
|
@ -483,8 +496,10 @@ void GLPortal::EndFrame()
|
|||
{
|
||||
Printf("%sProcessing %s, depth = %d, query = %d\n", indent.GetChars(), p->GetName(), renderdepth, usequery);
|
||||
}
|
||||
|
||||
p->RenderPortal(true, usequery);
|
||||
if (p->lines.Size() > 0)
|
||||
{
|
||||
p->RenderPortal(true, usequery);
|
||||
}
|
||||
delete p;
|
||||
}
|
||||
renderdepth--;
|
||||
|
@ -517,7 +532,7 @@ bool GLPortal::RenderFirstSkyPortal(int recursion)
|
|||
for(unsigned i=portals.Size()-1;i>=0 && portals[i]!=NULL;i--)
|
||||
{
|
||||
p=portals[i];
|
||||
if (p->IsSky())
|
||||
if (p->lines.Size() > 0 && p->IsSky())
|
||||
{
|
||||
// Cannot clear the depth buffer inside a portal recursion
|
||||
if (recursion && p->NeedDepthBuffer()) continue;
|
||||
|
@ -532,9 +547,8 @@ bool GLPortal::RenderFirstSkyPortal(int recursion)
|
|||
|
||||
if (best)
|
||||
{
|
||||
best->RenderPortal(false, false);
|
||||
portals.Delete(bestindex);
|
||||
|
||||
best->RenderPortal(false, false);
|
||||
delete best;
|
||||
return true;
|
||||
}
|
||||
|
@ -547,6 +561,7 @@ bool GLPortal::RenderFirstSkyPortal(int recursion)
|
|||
// FindPortal
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GLPortal * GLPortal::FindPortal(const void * src)
|
||||
{
|
||||
int i=portals.Size()-1;
|
||||
|
@ -556,6 +571,23 @@ GLPortal * GLPortal::FindPortal(const void * src)
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLPortal::SaveMapSection()
|
||||
{
|
||||
savedmapsection.Resize(currentmapsection.Size());
|
||||
memcpy(&savedmapsection[0], ¤tmapsection[0], currentmapsection.Size());
|
||||
memset(¤tmapsection[0], 0, currentmapsection.Size());
|
||||
}
|
||||
|
||||
void GLPortal::RestoreMapSection()
|
||||
{
|
||||
memcpy(¤tmapsection[0], &savedmapsection[0], currentmapsection.Size());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -611,6 +643,12 @@ void GLSkyboxPortal::DrawContents()
|
|||
GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
|
||||
GLRenderer->SetViewArea();
|
||||
ClearClipper();
|
||||
|
||||
int mapsection = R_PointInSubsector(viewx, viewy)->mapsection;
|
||||
|
||||
SaveMapSection();
|
||||
currentmapsection[mapsection>>3] |= 1 << (mapsection & 7);
|
||||
|
||||
GLRenderer->DrawScene();
|
||||
origin->flags&=~MF_JUSTHIT;
|
||||
inskybox=false;
|
||||
|
@ -619,6 +657,60 @@ void GLSkyboxPortal::DrawContents()
|
|||
|
||||
PlaneMirrorMode=old_pm;
|
||||
extralight = saved_extralight;
|
||||
|
||||
RestoreMapSection();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Sector stack Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLSectorStackPortal::SetupCoverage
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static BYTE SetCoverage(void *node)
|
||||
{
|
||||
if (numnodes == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!((size_t)node & 1)) // Keep going until found a subsector
|
||||
{
|
||||
node_t *bsp = (node_t *)node;
|
||||
BYTE coverage = SetCoverage(bsp->children[0]) | SetCoverage(bsp->children[1]);
|
||||
gl_drawinfo->no_renderflags[bsp-nodes] = coverage;
|
||||
return coverage;
|
||||
}
|
||||
else
|
||||
{
|
||||
subsector_t *sub = (subsector_t *)((BYTE *)node - 1);
|
||||
return gl_drawinfo->ss_renderflags[sub-subsectors] & SSRF_SEEN;
|
||||
}
|
||||
}
|
||||
|
||||
void GLSectorStackPortal::SetupCoverage()
|
||||
{
|
||||
for(unsigned i=0; i<subsectors.Size(); i++)
|
||||
{
|
||||
subsector_t *sub = subsectors[i];
|
||||
int plane = origin->plane;
|
||||
for(int j=0;j<sub->portalcoverage[plane].sscount; j++)
|
||||
{
|
||||
subsector_t *dsub = &::subsectors[sub->portalcoverage[plane].subsectors[j]];
|
||||
currentmapsection[dsub->mapsection>>3] |= 1 << (dsub->mapsection&7);
|
||||
gl_drawinfo->ss_renderflags[dsub-::subsectors] |= SSRF_SEEN;
|
||||
}
|
||||
}
|
||||
SetCoverage(&nodes[numnodes-1]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -628,11 +720,10 @@ void GLSkyboxPortal::DrawContents()
|
|||
//-----------------------------------------------------------------------------
|
||||
void GLSectorStackPortal::DrawContents()
|
||||
{
|
||||
FPortal *portal = &::portals[origin->origin->special1];
|
||||
portal->UpdateClipAngles();
|
||||
FPortal *portal = origin;
|
||||
|
||||
viewx += origin->origin->x - origin->origin->Mate->x;
|
||||
viewy += origin->origin->y - origin->origin->Mate->y;
|
||||
viewx += origin->xDisplacement;
|
||||
viewy += origin->yDisplacement;
|
||||
GLRenderer->mViewActor = NULL;
|
||||
GLRenderer->mCurrentPortal = this;
|
||||
|
||||
|
@ -640,153 +731,34 @@ void GLSectorStackPortal::DrawContents()
|
|||
validcount++;
|
||||
|
||||
// avoid recursions!
|
||||
if (origin->isupper) inupperstack=true;
|
||||
else inlowerstack=true;
|
||||
if (origin->plane != -1) instack[origin->plane]++;
|
||||
|
||||
GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
|
||||
SaveMapSection();
|
||||
SetupCoverage();
|
||||
ClearClipper();
|
||||
GLRenderer->DrawScene();
|
||||
RestoreMapSection();
|
||||
|
||||
if (origin->plane != -1) instack[origin->plane]--;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLSectorStackPortal::ClipSeg
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
int GLSectorStackPortal::ClipSeg(seg_t *seg)
|
||||
{
|
||||
FPortal *portal = &::portals[origin->origin->special1];
|
||||
angle_t *angles = &portal->ClipAngles[0];
|
||||
unsigned numpoints = portal->ClipAngles.Size()-1;
|
||||
angle_t clipangle = seg->v1->GetClipAngle();
|
||||
unsigned i, j;
|
||||
int relation;
|
||||
|
||||
// Check the front side of the portal. Anything in front of the shape must be discarded by the clipper.
|
||||
for(i=0;i<numpoints; i++)
|
||||
{
|
||||
if (angles[i+1] - clipangle <= ANGLE_180 && angles[i] - clipangle > ANGLE_180 && angles[i+1] - angles[i] < ANGLE_180)
|
||||
{
|
||||
relation = DMulScale32(seg->v1->y - portal->Shape[i]->y - portal->yDisplacement, portal->Shape[i+1]->x - portal->Shape[i]->x,
|
||||
portal->Shape[i]->x - seg->v1->x + portal->xDisplacement, portal->Shape[i+1]->y - portal->Shape[i]->y);
|
||||
if (relation > 0)
|
||||
{
|
||||
return PClip_InFront;
|
||||
}
|
||||
else if (relation == 0)
|
||||
{
|
||||
// If this vertex is on the boundary we need to check the second one, too. The line may be partially inside the shape
|
||||
// but outside the portal. We can use the same boundary line for this
|
||||
relation = DMulScale32(seg->v2->y - portal->Shape[i]->y - portal->yDisplacement, portal->Shape[i+1]->x - portal->Shape[i]->x,
|
||||
portal->Shape[i]->x - seg->v2->x + portal->xDisplacement, portal->Shape[i+1]->y - portal->Shape[i]->y);
|
||||
if (relation >= 0) return PClip_InFront;
|
||||
}
|
||||
return PClip_Inside;
|
||||
}
|
||||
}
|
||||
|
||||
// The first vertex did not yield any useful result. Check the second one.
|
||||
clipangle = seg->v2->GetClipAngle();
|
||||
for(j=0;j<numpoints; j++)
|
||||
{
|
||||
if (angles[j+1] - clipangle <= ANGLE_180 && angles[j] - clipangle > ANGLE_180 && angles[j+1] - angles[j] < ANGLE_180)
|
||||
{
|
||||
relation = DMulScale32(seg->v2->y - portal->Shape[j]->y - portal->yDisplacement, portal->Shape[j+1]->x - portal->Shape[j]->x,
|
||||
portal->Shape[j]->x - seg->v1->x + portal->xDisplacement, portal->Shape[j+1]->y - portal->Shape[j]->y);
|
||||
if (relation > 0)
|
||||
{
|
||||
return PClip_InFront;
|
||||
}
|
||||
else if (relation == 0)
|
||||
{
|
||||
// If this vertex is on the boundary we need to check the second one, too. The line may be partially inside the shape
|
||||
// but outside the portal. We can use the same boundary line for this
|
||||
relation = DMulScale32(seg->v2->y - portal->Shape[j]->y - portal->yDisplacement, portal->Shape[j+1]->x - portal->Shape[j]->x,
|
||||
portal->Shape[j]->x - seg->v2->x + portal->xDisplacement, portal->Shape[j+1]->y - portal->Shape[j]->y);
|
||||
if (relation >= 0) return PClip_InFront;
|
||||
}
|
||||
return PClip_Inside;
|
||||
}
|
||||
}
|
||||
return PClip_Inside; // The viewpoint is inside the portal
|
||||
|
||||
#if 0
|
||||
// Check backside of portal
|
||||
for(i=0;i<numpoints; i++)
|
||||
{
|
||||
if (angles[i+1] - clipangle > ANGLE_180 && angles[i] - clipangle <= ANGLE_180)
|
||||
{
|
||||
relation1 = DMulScale32(seg->v1->y - portal->Shape[i]->y - portal->yDisplacement, portal->Shape[i+1]->x - portal->Shape[i]->x,
|
||||
portal->Shape[i]->x - seg->v1->x + portal->xDisplacement, portal->Shape[i+1]->y - portal->Shape[i]->y);
|
||||
if (relation1 < 0) return PClip_Inside;
|
||||
// If this vertex is inside we need to check the second one, too. The line may be partially inside the shape
|
||||
// but outside the portal.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clipangle = seg->v2->GetClipAngle();
|
||||
for(j=0;j<numpoints; j++)
|
||||
{
|
||||
if (angles[j+1] - clipangle > ANGLE_180 && angles[j] - clipangle <= ANGLE_180)
|
||||
{
|
||||
relation2 = DMulScale32(seg->v2->y - portal->Shape[j]->y - portal->yDisplacement, portal->Shape[j+1]->x - portal->Shape[j]->x,
|
||||
portal->Shape[j]->x - seg->v2->x + portal->xDisplacement, portal->Shape[j+1]->y - portal->Shape[j]->y);
|
||||
if (relation2 < 0) return PClip_Inside;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return PClip_Behind;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLSectorStackPortal::ClipPoint
|
||||
//
|
||||
// Plane Mirror Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
int GLSectorStackPortal::ClipPoint(fixed_t x, fixed_t y)
|
||||
{
|
||||
FPortal *portal = &::portals[origin->origin->special1];
|
||||
angle_t *angles = &portal->ClipAngles[0];
|
||||
unsigned numpoints = portal->ClipAngles.Size()-1;
|
||||
angle_t clipangle = R_PointToPseudoAngle(viewx, viewy, x, y);
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<numpoints; i++)
|
||||
{
|
||||
if (angles[i+1] - clipangle <= ANGLE_180 && angles[i] - clipangle > ANGLE_180 && angles[i+1] - angles[i] < ANGLE_180)
|
||||
{
|
||||
int relation = DMulScale32(y - portal->Shape[i]->y - portal->yDisplacement, portal->Shape[i+1]->x - portal->Shape[i]->x,
|
||||
portal->Shape[i]->x - x + portal->xDisplacement, portal->Shape[i+1]->y - portal->Shape[i]->y);
|
||||
if (relation > 0) return PClip_InFront;
|
||||
return PClip_Inside;
|
||||
}
|
||||
}
|
||||
return PClip_Inside;
|
||||
|
||||
/*
|
||||
for(i=0;i<numpoints; i++)
|
||||
{
|
||||
if (clipangle >= angles[i] && clipangle < angles[i+1])
|
||||
{
|
||||
int relation = DMulScale32(y - portal->Shape[i]->y, portal->Shape[i+1]->x - portal->Shape[i]->x,
|
||||
portal->Shape[i]->x - x, portal->Shape[i+1]->y - portal->Shape[i]->y);
|
||||
if (relation > 0) return PClip_InFront;
|
||||
return PClip_Inside;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return PClip_Inside;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLPlaneMirrorPortal::DrawContents
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLPlaneMirrorPortal::DrawContents()
|
||||
{
|
||||
if (renderdepth>r_mirror_recursions)
|
||||
|
@ -820,6 +792,13 @@ void GLPlaneMirrorPortal::DrawContents()
|
|||
PlaneMirrorMode=old_pm;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLPlaneMirrorPortal::DrawContents
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -72,17 +72,8 @@ struct GLSkyInfo
|
|||
}
|
||||
};
|
||||
|
||||
struct GLSectorStackInfo
|
||||
{
|
||||
ASkyViewpoint *origin;
|
||||
bool isupper;
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern UniqueList<GLSkyInfo> UniqueSkies;
|
||||
extern UniqueList<GLHorizonInfo> UniqueHorizons;
|
||||
extern UniqueList<GLSectorStackInfo> UniqueStacks;
|
||||
extern UniqueList<secplane_t> UniquePlaneMirrors;
|
||||
|
||||
class GLPortal
|
||||
|
@ -97,8 +88,8 @@ protected:
|
|||
|
||||
public:
|
||||
static int PlaneMirrorMode;
|
||||
static bool inupperstack;
|
||||
static bool inlowerstack;
|
||||
static int inupperstack;
|
||||
static int instack[2];
|
||||
static bool inskybox;
|
||||
|
||||
private:
|
||||
|
@ -111,6 +102,8 @@ private:
|
|||
AActor * savedviewactor;
|
||||
area_t savedviewarea;
|
||||
unsigned char clipsave;
|
||||
GLPortal *NextPortal;
|
||||
TArray<BYTE> savedmapsection;
|
||||
|
||||
protected:
|
||||
TArray<GLWall> lines;
|
||||
|
@ -129,6 +122,8 @@ protected:
|
|||
virtual bool NeedDepthBuffer() { return true; }
|
||||
void ClearScreen();
|
||||
virtual const char *GetName() = 0;
|
||||
void SaveMapSection();
|
||||
void RestoreMapSection();
|
||||
|
||||
public:
|
||||
|
||||
|
@ -241,21 +236,25 @@ public:
|
|||
|
||||
struct GLSectorStackPortal : public GLPortal
|
||||
{
|
||||
TArray<subsector_t *> subsectors;
|
||||
protected:
|
||||
virtual void DrawContents();
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one.
|
||||
virtual const char *GetName();
|
||||
GLSectorStackInfo * origin;
|
||||
FPortal *origin;
|
||||
|
||||
public:
|
||||
|
||||
GLSectorStackPortal(GLSectorStackInfo * pt)
|
||||
GLSectorStackPortal(FPortal *pt)
|
||||
{
|
||||
origin=pt;
|
||||
}
|
||||
int ClipSeg(seg_t *seg);
|
||||
int ClipPoint(fixed_t x, fixed_t y);
|
||||
void SetupCoverage();
|
||||
void AddSubsector(subsector_t *sub)
|
||||
{
|
||||
subsectors.Push(sub);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "gl/dynlights/gl_glow.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/utility/gl_templates.h"
|
||||
|
||||
|
@ -679,7 +680,7 @@ void FDrawInfo::DrawUnhandledMissingTextures()
|
|||
if (seg->PartnerSeg && (seg->PartnerSeg->Subsector()->flags & SSECF_DEGENERATE)) continue;
|
||||
if (seg->backsector->transdoor) continue;
|
||||
if (seg->backsector->GetTexture(sector_t::ceiling)==skyflatnum) continue;
|
||||
if (seg->backsector->CeilingSkyBox && seg->backsector->CeilingSkyBox->bAlways) continue;
|
||||
if (seg->backsector->portals[sector_t::ceiling] != NULL) continue;
|
||||
|
||||
if (!glset.notexturefill) FloodUpperGap(seg);
|
||||
}
|
||||
|
@ -699,7 +700,7 @@ void FDrawInfo::DrawUnhandledMissingTextures()
|
|||
if (seg->frontsector->GetPlaneTexZ(sector_t::floor) > viewz) continue; // out of sight
|
||||
if (seg->backsector->transdoor) continue;
|
||||
if (seg->backsector->GetTexture(sector_t::floor)==skyflatnum) continue;
|
||||
if (seg->backsector->FloorSkyBox && seg->backsector->FloorSkyBox->bAlways) continue;
|
||||
if (seg->backsector->portals[sector_t::floor] != NULL) continue;
|
||||
|
||||
if (!glset.notexturefill) FloodLowerGap(seg);
|
||||
}
|
||||
|
@ -1058,7 +1059,7 @@ void FDrawInfo::CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor)
|
|||
sub->validcount=validcount;
|
||||
|
||||
// Has a sector stack or skybox itself!
|
||||
if (sub->render_sector->CeilingSkyBox && sub->render_sector->CeilingSkyBox->bAlways) return;
|
||||
if (sub->render_sector->portals[sector_t::ceiling] != NULL) return;
|
||||
|
||||
// Don't bother processing unrendered subsectors
|
||||
if (sub->numlines>2 && !(ss_renderflags[DWORD(sub-subsectors)]&SSRF_PROCESSED)) return;
|
||||
|
@ -1106,7 +1107,7 @@ void FDrawInfo::CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor)
|
|||
sub->validcount=validcount;
|
||||
|
||||
// Has a sector stack or skybox itself!
|
||||
if (sub->render_sector->FloorSkyBox && sub->render_sector->FloorSkyBox->bAlways) return;
|
||||
if (sub->render_sector->portals[sector_t::floor] != NULL) return;
|
||||
|
||||
// Don't bother processing unrendered subsectors
|
||||
if (sub->numlines>2 && !(ss_renderflags[DWORD(sub-subsectors)]&SSRF_PROCESSED)) return;
|
||||
|
@ -1155,7 +1156,8 @@ void FDrawInfo::ProcessSectorStacks()
|
|||
for (i=0;i<CeilingStacks.Size (); i++)
|
||||
{
|
||||
sector_t *sec = CeilingStacks[i];
|
||||
for(int k=0;k<sec->subsectorcount;k++)
|
||||
FPortal *portal = sec->portals[sector_t::ceiling];
|
||||
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
|
||||
{
|
||||
subsector_t * sub = sec->subsectors[k];
|
||||
if (ss_renderflags[sub-subsectors] & SSRF_PROCESSED)
|
||||
|
@ -1173,12 +1175,20 @@ void FDrawInfo::ProcessSectorStacks()
|
|||
}
|
||||
for(unsigned int j=0;j<HandledSubsectors.Size();j++)
|
||||
{
|
||||
ss_renderflags[DWORD(HandledSubsectors[j]-subsectors)] &= ~SSRF_RENDERCEILING;
|
||||
subsector_t *sub = HandledSubsectors[j];
|
||||
ss_renderflags[DWORD(sub-subsectors)] &= ~SSRF_RENDERCEILING;
|
||||
|
||||
if (sub->render_sector->CeilingSkyBox->PlaneAlpha!=0)
|
||||
if (sub->portalcoverage[sector_t::ceiling].subsectors == NULL)
|
||||
{
|
||||
gl_BuildPortalCoverage(&sub->portalcoverage[sector_t::ceiling], sub, portal);
|
||||
}
|
||||
|
||||
portal->GetGLPortal()->AddSubsector(sub);
|
||||
|
||||
if (sec->GetAlpha(sector_t::ceiling) != 0)
|
||||
{
|
||||
gl_subsectorrendernode * node = SSR_List.GetNew();
|
||||
node->sub = HandledSubsectors[j];
|
||||
node->sub = sub;
|
||||
AddOtherCeilingPlane(sub->render_sector->sectornum, node);
|
||||
}
|
||||
}
|
||||
|
@ -1190,7 +1200,8 @@ void FDrawInfo::ProcessSectorStacks()
|
|||
for (i=0;i<FloorStacks.Size (); i++)
|
||||
{
|
||||
sector_t *sec = FloorStacks[i];
|
||||
for(int k=0;k<sec->subsectorcount;k++)
|
||||
FPortal *portal = sec->portals[sector_t::floor];
|
||||
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
|
||||
{
|
||||
subsector_t * sub = sec->subsectors[k];
|
||||
if (ss_renderflags[sub-subsectors] & SSRF_PROCESSED)
|
||||
|
@ -1209,13 +1220,21 @@ void FDrawInfo::ProcessSectorStacks()
|
|||
|
||||
for(unsigned int j=0;j<HandledSubsectors.Size();j++)
|
||||
{
|
||||
//Printf("%d: ss %d, sec %d\n", j, HandledSubsectors[j]-subsectors, HandledSubsectors[j]->render_sector->sectornum);
|
||||
ss_renderflags[DWORD(HandledSubsectors[j]-subsectors)] &= ~SSRF_RENDERFLOOR;
|
||||
subsector_t *sub = HandledSubsectors[j];
|
||||
ss_renderflags[DWORD(sub-subsectors)] &= ~SSRF_RENDERFLOOR;
|
||||
|
||||
if (sub->render_sector->FloorSkyBox->PlaneAlpha!=0)
|
||||
if (sub->portalcoverage[sector_t::floor].subsectors == NULL)
|
||||
{
|
||||
gl_BuildPortalCoverage(&sub->portalcoverage[sector_t::floor], sub, portal);
|
||||
}
|
||||
|
||||
GLSectorStackPortal *glportal = portal->GetGLPortal();
|
||||
glportal->AddSubsector(sub);
|
||||
|
||||
if (sec->GetAlpha(sector_t::floor)!=0)
|
||||
{
|
||||
gl_subsectorrendernode * node = SSR_List.GetNew();
|
||||
node->sub = HandledSubsectors[j];
|
||||
node->sub = sub;
|
||||
AddOtherFloorPlane(sub->render_sector->sectornum, node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ extern int viewpitch;
|
|||
|
||||
DWORD gl_fixedcolormap;
|
||||
area_t in_area;
|
||||
TArray<BYTE> currentmapsection;
|
||||
|
||||
|
||||
void R_SetupFrame (AActor * camera);
|
||||
|
@ -312,6 +313,7 @@ void FGLRenderer::CreateScene()
|
|||
ProcessAll.Clock();
|
||||
|
||||
// clip the scene and fill the drawlists
|
||||
for(unsigned i=0;i<portals.Size(); i++) portals[i]->glportal = NULL;
|
||||
gl_spriteindex=0;
|
||||
Bsp.Clock();
|
||||
gl_RenderBSPNode (nodes + numnodes - 1);
|
||||
|
@ -847,6 +849,9 @@ void FGLRenderer::ProcessScene(bool toscreen)
|
|||
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
|
||||
GLPortal::BeginScene();
|
||||
|
||||
int mapsection = R_PointInSubsector(viewx, viewy)->mapsection;
|
||||
memset(¤tmapsection[0], 0, currentmapsection.Size());
|
||||
currentmapsection[mapsection>>3] |= 1 << (mapsection & 7);
|
||||
DrawScene(toscreen);
|
||||
FDrawInfo::EndDrawInfo();
|
||||
|
||||
|
@ -951,9 +956,6 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
|
|||
//-----------------------------------------------------------------------------
|
||||
static FRandom pr_glhom;
|
||||
EXTERN_CVAR(Int, r_clearbuffer)
|
||||
CVAR(Bool, gl_testdl, false, 0)
|
||||
static int dl = -1;
|
||||
static int indl = 0;
|
||||
|
||||
void FGLRenderer::RenderView (player_t* player)
|
||||
{
|
||||
|
@ -1035,31 +1037,9 @@ void FGLRenderer::RenderView (player_t* player)
|
|||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
GLRenderer->mLightCount = ((it.Next()) != NULL);
|
||||
|
||||
if (gl_testdl)
|
||||
{
|
||||
if (dl == -1)
|
||||
{
|
||||
dl = glGenLists(1);
|
||||
glNewList(dl, GL_COMPILE_AND_EXECUTE);
|
||||
indl = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
glCallList(dl);
|
||||
All.Unclock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sector_t * viewsector = RenderViewpoint(player->camera, NULL, FieldOfView * 360.0f / FINEANGLES, ratio, fovratio, true, true);
|
||||
EndDrawScene(viewsector);
|
||||
|
||||
if (gl_testdl && indl)
|
||||
{
|
||||
indl = false;
|
||||
glEndList();
|
||||
}
|
||||
|
||||
All.Unclock();
|
||||
}
|
||||
|
||||
|
|
|
@ -62,118 +62,104 @@ enum
|
|||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Calculate mirrorplane
|
||||
//
|
||||
//==========================================================================
|
||||
void GLWall::MirrorPlane(secplane_t * plane, bool ceiling)
|
||||
{
|
||||
if (!(gl.flags&RFL_NOSTENCIL))
|
||||
{
|
||||
if (ceiling && FIXED2FLOAT(viewz) >= plane->ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy))) return;
|
||||
if (!ceiling && FIXED2FLOAT(viewz) <= plane->ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy))) return;
|
||||
type=RENDERWALL_PLANEMIRROR;
|
||||
planemirror=plane;
|
||||
PutWall(0);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Calculate sky texture
|
||||
//
|
||||
//==========================================================================
|
||||
void GLWall::SkyTexture(int sky1,ASkyViewpoint * skyboxx, bool ceiling)
|
||||
void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect)
|
||||
{
|
||||
GLSkyInfo skyinfo;
|
||||
|
||||
// JUSTHIT is used as an indicator that a skybox is in use.
|
||||
// This is to avoid recursion
|
||||
if (!gl_noskyboxes && !(gl.flags&RFL_NOSTENCIL) && skyboxx && GLRenderer->mViewActor!=skyboxx && !(skyboxx->flags&MF_JUSTHIT))
|
||||
FPortal *portal = sector->portals[plane];
|
||||
if (portal != NULL)
|
||||
{
|
||||
if (!skyboxx->Mate)
|
||||
if (GLPortal::instack[1-plane]) return;
|
||||
type=RENDERWALL_SECTORSTACK;
|
||||
this->portal = portal;
|
||||
}
|
||||
else if (sector->GetTexture(plane)==skyflatnum)
|
||||
{
|
||||
GLSkyInfo skyinfo;
|
||||
ASkyViewpoint * skyboxx = plane == sector_t::floor? sector->FloorSkyBox : sector->CeilingSkyBox;
|
||||
|
||||
// JUSTHIT is used as an indicator that a skybox is in use.
|
||||
// This is to avoid recursion
|
||||
|
||||
if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor!=skyboxx && !(skyboxx->flags&MF_JUSTHIT))
|
||||
{
|
||||
type=RENDERWALL_SKYBOX;
|
||||
skybox=skyboxx;
|
||||
}
|
||||
else
|
||||
{
|
||||
static GLSectorStackInfo stackinfo;
|
||||
if (ceiling && GLPortal::inlowerstack) return;
|
||||
if (!ceiling && GLPortal::inupperstack) return;
|
||||
type=RENDERWALL_SECTORSTACK;
|
||||
stackinfo.origin = skyboxx;
|
||||
stackinfo.isupper= ceiling;
|
||||
stack=&stackinfo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skyboxx && skyboxx->Mate) return;
|
||||
|
||||
memset(&skyinfo, 0, sizeof(skyinfo));
|
||||
if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT-1)) && !(gl.flags&RFL_NOSTENCIL))
|
||||
{
|
||||
const line_t *l = &lines[(sky1&(PL_SKYFLAT-1))-1];
|
||||
const side_t *s = l->sidedef[0];
|
||||
int pos;
|
||||
|
||||
if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
|
||||
{
|
||||
pos = side_t::bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = side_t::top;
|
||||
}
|
||||
|
||||
FTextureID texno = s->GetTexture(pos);
|
||||
skyinfo.texture[0] = FMaterial::ValidateTexture(texno, true);
|
||||
if (!skyinfo.texture[0] || skyinfo.texture[0]->tex->UseType == FTexture::TEX_Null) goto normalsky;
|
||||
skyinfo.skytexno1 = texno;
|
||||
skyinfo.x_offset[0] = ANGLE_TO_FLOAT(s->GetTextureXOffset(pos));
|
||||
skyinfo.y_offset = FIXED2FLOAT(s->GetTextureYOffset(pos));
|
||||
skyinfo.mirrored = !l->args[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
normalsky:
|
||||
if (level.flags&LEVEL_DOUBLESKY)
|
||||
int sky1 = sector->sky;
|
||||
memset(&skyinfo, 0, sizeof(skyinfo));
|
||||
if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT-1)))
|
||||
{
|
||||
skyinfo.texture[1]=FMaterial::ValidateTexture(sky1texture, true);
|
||||
if (!skyinfo.texture[1]) return;
|
||||
skyinfo.x_offset[1] = GLRenderer->mSky1Pos;
|
||||
skyinfo.doublesky = true;
|
||||
}
|
||||
|
||||
if ((level.flags&LEVEL_SWAPSKIES || (sky1==PL_SKYFLAT && !(gl.flags&RFL_NOSTENCIL)) || (level.flags&LEVEL_DOUBLESKY)) &&
|
||||
sky2texture!=sky1texture) // If both skies are equal use the scroll offset of the first!
|
||||
{
|
||||
skyinfo.texture[0]=FMaterial::ValidateTexture(sky2texture, true);
|
||||
skyinfo.skytexno1=sky2texture;
|
||||
skyinfo.sky2 = true;
|
||||
skyinfo.x_offset[0] = GLRenderer->mSky2Pos;
|
||||
const line_t *l = &lines[(sky1&(PL_SKYFLAT-1))-1];
|
||||
const side_t *s = l->sidedef[0];
|
||||
int pos;
|
||||
|
||||
if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
|
||||
{
|
||||
pos = side_t::bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = side_t::top;
|
||||
}
|
||||
|
||||
FTextureID texno = s->GetTexture(pos);
|
||||
skyinfo.texture[0] = FMaterial::ValidateTexture(texno, true);
|
||||
if (!skyinfo.texture[0] || skyinfo.texture[0]->tex->UseType == FTexture::TEX_Null) goto normalsky;
|
||||
skyinfo.skytexno1 = texno;
|
||||
skyinfo.x_offset[0] = ANGLE_TO_FLOAT(s->GetTextureXOffset(pos));
|
||||
skyinfo.y_offset = FIXED2FLOAT(s->GetTextureYOffset(pos));
|
||||
skyinfo.mirrored = !l->args[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
skyinfo.texture[0]=FMaterial::ValidateTexture(sky1texture, true);
|
||||
skyinfo.skytexno1=sky1texture;
|
||||
skyinfo.x_offset[0] = GLRenderer->mSky1Pos;
|
||||
normalsky:
|
||||
if (level.flags&LEVEL_DOUBLESKY)
|
||||
{
|
||||
skyinfo.texture[1]=FMaterial::ValidateTexture(sky1texture, true);
|
||||
skyinfo.x_offset[1] = GLRenderer->mSky1Pos;
|
||||
skyinfo.doublesky = true;
|
||||
}
|
||||
|
||||
if ((level.flags&LEVEL_SWAPSKIES || (sky1==PL_SKYFLAT) || (level.flags&LEVEL_DOUBLESKY)) &&
|
||||
sky2texture!=sky1texture) // If both skies are equal use the scroll offset of the first!
|
||||
{
|
||||
skyinfo.texture[0]=FMaterial::ValidateTexture(sky2texture, true);
|
||||
skyinfo.skytexno1=sky2texture;
|
||||
skyinfo.sky2 = true;
|
||||
skyinfo.x_offset[0] = GLRenderer->mSky2Pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
skyinfo.texture[0]=FMaterial::ValidateTexture(sky1texture, true);
|
||||
skyinfo.skytexno1=sky1texture;
|
||||
skyinfo.x_offset[0] = GLRenderer->mSky1Pos;
|
||||
}
|
||||
}
|
||||
if (!skyinfo.texture[0]) return;
|
||||
if (skyfog>0)
|
||||
{
|
||||
skyinfo.fadecolor=Colormap.FadeColor;
|
||||
skyinfo.fadecolor.a=0;
|
||||
}
|
||||
else skyinfo.fadecolor=0;
|
||||
|
||||
type=RENDERWALL_SKY;
|
||||
sky=UniqueSkies.Get(&skyinfo);
|
||||
}
|
||||
if (skyfog>0)
|
||||
{
|
||||
skyinfo.fadecolor=Colormap.FadeColor;
|
||||
skyinfo.fadecolor.a=0;
|
||||
}
|
||||
else skyinfo.fadecolor=0;
|
||||
|
||||
type=RENDERWALL_SKY;
|
||||
sky = &skyinfo;
|
||||
}
|
||||
else if (allowreflect && sector->GetReflect(plane) > 0)
|
||||
{
|
||||
if ((plane == sector_t::ceiling && viewz > sector->ceilingplane.d) ||
|
||||
(plane == sector_t::floor && viewz < -sector->floorplane.d)) return;
|
||||
type=RENDERWALL_PLANEMIRROR;
|
||||
planemirror = plane == sector_t::ceiling? §or->ceilingplane : §or->floorplane;
|
||||
}
|
||||
else return;
|
||||
PutWall(0);
|
||||
}
|
||||
|
||||
|
@ -183,34 +169,26 @@ void GLWall::SkyTexture(int sky1,ASkyViewpoint * skyboxx, bool ceiling)
|
|||
// Skies on one sided walls
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLWall::SkyNormal(sector_t * fs,vertex_t * v1,vertex_t * v2)
|
||||
{
|
||||
bool ceilingsky = fs->GetTexture(sector_t::ceiling)==skyflatnum || (fs->CeilingSkyBox && fs->CeilingSkyBox->bAlways);
|
||||
if (ceilingsky || fs->ceiling_reflect)
|
||||
{
|
||||
ztop[0]=ztop[1]=32768.0f;
|
||||
zbottom[0]=zceil[0];
|
||||
zbottom[1]=zceil[1];
|
||||
if (ceilingsky) SkyTexture(fs->sky,fs->CeilingSkyBox, true);
|
||||
else MirrorPlane(&fs->ceilingplane, true);
|
||||
}
|
||||
bool floorsky = fs->GetTexture(sector_t::floor)==skyflatnum || (fs->FloorSkyBox && fs->FloorSkyBox->bAlways);
|
||||
if (floorsky || fs->floor_reflect)
|
||||
{
|
||||
ztop[0]=zfloor[0];
|
||||
ztop[1]=zfloor[1];
|
||||
zbottom[0]=zbottom[1]=-32768.0f;
|
||||
if (floorsky) SkyTexture(fs->sky,fs->FloorSkyBox, false);
|
||||
else MirrorPlane(&fs->floorplane, false);
|
||||
}
|
||||
}
|
||||
ztop[0]=ztop[1]=32768.0f;
|
||||
zbottom[0]=zceil[0];
|
||||
zbottom[1]=zceil[1];
|
||||
SkyPlane(fs, sector_t::ceiling, true);
|
||||
|
||||
ztop[0]=zfloor[0];
|
||||
ztop[1]=zfloor[1];
|
||||
zbottom[0]=zbottom[1]=-32768.0f;
|
||||
SkyPlane(fs, sector_t::floor, true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Upper Skies on two sided walls
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
|
||||
{
|
||||
if (fs->GetTexture(sector_t::ceiling)==skyflatnum)
|
||||
|
@ -241,7 +219,7 @@ void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex
|
|||
ztop[0]=ztop[1]=32768.0f;
|
||||
zbottom[0]=zbottom[1]=
|
||||
FIXED2FLOAT(bs->ceilingplane.ZatPoint(v2) + seg->sidedef->GetTextureYOffset(side_t::mid));
|
||||
SkyTexture(fs->sky,fs->CeilingSkyBox, true);
|
||||
SkyPlane(fs, sector_t::ceiling, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -263,25 +241,36 @@ void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex
|
|||
zbottom[1]=FIXED2FLOAT(bs->ceilingplane.ZatPoint(v2));
|
||||
flags|=GLWF_SKYHACK; // mid textures on such lines need special treatment!
|
||||
}
|
||||
|
||||
SkyTexture(fs->sky,fs->CeilingSkyBox, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ceilingsky = (fs->CeilingSkyBox && fs->CeilingSkyBox->bAlways && fs->CeilingSkyBox!=bs->CeilingSkyBox);
|
||||
if (ceilingsky || fs->ceiling_reflect)
|
||||
FPortal *pfront = fs->portals[sector_t::ceiling];
|
||||
FPortal *pback = bs->portals[sector_t::ceiling];
|
||||
float frontreflect = fs->GetReflect(sector_t::ceiling);
|
||||
if (frontreflect > 0)
|
||||
{
|
||||
// stacked sectors
|
||||
fixed_t fsc1=fs->ceilingplane.ZatPoint(v1);
|
||||
fixed_t fsc2=fs->ceilingplane.ZatPoint(v2);
|
||||
|
||||
ztop[0]=ztop[1]=32768.0f;
|
||||
zbottom[0]=FIXED2FLOAT(fsc1);
|
||||
zbottom[1]=FIXED2FLOAT(fsc2);
|
||||
if (ceilingsky) SkyTexture(fs->sky,fs->CeilingSkyBox, true);
|
||||
else MirrorPlane(&fs->ceilingplane, true);
|
||||
float backreflect = bs->GetReflect(sector_t::ceiling);
|
||||
if (backreflect > 0 && bs->ceilingplane.d == fs->ceilingplane.d)
|
||||
{
|
||||
// Don't add intra-portal line to the portal.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (pfront == NULL || pfront == pback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// stacked sectors
|
||||
fixed_t fsc1=fs->ceilingplane.ZatPoint(v1);
|
||||
fixed_t fsc2=fs->ceilingplane.ZatPoint(v2);
|
||||
|
||||
ztop[0]=ztop[1]=32768.0f;
|
||||
zbottom[0]=FIXED2FLOAT(fsc1);
|
||||
zbottom[1]=FIXED2FLOAT(fsc2);
|
||||
}
|
||||
|
||||
SkyPlane(fs, sector_t::ceiling, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -290,6 +279,7 @@ void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex
|
|||
// Lower Skies on two sided walls
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLWall::SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
|
||||
{
|
||||
if (fs->GetTexture(sector_t::floor)==skyflatnum)
|
||||
|
@ -327,24 +317,35 @@ void GLWall::SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,ver
|
|||
ztop[1]=FIXED2FLOAT(bs->floorplane.ZatPoint(v2));
|
||||
flags|=GLWF_SKYHACK; // mid textures on such lines need special treatment!
|
||||
}
|
||||
|
||||
SkyTexture(fs->sky,fs->FloorSkyBox, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool floorsky = (fs->FloorSkyBox && fs->FloorSkyBox->bAlways && fs->FloorSkyBox!=bs->FloorSkyBox);
|
||||
if (floorsky || fs->floor_reflect)
|
||||
FPortal *pfront = fs->portals[sector_t::floor];
|
||||
FPortal *pback = bs->portals[sector_t::floor];
|
||||
float frontreflect = fs->GetReflect(sector_t::floor);
|
||||
if (frontreflect > 0)
|
||||
{
|
||||
// stacked sectors
|
||||
fixed_t fsc1=fs->floorplane.ZatPoint(v1);
|
||||
fixed_t fsc2=fs->floorplane.ZatPoint(v2);
|
||||
|
||||
zbottom[0]=zbottom[1]=-32768.0f;
|
||||
ztop[0]=FIXED2FLOAT(fsc1);
|
||||
ztop[1]=FIXED2FLOAT(fsc2);
|
||||
|
||||
if (floorsky) SkyTexture(fs->sky,fs->FloorSkyBox, false);
|
||||
else MirrorPlane(&fs->floorplane, false);
|
||||
float backreflect = bs->GetReflect(sector_t::floor);
|
||||
if (backreflect > 0 && bs->floorplane.d == fs->floorplane.d)
|
||||
{
|
||||
// Don't add intra-portal line to the portal.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (pfront == NULL || pfront == pback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// stacked sectors
|
||||
fixed_t fsc1=fs->floorplane.ZatPoint(v1);
|
||||
fixed_t fsc2=fs->floorplane.ZatPoint(v2);
|
||||
|
||||
zbottom[0]=zbottom[1]=-32768.0f;
|
||||
ztop[0]=FIXED2FLOAT(fsc1);
|
||||
ztop[1]=FIXED2FLOAT(fsc2);
|
||||
}
|
||||
|
||||
SkyPlane(fs, sector_t::floor, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,10 @@ CVAR(Float, gl_sclipfactor, 1.8, CVAR_ARCHIVE)
|
|||
CVAR(Int, gl_particles_style, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // 0 = square, 1 = round, 2 = smooth
|
||||
CVAR(Int, gl_billboard_mode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, gl_enhanced_nv_stealth, 3, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CUSTOM_CVAR(Int, gl_fuzztype, 0, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0 || self > 7) self = 0;
|
||||
}
|
||||
|
||||
extern bool r_showviewer;
|
||||
EXTERN_CVAR (Float, transsouls)
|
||||
|
@ -136,7 +140,7 @@ void GLSprite::Draw(int pass)
|
|||
gl_RenderState.AlphaFunc(GL_GEQUAL,trans*gl_mask_sprite_threshold);
|
||||
}
|
||||
|
||||
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||
if (RenderStyle.BlendOp == STYLEOP_Shadow)
|
||||
{
|
||||
float fuzzalpha=0.44f;
|
||||
float minalpha=0.1f;
|
||||
|
@ -166,7 +170,7 @@ void GLSprite::Draw(int pass)
|
|||
additivefog = true;
|
||||
}
|
||||
}
|
||||
if (RenderStyle.BlendOp!=STYLEOP_Fuzz)
|
||||
if (RenderStyle.BlendOp!=STYLEOP_Shadow)
|
||||
{
|
||||
if (actor)
|
||||
{
|
||||
|
@ -203,7 +207,7 @@ void GLSprite::Draw(int pass)
|
|||
|
||||
gl_SetFog(foglevel, rel, &Colormap, additivefog);
|
||||
|
||||
if (gltexture) gltexture->BindPatch(Colormap.colormap,translation);
|
||||
if (gltexture) gltexture->BindPatch(Colormap.colormap, translation, OverrideShader);
|
||||
else if (!modelframe) gl_RenderState.EnableTexture(false);
|
||||
|
||||
if (!modelframe)
|
||||
|
@ -446,6 +450,9 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
|
|||
return;
|
||||
}
|
||||
|
||||
// If this thing is in a map section that's not in view it can't possible be visible
|
||||
if (!(currentmapsection[thing->subsector->mapsection>>3] & (1 << (thing->subsector->mapsection & 7)))) return;
|
||||
|
||||
// [RH] Interpolate the sprite's position to make it look smooth
|
||||
fixed_t thingx = thing->PrevX + FixedMul (r_TicFrac, thing->x - thing->PrevX);
|
||||
fixed_t thingy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY);
|
||||
|
@ -726,10 +733,30 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
|
|||
|
||||
ThingColor=0xffffff;
|
||||
RenderStyle = thing->RenderStyle;
|
||||
RenderStyle.CheckFuzz();
|
||||
OverrideShader = 0;
|
||||
trans = FIXED2FLOAT(thing->alpha);
|
||||
hw_styleflags = STYLEHW_Normal;
|
||||
|
||||
if (RenderStyle.BlendOp >= STYLEOP_Fuzz && RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub)
|
||||
{
|
||||
RenderStyle.CheckFuzz();
|
||||
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||
{
|
||||
if (gl.shadermodel >= 4 && gl_fuzztype != 0)
|
||||
{
|
||||
// Todo: implement shader selection here
|
||||
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
OverrideShader = gl_fuzztype + 4;
|
||||
trans = 0.99f; // trans may not be 1 here
|
||||
hw_styleflags |= STYLEHW_NoAlphaTest;
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderStyle.BlendOp = STYLEOP_Shadow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RenderStyle.Flags & STYLEF_TransSoulsAlpha)
|
||||
{
|
||||
trans = transsouls;
|
||||
|
@ -739,7 +766,7 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
|
|||
trans = 1.f;
|
||||
}
|
||||
|
||||
if (trans >= 1.f-FLT_EPSILON && RenderStyle.BlendOp != STYLEOP_Fuzz && (
|
||||
if (trans >= 1.f-FLT_EPSILON && RenderStyle.BlendOp != STYLEOP_Shadow && (
|
||||
(RenderStyle.SrcAlpha == STYLEALPHA_One && RenderStyle.DestAlpha == STYLEALPHA_Zero) ||
|
||||
(RenderStyle.SrcAlpha == STYLEALPHA_Src && RenderStyle.DestAlpha == STYLEALPHA_InvSrc)
|
||||
))
|
||||
|
@ -774,7 +801,7 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
|
|||
|
||||
if (enhancedvision && gl_enhanced_nightvision)
|
||||
{
|
||||
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||
if (RenderStyle.BlendOp == STYLEOP_Shadow)
|
||||
{
|
||||
// enhanced vision makes them more visible!
|
||||
trans=0.5f;
|
||||
|
@ -865,6 +892,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s
|
|||
|
||||
trans=particle->trans/255.0f;
|
||||
RenderStyle = STYLE_Translucent;
|
||||
OverrideShader = 0;
|
||||
|
||||
ThingColor = GPalette.BaseColors[particle->color];
|
||||
ThingColor.a=0;
|
||||
|
|
|
@ -263,7 +263,7 @@ int gl_SetSpriteLighting(FRenderStyle style, AActor *thing, int lightlevel, int
|
|||
cm->LightColor.r = cm->LightColor.g = cm->LightColor.b = gray;
|
||||
}
|
||||
|
||||
if (style.BlendOp == STYLEOP_Fuzz)
|
||||
if (style.BlendOp == STYLEOP_Shadow)
|
||||
{
|
||||
gl.Color4f(0.2f * ThingColor.r / 255.f, 0.2f * ThingColor.g / 255.f,
|
||||
0.2f * ThingColor.b / 255.f, (alpha = 0.33f));
|
||||
|
|
|
@ -18,8 +18,8 @@ class ADynamicLight;
|
|||
class FMaterial;
|
||||
struct GLDrawList;
|
||||
struct GLSkyInfo;
|
||||
struct GLSectorStackInfo;
|
||||
struct FTexCoordInfo;
|
||||
struct FPortal;
|
||||
|
||||
|
||||
enum WallTypes
|
||||
|
@ -135,7 +135,7 @@ public:
|
|||
AActor * skybox; // for skyboxes
|
||||
GLSkyInfo * sky; // for normal sky
|
||||
GLHorizonInfo * horizon; // for horizon information
|
||||
GLSectorStackInfo * stack; // for sector stacks
|
||||
FPortal * portal; // stacked sector portals
|
||||
secplane_t * planemirror; // for plane mirrors
|
||||
};
|
||||
|
||||
|
@ -163,12 +163,11 @@ private:
|
|||
|
||||
void FloodPlane(int pass);
|
||||
|
||||
void MirrorPlane(secplane_t * plane, bool ceiling);
|
||||
void SkyTexture(int sky1,ASkyViewpoint * skyboxx, bool ceiling);
|
||||
|
||||
void SkyPlane(sector_t *sector, int plane, bool allowmirror);
|
||||
void SkyNormal(sector_t * fs,vertex_t * v1,vertex_t * v2);
|
||||
void SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2);
|
||||
void SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2);
|
||||
|
||||
void Put3DWall(lightlist_t * lightlist, bool translucent);
|
||||
void SplitWall(sector_t * frontsector, bool translucent);
|
||||
void LightPass();
|
||||
|
@ -185,6 +184,7 @@ private:
|
|||
int v_offset);
|
||||
|
||||
void DoMidTexture(seg_t * seg, bool drawfogboundary,
|
||||
sector_t * front, sector_t * back,
|
||||
sector_t * realfront, sector_t * realback,
|
||||
fixed_t fch1, fixed_t fch2, fixed_t ffh1, fixed_t ffh2,
|
||||
fixed_t bch1, fixed_t bch2, fixed_t bfh1, fixed_t bfh2);
|
||||
|
@ -305,6 +305,7 @@ public:
|
|||
FColormap Colormap;
|
||||
FSpriteModelFrame * modelframe;
|
||||
FRenderStyle RenderStyle;
|
||||
int OverrideShader;
|
||||
|
||||
int translation;
|
||||
int index;
|
||||
|
|
|
@ -214,9 +214,7 @@ void GLWall::PutWall(bool translucent)
|
|||
|
||||
case RENDERWALL_SECTORSTACK:
|
||||
//@sync-portal
|
||||
stack=UniqueStacks.Get(stack); // map all stacks with the same displacement together
|
||||
portal=GLPortal::FindPortal(stack);
|
||||
if (!portal) portal=new GLSectorStackPortal(stack);
|
||||
portal = this->portal->GetGLPortal();
|
||||
portal->AddLine(this);
|
||||
break;
|
||||
|
||||
|
@ -246,7 +244,6 @@ void GLWall::PutWall(bool translucent)
|
|||
|
||||
case RENDERWALL_SKY:
|
||||
//@sync-portal
|
||||
sky=UniqueSkies.Get(sky);
|
||||
portal=GLPortal::FindPortal(sky);
|
||||
if (!portal) portal=new GLSkyPortal(sky);
|
||||
portal->AddLine(this);
|
||||
|
@ -505,7 +502,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2)
|
|||
|
||||
if (fs->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||
{
|
||||
SkyTexture(fs->sky, fs->CeilingSkyBox, true);
|
||||
SkyPlane(fs, sector_t::ceiling, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -534,7 +531,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2)
|
|||
zbottom[1] = zbottom[0] = FIXED2FLOAT(fs->GetPlaneTexZ(sector_t::floor));
|
||||
if (fs->GetTexture(sector_t::floor) == skyflatnum)
|
||||
{
|
||||
SkyTexture(fs->sky, fs->FloorSkyBox, false);
|
||||
SkyPlane(fs, sector_t::floor, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -755,8 +752,7 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg,
|
|||
|
||||
gltexture->GetTexCoordInfo(&tci, seg->sidedef->GetTextureXScale(texpos), seg->sidedef->GetTextureYScale(texpos));
|
||||
|
||||
type = (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S &&
|
||||
!(gl.flags & RFL_NOSTENCIL) && gl_mirrors) ? RENDERWALL_MIRROR : _type;
|
||||
type = (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors) ? RENDERWALL_MIRROR : _type;
|
||||
|
||||
float floatceilingref = FIXED2FLOAT(ceilingrefheight) +
|
||||
FIXED2FLOAT(tci.RowOffset(seg->sidedef->GetTextureYOffset(texpos))) +
|
||||
|
@ -785,6 +781,7 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg,
|
|||
//==========================================================================
|
||||
|
||||
void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
|
||||
sector_t * front, sector_t * back,
|
||||
sector_t * realfront, sector_t * realback,
|
||||
fixed_t fch1, fixed_t fch2, fixed_t ffh1, fixed_t ffh2,
|
||||
fixed_t bch1, fixed_t bch2, fixed_t bfh1, fixed_t bfh2)
|
||||
|
@ -837,9 +834,18 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
|
|||
FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::top));
|
||||
if (!tex || tex->UseType==FTexture::TEX_Null)
|
||||
{
|
||||
// texture is missing - use the higher plane
|
||||
topleft = MAX(bch1,fch1);
|
||||
topright = MAX(bch2,fch2);
|
||||
if (front->GetTexture(sector_t::ceiling) == skyflatnum &&
|
||||
back->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||
{
|
||||
// intra-sky lines do not clip the texture at all if there's no upper texture
|
||||
topleft = topright = texturetop;
|
||||
}
|
||||
else
|
||||
{
|
||||
// texture is missing - use the higher plane
|
||||
topleft = MAX(bch1,fch1);
|
||||
topright = MAX(bch2,fch2);
|
||||
}
|
||||
}
|
||||
else if ((bch1>fch1 || bch2>fch2) &&
|
||||
(seg->frontsector->GetTexture(sector_t::ceiling)!=skyflatnum || seg->backsector->GetTexture(sector_t::ceiling)==skyflatnum))
|
||||
|
@ -1436,7 +1442,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
|
|||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _DEBUG
|
||||
if (seg->linedef-lines==8)
|
||||
if (seg->linedef-lines==1095)
|
||||
__asm nop
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1545,7 +1551,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
|
|||
}
|
||||
|
||||
|
||||
if (seg->linedef->special==Line_Horizon && !(gl.flags&RFL_NOSTENCIL))
|
||||
if (seg->linedef->special==Line_Horizon)
|
||||
{
|
||||
SkyNormal(frontsector,v1,v2);
|
||||
DoHorizon(seg,frontsector, v1,v2);
|
||||
|
@ -1648,7 +1654,8 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
|
|||
gltexture=FMaterial::ValidateTexture(seg->sidedef->GetTexture(side_t::mid), true);
|
||||
if (gltexture || drawfogboundary)
|
||||
{
|
||||
DoMidTexture(seg, drawfogboundary, realfront, realback, fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
|
||||
DoMidTexture(seg, drawfogboundary, frontsector, backsector, realfront, realback,
|
||||
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
|
||||
}
|
||||
|
||||
if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
EXTERN_CVAR (Bool, r_drawplayersprites)
|
||||
EXTERN_CVAR(Float, transsouls)
|
||||
EXTERN_CVAR (Bool, st_scale)
|
||||
EXTERN_CVAR(Int, gl_fuzztype)
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -65,7 +66,7 @@ EXTERN_CVAR (Bool, st_scale)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed_t sy, int cm_index, bool hudModelStep)
|
||||
void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed_t sy, int cm_index, bool hudModelStep, int OverrideShader)
|
||||
{
|
||||
float fU1,fV1;
|
||||
float fU2,fV2;
|
||||
|
@ -91,7 +92,7 @@ void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed
|
|||
FMaterial * tex = FMaterial::ValidateTexture(lump, false);
|
||||
if (!tex) return;
|
||||
|
||||
tex->BindPatch(cm_index, 0);
|
||||
tex->BindPatch(cm_index, 0, OverrideShader);
|
||||
|
||||
int vw = viewwidth;
|
||||
int vh = viewheight;
|
||||
|
@ -144,7 +145,10 @@ void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed
|
|||
fV2=tex->GetVB();
|
||||
}
|
||||
|
||||
if (tex->tex->gl_info.mIsTransparent) gl_RenderState.EnableAlphaTest(false);
|
||||
if (tex->GetTransparent() || OverrideShader != 0)
|
||||
{
|
||||
gl_RenderState.EnableAlphaTest(false);
|
||||
}
|
||||
gl_RenderState.Apply();
|
||||
gl.Begin(GL_TRIANGLE_STRIP);
|
||||
gl.TexCoord2f(fU1, fV1); gl.Vertex2f(x1,y1);
|
||||
|
@ -152,7 +156,10 @@ void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed
|
|||
gl.TexCoord2f(fU2, fV1); gl.Vertex2f(x2,y1);
|
||||
gl.TexCoord2f(fU2, fV2); gl.Vertex2f(x2,y2);
|
||||
gl.End();
|
||||
if (tex->tex->gl_info.mIsTransparent) gl_RenderState.EnableAlphaTest(true);
|
||||
if (tex->GetTransparent() || OverrideShader != 0)
|
||||
{
|
||||
gl_RenderState.EnableAlphaTest(true);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -264,10 +271,31 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
}
|
||||
|
||||
// Set the render parameters
|
||||
vis.RenderStyle.CheckFuzz();
|
||||
|
||||
int OverrideShader = 0;
|
||||
float trans = 0.f;
|
||||
if (vis.RenderStyle.BlendOp >= STYLEOP_Fuzz && vis.RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub)
|
||||
{
|
||||
vis.RenderStyle.CheckFuzz();
|
||||
if (vis.RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||
{
|
||||
if (gl.shadermodel >= 4 && gl_fuzztype != 0)
|
||||
{
|
||||
// Todo: implement shader selection here
|
||||
vis.RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
OverrideShader = gl_fuzztype + 4;
|
||||
trans = 0.99f; // trans may not be 1 here
|
||||
}
|
||||
else
|
||||
{
|
||||
vis.RenderStyle.BlendOp = STYLEOP_Shadow;
|
||||
}
|
||||
}
|
||||
statebright[0] = statebright[1] = false;
|
||||
}
|
||||
|
||||
gl_SetRenderStyle(vis.RenderStyle, false, false);
|
||||
|
||||
float trans;
|
||||
if (vis.RenderStyle.Flags & STYLEF_TransSoulsAlpha)
|
||||
{
|
||||
trans = transsouls;
|
||||
|
@ -276,7 +304,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
{
|
||||
trans = 1.f;
|
||||
}
|
||||
else
|
||||
else if (trans == 0.f)
|
||||
{
|
||||
trans = FIXED2FLOAT(vis.alpha);
|
||||
}
|
||||
|
@ -313,7 +341,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
// set the lighting parameters (only calls glColor and glAlphaFunc)
|
||||
gl_SetSpriteLighting(vis.RenderStyle, playermo, statebright[i]? 255 : lightlevel,
|
||||
0, &cmc, 0xffffff, trans, statebright[i], true);
|
||||
DrawPSprite (player,psp,psp->sx+ofsx, psp->sy+ofsy, cm.colormap, hudModelStep);
|
||||
DrawPSprite (player,psp,psp->sx+ofsx, psp->sy+ofsy, cm.colormap, hudModelStep, OverrideShader);
|
||||
}
|
||||
}
|
||||
gl_RenderState.EnableBrightmap(false);
|
||||
|
@ -344,5 +372,5 @@ void FGLRenderer::DrawTargeterSprites()
|
|||
|
||||
// The Targeter's sprites are always drawn normally.
|
||||
for (i=ps_targetcenter, psp = &player->psprites[ps_targetcenter]; i<NUMPSPRITES; i++,psp++)
|
||||
if (psp->state) DrawPSprite (player,psp,psp->sx, psp->sy, CM_DEFAULT, false);
|
||||
if (psp->state) DrawPSprite (player,psp,psp->sx, psp->sy, CM_DEFAULT, false, 0);
|
||||
}
|
|
@ -389,6 +389,13 @@ static const FDefaultShader defaultshaders[]=
|
|||
{"Warp 2", "shaders/glsl/func_warp2.fp"},
|
||||
{"Brightmap","shaders/glsl/func_brightmap.fp"},
|
||||
{"No Texture", "shaders/glsl/func_notexture.fp"},
|
||||
{"Basic Fuzz", "shaders/glsl/fuzz_standard.fp"},
|
||||
{"Smooth Fuzz", "shaders/glsl/fuzz_smooth.fp"},
|
||||
{"Swirly Fuzz", "shaders/glsl/fuzz_swirly.fp"},
|
||||
{"Translucent Fuzz", "shaders/glsl/fuzz_smoothtranslucent.fp"},
|
||||
{"Jagged Fuzz", "shaders/glsl/fuzz_jagged.fp"},
|
||||
{"Noise Fuzz", "shaders/glsl/fuzz_noise.fp"},
|
||||
{"Smooth Noise Fuzz", "shaders/glsl/fuzz_smoothnoise.fp"},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
|
@ -564,6 +571,17 @@ FShader *FShaderManager::BindEffect(int effect)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void gl_DestroyUserShaders()
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses a shader definition
|
||||
|
|
|
@ -131,7 +131,7 @@ class FShaderManager
|
|||
|
||||
void Clean();
|
||||
void CompileShaders();
|
||||
|
||||
|
||||
public:
|
||||
FShaderManager();
|
||||
~FShaderManager();
|
||||
|
|
|
@ -629,3 +629,12 @@ void OpenGLFrameBuffer::DrawRemainingPlayerSprites()
|
|||
{
|
||||
// not used by hardware renderer
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::GameRestart()
|
||||
{
|
||||
memcpy (SourcePalette, GPalette.BaseColors, sizeof(PalEntry)*256);
|
||||
UpdatePalette ();
|
||||
ScreenshotBuffer = NULL;
|
||||
LastCamera = NULL;
|
||||
gl_GenerateGlobalBrightmapFromColormap();
|
||||
}
|
|
@ -48,6 +48,7 @@ public:
|
|||
int GetPageCount();
|
||||
bool Begin2D(bool copy3d);
|
||||
void GetHitlist(BYTE *hitlist);
|
||||
void GameRestart();
|
||||
|
||||
// Retrieves a buffer containing image data for a screenshot.
|
||||
// Hint: Pitch can be negative for upside-down images, in which case buffer
|
||||
|
|
|
@ -5,20 +5,17 @@ enum RenderFlags
|
|||
{
|
||||
RFL_NPOT_TEXTURE=1,
|
||||
RFL_NOSTENCIL=2,
|
||||
RFL_FRAGMENT_PROGRAM=4,
|
||||
RFL_OCCLUSION_QUERY=16,
|
||||
RFL_TEX_ENV_COMBINE4_NV=32,
|
||||
RFL_TEX_ENV_COMBINE3_ATI=64,
|
||||
RFL_OCCLUSION_QUERY=4,
|
||||
// [BB] Added texture compression flags.
|
||||
RFL_TEXTURE_COMPRESSION=128,
|
||||
RFL_TEXTURE_COMPRESSION_S3TC=256,
|
||||
RFL_TEXTURE_COMPRESSION=8,
|
||||
RFL_TEXTURE_COMPRESSION_S3TC=16,
|
||||
|
||||
RFL_VBO = 512,
|
||||
RFL_MAP_BUFFER_RANGE = 1024,
|
||||
RFL_FRAMEBUFFER = 2048,
|
||||
RFL_TEXTUREBUFFER = 4096,
|
||||
RFL_NVIDIA = 8192,
|
||||
RFL_ATI = 16384,
|
||||
RFL_VBO = 32,
|
||||
RFL_MAP_BUFFER_RANGE = 64,
|
||||
RFL_FRAMEBUFFER = 128,
|
||||
RFL_TEXTUREBUFFER = 256,
|
||||
RFL_NVIDIA = 512,
|
||||
RFL_ATI = 1024,
|
||||
|
||||
|
||||
RFL_GL_20 = 0x10000000,
|
||||
|
|
|
@ -834,10 +834,10 @@ outl:
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void FMaterial::Bind(int cm, int clampmode, int translation)
|
||||
void FMaterial::Bind(int cm, int clampmode, int translation, int overrideshader)
|
||||
{
|
||||
int usebright = false;
|
||||
int shaderindex = mShaderIndex;
|
||||
int shaderindex = overrideshader > 0? overrideshader : mShaderIndex;
|
||||
int maxbound = 0;
|
||||
bool allowhires = tex->xScale == FRACUNIT && tex->yScale == FRACUNIT;
|
||||
|
||||
|
@ -848,7 +848,7 @@ void FMaterial::Bind(int cm, int clampmode, int translation)
|
|||
else clampmode = 4;
|
||||
|
||||
const FHardwareTexture *gltexture = mBaseLayer->Bind(0, cm, clampmode, translation, allowhires? tex:NULL, softwarewarp);
|
||||
if (gltexture != NULL && shaderindex > 0)
|
||||
if (gltexture != NULL && shaderindex > 0 && overrideshader == 0)
|
||||
{
|
||||
for(unsigned i=0;i<mTextureLayers.Size();i++)
|
||||
{
|
||||
|
@ -882,10 +882,10 @@ void FMaterial::Bind(int cm, int clampmode, int translation)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void FMaterial::BindPatch(int cm, int translation)
|
||||
void FMaterial::BindPatch(int cm, int translation, int overrideshader)
|
||||
{
|
||||
int usebright = false;
|
||||
int shaderindex = mShaderIndex;
|
||||
int shaderindex = overrideshader > 0? overrideshader : mShaderIndex;
|
||||
int maxbound = 0;
|
||||
|
||||
int softwarewarp = gl_RenderState.SetupShader(tex->bHasCanvas, shaderindex, cm, tex->gl_info.shaderspeed);
|
||||
|
|
|
@ -134,8 +134,8 @@ public:
|
|||
return !!mBaseLayer->tex->bMasked;
|
||||
}
|
||||
|
||||
void Bind(int cm, int clamp=0, int translation=0);
|
||||
void BindPatch(int cm, int translation=0);
|
||||
void Bind(int cm, int clamp = 0, int translation = 0, int overrideshader = 0);
|
||||
void BindPatch(int cm, int translation = 0, int overrideshader = 0);
|
||||
|
||||
unsigned char * CreateTexBuffer(int cm, int translation, int & w, int & h, bool expand = false, bool allowhires=true) const
|
||||
{
|
||||
|
|
|
@ -132,6 +132,7 @@ FRemapTable GlobalBrightmap;
|
|||
|
||||
void gl_GenerateGlobalBrightmapFromColormap()
|
||||
{
|
||||
HasGlobalBrightmap = false;
|
||||
int lump = Wads.CheckNumForName("COLORMAP");
|
||||
if (lump == -1) lump = Wads.CheckNumForName("COLORMAP", ns_colormaps);
|
||||
if (lump == -1) return;
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include "g_level.h"
|
||||
|
||||
extern void LoadActors ();
|
||||
extern void InitBotStuff();
|
||||
extern void ClearStrifeTypes();
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -100,6 +102,7 @@ int GetSpriteIndex(const char * spritename)
|
|||
|
||||
void FActorInfo::StaticInit ()
|
||||
{
|
||||
sprites.Clear();
|
||||
if (sprites.Size() == 0)
|
||||
{
|
||||
spritedef_t temp;
|
||||
|
@ -120,7 +123,9 @@ void FActorInfo::StaticInit ()
|
|||
}
|
||||
|
||||
Printf ("LoadActors: Load actor definitions.\n");
|
||||
ClearStrifeTypes();
|
||||
LoadActors ();
|
||||
InitBotStuff();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -110,10 +110,9 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first)
|
|||
{
|
||||
texname = GStrings[texname+1];
|
||||
}
|
||||
FTextureID tex = TexMan.CheckForTexture(texname, FTexture::TEX_MiscPatch);
|
||||
if (tex.isValid())
|
||||
if (texname[0] != 0)
|
||||
{
|
||||
mBackground = tex;
|
||||
mBackground = TexMan.CheckForTexture(texname, FTexture::TEX_MiscPatch);
|
||||
mFlatfill = desc->mFlatfill;
|
||||
}
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, desc->mSound, 1.0f, ATTN_NONE);
|
||||
|
@ -392,7 +391,12 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first)
|
|||
mName = static_cast<FIntermissionActionCast*>(desc)->mName;
|
||||
mClass = PClass::FindClass(static_cast<FIntermissionActionCast*>(desc)->mCastClass);
|
||||
if (mClass != NULL) mDefaults = GetDefaultByType(mClass);
|
||||
else mDefaults = NULL;
|
||||
else
|
||||
{
|
||||
mDefaults = NULL;
|
||||
caststate = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
mCastSounds.Resize(static_cast<FIntermissionActionCast*>(desc)->mCastSounds.Size());
|
||||
for (unsigned i=0; i < mCastSounds.Size(); i++)
|
||||
|
@ -405,15 +409,17 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first)
|
|||
if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
advplayerstate = mDefaults->MissileState;
|
||||
castsprite = skins[players[consoleplayer].userinfo.skin].sprite;
|
||||
casttranslation = translationtables[TRANSLATION_Players][consoleplayer];
|
||||
}
|
||||
else
|
||||
{
|
||||
advplayerstate = NULL;
|
||||
if (caststate != NULL) castsprite = caststate->sprite;
|
||||
else castsprite = -1;
|
||||
casttranslation = NULL;
|
||||
if (mDefaults->Translation != 0)
|
||||
{
|
||||
casttranslation = translationtables[GetTranslationType(mDefaults->Translation)]
|
||||
[GetTranslationIndex(mDefaults->Translation)];
|
||||
}
|
||||
}
|
||||
castdeath = false;
|
||||
castframes = 0;
|
||||
|
@ -433,21 +439,26 @@ int DIntermissionScreenCast::Responder (event_t *ev)
|
|||
return 1; // already in dying frames
|
||||
|
||||
castdeath = true;
|
||||
caststate = mClass->ActorInfo->FindState(NAME_Death);
|
||||
if (caststate == NULL) return -1;
|
||||
|
||||
casttics = caststate->GetTics();
|
||||
castframes = 0;
|
||||
castattacking = false;
|
||||
if (mClass != NULL)
|
||||
{
|
||||
FName label[] = {NAME_Death, NAME_Cast};
|
||||
caststate = mClass->ActorInfo->FindState(2, label);
|
||||
if (caststate == NULL) return -1;
|
||||
|
||||
if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
int snd = S_FindSkinnedSound(players[consoleplayer].mo, "*death");
|
||||
if (snd != 0) S_Sound (CHAN_VOICE | CHAN_UI, snd, 1, ATTN_NONE);
|
||||
}
|
||||
else if (mDefaults->DeathSound)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, mDefaults->DeathSound, 1, ATTN_NONE);
|
||||
casttics = caststate->GetTics();
|
||||
castframes = 0;
|
||||
castattacking = false;
|
||||
|
||||
if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
int snd = S_FindSkinnedSound(players[consoleplayer].mo, "*death");
|
||||
if (snd != 0) S_Sound (CHAN_VOICE | CHAN_UI, snd, 1, ATTN_NONE);
|
||||
}
|
||||
else if (mDefaults->DeathSound)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, mDefaults->DeathSound, 1, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -478,7 +489,8 @@ int DIntermissionScreenCast::Ticker ()
|
|||
if (--casttics > 0 && caststate != NULL)
|
||||
return 0; // not time to change state yet
|
||||
|
||||
if (caststate == NULL || caststate->GetTics() == -1 || caststate->GetNextState() == NULL)
|
||||
if (caststate == NULL || caststate->GetTics() == -1 || caststate->GetNextState() == NULL ||
|
||||
(caststate->GetNextState() == caststate && castdeath))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -494,7 +506,7 @@ int DIntermissionScreenCast::Ticker ()
|
|||
castframes++;
|
||||
}
|
||||
|
||||
if (castframes == 12)
|
||||
if (castframes == 12 && !castdeath)
|
||||
{
|
||||
// go into attack frame
|
||||
castattacking = true;
|
||||
|
@ -559,6 +571,20 @@ void DIntermissionScreenCast::Drawer ()
|
|||
// draw the current frame in the middle of the screen
|
||||
if (caststate != NULL)
|
||||
{
|
||||
int castsprite;
|
||||
|
||||
if (!(mDefaults->flags4 & MF4_NOSKIN) &&
|
||||
mDefaults->SpawnState != NULL && caststate->sprite == mDefaults->SpawnState->sprite &&
|
||||
mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)) &&
|
||||
skins != NULL)
|
||||
{
|
||||
castsprite = skins[players[consoleplayer].userinfo.skin].sprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
castsprite = caststate->sprite;
|
||||
}
|
||||
|
||||
sprframe = &SpriteFrames[sprites[castsprite].spriteframes + caststate->GetFrame()];
|
||||
pic = TexMan(sprframe->Texture[0]);
|
||||
|
||||
|
@ -811,6 +837,7 @@ void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, BYTE stat
|
|||
viewactive = false;
|
||||
automapactive = false;
|
||||
DIntermissionController::CurrentIntermission = new DIntermissionController(desc, deleteme, state);
|
||||
GC::WriteBarrier(DIntermissionController::CurrentIntermission);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ struct FIntermissionAction
|
|||
TArray<FIntermissionPatch> mOverlays;
|
||||
|
||||
FIntermissionAction();
|
||||
virtual ~FIntermissionAction() {}
|
||||
virtual bool ParseKey(FScanner &sc);
|
||||
};
|
||||
|
||||
|
@ -145,7 +146,7 @@ struct FIntermissionActionScroller : public FIntermissionAction
|
|||
struct FIntermissionDescriptor
|
||||
{
|
||||
FName mLink;
|
||||
TArray<FIntermissionAction *> mActions;
|
||||
TDeletingArray<FIntermissionAction *> mActions;
|
||||
};
|
||||
|
||||
typedef TMap<FName, FIntermissionDescriptor*> FIntermissionDescriptorList;
|
||||
|
@ -233,7 +234,6 @@ class DIntermissionScreenCast : public DIntermissionScreen
|
|||
TArray<FICastSound> mCastSounds;
|
||||
|
||||
int casttics;
|
||||
int castsprite; // [RH] For overriding the player sprite with a skin
|
||||
const FRemapTable *casttranslation; // [RH] Draw "our hero" with their chosen suit color
|
||||
FState* caststate;
|
||||
FState* basestate;
|
||||
|
|
|
@ -47,6 +47,20 @@ static void ReplaceIntermission(FName intname,FIntermissionDescriptor *desc)
|
|||
IntermissionDescriptors[intname] = desc;
|
||||
}
|
||||
|
||||
void DeinitIntermissions()
|
||||
{
|
||||
FIntermissionDescriptorList::Iterator it(IntermissionDescriptors);
|
||||
|
||||
FIntermissionDescriptorList::Pair *pair;
|
||||
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
delete pair->Value;
|
||||
pair->Value = NULL;
|
||||
}
|
||||
IntermissionDescriptors.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FIntermissionAction
|
||||
|
@ -820,7 +834,15 @@ void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int
|
|||
textscreen->mText << '$' << text;
|
||||
}
|
||||
textscreen->mTextDelay = 10;
|
||||
textscreen->mBackground = flat;
|
||||
if (flat != NULL && *flat != 0)
|
||||
{
|
||||
textscreen->mBackground = flat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// force a black screen if no texture is set.
|
||||
textscreen->mBackground = "-";
|
||||
}
|
||||
textscreen->mFlatfill = !finalePic;
|
||||
|
||||
if (music != NULL && *music != 0)
|
||||
|
|
|
@ -41,14 +41,16 @@
|
|||
#include "c_bind.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
TArray<FKeySection> KeySections;
|
||||
extern TArray<FString> KeyConfWeapons;
|
||||
|
||||
static void LoadKeys (const char *modname, bool dbl)
|
||||
{
|
||||
char section[64];
|
||||
|
||||
mysnprintf (section, countof(section), "%s.%s%sBindings", gameinfo.ConfigName, modname,
|
||||
mysnprintf (section, countof(section), "%s.%s%sBindings", gameinfo.ConfigName.GetChars(), modname,
|
||||
dbl ? ".Double" : ".");
|
||||
|
||||
FKeyBindings *bindings = dbl? &DoubleBindings : &Bindings;
|
||||
|
@ -141,3 +143,79 @@ CCMD (addmenukey)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// D_LoadWadSettings
|
||||
//
|
||||
// Parses any loaded KEYCONF lumps. These are restricted console scripts
|
||||
// that can only execute the alias, defaultbind, addkeysection,
|
||||
// addmenukey, weaponsection, and addslotdefault commands.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void D_LoadWadSettings ()
|
||||
{
|
||||
char cmd[4096];
|
||||
int lump, lastlump = 0;
|
||||
|
||||
ParsingKeyConf = true;
|
||||
KeySections.Clear();
|
||||
KeyConfWeapons.Clear();
|
||||
|
||||
while ((lump = Wads.FindLump ("KEYCONF", &lastlump)) != -1)
|
||||
{
|
||||
FMemLump data = Wads.ReadLump (lump);
|
||||
const char *eof = (char *)data.GetMem() + Wads.LumpLength (lump);
|
||||
const char *conf = (char *)data.GetMem();
|
||||
|
||||
while (conf < eof)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// Fetch a line to execute
|
||||
for (i = 0; conf + i < eof && conf[i] != '\n'; ++i)
|
||||
{
|
||||
cmd[i] = conf[i];
|
||||
}
|
||||
cmd[i] = 0;
|
||||
conf += i;
|
||||
if (*conf == '\n')
|
||||
{
|
||||
conf++;
|
||||
}
|
||||
|
||||
// Comments begin with //
|
||||
char *stop = cmd + i - 1;
|
||||
char *comment = cmd;
|
||||
int inQuote = 0;
|
||||
|
||||
if (*stop == '\r')
|
||||
*stop-- = 0;
|
||||
|
||||
while (comment < stop)
|
||||
{
|
||||
if (*comment == '\"')
|
||||
{
|
||||
inQuote ^= 1;
|
||||
}
|
||||
else if (!inQuote && *comment == '/' && *(comment + 1) == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
comment++;
|
||||
}
|
||||
if (comment == cmd)
|
||||
{ // Comment at line beginning
|
||||
continue;
|
||||
}
|
||||
else if (comment < stop)
|
||||
{ // Comment in middle of line
|
||||
*comment = 0;
|
||||
}
|
||||
|
||||
AddCommandString (cmd);
|
||||
}
|
||||
}
|
||||
ParsingKeyConf = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -230,6 +230,26 @@ FString DArgs::TakeValue(const char *check)
|
|||
return out;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: RemoveArg
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::RemoveArgs(const char *check)
|
||||
{
|
||||
int i = CheckParm(check);
|
||||
|
||||
if (i > 0 && i < (int)Argv.Size() - 1)
|
||||
{
|
||||
do
|
||||
{
|
||||
RemoveArg(i);
|
||||
}
|
||||
while (Argv[i][0] != '+' && Argv[i][0] != '-' && i < (int)Argv.Size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: GetArg
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
void AppendArg(FString arg);
|
||||
void AppendArgs(int argc, const FString *argv);
|
||||
void RemoveArg(int argindex);
|
||||
void RemoveArgs(const char *check);
|
||||
void SetArgs(int argc, char **argv);
|
||||
void CollectFiles(const char *param, const char *extension);
|
||||
DArgs *GatherFiles(const char *param) const;
|
||||
|
|
|
@ -139,5 +139,6 @@ inline SDWORD ModDiv (SDWORD num, SDWORD den, SDWORD *dmval)
|
|||
|
||||
#define FLOAT2FIXED(f) xs_Fix<16>::ToFix(f)
|
||||
#define FIXED2FLOAT(f) ((f) / float(65536))
|
||||
#define FIXED2DBL(f) ((f) / double(65536))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,9 +53,10 @@
|
|||
class DLoadSaveMenu : public DListMenu
|
||||
{
|
||||
DECLARE_CLASS(DLoadSaveMenu, DListMenu)
|
||||
friend void ClearSaveGames();
|
||||
|
||||
protected:
|
||||
static TDeletingArray<FSaveGameNode*> SaveGames;
|
||||
static TArray<FSaveGameNode*> SaveGames;
|
||||
static int LastSaved;
|
||||
static int LastAccessed;
|
||||
|
||||
|
@ -114,7 +115,7 @@ public:
|
|||
|
||||
IMPLEMENT_CLASS(DLoadSaveMenu)
|
||||
|
||||
TDeletingArray<FSaveGameNode*> DLoadSaveMenu::SaveGames;
|
||||
TArray<FSaveGameNode*> DLoadSaveMenu::SaveGames;
|
||||
int DLoadSaveMenu::LastSaved = -1;
|
||||
int DLoadSaveMenu::LastAccessed = -1;
|
||||
|
||||
|
@ -126,6 +127,21 @@ FSaveGameNode *quickSaveSlot;
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void ClearSaveGames()
|
||||
{
|
||||
for(unsigned i=0;i<DLoadSaveMenu::SaveGames.Size(); i++)
|
||||
{
|
||||
delete DLoadSaveMenu::SaveGames[i];
|
||||
}
|
||||
DLoadSaveMenu::SaveGames.Clear();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Save data maintenance (stored statically)
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int DLoadSaveMenu::RemoveSaveSlot (int index)
|
||||
{
|
||||
FSaveGameNode *file = SaveGames[index];
|
||||
|
@ -194,6 +210,8 @@ void DLoadSaveMenu::ReadSaveStrings ()
|
|||
findstate_t c_file;
|
||||
FString filter;
|
||||
|
||||
LastSaved = LastAccessed = -1;
|
||||
quickSaveSlot = NULL;
|
||||
filter = G_BuildSaveName ("*.zds", -1);
|
||||
filefirst = I_FindFirst (filter.GetChars(), &c_file);
|
||||
if (filefirst != ((void *)(-1)))
|
||||
|
|
|
@ -70,7 +70,6 @@ CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
DMenu *DMenu::CurrentMenu;
|
||||
int DMenu::MenuTime;
|
||||
|
||||
FListMenuDescriptor *MainMenu;
|
||||
FGameStartup GameStartupInfo;
|
||||
EMenuState menuactive;
|
||||
bool M_DemoNoPlay;
|
||||
|
@ -544,7 +543,7 @@ bool M_Responder (event_t *ev)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (ev->type == EV_KeyDown || ev->type == EV_KeyUp)
|
||||
else if (menuactive != MENU_WaitKey && (ev->type == EV_KeyDown || ev->type == EV_KeyUp))
|
||||
{
|
||||
keyup = ev->type == EV_KeyUp;
|
||||
|
||||
|
|
|
@ -111,6 +111,22 @@ struct FListMenuDescriptor : public FMenuDescriptor
|
|||
const PClass *mClass;
|
||||
FMenuDescriptor *mRedirect; // used to redirect overlong skill and episode menus to option menu based alternatives
|
||||
bool mCenter;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
// Reset the default settings (ignore all other values in the struct)
|
||||
mSelectOfsX = 0;
|
||||
mSelectOfsY = 0;
|
||||
mSelector.SetInvalid();
|
||||
mDisplayTop = 0;
|
||||
mXpos = 0;
|
||||
mYpos = 0;
|
||||
mLinespacing = 0;
|
||||
mNetgameMessage = "";
|
||||
mFont = NULL;
|
||||
mFontColor = CR_UNTRANSLATED;
|
||||
mFontColor2 = CR_UNTRANSLATED;
|
||||
}
|
||||
};
|
||||
|
||||
struct FOptionMenuSettings
|
||||
|
@ -141,6 +157,14 @@ struct FOptionMenuDescriptor : public FMenuDescriptor
|
|||
|
||||
void CalcIndent();
|
||||
FOptionMenuItem *GetItem(FName name);
|
||||
void Reset()
|
||||
{
|
||||
// Reset the default settings (ignore all other values in the struct)
|
||||
mPosition = 0;
|
||||
mScrollTop = 0;
|
||||
mIndent = 0;
|
||||
mDontDim = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
void ClearSaveGames();
|
||||
|
||||
MenuDescriptorList MenuDescriptors;
|
||||
static FListMenuDescriptor DefaultListMenuSettings; // contains common settings for all list menus
|
||||
static FOptionMenuDescriptor DefaultOptionMenuSettings; // contains common settings for all Option menus
|
||||
|
@ -83,7 +85,11 @@ static void DeinitMenus()
|
|||
pair->Value = NULL;
|
||||
}
|
||||
}
|
||||
MenuDescriptors.Clear();
|
||||
OptionValues.Clear();
|
||||
DMenu::CurrentMenu = NULL;
|
||||
DefaultListMenuSettings.mItems.Clear();
|
||||
ClearSaveGames();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -825,8 +831,11 @@ void M_ParseMenuDefs()
|
|||
OptionSettings.mFontColorHeader = V_FindFontColor(gameinfo.mFontColorHeader);
|
||||
OptionSettings.mFontColorHighlight = V_FindFontColor(gameinfo.mFontColorHighlight);
|
||||
OptionSettings.mFontColorSelection = V_FindFontColor(gameinfo.mFontColorSelection);
|
||||
DefaultListMenuSettings.Reset();
|
||||
DefaultOptionMenuSettings.Reset();
|
||||
|
||||
atterm( DeinitMenus);
|
||||
DeinitMenus();
|
||||
while ((lump = Wads.FindLump ("MENUDEF", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump);
|
||||
|
@ -841,6 +850,10 @@ void M_ParseMenuDefs()
|
|||
else if (sc.Compare("DEFAULTLISTMENU"))
|
||||
{
|
||||
ParseListMenuBody(sc, &DefaultListMenuSettings);
|
||||
if (DefaultListMenuSettings.mItems.Size() > 0)
|
||||
{
|
||||
I_FatalError("You cannot add menu items to the menu default settings.");
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("OPTIONVALUE"))
|
||||
{
|
||||
|
@ -861,6 +874,10 @@ void M_ParseMenuDefs()
|
|||
else if (sc.Compare("DEFAULTOPTIONMENU"))
|
||||
{
|
||||
ParseOptionMenuBody(sc, &DefaultOptionMenuSettings);
|
||||
if (DefaultOptionMenuSettings.mItems.Size() > 0)
|
||||
{
|
||||
I_FatalError("You cannot add menu items to the menu default settings.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1221,10 +1238,11 @@ void M_CreateMenus()
|
|||
// THe skill menu must be refeshed each time it starts up
|
||||
//
|
||||
//=============================================================================
|
||||
extern int restart;
|
||||
|
||||
void M_StartupSkillMenu(FGameStartup *gs)
|
||||
{
|
||||
static bool done = false;
|
||||
static int done = -1;
|
||||
bool success = false;
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Skillmenu);
|
||||
if (desc != NULL)
|
||||
|
@ -1250,9 +1268,9 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
if (done != restart)
|
||||
{
|
||||
done = true;
|
||||
done = restart;
|
||||
int defskill = DefaultSkill;
|
||||
if ((unsigned int)defskill >= AllSkills.Size())
|
||||
{
|
||||
|
@ -1327,7 +1345,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
}
|
||||
if (AllEpisodes[gs->Episode].mNoSkill || AllSkills.Size() == 1)
|
||||
{
|
||||
ld->mAutoselect = firstitem + MIN(2u, AllEpisodes.Size()-1);
|
||||
ld->mAutoselect = firstitem + MIN(2u, AllSkills.Size()-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -679,7 +679,7 @@ CCMD (quickload)
|
|||
|
||||
if (netgame)
|
||||
{
|
||||
M_StartMessage (GStrings("QLOADNET"), NULL);
|
||||
M_StartMessage (GStrings("QLOADNET"), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -891,13 +891,13 @@ public:
|
|||
if (mkey == MKEY_Left)
|
||||
{
|
||||
if (--mSelection < 0) mSelection = mMaxValid;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Right)
|
||||
{
|
||||
if (++mSelection > mMaxValid) mSelection = 0;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -115,23 +115,34 @@ bool FPlayerNameBox::GetString(int i, char *s, int len)
|
|||
|
||||
void FPlayerNameBox::DrawBorder (int x, int y, int len)
|
||||
{
|
||||
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
||||
FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)];
|
||||
FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)];
|
||||
FTexture *right = TexMan[TexMan.CheckForTexture("M_LSRGHT", FTexture::TEX_MiscPatch)];
|
||||
if (left != NULL && right != NULL && mid != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
screen->DrawTexture (TexMan["M_LSLEFT"], x-8, y+7, DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawTexture (left, x-8, y+7, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
screen->DrawTexture (TexMan["M_LSCNTR"], x, y+7, DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawTexture (mid, x, y+7, DTA_Clean, true, TAG_DONE);
|
||||
x += 8;
|
||||
}
|
||||
|
||||
screen->DrawTexture (TexMan["M_LSRGHT"], x, y+7, DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawTexture (right, x, y+7, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture (TexMan["M_FSLOT"], x, y+1, DTA_Clean, true, TAG_DONE);
|
||||
FTexture *slot = TexMan[TexMan.CheckForTexture("M_FSLOT", FTexture::TEX_MiscPatch)];
|
||||
if (slot != NULL)
|
||||
{
|
||||
screen->DrawTexture (slot, x, y+1, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->Clear(x, y, x + len, y + SmallFont->GetHeight() * 3/2, -1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -901,7 +912,7 @@ void DPlayerMenu::ClassChanged (FListMenuItem *li)
|
|||
players[consoleplayer].userinfo.PlayerClass = sel-1;
|
||||
PickPlayerClass();
|
||||
|
||||
cvar_set ("playerclass", sel == 0 ? "Random" : PlayerClass->Type->TypeName);
|
||||
cvar_set ("playerclass", sel == 0 ? "Random" : PlayerClass->Type->Meta.GetMetaString (APMETA_DisplayName));
|
||||
|
||||
UpdateSkins();
|
||||
UpdateColorsets();
|
||||
|
|
|
@ -105,12 +105,6 @@ xx(ArtiPoisonBag3)
|
|||
// Strife quests
|
||||
xx(QuestItem)
|
||||
|
||||
// Auto-usable health items
|
||||
xx(ArtiHealth)
|
||||
xx(ArtiSuperHealth)
|
||||
xx(MedicalKit)
|
||||
xx(MedPatch)
|
||||
|
||||
// Armor
|
||||
xx(BasicArmor)
|
||||
|
||||
|
@ -251,6 +245,7 @@ xx(PoisonCloud) // makes monsters howl.
|
|||
// a damage type if you wanted to force an extreme death.
|
||||
xx(Extreme)
|
||||
xx(MDK)
|
||||
xx(Cast) // 'damage type' for the cast call
|
||||
|
||||
// Special names for thingdef_exp.cpp
|
||||
xx(Random)
|
||||
|
@ -285,6 +280,8 @@ xx(Communicator)
|
|||
// Textmap properties
|
||||
//xx(X)
|
||||
//xx(Y)
|
||||
xx(ZFloor)
|
||||
xx(ZCeiling)
|
||||
xx(Height)
|
||||
//xx(Tid)
|
||||
//xx(Angle)
|
||||
|
@ -424,6 +421,8 @@ xx(Silent)
|
|||
xx(Nofallingdamage)
|
||||
xx(Dropactors)
|
||||
xx(NoRespawn)
|
||||
xx(Alphafloor)
|
||||
xx(Alphaceiling)
|
||||
|
||||
xx(offsetx_top)
|
||||
xx(offsety_top)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue