mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-19 07:51:43 +00:00
Merge tag 'SRB2_release_2.1.23' into md3-vanilla-ssn
This commit is contained in:
commit
74d6921f47
87 changed files with 4400 additions and 2081 deletions
|
@ -227,7 +227,6 @@ matrix:
|
|||
- compiler: clang-3.9
|
||||
- compiler: clang-4.0
|
||||
- compiler: clang-5.0
|
||||
- compiler: gcc-8
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
project(SRB2
|
||||
VERSION 2.1.21
|
||||
VERSION 2.1.23
|
||||
LANGUAGES C)
|
||||
|
||||
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version: 2.1.21.{branch}-{build}
|
||||
version: 2.1.23.{branch}-{build}
|
||||
os: MinGW
|
||||
|
||||
environment:
|
||||
|
|
4
debian/changelog
vendored
4
debian/changelog
vendored
|
@ -1,6 +1,6 @@
|
|||
srb2 (2.1.21~9) trusty; urgency=high
|
||||
srb2 (2.1.23~9) trusty; urgency=high
|
||||
|
||||
* SRB2 v2.1.21 release
|
||||
* SRB2 v2.1.23 release
|
||||
|
||||
-- Marco Zafra <marco.a.zafra@gmail.com> Mon, 27 Nov 2018 16:45:00 -0500
|
||||
|
||||
|
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -18,7 +18,7 @@ Homepage: http://www.srb2.org
|
|||
|
||||
Package: srb2
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.21)
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.23)
|
||||
Description: A cross-platform 3D Sonic fangame
|
||||
Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog
|
||||
fangame built using a modified version of the Doom Legacy
|
||||
|
@ -31,7 +31,7 @@ Description: A cross-platform 3D Sonic fangame
|
|||
Package: srb2-dbg
|
||||
Architecture: any
|
||||
# FIXME: should be Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (= 2.1.14), srb2 but dh_shlibdeps is being an asshat
|
||||
Depends: libc6, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.21), srb2
|
||||
Depends: libc6, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.23), srb2
|
||||
Description: A cross-platform 3D Sonic fangame
|
||||
Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog
|
||||
fangame built using a modified version of the Doom Legacy
|
||||
|
|
3
debian/rules
vendored
3
debian/rules
vendored
|
@ -59,6 +59,7 @@ DBGNAME = debug/$(EXENAME)
|
|||
|
||||
PKGDIR = usr/games/SRB2
|
||||
DBGDIR = usr/lib/debug/$(PKGDIR)
|
||||
LINKDIR = usr/games
|
||||
PIXMAPS_DIR = usr/share/pixmaps
|
||||
DESKTOP_DIR = usr/share/applications
|
||||
PREFIX = $(shell test "$(CROSS_COMPILE_BUILD)" != "$(CROSS_COMPILE_HOST)" && echo "PREFIX=$(CROSS_COMPILE_HOST)")
|
||||
|
@ -133,7 +134,7 @@ binary-arch:
|
|||
# dh_installcron
|
||||
# dh_installinfo
|
||||
# dh_installman
|
||||
# dh_link
|
||||
dh_link $(PKGDIR)/$(EXENAME) $(LINKDIR)/$(EXENAME)
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
# dh_perl
|
||||
|
|
|
@ -112,9 +112,7 @@ ifndef GCC295
|
|||
WFLAGS+=-Wno-div-by-zero
|
||||
endif
|
||||
#WFLAGS+=-Wsystem-headers
|
||||
ifndef ERRORMODE
|
||||
#WFLAGS+=-Wfloat-equal
|
||||
endif
|
||||
WFLAGS+=-Wfloat-equal
|
||||
#WFLAGS+=-Wtraditional
|
||||
ifdef VCHELP
|
||||
WFLAGS+=-Wdeclaration-after-statement
|
||||
|
|
348
src/am_map.c
348
src/am_map.c
|
@ -11,8 +11,8 @@
|
|||
/// \file am_map.c
|
||||
/// \brief Code for the 'automap', former Doom feature used for DEVMODE testing
|
||||
|
||||
#include "g_game.h"
|
||||
#include "am_map.h"
|
||||
#include "g_game.h"
|
||||
#include "g_input.h"
|
||||
#include "p_local.h"
|
||||
#include "p_slopes.h"
|
||||
|
@ -33,7 +33,6 @@ static const UINT8 GRAYSRANGE = 16;
|
|||
static const UINT8 BROWNS = (3*16);
|
||||
static const UINT8 YELLOWS = (7*16);
|
||||
static const UINT8 GREENS = (10*16);
|
||||
static const UINT8 GREENRANGE = 16;
|
||||
static const UINT8 DBLACK = 31;
|
||||
static const UINT8 DWHITE = 0;
|
||||
|
||||
|
@ -50,8 +49,6 @@ static const UINT8 NOCLIMBYELLOWS = (11*16);
|
|||
|
||||
// Automap colors
|
||||
#define BACKGROUND DBLACK
|
||||
#define YOURCOLORS DWHITE
|
||||
#define YOURRANGE 0
|
||||
#define WALLCOLORS (REDS + REDRANGE/2)
|
||||
#define WALLRANGE (REDRANGE/2)
|
||||
#define NOCLIMBWALLCOLORS (NOCLIMBREDS + NOCLIMBREDRANGE/2)
|
||||
|
@ -68,31 +65,23 @@ static const UINT8 NOCLIMBYELLOWS = (11*16);
|
|||
#define CDWALLCOLORS YELLOWS
|
||||
#define NOCLIMBCDWALLCOLORS NOCLIMBYELLOWS
|
||||
#define THINGCOLORS GREENS
|
||||
#define THINGRANGE GREENRANGE
|
||||
#define SECRETWALLCOLORS WALLCOLORS
|
||||
#define SECRETWALLRANGE WALLRANGE
|
||||
#define GRIDCOLORS (GRAYS + GRAYSRANGE/2)
|
||||
#define GRIDRANGE 0
|
||||
#define XHAIRCOLORS GRAYS
|
||||
|
||||
// drawing stuff
|
||||
#define FB 0
|
||||
|
||||
#define AM_PANDOWNKEY KEY_DOWNARROW
|
||||
// controls
|
||||
#define AM_PANUPKEY KEY_UPARROW
|
||||
#define AM_PANRIGHTKEY KEY_RIGHTARROW
|
||||
#define AM_PANDOWNKEY KEY_DOWNARROW
|
||||
#define AM_PANLEFTKEY KEY_LEFTARROW
|
||||
#define AM_PANRIGHTKEY KEY_RIGHTARROW
|
||||
|
||||
#define AM_ZOOMINKEY '='
|
||||
#define AM_ZOOMOUTKEY '-'
|
||||
#define AM_STARTKEY KEY_TAB
|
||||
#define AM_ENDKEY KEY_TAB
|
||||
#define AM_GOBIGKEY '0'
|
||||
|
||||
#define AM_FOLLOWKEY 'f'
|
||||
#define AM_GRIDKEY 'g'
|
||||
#define AM_MARKKEY 'm'
|
||||
#define AM_CLEARMARKKEY 'c'
|
||||
|
||||
#define AM_NUMMARKPOINTS 10
|
||||
#define AM_TOGGLEKEY KEY_TAB
|
||||
|
||||
// scale on entry
|
||||
#define INITSCALEMTOF (FRACUNIT/5)
|
||||
|
@ -113,6 +102,9 @@ static const UINT8 NOCLIMBYELLOWS = (11*16);
|
|||
#define CXMTOF(x) (f_x + MTOF((x)-m_x))
|
||||
#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y)))
|
||||
|
||||
#define MAPBITS (FRACBITS-4)
|
||||
#define FRACTOMAPBITS (FRACBITS-MAPBITS)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x, y;
|
||||
|
@ -133,7 +125,10 @@ typedef struct
|
|||
// A line drawing of the player pointing right,
|
||||
// starting from the middle.
|
||||
//
|
||||
|
||||
#define PLAYERRADIUS (16*(1<<MAPBITS))
|
||||
#define R ((8*PLAYERRADIUS)/7)
|
||||
|
||||
static const mline_t player_arrow[] = {
|
||||
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
||||
{ { R, 0 }, { R-R/2, R/4 } }, // ----->
|
||||
|
@ -166,27 +161,15 @@ static const mline_t thintriangle_guy[] = {
|
|||
#undef R
|
||||
#define NUMTHINTRIANGLEGUYLINES (sizeof (thintriangle_guy)/sizeof (mline_t))
|
||||
|
||||
static INT32 bigstate; //added : 24-01-98 : moved here, toggle between
|
||||
// user view and large view (full map view)
|
||||
|
||||
static INT32 grid = 0;
|
||||
|
||||
static INT32 leveljuststarted = 1; // kluge until AM_LevelInit() is called
|
||||
static boolean bigstate; // user view and large view (full map view)
|
||||
static boolean draw_grid = false;
|
||||
|
||||
boolean automapactive = false;
|
||||
boolean am_recalc = false; //added : 05-02-98 : true when screen size changes
|
||||
static boolean am_stopped = true;
|
||||
|
||||
// location of window on screen
|
||||
static INT32 f_x;
|
||||
static INT32 f_y;
|
||||
|
||||
// size of window on screen
|
||||
static INT32 f_w;
|
||||
static INT32 f_h;
|
||||
|
||||
static INT32 lightlev; // used for funky strobing effect
|
||||
static UINT8 *fb; // pseudo-frame buffer
|
||||
static INT32 amclock;
|
||||
static INT32 f_x, f_y; // location of window on screen (always zero for both)
|
||||
static INT32 f_w, f_h; // size of window on screen (always the screen width and height respectively)
|
||||
|
||||
static mpoint_t m_paninc; // how far the window pans each tic (map coords)
|
||||
static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
|
||||
|
@ -210,11 +193,6 @@ static fixed_t max_y;
|
|||
static fixed_t max_w; // max_x-min_x,
|
||||
static fixed_t max_h; // max_y-min_y
|
||||
|
||||
// based on player size
|
||||
static fixed_t min_w;
|
||||
static fixed_t min_h;
|
||||
|
||||
|
||||
static fixed_t min_scale_mtof; // used to tell when to stop zooming out
|
||||
static fixed_t max_scale_mtof; // used to tell when to stop zooming in
|
||||
|
||||
|
@ -232,13 +210,7 @@ static fixed_t scale_ftom;
|
|||
|
||||
static player_t *plr; // the player represented by an arrow
|
||||
|
||||
static patch_t *marknums[10]; // numbers used for marking by the automap
|
||||
static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
|
||||
static INT32 markpointnum = 0; // next point to be assigned
|
||||
|
||||
static INT32 followplayer = 1; // specifies whether to follow the player around
|
||||
|
||||
static boolean stopped = true;
|
||||
static INT32 followplayer = true; // specifies whether to follow the player around
|
||||
|
||||
// function for drawing lines, depends on rendermode
|
||||
typedef void (*AMDRAWFLINEFUNC) (const fline_t *fl, INT32 color);
|
||||
|
@ -277,8 +249,8 @@ static inline void AM_restoreScaleAndLoc(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_x = plr->mo->x - m_w/2;
|
||||
m_y = plr->mo->y - m_h/2;
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
}
|
||||
m_x2 = m_x + m_w;
|
||||
m_y2 = m_y + m_h;
|
||||
|
@ -288,15 +260,6 @@ static inline void AM_restoreScaleAndLoc(void)
|
|||
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
|
||||
}
|
||||
|
||||
/** Adds a marker at the current location.
|
||||
*/
|
||||
static inline void AM_addMark(void)
|
||||
{
|
||||
markpoints[markpointnum].x = m_x + m_w/2;
|
||||
markpoints[markpointnum].y = m_y + m_h/2;
|
||||
markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
|
||||
}
|
||||
|
||||
/** Determines the bounding box around all vertices.
|
||||
* This is used to set global variables controlling the zoom range.
|
||||
*/
|
||||
|
@ -322,11 +285,8 @@ static void AM_findMinMaxBoundaries(void)
|
|||
max_y = vertexes[i].y;
|
||||
}
|
||||
|
||||
max_w = max_x - min_x;
|
||||
max_h = max_y - min_y;
|
||||
|
||||
min_w = 2*PLAYERRADIUS; // const? never changed?
|
||||
min_h = 2*PLAYERRADIUS;
|
||||
max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS);
|
||||
max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS);
|
||||
|
||||
a = FixedDiv(f_w<<FRACBITS, max_w);
|
||||
b = FixedDiv(f_h<<FRACBITS, max_h);
|
||||
|
@ -339,7 +299,7 @@ static void AM_changeWindowLoc(void)
|
|||
{
|
||||
if (m_paninc.x || m_paninc.y)
|
||||
{
|
||||
followplayer = 0;
|
||||
followplayer = false;
|
||||
f_oldloc.x = INT32_MAX;
|
||||
}
|
||||
|
||||
|
@ -365,11 +325,7 @@ static void AM_initVariables(void)
|
|||
INT32 pnum;
|
||||
|
||||
automapactive = true;
|
||||
fb = screens[0];
|
||||
|
||||
f_oldloc.x = INT32_MAX;
|
||||
amclock = 0;
|
||||
lightlev = 0;
|
||||
|
||||
m_paninc.x = m_paninc.y = 0;
|
||||
ftom_zoommul = FRACUNIT;
|
||||
|
@ -385,8 +341,11 @@ static void AM_initVariables(void)
|
|||
break;
|
||||
|
||||
plr = &players[pnum];
|
||||
m_x = plr->mo->x - m_w/2;
|
||||
m_y = plr->mo->y - m_h/2;
|
||||
if (plr != NULL && plr->mo != NULL)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
}
|
||||
AM_changeWindowLoc();
|
||||
|
||||
// for saving & restoring
|
||||
|
@ -396,41 +355,21 @@ static void AM_initVariables(void)
|
|||
old_m_h = m_h;
|
||||
}
|
||||
|
||||
static const UINT8 *maplump; // pointer to the raw data for the automap background.
|
||||
|
||||
/** Clears all map markers.
|
||||
*/
|
||||
static void AM_clearMarks(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < AM_NUMMARKPOINTS; i++)
|
||||
markpoints[i].x = -1; // means empty
|
||||
markpointnum = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// should be called at the start of every level
|
||||
// right now, i figure it out myself
|
||||
//
|
||||
static void AM_LevelInit(void)
|
||||
{
|
||||
leveljuststarted = 0;
|
||||
|
||||
f_x = f_y = 0;
|
||||
f_w = vid.width;
|
||||
f_h = vid.height;
|
||||
|
||||
if (rendermode == render_soft)
|
||||
AM_drawFline = AM_drawFline_soft;
|
||||
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
||||
else if (rendermode != render_none)
|
||||
AM_drawFline = AM_drawFline_soft;
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
AM_drawFline = HWR_drawAMline;
|
||||
#endif
|
||||
else
|
||||
I_Error("Automap can't run without a render system");
|
||||
|
||||
AM_clearMarks();
|
||||
|
||||
AM_findMinMaxBoundaries();
|
||||
scale_mtof = FixedDiv(min_scale_mtof*10, 7*FRACUNIT);
|
||||
|
@ -446,7 +385,7 @@ static void AM_LevelInit(void)
|
|||
void AM_Stop(void)
|
||||
{
|
||||
automapactive = false;
|
||||
stopped = true;
|
||||
am_stopped = true;
|
||||
}
|
||||
|
||||
/** Enables automap.
|
||||
|
@ -457,15 +396,14 @@ static inline void AM_Start(void)
|
|||
{
|
||||
static INT32 lastlevel = -1;
|
||||
|
||||
if (!stopped)
|
||||
if (!am_stopped)
|
||||
AM_Stop();
|
||||
stopped = false;
|
||||
am_stopped = false;
|
||||
if (lastlevel != gamemap || am_recalc) // screen size changed
|
||||
{
|
||||
am_recalc = false;
|
||||
|
||||
AM_LevelInit();
|
||||
lastlevel = gamemap;
|
||||
am_recalc = false;
|
||||
}
|
||||
AM_initVariables();
|
||||
}
|
||||
|
@ -503,7 +441,7 @@ boolean AM_Responder(event_t *ev)
|
|||
{
|
||||
if (!automapactive)
|
||||
{
|
||||
if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
|
||||
if (ev->type == ev_keydown && ev->data1 == AM_TOGGLEKEY)
|
||||
{
|
||||
//faB: prevent alt-tab in win32 version to activate automap just before
|
||||
// minimizing the app; doesn't do any harm to the DOS version
|
||||
|
@ -515,10 +453,8 @@ boolean AM_Responder(event_t *ev)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (ev->type == ev_keydown)
|
||||
{
|
||||
|
||||
rc = true;
|
||||
switch (ev->data1)
|
||||
{
|
||||
|
@ -554,7 +490,7 @@ boolean AM_Responder(event_t *ev)
|
|||
mtof_zoommul = M_ZOOMIN;
|
||||
ftom_zoommul = M_ZOOMOUT;
|
||||
break;
|
||||
case AM_ENDKEY:
|
||||
case AM_TOGGLEKEY:
|
||||
AM_Stop();
|
||||
break;
|
||||
case AM_GOBIGKEY:
|
||||
|
@ -572,13 +508,7 @@ boolean AM_Responder(event_t *ev)
|
|||
f_oldloc.x = INT32_MAX;
|
||||
break;
|
||||
case AM_GRIDKEY:
|
||||
grid = !grid;
|
||||
break;
|
||||
case AM_MARKKEY:
|
||||
AM_addMark();
|
||||
break;
|
||||
case AM_CLEARMARKKEY:
|
||||
AM_clearMarks();
|
||||
draw_grid = !draw_grid;
|
||||
break;
|
||||
default:
|
||||
rc = false;
|
||||
|
@ -632,8 +562,8 @@ static inline void AM_doFollowPlayer(void)
|
|||
{
|
||||
if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
|
||||
{
|
||||
m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
|
||||
m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
|
||||
m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2;
|
||||
m_y = FTOM(MTOF(plr->mo->y >> FRACTOMAPBITS)) - m_h/2;
|
||||
m_x2 = m_x + m_w;
|
||||
m_y2 = m_y + m_h;
|
||||
f_oldloc.x = plr->mo->x;
|
||||
|
@ -651,8 +581,6 @@ void AM_Ticker(void)
|
|||
if (dedicated || !automapactive)
|
||||
return;
|
||||
|
||||
amclock++;
|
||||
|
||||
if (followplayer)
|
||||
AM_doFollowPlayer();
|
||||
|
||||
|
@ -671,72 +599,7 @@ void AM_Ticker(void)
|
|||
*/
|
||||
static void AM_clearFB(INT32 color)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
HWR_clearAutomap();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!maplump)
|
||||
memset(fb, color, f_w*f_h*vid.bpp);
|
||||
else
|
||||
{
|
||||
INT32 dmapx, dmapy, i, y;
|
||||
static INT32 mapxstart, mapystart;
|
||||
UINT8 *dest = screens[0];
|
||||
const UINT8 *src;
|
||||
#define MAPLUMPHEIGHT (200 - 42)
|
||||
|
||||
if (followplayer)
|
||||
{
|
||||
static vertex_t oldplr;
|
||||
|
||||
dmapx = MTOF(plr->mo->x) - MTOF(oldplr.x); //fixed point
|
||||
dmapy = MTOF(oldplr.y) - MTOF(plr->mo->y);
|
||||
|
||||
oldplr.x = plr->mo->x;
|
||||
oldplr.y = plr->mo->y;
|
||||
mapxstart += dmapx>>1;
|
||||
mapystart += dmapy>>1;
|
||||
|
||||
while (mapxstart >= BASEVIDWIDTH)
|
||||
mapxstart -= BASEVIDWIDTH;
|
||||
while (mapxstart < 0)
|
||||
mapxstart += BASEVIDWIDTH;
|
||||
while (mapystart >= MAPLUMPHEIGHT)
|
||||
mapystart -= MAPLUMPHEIGHT;
|
||||
while (mapystart < 0)
|
||||
mapystart += MAPLUMPHEIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapxstart += (MTOF(m_paninc.x)>>1);
|
||||
mapystart -= (MTOF(m_paninc.y)>>1);
|
||||
if (mapxstart >= BASEVIDWIDTH)
|
||||
mapxstart -= BASEVIDWIDTH;
|
||||
if (mapxstart < 0)
|
||||
mapxstart += BASEVIDWIDTH;
|
||||
if (mapystart >= MAPLUMPHEIGHT)
|
||||
mapystart -= MAPLUMPHEIGHT;
|
||||
if (mapystart < 0)
|
||||
mapystart += MAPLUMPHEIGHT;
|
||||
}
|
||||
|
||||
//blit the automap background to the screen.
|
||||
for (y = 0; y < f_h; y++)
|
||||
{
|
||||
src = maplump + mapxstart + (y + mapystart)*BASEVIDWIDTH;
|
||||
for (i = 0; i < BASEVIDWIDTH*vid.dupx; i++)
|
||||
{
|
||||
while (src > maplump + BASEVIDWIDTH*MAPLUMPHEIGHT)
|
||||
src -= BASEVIDWIDTH*MAPLUMPHEIGHT;
|
||||
*dest++ = *src++;
|
||||
}
|
||||
dest += vid.width - vid.dupx*BASEVIDWIDTH;
|
||||
}
|
||||
}
|
||||
V_DrawFill(f_x, f_y, f_w, f_h, color|V_NOSCALESTART);
|
||||
}
|
||||
|
||||
/** Performs automap clipping of lines.
|
||||
|
@ -871,7 +734,7 @@ static boolean AM_clipMline(const mline_t *ml, fline_t *fl)
|
|||
//
|
||||
static void AM_drawFline_soft(const fline_t *fl, INT32 color)
|
||||
{
|
||||
register INT32 x, y, dx, dy, sx, sy, ax, ay, d;
|
||||
INT32 x, y, dx, dy, sx, sy, ax, ay, d;
|
||||
|
||||
#ifdef _DEBUG
|
||||
static INT32 num = 0;
|
||||
|
@ -887,7 +750,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define PUTDOT(xx,yy,cc) fb[(yy)*f_w + (xx)]=(UINT8)(cc)
|
||||
#define PUTDOT(xx,yy,cc) V_DrawFill(xx,yy,1,1,cc|V_NOSCALESTART);
|
||||
|
||||
dx = fl->b.x - fl->a.x;
|
||||
ax = 2 * (dx < 0 ? -dx : dx);
|
||||
|
@ -905,7 +768,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
|
|||
d = ay - ax/2;
|
||||
for (;;)
|
||||
{
|
||||
PUTDOT(x, y, color);
|
||||
PUTDOT(x, y, color)
|
||||
if (x == fl->b.x)
|
||||
return;
|
||||
if (d >= 0)
|
||||
|
@ -922,7 +785,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
|
|||
d = ax - ay/2;
|
||||
for (;;)
|
||||
{
|
||||
PUTDOT(x, y, color);
|
||||
PUTDOT(x, y, color)
|
||||
if (y == fl->b.y)
|
||||
return;
|
||||
if (d >= 0)
|
||||
|
@ -934,6 +797,8 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
|
|||
d += ax;
|
||||
}
|
||||
}
|
||||
|
||||
#undef PUTDOT
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1004,15 +869,15 @@ static inline void AM_drawWalls(void)
|
|||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
l.a.x = lines[i].v1->x;
|
||||
l.a.y = lines[i].v1->y;
|
||||
l.b.x = lines[i].v2->x;
|
||||
l.b.y = lines[i].v2->y;
|
||||
l.a.x = lines[i].v1->x >> FRACTOMAPBITS;
|
||||
l.a.y = lines[i].v1->y >> FRACTOMAPBITS;
|
||||
l.b.x = lines[i].v2->x >> FRACTOMAPBITS;
|
||||
l.b.y = lines[i].v2->y >> FRACTOMAPBITS;
|
||||
#ifdef ESLOPE
|
||||
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
|
||||
if (slope) { \
|
||||
end1 = P_GetZAt(slope, l.a.x, l.a.y); \
|
||||
end2 = P_GetZAt(slope, l.b.x, l.b.y); \
|
||||
end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y); \
|
||||
end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y); \
|
||||
} else \
|
||||
end1 = end2 = normalheight;
|
||||
|
||||
|
@ -1025,17 +890,12 @@ static inline void AM_drawWalls(void)
|
|||
#undef SLOPEPARAMS
|
||||
#endif
|
||||
|
||||
// AM_drawMline(&l, GRAYS + 3); // Old, everything-is-gray automap
|
||||
if (!lines[i].backsector) // 1-sided
|
||||
{
|
||||
if (lines[i].flags & ML_NOCLIMB)
|
||||
{
|
||||
AM_drawMline(&l, NOCLIMBWALLCOLORS+lightlev);
|
||||
}
|
||||
AM_drawMline(&l, NOCLIMBWALLCOLORS);
|
||||
else
|
||||
{
|
||||
AM_drawMline(&l, WALLCOLORS+lightlev);
|
||||
}
|
||||
AM_drawMline(&l, WALLCOLORS);
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
else if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier
|
||||
|
@ -1052,24 +912,16 @@ static inline void AM_drawWalls(void)
|
|||
#endif
|
||||
{
|
||||
if (lines[i].flags & ML_NOCLIMB)
|
||||
{
|
||||
AM_drawMline(&l, NOCLIMBTSWALLCOLORS+lightlev);
|
||||
}
|
||||
AM_drawMline(&l, NOCLIMBTSWALLCOLORS);
|
||||
else
|
||||
{
|
||||
AM_drawMline(&l, TSWALLCOLORS+lightlev);
|
||||
}
|
||||
AM_drawMline(&l, TSWALLCOLORS);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lines[i].flags & ML_NOCLIMB)
|
||||
{
|
||||
AM_drawMline(&l, NOCLIMBTHOKWALLCOLORS+lightlev);
|
||||
}
|
||||
AM_drawMline(&l, NOCLIMBTHOKWALLCOLORS);
|
||||
else
|
||||
{
|
||||
AM_drawMline(&l, THOKWALLCOLORS+lightlev);
|
||||
}
|
||||
AM_drawMline(&l, THOKWALLCOLORS);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1081,7 +933,7 @@ static inline void AM_drawWalls(void)
|
|||
if (lines[i].backsector->floorheight
|
||||
!= lines[i].frontsector->floorheight) {
|
||||
#endif
|
||||
AM_drawMline(&l, NOCLIMBFDWALLCOLORS + lightlev); // floor level change
|
||||
AM_drawMline(&l, NOCLIMBFDWALLCOLORS); // floor level change
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
else if (backc1 != frontc1 || backc2 != frontc2) {
|
||||
|
@ -1089,11 +941,10 @@ static inline void AM_drawWalls(void)
|
|||
else if (lines[i].backsector->ceilingheight
|
||||
!= lines[i].frontsector->ceilingheight) {
|
||||
#endif
|
||||
AM_drawMline(&l, NOCLIMBCDWALLCOLORS+lightlev); // ceiling level change
|
||||
}
|
||||
else {
|
||||
AM_drawMline(&l, NOCLIMBTSWALLCOLORS+lightlev);
|
||||
AM_drawMline(&l, NOCLIMBCDWALLCOLORS); // ceiling level change
|
||||
}
|
||||
else
|
||||
AM_drawMline(&l, NOCLIMBTSWALLCOLORS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1103,7 +954,7 @@ static inline void AM_drawWalls(void)
|
|||
if (lines[i].backsector->floorheight
|
||||
!= lines[i].frontsector->floorheight) {
|
||||
#endif
|
||||
AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
|
||||
AM_drawMline(&l, FDWALLCOLORS); // floor level change
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
else if (backc1 != frontc1 || backc2 != frontc2) {
|
||||
|
@ -1111,11 +962,10 @@ static inline void AM_drawWalls(void)
|
|||
else if (lines[i].backsector->ceilingheight
|
||||
!= lines[i].frontsector->ceilingheight) {
|
||||
#endif
|
||||
AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
|
||||
}
|
||||
else {
|
||||
AM_drawMline(&l, TSWALLCOLORS+lightlev);
|
||||
AM_drawMline(&l, CDWALLCOLORS); // ceiling level change
|
||||
}
|
||||
else
|
||||
AM_drawMline(&l, TSWALLCOLORS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1176,6 +1026,11 @@ static void AM_drawLineCharacter(const mline_t *lineguy, size_t lineguylines, fi
|
|||
l.b.x += x;
|
||||
l.b.y += y;
|
||||
|
||||
l.a.x >>= FRACTOMAPBITS;
|
||||
l.a.y >>= FRACTOMAPBITS;
|
||||
l.b.x >>= FRACTOMAPBITS;
|
||||
l.b.y >>= FRACTOMAPBITS;
|
||||
|
||||
AM_drawMline(&l, color);
|
||||
}
|
||||
}
|
||||
|
@ -1184,83 +1039,51 @@ static inline void AM_drawPlayers(void)
|
|||
{
|
||||
INT32 i;
|
||||
player_t *p;
|
||||
INT32 color;
|
||||
INT32 color = GREENS;
|
||||
|
||||
if (!multiplayer)
|
||||
{
|
||||
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0,
|
||||
plr->mo->angle, DWHITE, plr->mo->x, plr->mo->y);
|
||||
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, DWHITE, plr->mo->x, plr->mo->y);
|
||||
return;
|
||||
}
|
||||
|
||||
// multiplayer
|
||||
// multiplayer (how??)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
p = &players[i];
|
||||
if (p->skincolor == 0)
|
||||
color = GREENS;
|
||||
else
|
||||
if (p->skincolor > 0)
|
||||
color = R_GetTranslationColormap(TC_DEFAULT, p->skincolor, GTC_CACHE)[GREENS + 8];
|
||||
|
||||
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle,
|
||||
color, p->mo->x, p->mo->y);
|
||||
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, color, p->mo->x, p->mo->y);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void AM_drawThings(INT32 colors, INT32 colorrange)
|
||||
static inline void AM_drawThings(UINT8 colors)
|
||||
{
|
||||
size_t i;
|
||||
mobj_t *t;
|
||||
|
||||
(void)colorrange;
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
t = sectors[i].thinglist;
|
||||
while (t)
|
||||
{
|
||||
AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
|
||||
16<<FRACBITS, t->angle, colors + lightlev, t->x, t->y);
|
||||
AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, t->angle, colors, t->x, t->y);
|
||||
t = t->snext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void AM_drawMarks(void)
|
||||
{
|
||||
INT32 i, fx, fy, w, h;
|
||||
|
||||
for (i = 0; i < AM_NUMMARKPOINTS; i++)
|
||||
{
|
||||
if (markpoints[i].x != -1 && marknums[i])
|
||||
{
|
||||
// w = SHORT(marknums[i]->width);
|
||||
// h = SHORT(marknums[i]->height);
|
||||
w = 5; // because something's wrong with the wad, i guess
|
||||
h = 6; // because something's wrong with the wad, i guess
|
||||
fx = CXMTOF(markpoints[i].x);
|
||||
fy = CYMTOF(markpoints[i].y);
|
||||
if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
|
||||
V_DrawPatch(fx, fy, FB, marknums[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Draws the crosshair, actually just a dot in software mode.
|
||||
*
|
||||
* \param color Color for the crosshair.
|
||||
*/
|
||||
static inline void AM_drawCrosshair(INT32 color)
|
||||
static inline void AM_drawCrosshair(UINT8 color)
|
||||
{
|
||||
if (rendermode != render_soft)
|
||||
return; // BP: should be putpixel here
|
||||
|
||||
if (scr_bpp == 1)
|
||||
fb[(f_w*(f_h + 1))/2] = (UINT8)color; // single point for now
|
||||
else
|
||||
*((INT16 *)(void *)fb + (f_w*(f_h + 1))/2) = (INT16)color;
|
||||
V_DrawFill(f_w/2 + f_x, f_h/2 + f_y, 1, 1, color|V_NOSCALESTART);
|
||||
}
|
||||
|
||||
/** Draws the automap.
|
||||
|
@ -1271,13 +1094,10 @@ void AM_Drawer(void)
|
|||
return;
|
||||
|
||||
AM_clearFB(BACKGROUND);
|
||||
if (grid)
|
||||
AM_drawGrid(GRIDCOLORS);
|
||||
if (draw_grid) AM_drawGrid(GRIDCOLORS);
|
||||
AM_drawWalls();
|
||||
AM_drawPlayers();
|
||||
AM_drawThings(THINGCOLORS, THINGRANGE);
|
||||
AM_drawThings(THINGCOLORS);
|
||||
|
||||
AM_drawCrosshair(XHAIRCOLORS);
|
||||
|
||||
AM_drawMarks();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "p_setup.h"
|
||||
#include "lua_script.h"
|
||||
#include "d_netfil.h" // findfile
|
||||
|
||||
//========
|
||||
// protos.
|
||||
|
@ -49,6 +50,7 @@ static void COM_Wait_f(void);
|
|||
static void COM_Help_f(void);
|
||||
static void COM_Toggle_f(void);
|
||||
|
||||
static void CV_EnforceExecVersion(void);
|
||||
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
|
||||
static boolean CV_Command(void);
|
||||
static consvar_t *CV_FindVar(const char *name);
|
||||
|
@ -63,10 +65,11 @@ CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}};
|
|||
CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}};
|
||||
CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
|
||||
|
||||
// Filter consvars by MODVERSION
|
||||
// Filter consvars by EXECVERSION
|
||||
// First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
|
||||
// Also set CV_HIDEN during runtime, after config is loaded
|
||||
consvar_t cv_execversion = {"execversion","25",0,CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static boolean execversion_enabled = false;
|
||||
consvar_t cv_execversion = {"execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// for default joyaxis detection
|
||||
static boolean joyaxis_default = false;
|
||||
|
@ -641,6 +644,7 @@ static void COM_CEchoDuration_f(void)
|
|||
static void COM_Exec_f(void)
|
||||
{
|
||||
UINT8 *buf = NULL;
|
||||
char filename[256];
|
||||
|
||||
if (COM_Argc() < 2 || COM_Argc() > 3)
|
||||
{
|
||||
|
@ -649,13 +653,23 @@ static void COM_Exec_f(void)
|
|||
}
|
||||
|
||||
// load file
|
||||
// Try with Argv passed verbatim first, for back compat
|
||||
FIL_ReadFile(COM_Argv(1), &buf);
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
if (!COM_CheckParm("-noerror"))
|
||||
CONS_Printf(M_GetText("couldn't execute file %s\n"), COM_Argv(1));
|
||||
return;
|
||||
// Now try by searching the file path
|
||||
// filename is modified with the full found path
|
||||
strcpy(filename, COM_Argv(1));
|
||||
if (findfile(filename, NULL, true) != FS_NOTFOUND)
|
||||
FIL_ReadFile(filename, &buf);
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
if (!COM_CheckParm("-noerror"))
|
||||
CONS_Printf(M_GetText("couldn't execute file %s\n"), COM_Argv(1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!COM_CheckParm("-silent"))
|
||||
|
@ -1090,7 +1104,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
|
|||
if (var->flags & CV_FLOAT)
|
||||
{
|
||||
double d = atof(valstr);
|
||||
if (!d && valstr[0] != '0')
|
||||
if (fpclassify(d) == FP_ZERO && valstr[0] != '0')
|
||||
v = INT32_MIN;
|
||||
else
|
||||
v = (INT32)(d * FRACUNIT);
|
||||
|
@ -1586,10 +1600,21 @@ void CV_InitFilterVar(void)
|
|||
joyaxis_count = joyaxis2_count = 0;
|
||||
}
|
||||
|
||||
void CV_ToggleExecVersion(boolean enable)
|
||||
{
|
||||
execversion_enabled = enable;
|
||||
}
|
||||
|
||||
static void CV_EnforceExecVersion(void)
|
||||
{
|
||||
if (!execversion_enabled)
|
||||
CV_StealthSetValue(&cv_execversion, EXECVERSION);
|
||||
}
|
||||
|
||||
static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
|
||||
{
|
||||
// If ALL axis settings are previous defaults, set them to the new defaults
|
||||
// MODVERSION < 26 (2.1.21)
|
||||
// EXECVERSION < 26 (2.1.21)
|
||||
|
||||
if (joyaxis_default)
|
||||
{
|
||||
|
@ -1737,8 +1762,7 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
|
|||
if (!(v->flags & CV_SAVE))
|
||||
return true;
|
||||
|
||||
// We go by MODVERSION here
|
||||
if (cv_execversion.value < 26) // 26 = 2.1.21
|
||||
if (GETMAJOREXECVERSION(cv_execversion.value) < 26) // 26 = 2.1.21
|
||||
{
|
||||
// MOUSE SETTINGS
|
||||
// alwaysfreelook split between first and third person (chasefreelook)
|
||||
|
|
|
@ -130,6 +130,7 @@ extern CV_PossibleValue_t CV_Natural[];
|
|||
extern consvar_t cv_execversion;
|
||||
|
||||
void CV_InitFilterVar(void);
|
||||
void CV_ToggleExecVersion(boolean enable);
|
||||
|
||||
// register a variable for use at the console
|
||||
void CV_RegisterVar(consvar_t *variable);
|
||||
|
|
|
@ -27,14 +27,15 @@
|
|||
#else
|
||||
|
||||
/* Manually defined asset hashes for non-CMake builds
|
||||
* Last updated 2015 / 05 / 03
|
||||
* Last updated 2015 / 05 / 03 - v2.1.15 - main assets
|
||||
* Last updated 2018 / 12 / 23 - v2.1.22 - patch.dta
|
||||
*/
|
||||
#define ASSET_HASH_SRB2_SRB "c1b9577687f8a795104aef4600720ea7"
|
||||
#define ASSET_HASH_ZONES_DTA "303838c6c534d9540288360fa49cca60"
|
||||
#define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799"
|
||||
#define ASSET_HASH_RINGS_DTA "85901ad4bf94637e5753d2ac2c03ea26"
|
||||
#ifdef USE_PATCH_DTA
|
||||
#define ASSET_HASH_PATCH_DTA "dbbf8bc6121618ee3be2d5b14650429b"
|
||||
#define ASSET_HASH_PATCH_DTA "b04fd9624bfd94dc96dcf4f400f7deb4"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "i_system.h"
|
||||
#include "d_main.h"
|
||||
#include "m_menu.h"
|
||||
#include "filesrch.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include "win32/win_main.h"
|
||||
|
@ -58,10 +59,7 @@ static boolean consoleready; // console prompt is ready
|
|||
INT32 con_destlines; // vid lines used by console at final position
|
||||
static INT32 con_curlines; // vid lines currently used by console
|
||||
|
||||
INT32 con_clipviewtop; // clip value for planes & sprites, so that the
|
||||
// part of the view covered by the console is not
|
||||
// drawn when not needed, this must be -1 when
|
||||
// console is off
|
||||
INT32 con_clipviewtop; // (useless)
|
||||
|
||||
static INT32 con_hudlines; // number of console heads up message lines
|
||||
static INT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines
|
||||
|
@ -131,10 +129,15 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}
|
|||
// whether to use console background picture, or translucent mode
|
||||
static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"},
|
||||
{3, "Red"}, {4, "Orange"}, {5, "Yellow"},
|
||||
{6, "Green"}, {7, "Blue"}, {8, "Cyan"},
|
||||
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"},
|
||||
{3, "Brown"}, {4, "Pink"}, {5, "Raspberry"},
|
||||
{6, "Red"}, {7, "Creamsicle"}, {8, "Orange"},
|
||||
{9, "Gold"}, {10,"Yellow"}, {11,"Emerald"},
|
||||
{12,"Green"}, {13,"Cyan"}, {14,"Steel"},
|
||||
{15,"Periwinkle"}, {16,"Blue"}, {17,"Purple"},
|
||||
{18,"Lavender"},
|
||||
{0, NULL}};
|
||||
|
||||
consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static void CON_Print(char *msg);
|
||||
|
@ -241,29 +244,41 @@ void CON_SetupBackColormap(void)
|
|||
UINT16 i, palsum;
|
||||
UINT8 j, palindex;
|
||||
UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE);
|
||||
INT32 shift = 6;
|
||||
|
||||
if (!consolebgmap)
|
||||
consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
|
||||
|
||||
switch (cons_backcolor.value)
|
||||
{
|
||||
case 0: palindex = 15; break; // White
|
||||
case 1: palindex = 31; break; // Gray
|
||||
case 2: palindex = 63; break; // Brown
|
||||
case 3: palindex = 143; break; // Red
|
||||
case 4: palindex = 95; break; // Orange
|
||||
case 5: palindex = 111; break; // Yellow
|
||||
case 6: palindex = 175; break; // Green
|
||||
case 7: palindex = 239; break; // Blue
|
||||
case 8: palindex = 219; break; // Cyan
|
||||
case 0: palindex = 15; break; // White
|
||||
case 1: palindex = 31; break; // Gray
|
||||
case 2: palindex = 47; break; // Sepia
|
||||
case 3: palindex = 63; break; // Brown
|
||||
case 4: palindex = 150; shift = 7; break; // Pink
|
||||
case 5: palindex = 127; shift = 7; break; // Raspberry
|
||||
case 6: palindex = 143; break; // Red
|
||||
case 7: palindex = 86; shift = 7; break; // Creamsicle
|
||||
case 8: palindex = 95; break; // Orange
|
||||
case 9: palindex = 119; shift = 7; break; // Gold
|
||||
case 10: palindex = 111; break; // Yellow
|
||||
case 11: palindex = 191; shift = 7; break; // Emerald
|
||||
case 12: palindex = 175; break; // Green
|
||||
case 13: palindex = 219; break; // Cyan
|
||||
case 14: palindex = 207; shift = 7; break; // Steel
|
||||
case 15: palindex = 230; shift = 7; break; // Periwinkle
|
||||
case 16: palindex = 239; break; // Blue
|
||||
case 17: palindex = 199; shift = 7; break; // Purple
|
||||
case 18: palindex = 255; shift = 7; break; // Lavender
|
||||
// Default green
|
||||
default: palindex = 175; break;
|
||||
|
||||
}
|
||||
|
||||
// setup background colormap
|
||||
for (i = 0, j = 0; i < 768; i += 3, j++)
|
||||
{
|
||||
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> 6;
|
||||
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> shift;
|
||||
consolebgmap[j] = (UINT8)(palindex - palsum);
|
||||
}
|
||||
}
|
||||
|
@ -842,7 +857,7 @@ boolean CON_Responder(event_t *ev)
|
|||
|
||||
// ...why shouldn't it eat the key? if it doesn't, it just means you
|
||||
// can control Sonic from the console, which is silly
|
||||
return true; //return false;
|
||||
return true;//return false;
|
||||
}
|
||||
|
||||
// command completion forward (tab) and backward (shift-tab)
|
||||
|
@ -1036,15 +1051,30 @@ boolean CON_Responder(event_t *ev)
|
|||
else if (key == KEY_KPADSLASH)
|
||||
key = '/';
|
||||
|
||||
if (shiftdown)
|
||||
// capslock
|
||||
if (key == KEY_CAPSLOCK) // it's a toggle.
|
||||
{
|
||||
if (capslock)
|
||||
capslock = false;
|
||||
else
|
||||
capslock = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key >= 'a' && key <= 'z')
|
||||
{
|
||||
if (capslock ^ shiftdown)
|
||||
key = shiftxform[key];
|
||||
}
|
||||
else if (shiftdown)
|
||||
key = shiftxform[key];
|
||||
|
||||
// enter a char into the command prompt
|
||||
if (key < 32 || key > 127)
|
||||
return true; // even if key can't be printed, eat it anyway
|
||||
return true;
|
||||
|
||||
// add key to cmd line here
|
||||
if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers
|
||||
if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers
|
||||
key = key + 'a' - 'A';
|
||||
|
||||
if (input_sel != input_cur)
|
||||
|
@ -1261,12 +1291,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...)
|
|||
switch (level)
|
||||
{
|
||||
case CONS_NOTICE:
|
||||
// no notice for notices, hehe
|
||||
CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:"));
|
||||
break;
|
||||
case CONS_WARNING:
|
||||
refreshdirmenu |= REFRESHDIR_WARNING;
|
||||
CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:"));
|
||||
break;
|
||||
case CONS_ERROR:
|
||||
refreshdirmenu |= REFRESHDIR_ERROR;
|
||||
CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:"));
|
||||
break;
|
||||
}
|
||||
|
@ -1422,8 +1455,8 @@ static void CON_DrawHudlines(void)
|
|||
if (con_hudlines <= 0)
|
||||
return;
|
||||
|
||||
if (chat_on)
|
||||
y = charheight; // leave place for chat input in the first row of text
|
||||
if (chat_on && OLDCHAT)
|
||||
y = charheight; // leave place for chat input in the first row of text (only do it if consolechat is on.)
|
||||
else
|
||||
y = 0;
|
||||
|
||||
|
|
|
@ -2762,7 +2762,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
msg = KICK_MSG_CON_FAIL;
|
||||
}
|
||||
|
||||
CONS_Printf("\x82%s ", player_names[pnum]);
|
||||
//CONS_Printf("\x82%s ", player_names[pnum]);
|
||||
|
||||
// If a verified admin banned someone, the server needs to know about it.
|
||||
// If the playernum isn't zero (the server) then the server needs to record the ban.
|
||||
|
@ -2779,17 +2779,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
switch (msg)
|
||||
{
|
||||
case KICK_MSG_GO_AWAY:
|
||||
CONS_Printf(M_GetText("has been kicked (Go away)\n"));
|
||||
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
|
||||
kickreason = KR_KICK;
|
||||
break;
|
||||
#ifdef NEWPING
|
||||
case KICK_MSG_PING_HIGH:
|
||||
CONS_Printf(M_GetText("left the game (Broke ping limit)\n"));
|
||||
HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
|
||||
kickreason = KR_PINGLIMIT;
|
||||
break;
|
||||
#endif
|
||||
case KICK_MSG_CON_FAIL:
|
||||
CONS_Printf(M_GetText("left the game (Synch failure)\n"));
|
||||
HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
|
||||
kickreason = KR_SYNCH;
|
||||
|
||||
if (M_CheckParm("-consisdump")) // Helps debugging some problems
|
||||
|
@ -2826,26 +2826,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
}
|
||||
break;
|
||||
case KICK_MSG_TIMEOUT:
|
||||
CONS_Printf(M_GetText("left the game (Connection timeout)\n"));
|
||||
HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false);
|
||||
kickreason = KR_TIMEOUT;
|
||||
break;
|
||||
case KICK_MSG_PLAYER_QUIT:
|
||||
if (netgame) // not splitscreen/bots
|
||||
CONS_Printf(M_GetText("left the game\n"));
|
||||
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
|
||||
kickreason = KR_LEAVE;
|
||||
break;
|
||||
case KICK_MSG_BANNED:
|
||||
CONS_Printf(M_GetText("has been banned (Don't come back)\n"));
|
||||
HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false);
|
||||
kickreason = KR_BAN;
|
||||
break;
|
||||
case KICK_MSG_CUSTOM_KICK:
|
||||
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
|
||||
CONS_Printf(M_GetText("has been kicked (%s)\n"), reason);
|
||||
HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false);
|
||||
kickreason = KR_KICK;
|
||||
break;
|
||||
case KICK_MSG_CUSTOM_BAN:
|
||||
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
|
||||
CONS_Printf(M_GetText("has been banned (%s)\n"), reason);
|
||||
HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false);
|
||||
kickreason = KR_BAN;
|
||||
break;
|
||||
}
|
||||
|
@ -3119,9 +3119,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
if (newplayernum+1 > doomcom->numslots)
|
||||
doomcom->numslots = (INT16)(newplayernum+1);
|
||||
|
||||
if (netgame)
|
||||
CONS_Printf(M_GetText("Player %d has joined the game (node %d)\n"), newplayernum+1, node);
|
||||
|
||||
// the server is creating my player
|
||||
if (node == mynode)
|
||||
{
|
||||
|
@ -3143,11 +3140,17 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
D_SendPlayerConfig();
|
||||
addedtogame = true;
|
||||
}
|
||||
else if (server && netgame && cv_showjoinaddress.value)
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
const char *address;
|
||||
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
|
||||
CONS_Printf(M_GetText("Player Address is %s\n"), address);
|
||||
if (server && cv_showjoinaddress.value)
|
||||
{
|
||||
const char *address;
|
||||
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
|
||||
HU_AddChatText(va("\x82*Player %d has joined the game (node %d) (%s)", newplayernum+1, node, address), false); // merge join notification + IP to avoid clogging console/chat.
|
||||
}
|
||||
else
|
||||
HU_AddChatText(va("\x82*Player %d has joined the game (node %d)", newplayernum+1, node), false); // if you don't wanna see the join address.
|
||||
}
|
||||
|
||||
if (server && multiplayer && motd[0] != '\0')
|
||||
|
|
|
@ -309,6 +309,7 @@ typedef struct
|
|||
} ATTRPACK clientconfig_pak;
|
||||
|
||||
#define MAXSERVERNAME 32
|
||||
#define MAXFILENEEDED 915
|
||||
// This packet is too large
|
||||
typedef struct
|
||||
{
|
||||
|
@ -330,7 +331,7 @@ typedef struct
|
|||
unsigned char mapmd5[16];
|
||||
UINT8 actnum;
|
||||
UINT8 iszone;
|
||||
UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h)
|
||||
UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
|
||||
} ATTRPACK serverinfo_pak;
|
||||
|
||||
typedef struct
|
||||
|
@ -429,9 +430,9 @@ extern doomdata_t *netbuffer;
|
|||
|
||||
extern consvar_t cv_playbackspeed;
|
||||
|
||||
#define BASEPACKETSIZE ((size_t)&(((doomdata_t *)0)->u))
|
||||
#define FILETXHEADER ((size_t)((filetx_pak *)0)->data)
|
||||
#define BASESERVERTICSSIZE ((size_t)&(((doomdata_t *)0)->u.serverpak.cmds[0]))
|
||||
#define BASEPACKETSIZE offsetof(doomdata_t, u)
|
||||
#define FILETXHEADER offsetof(filetx_pak, data)
|
||||
#define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0])
|
||||
|
||||
#define KICK_MSG_GO_AWAY 1
|
||||
#define KICK_MSG_CON_FAIL 2
|
||||
|
|
63
src/d_main.c
63
src/d_main.c
|
@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "m_cond.h" // condition initialization
|
||||
#include "fastcmp.h"
|
||||
#include "keys.h"
|
||||
#include "filesrch.h" // refreshdirmenu, mainwadstally
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
#include "config.h"
|
||||
|
@ -178,6 +179,7 @@ void D_PostEvent_end(void) {};
|
|||
UINT8 shiftdown = 0; // 0x1 left, 0x2 right
|
||||
UINT8 ctrldown = 0; // 0x1 left, 0x2 right
|
||||
UINT8 altdown = 0; // 0x1 left, 0x2 right
|
||||
boolean capslock = 0; // gee i wonder what this does.
|
||||
//
|
||||
// D_ModifierKeyResponder
|
||||
// Sets global shift/ctrl/alt variables, never actually eats events
|
||||
|
@ -319,8 +321,7 @@ static void D_Display(void)
|
|||
if (!gametic)
|
||||
break;
|
||||
HU_Erase();
|
||||
if (automapactive)
|
||||
AM_Drawer();
|
||||
AM_Drawer();
|
||||
break;
|
||||
|
||||
case GS_INTERMISSION:
|
||||
|
@ -374,12 +375,10 @@ static void D_Display(void)
|
|||
break;
|
||||
}
|
||||
|
||||
// clean up border stuff
|
||||
// see if the border needs to be initially drawn
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
// draw the view directly
|
||||
if (!automapactive && !dedicated && cv_renderview.value)
|
||||
if (cv_renderview.value && !automapactive)
|
||||
{
|
||||
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
|
||||
{
|
||||
|
@ -437,7 +436,6 @@ static void D_Display(void)
|
|||
}
|
||||
|
||||
ST_Drawer();
|
||||
|
||||
HU_Drawer();
|
||||
}
|
||||
|
||||
|
@ -586,6 +584,8 @@ void D_SRB2Loop(void)
|
|||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
|
||||
#ifdef DEBUGFILE
|
||||
if (!realtics)
|
||||
if (debugload)
|
||||
|
@ -850,17 +850,21 @@ static void IdentifyVersion(void)
|
|||
|
||||
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
|
||||
{
|
||||
#define MUSICTEST(str) \
|
||||
{\
|
||||
const char *musicpath = va(pandf,srb2waddir,str);\
|
||||
int ms = W_VerifyNMUSlumps(musicpath); \
|
||||
if (ms == 1) \
|
||||
D_AddFile(musicpath); \
|
||||
else if (ms == 0) \
|
||||
I_Error("File "str" has been modified with non-music/sound lumps"); \
|
||||
}
|
||||
|
||||
#if defined (DC) && 0
|
||||
const char *musicfile = "music_dc.dta";
|
||||
MUSICTEST("music_dc.dta")
|
||||
#else
|
||||
const char *musicfile = "music.dta";
|
||||
MUSICTEST("music.dta")
|
||||
#endif
|
||||
const char *musicpath = va(pandf,srb2waddir,musicfile);
|
||||
int ms = W_VerifyNMUSlumps(musicpath); // Don't forget the music!
|
||||
if (ms == 1)
|
||||
D_AddFile(musicpath);
|
||||
else if (ms == 0)
|
||||
I_Error("File %s has been modified with non-music lumps",musicfile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1136,25 +1140,36 @@ void D_SRB2Main(void)
|
|||
#endif
|
||||
D_CleanFile();
|
||||
|
||||
mainwads = 0;
|
||||
|
||||
#ifndef DEVELOP // md5s last updated 12/14/14
|
||||
|
||||
// Check MD5s of autoloaded files
|
||||
W_VerifyFileMD5(0, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad
|
||||
W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
|
||||
W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
|
||||
W_VerifyFileMD5(3, ASSET_HASH_RINGS_DTA); // rings.dta
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_ZONES_DTA); // zones.dta
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_PLAYER_DTA); // player.dta
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_RINGS_DTA); // rings.dta
|
||||
#ifdef USE_PATCH_DTA
|
||||
W_VerifyFileMD5(4, ASSET_HASH_PATCH_DTA); // patch.dta
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_PATCH_DTA); // patch.dta
|
||||
#endif
|
||||
|
||||
// don't check music.dta because people like to modify it, and it doesn't matter if they do
|
||||
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
|
||||
//mainwads++; // music.dta does not increment mainwads (see <= 2.1.21)
|
||||
|
||||
#else
|
||||
|
||||
mainwads++; // srb2.srb/srb2.wad
|
||||
mainwads++; // zones.dta
|
||||
mainwads++; // player.dta
|
||||
mainwads++; // rings.dta
|
||||
#ifdef USE_PATCH_DTA
|
||||
mainwads++; // patch.dta
|
||||
#endif
|
||||
//mainwads++; // music.dta does not increment mainwads (see <= 2.1.21)
|
||||
|
||||
#endif //ifndef DEVELOP
|
||||
|
||||
mainwads = 4; // there are 4 wads not to unload
|
||||
#ifdef USE_PATCH_DTA
|
||||
++mainwads; // patch.dta adds one more
|
||||
#endif
|
||||
mainwadstally = packetsizetally;
|
||||
|
||||
cht_Init();
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "d_clisrv.h"
|
||||
#include "z_zone.h"
|
||||
#include "i_tcp.h"
|
||||
#include "d_main.h" // srb2home
|
||||
|
||||
//
|
||||
// NETWORKING
|
||||
|
@ -1374,12 +1375,12 @@ boolean D_CheckNetGame(void)
|
|||
{
|
||||
k++;
|
||||
sprintf(filename, "debug%d.txt", k);
|
||||
debugfile = fopen(filename, "w");
|
||||
debugfile = fopen(va("%s" PATHSEP "%s", srb2home, filename), "w");
|
||||
}
|
||||
if (debugfile)
|
||||
CONS_Printf(M_GetText("debug output to: %s\n"), filename);
|
||||
CONS_Printf(M_GetText("debug output to: %s\n"), va("%s" PATHSEP "%s", srb2home, filename));
|
||||
else
|
||||
CONS_Alert(CONS_WARNING, M_GetText("cannot debug output to file %s!\n"), filename);
|
||||
CONS_Alert(CONS_WARNING, M_GetText("cannot debug output to file %s!\n"), va("%s" PATHSEP "%s", srb2home, filename));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define MAXNETNODES 32
|
||||
#define BROADCASTADDR MAXNETNODES
|
||||
#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer
|
||||
//#define NETSPLITSCREEN // Kart's splitscreen netgame feature
|
||||
|
||||
#define STATLENGTH (TICRATE*2)
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "d_main.h"
|
||||
#include "m_random.h"
|
||||
#include "f_finale.h"
|
||||
#include "filesrch.h"
|
||||
#include "mserv.h"
|
||||
#include "md5.h"
|
||||
#include "z_zone.h"
|
||||
|
@ -673,6 +674,14 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_usegamma);
|
||||
|
||||
// m_menu.c
|
||||
CV_RegisterVar(&cv_compactscoreboard);
|
||||
CV_RegisterVar(&cv_chatheight);
|
||||
CV_RegisterVar(&cv_chatwidth);
|
||||
CV_RegisterVar(&cv_chattime);
|
||||
CV_RegisterVar(&cv_chatspamprotection);
|
||||
CV_RegisterVar(&cv_chatbacktint);
|
||||
CV_RegisterVar(&cv_consolechat);
|
||||
CV_RegisterVar(&cv_chatnotifications);
|
||||
CV_RegisterVar(&cv_crosshair);
|
||||
CV_RegisterVar(&cv_crosshair2);
|
||||
CV_RegisterVar(&cv_alwaysfreelook);
|
||||
|
@ -689,11 +698,23 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_moveaxis2);
|
||||
CV_RegisterVar(&cv_lookaxis);
|
||||
CV_RegisterVar(&cv_lookaxis2);
|
||||
CV_RegisterVar(&cv_jumpaxis);
|
||||
CV_RegisterVar(&cv_jumpaxis2);
|
||||
CV_RegisterVar(&cv_spinaxis);
|
||||
CV_RegisterVar(&cv_spinaxis2);
|
||||
CV_RegisterVar(&cv_fireaxis);
|
||||
CV_RegisterVar(&cv_fireaxis2);
|
||||
CV_RegisterVar(&cv_firenaxis);
|
||||
CV_RegisterVar(&cv_firenaxis2);
|
||||
|
||||
// filesrch.c
|
||||
CV_RegisterVar(&cv_addons_option);
|
||||
CV_RegisterVar(&cv_addons_folder);
|
||||
CV_RegisterVar(&cv_addons_md5);
|
||||
CV_RegisterVar(&cv_addons_showall);
|
||||
CV_RegisterVar(&cv_addons_search_type);
|
||||
CV_RegisterVar(&cv_addons_search_case);
|
||||
|
||||
// WARNING: the order is important when initialising mouse2
|
||||
// we need the mouse2port
|
||||
CV_RegisterVar(&cv_mouse2port);
|
||||
|
@ -984,8 +1005,8 @@ static void SetPlayerName(INT32 playernum, char *newname)
|
|||
if (strcasecmp(newname, player_names[playernum]) != 0)
|
||||
{
|
||||
if (netgame)
|
||||
CONS_Printf(M_GetText("%s renamed to %s\n"),
|
||||
player_names[playernum], newname);
|
||||
HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
|
||||
|
||||
strcpy(player_names[playernum], newname);
|
||||
}
|
||||
}
|
||||
|
@ -3143,25 +3164,12 @@ static void Command_Addfile(void)
|
|||
break;
|
||||
++p;
|
||||
// check total packet size and no of files currently loaded
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
{
|
||||
size_t packetsize = 0;
|
||||
serverinfo_pak *dummycheck = NULL;
|
||||
|
||||
// Shut the compiler up.
|
||||
(void)dummycheck;
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
|
||||
|
||||
packetsize += nameonlylength(fn) + 22;
|
||||
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| (packetsize > sizeof(dummycheck->fileneeded)))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
|
||||
return;
|
||||
}
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
|
||||
return;
|
||||
}
|
||||
|
||||
WRITESTRINGN(buf_p,p,240);
|
||||
|
@ -3247,7 +3255,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
boolean kick = false;
|
||||
boolean toomany = false;
|
||||
INT32 i,j;
|
||||
size_t packetsize = 0;
|
||||
serverinfo_pak *dummycheck = NULL;
|
||||
|
||||
// Shut the compiler up.
|
||||
|
@ -3278,13 +3285,8 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
|
||||
|
||||
packetsize += nameonlylength(filename) + 22;
|
||||
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| (packetsize > sizeof(dummycheck->fileneeded)))
|
||||
|| ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfile(filename,md5sum,true);
|
||||
|
@ -3440,7 +3442,7 @@ static void Command_Version_f(void)
|
|||
#elif defined(__linux__)
|
||||
CONS_Printf("Linux ");
|
||||
#elif defined(MACOSX)
|
||||
CONS_Printf("macOS" );
|
||||
CONS_Printf("macOS ");
|
||||
#elif defined(UNIXCOMMON)
|
||||
CONS_Printf("Unix (Common) ");
|
||||
#else
|
||||
|
@ -3465,6 +3467,11 @@ static void Command_Version_f(void)
|
|||
CONS_Printf("\x85" "DEBUG " "\x80");
|
||||
#endif
|
||||
|
||||
// DEVELOP build
|
||||
#ifdef DEVELOP
|
||||
CONS_Printf("\x87" "DEVELOP " "\x80");
|
||||
#endif
|
||||
|
||||
CONS_Printf("\n");
|
||||
}
|
||||
|
||||
|
@ -3509,6 +3516,9 @@ static void Command_Playintro_f(void)
|
|||
if (netgame)
|
||||
return;
|
||||
|
||||
if (dirmenu)
|
||||
closefilemenu(true);
|
||||
|
||||
F_StartIntro();
|
||||
}
|
||||
|
||||
|
@ -4066,6 +4076,9 @@ void Command_ExitGame_f(void)
|
|||
cv_debug = 0;
|
||||
emeralds = 0;
|
||||
|
||||
if (dirmenu)
|
||||
closefilemenu(true);
|
||||
|
||||
if (!modeattacking)
|
||||
D_StartTitle();
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ INT32 lastfilenum = -1;
|
|||
/** Fills a serverinfo packet with information about wad files loaded.
|
||||
*
|
||||
* \todo Give this function a better name since it is in global scope.
|
||||
* Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c
|
||||
*
|
||||
*/
|
||||
UINT8 *PutFileNeeded(void)
|
||||
|
@ -112,29 +113,22 @@ UINT8 *PutFileNeeded(void)
|
|||
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
|
||||
char wadfilename[MAX_WADPATH] = "";
|
||||
UINT8 filestatus;
|
||||
size_t bytesused = 0;
|
||||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
// If it has only music/sound lumps, mark it as unimportant
|
||||
if (W_VerifyNMUSlumps(wadfiles[i]->filename))
|
||||
filestatus = 0;
|
||||
else
|
||||
filestatus = 1; // Important
|
||||
// If it has only music/sound lumps, don't put it in the list
|
||||
if (!wadfiles[i]->important)
|
||||
continue;
|
||||
|
||||
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
|
||||
|
||||
// Store in the upper four bits
|
||||
if (!cv_downloading.value)
|
||||
filestatus += (2 << 4); // Won't send
|
||||
else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024))
|
||||
filestatus += (0 << 4); // Won't send
|
||||
else
|
||||
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
|
||||
filestatus += (1 << 4); // Will send if requested
|
||||
|
||||
bytesused += (nameonlylength(wadfilename) + 22);
|
||||
|
||||
// Don't write too far...
|
||||
if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded))
|
||||
I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename);
|
||||
// else
|
||||
// filestatus += (0 << 4); -- Won't send, too big
|
||||
|
||||
WRITEUINT8(p, filestatus);
|
||||
|
||||
|
@ -167,7 +161,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
|
|||
{
|
||||
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
|
||||
filestatus = READUINT8(p); // The first byte is the file status
|
||||
fileneeded[i].important = (UINT8)(filestatus & 3);
|
||||
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
||||
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
||||
fileneeded[i].file = NULL; // The file isn't open yet
|
||||
|
@ -197,7 +190,7 @@ boolean CL_CheckDownloadable(void)
|
|||
UINT8 i,dlstatus = 0;
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||
{
|
||||
if (fileneeded[i].willsend == 1)
|
||||
continue;
|
||||
|
@ -218,7 +211,7 @@ boolean CL_CheckDownloadable(void)
|
|||
// not downloadable, put reason in console
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||
{
|
||||
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
|
||||
|
||||
|
@ -271,7 +264,7 @@ boolean CL_SendRequestFile(void)
|
|||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
|
||||
&& fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
||||
&& (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
||||
{
|
||||
I_Error("Attempted to download files that were not sendable");
|
||||
}
|
||||
|
@ -280,8 +273,7 @@ boolean CL_SendRequestFile(void)
|
|||
netbuffer->packettype = PT_REQUESTFILE;
|
||||
p = (char *)netbuffer->u.textcmd;
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
|
||||
&& fileneeded[i].important)
|
||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
|
||||
{
|
||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||
nameonly(fileneeded[i].filename);
|
||||
|
@ -339,10 +331,6 @@ INT32 CL_CheckFiles(void)
|
|||
INT32 ret = 1;
|
||||
size_t packetsize = 0;
|
||||
size_t filestoget = 0;
|
||||
serverinfo_pak *dummycheck = NULL;
|
||||
|
||||
// Shut the compiler up.
|
||||
(void)dummycheck;
|
||||
|
||||
// if (M_CheckParm("-nofiles"))
|
||||
// return 1;
|
||||
|
@ -360,13 +348,7 @@ INT32 CL_CheckFiles(void)
|
|||
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
|
||||
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
|
||||
{
|
||||
if (i < fileneedednum && !fileneeded[i].important)
|
||||
{
|
||||
// Eh whatever, don't care
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename))
|
||||
if (j < numwadfiles && !wadfiles[j]->important)
|
||||
{
|
||||
// Unimportant on our side. still don't care.
|
||||
++j;
|
||||
|
@ -392,8 +374,7 @@ INT32 CL_CheckFiles(void)
|
|||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
|
||||
packetsize = packetsizetally;
|
||||
|
||||
for (i = 1; i < fileneedednum; i++)
|
||||
{
|
||||
|
@ -411,13 +392,13 @@ INT32 CL_CheckFiles(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important)
|
||||
if (fileneeded[i].status != FS_NOTFOUND)
|
||||
continue;
|
||||
|
||||
packetsize += nameonlylength(fileneeded[i].filename) + 22;
|
||||
|
||||
if ((numwadfiles+filestoget >= MAX_WADFILES)
|
||||
|| (packetsize > sizeof(dummycheck->fileneeded)))
|
||||
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
|
||||
return 3;
|
||||
|
||||
filestoget++;
|
||||
|
@ -449,27 +430,8 @@ void CL_LoadServerFiles(void)
|
|||
fileneeded[i].status = FS_OPEN;
|
||||
}
|
||||
else if (fileneeded[i].status == FS_MD5SUMBAD)
|
||||
{
|
||||
// If the file is marked important, don't even bother proceeding.
|
||||
if (fileneeded[i].important)
|
||||
I_Error("Wrong version of important file %s", fileneeded[i].filename);
|
||||
|
||||
// If it isn't, no need to worry the user with a console message,
|
||||
// although it can't hurt to put something in the debug file.
|
||||
|
||||
// ...but wait a second. What if the local version is "important"?
|
||||
if (!W_VerifyNMUSlumps(fileneeded[i].filename))
|
||||
I_Error("File %s should only contain music and sound effects!",
|
||||
fileneeded[i].filename);
|
||||
|
||||
// Okay, NOW we know it's safe. Whew.
|
||||
P_AddWadFile(fileneeded[i].filename);
|
||||
if (fileneeded[i].important)
|
||||
G_SetGameModified(true);
|
||||
fileneeded[i].status = FS_OPEN;
|
||||
DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename));
|
||||
}
|
||||
else if (fileneeded[i].important)
|
||||
I_Error("Wrong version of file %s", fileneeded[i].filename);
|
||||
else
|
||||
{
|
||||
const char *s;
|
||||
switch(fileneeded[i].status)
|
||||
|
@ -939,10 +901,11 @@ void nameonly(char *s)
|
|||
{
|
||||
ns = &(s[j+1]);
|
||||
len = strlen(ns);
|
||||
if (false)
|
||||
#if 0
|
||||
M_Memcpy(s, ns, len+1);
|
||||
else
|
||||
#else
|
||||
memmove(s, ns, len+1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ typedef enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 important;
|
||||
UINT8 willsend; // Is the server willing to send it?
|
||||
char filename[MAX_WADPATH];
|
||||
UINT8 md5sum[16];
|
||||
|
|
|
@ -1248,6 +1248,18 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
deh_warning("Level header %d: invalid bonus type number %d", num, i);
|
||||
}
|
||||
|
||||
else if (fastcmp(word, "SAVEOVERRIDE"))
|
||||
{
|
||||
if (fastcmp(word2, "DEFAULT")) i = SAVE_DEFAULT;
|
||||
else if (fastcmp(word2, "ALWAYS")) i = SAVE_ALWAYS;
|
||||
else if (fastcmp(word2, "NEVER")) i = SAVE_NEVER;
|
||||
|
||||
if (i >= SAVE_NEVER && i <= SAVE_ALWAYS)
|
||||
mapheaderinfo[num-1]->saveoverride = (SINT8)i;
|
||||
else
|
||||
deh_warning("Level header %d: invalid save override number %d", num, i);
|
||||
}
|
||||
|
||||
else if (fastcmp(word, "LEVELFLAGS"))
|
||||
mapheaderinfo[num-1]->levelflags = (UINT8)i;
|
||||
else if (fastcmp(word, "MENUFLAGS"))
|
||||
|
@ -2940,7 +2952,7 @@ static void readmaincfg(MYFILE *f)
|
|||
else if (fastcmp(word, "USENIGHTSSS"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", useNightsSS), UNDO_NONE);
|
||||
useNightsSS = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
useNightsSS = (value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
else if (fastcmp(word, "REDTEAM"))
|
||||
{
|
||||
|
@ -3014,7 +3026,7 @@ static void readmaincfg(MYFILE *f)
|
|||
else if (fastcmp(word, "LOOPTITLE"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE);
|
||||
looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
looptitle = (value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
else if (fastcmp(word, "TITLESCROLLSPEED"))
|
||||
{
|
||||
|
@ -3032,7 +3044,7 @@ static void readmaincfg(MYFILE *f)
|
|||
else if (fastcmp(word, "DISABLESPEEDADJUST"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", disableSpeedAdjust), UNDO_NONE);
|
||||
disableSpeedAdjust = (UINT8)get_number(word2);
|
||||
disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
else if (fastcmp(word, "NUMDEMOS"))
|
||||
{
|
||||
|
@ -3080,7 +3092,7 @@ static void readmaincfg(MYFILE *f)
|
|||
strncpy(timeattackfolder, gamedatafilename, min(filenamelen, sizeof (timeattackfolder)));
|
||||
timeattackfolder[min(filenamelen, sizeof (timeattackfolder) - 1)] = '\0';
|
||||
|
||||
strncpy(savegamename, timeattackfolder, strlen(timeattackfolder));
|
||||
strcpy(savegamename, timeattackfolder);
|
||||
strlcat(savegamename, "%u.ssg", sizeof(savegamename));
|
||||
// can't use sprintf since there is %u in savegamename
|
||||
strcatbf(savegamename, srb2home, PATHSEP);
|
||||
|
@ -7074,6 +7086,11 @@ struct {
|
|||
{"LF2_NIGHTSATTACK",LF2_NIGHTSATTACK},
|
||||
{"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED},
|
||||
|
||||
// Save override
|
||||
{"SAVE_NEVER",SAVE_NEVER},
|
||||
{"SAVE_DEFAULT",SAVE_DEFAULT},
|
||||
{"SAVE_ALWAYS",SAVE_ALWAYS},
|
||||
|
||||
// NiGHTS grades
|
||||
{"GRADE_F",GRADE_F},
|
||||
{"GRADE_E",GRADE_E},
|
||||
|
@ -8303,6 +8320,7 @@ static inline int lib_getenum(lua_State *L)
|
|||
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array.
|
||||
LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)");
|
||||
if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer))
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER);
|
||||
|
@ -8320,7 +8338,6 @@ static inline int lib_getenum(lua_State *L)
|
|||
lua_pushinteger(L, token);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,9 +150,9 @@ extern FILE *logstream;
|
|||
// we use comprevision and compbranch instead.
|
||||
#else
|
||||
#define VERSION 201 // Game version
|
||||
#define SUBVERSION 21 // more precise version number
|
||||
#define VERSIONSTRING "v2.1.21"
|
||||
#define VERSIONSTRINGW L"v2.1.21"
|
||||
#define SUBVERSION 23 // more precise version number
|
||||
#define VERSIONSTRING "v2.1.23"
|
||||
#define VERSIONSTRINGW L"v2.1.23"
|
||||
// Hey! If you change this, add 1 to the MODVERSION below!
|
||||
// Otherwise we can't force updates!
|
||||
#endif
|
||||
|
@ -161,6 +161,9 @@ extern FILE *logstream;
|
|||
// Comment or uncomment this as necessary.
|
||||
#define USE_PATCH_DTA
|
||||
|
||||
// Use .kart extension addons
|
||||
//#define USE_KART
|
||||
|
||||
// Modification options
|
||||
// If you want to take advantage of the Master Server's ability to force clients to update
|
||||
// to the latest version, fill these out. Otherwise, just comment out UPDATE_ALERT and leave
|
||||
|
@ -214,7 +217,21 @@ extern FILE *logstream;
|
|||
// it's only for detection of the version the player is using so the MS can alert them of an update.
|
||||
// Only set it higher, not lower, obviously.
|
||||
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
|
||||
#define MODVERSION 26
|
||||
#define MODVERSION 28
|
||||
|
||||
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
|
||||
// Increment MINOREXECVERSION whenever a config change is needed that does not correspond
|
||||
// to an increment in MODVERSION. This might never happen in practice.
|
||||
// If MODVERSION increases, set MINOREXECVERSION to 0.
|
||||
#define MAJOREXECVERSION MODVERSION
|
||||
#define MINOREXECVERSION 0
|
||||
// (It would have been nice to use VERSION and SUBVERSION but those are zero'd out for DEVELOP builds)
|
||||
|
||||
// Macros
|
||||
#define GETMAJOREXECVERSION(v) (v & 0xFFFF)
|
||||
#define GETMINOREXECVERSION(v) (v >> 16)
|
||||
#define GETEXECVERSION(major,minor) (major + (minor << 16))
|
||||
#define EXECVERSION GETEXECVERSION(MAJOREXECVERSION, MINOREXECVERSION)
|
||||
|
||||
// =========================================================================
|
||||
|
||||
|
@ -396,6 +413,7 @@ extern INT32 cv_debug;
|
|||
|
||||
// Modifier key variables, accessible anywhere
|
||||
extern UINT8 shiftdown, ctrldown, altdown;
|
||||
extern boolean capslock;
|
||||
|
||||
// if we ever make our alloc stuff...
|
||||
#define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL)
|
||||
|
@ -410,6 +428,15 @@ INT32 I_GetKey(void);
|
|||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
// Floating point comparison epsilons from float.h
|
||||
#ifndef FLT_EPSILON
|
||||
#define FLT_EPSILON 1.1920928955078125e-7f
|
||||
#endif
|
||||
|
||||
#ifndef DBL_EPSILON
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#endif
|
||||
|
||||
// An assert-type mechanism.
|
||||
#ifdef PARANOIA
|
||||
#define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__))
|
||||
|
|
|
@ -234,6 +234,7 @@ typedef struct
|
|||
SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no.
|
||||
UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in?
|
||||
SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.)
|
||||
SINT8 saveoverride; ///< Set how the game is allowed to save (1 for always, -1 for never, 0 is 2.1 default)
|
||||
|
||||
UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below
|
||||
UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus
|
||||
|
@ -261,6 +262,11 @@ typedef struct
|
|||
#define LF2_NIGHTSATTACK 8 ///< Show this map in NiGHTS mode menu
|
||||
#define LF2_NOVISITNEEDED 16 ///< Available in time attack/nights mode without visiting the level
|
||||
|
||||
// Save override
|
||||
#define SAVE_NEVER -1
|
||||
#define SAVE_DEFAULT 0
|
||||
#define SAVE_ALWAYS 1
|
||||
|
||||
extern mapheader_t* mapheaderinfo[NUMMAPS];
|
||||
|
||||
enum TypeOfLevel
|
||||
|
|
|
@ -997,7 +997,9 @@ static const char *credits[] = {
|
|||
"Gregor \"Oogaland\" Dick",
|
||||
"Louis-Antoine \"LJSonic\" de Moulins", // for fixing 2.1's netcode (de Rochefort doesn't quite fit on the screen sorry lol)
|
||||
"Julio \"Chaos Zero 64\" Guir",
|
||||
"\"Jimita\"",
|
||||
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
|
||||
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart
|
||||
"Matthew \"Shuffle\" Marsalko",
|
||||
"Steven \"StroggOnMeth\" McGranahan",
|
||||
"\"Morph\"", // For SRB2Morphed stuff
|
||||
|
@ -1006,9 +1008,9 @@ static const char *credits[] = {
|
|||
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
|
||||
"\"Steel Titanium\"",
|
||||
"Ben \"Cue\" Woodford",
|
||||
// Git contributors with 5+ approved merges, at least a few of substantive quality, may be named
|
||||
// Everyone else is acknowledged here
|
||||
"STJr Git Contributors",
|
||||
// Git contributors with 5+ approved merges of substantive quality,
|
||||
// or contributors with at least one groundbreaking merge, may be named.
|
||||
// Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors".
|
||||
"",
|
||||
"\1Sprite Artists",
|
||||
"Odi \"Iceman404\" Atunzu",
|
||||
|
@ -1082,11 +1084,17 @@ static const char *credits[] = {
|
|||
"Bill \"Tets\" Reed",
|
||||
"",
|
||||
"\1Special Thanks",
|
||||
"Doom Legacy Project",
|
||||
"iD Software",
|
||||
"Alex \"MistaED\" Fuller",
|
||||
"Doom Legacy Project",
|
||||
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
|
||||
"Alex \"MistaED\" Fuller",
|
||||
"Pascal \"CodeImp\" vd Heiden", // Doom Builder developer
|
||||
"Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked
|
||||
"Simon \"sirjuddington\" Judd", // SLADE developer
|
||||
// Acknowledged here are the following:
|
||||
// Minor merge request authors, see guideline above
|
||||
// Golden - Expanded thin font
|
||||
"SRB2 Community Contributors",
|
||||
"",
|
||||
"\1Produced By",
|
||||
"Sonic Team Junior",
|
||||
|
|
477
src/filesrch.c
477
src/filesrch.c
|
@ -31,6 +31,8 @@
|
|||
#include "filesrch.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_misc.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_menu.h" // Addons_option_Onchange
|
||||
|
||||
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)
|
||||
|
||||
|
@ -255,6 +257,28 @@ readdir (DIR * dirp)
|
|||
return (struct dirent *) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* rewinddir
|
||||
*
|
||||
* Makes the next readdir start from the beginning.
|
||||
*/
|
||||
int
|
||||
rewinddir (DIR * dirp)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
/* Check for valid DIR struct. */
|
||||
if (!dirp)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dirp->dd_stat = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* closedir
|
||||
*
|
||||
|
@ -285,6 +309,41 @@ closedir (DIR * dirp)
|
|||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"},
|
||||
#if 1
|
||||
{1, "HOME"}, {2, "SRB2"},
|
||||
#endif
|
||||
{3, "CUSTOM"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
|
||||
consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
|
||||
consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
char menupath[1024];
|
||||
size_t menupathindex[menudepth];
|
||||
size_t menudepthleft = menudepth;
|
||||
|
||||
char menusearch[MAXSTRINGLENGTH+1];
|
||||
|
||||
char **dirmenu, **coredirmenu; // core only local for this file
|
||||
size_t sizedirmenu, sizecoredirmenu; // ditto
|
||||
size_t dir_on[menudepth];
|
||||
UINT8 refreshdirmenu = 0;
|
||||
char *refreshdirname = NULL;
|
||||
|
||||
size_t packetsizetally = 0;
|
||||
size_t mainwadstally = 0;
|
||||
|
||||
#if defined (_XBOX) && defined (_MSC_VER)
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth)
|
||||
|
@ -296,6 +355,25 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
completepath = false;
|
||||
return FS_NOTFOUND;
|
||||
}
|
||||
|
||||
void closefilemenu(boolean validsize)
|
||||
{
|
||||
(void)validsize;
|
||||
return;
|
||||
}
|
||||
|
||||
void searchfilemenu(char *tempname)
|
||||
{
|
||||
(void)tempname;
|
||||
return;
|
||||
}
|
||||
|
||||
boolean preparefilemenu(boolean samedepth)
|
||||
{
|
||||
(void)samedepth;
|
||||
return false;
|
||||
}
|
||||
|
||||
#elif defined (_WIN32_WCE)
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth)
|
||||
|
@ -346,7 +424,27 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
#endif
|
||||
return FS_NOTFOUND;
|
||||
}
|
||||
|
||||
void closefilemenu(boolean validsize)
|
||||
{
|
||||
(void)validsize;
|
||||
return;
|
||||
}
|
||||
|
||||
void searchfilemenu(char *tempname)
|
||||
{
|
||||
(void)tempname;
|
||||
return;
|
||||
}
|
||||
|
||||
boolean preparefilemenu(boolean samedepth)
|
||||
{
|
||||
(void)samedepth;
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
|
||||
{
|
||||
filestatus_t retval = FS_NOTFOUND;
|
||||
|
@ -387,25 +485,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
{
|
||||
searchpath[searchpathindex[depthleft]]=0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
if (dent)
|
||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
||||
|
||||
if (!dent)
|
||||
{
|
||||
closedir(dirhandle[depthleft++]);
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
{
|
||||
// we don't want to scan uptree
|
||||
continue;
|
||||
}
|
||||
else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
{
|
||||
// was the file (re)moved? can't stat it
|
||||
}
|
||||
|
||||
// okay, now we actually want searchpath to incorporate d_name
|
||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
||||
|
||||
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
; // was the file (re)moved? can't stat it
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
||||
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
||||
dirhandle[depthleft] = opendir(searchpath);
|
||||
if (!dirhandle[depthleft])
|
||||
|
@ -444,6 +546,365 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
free(searchname);
|
||||
free(searchpathindex);
|
||||
free(dirhandle);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)
|
||||
"\5.txt", "\5.cfg", // exec
|
||||
"\5.wad",
|
||||
#ifdef USE_KART
|
||||
"\6.kart",
|
||||
#endif
|
||||
"\5.pk3", "\5.soc", "\5.lua"}; // addfile
|
||||
|
||||
char filenamebuf[MAX_WADFILES][MAX_WADPATH];
|
||||
|
||||
|
||||
static boolean filemenucmp(char *haystack, char *needle)
|
||||
{
|
||||
static char localhaystack[128];
|
||||
strlcpy(localhaystack, haystack, 128);
|
||||
if (!cv_addons_search_case.value)
|
||||
strupr(localhaystack);
|
||||
if (cv_addons_search_type.value)
|
||||
return (strstr(localhaystack, needle) != 0);
|
||||
return (!strncmp(localhaystack, needle, menusearch[0]));
|
||||
}
|
||||
|
||||
void closefilemenu(boolean validsize)
|
||||
{
|
||||
// search
|
||||
if (dirmenu)
|
||||
{
|
||||
if (dirmenu != coredirmenu)
|
||||
{
|
||||
if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS))
|
||||
{
|
||||
Z_Free(dirmenu[0]);
|
||||
dirmenu[0] = NULL;
|
||||
}
|
||||
Z_Free(dirmenu);
|
||||
}
|
||||
dirmenu = NULL;
|
||||
sizedirmenu = 0;
|
||||
}
|
||||
|
||||
if (coredirmenu)
|
||||
{
|
||||
// core
|
||||
if (validsize)
|
||||
{
|
||||
for (; sizecoredirmenu > 0; sizecoredirmenu--)
|
||||
{
|
||||
Z_Free(coredirmenu[sizecoredirmenu-1]);
|
||||
coredirmenu[sizecoredirmenu-1] = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
sizecoredirmenu = 0;
|
||||
|
||||
Z_Free(coredirmenu);
|
||||
coredirmenu = NULL;
|
||||
}
|
||||
|
||||
if (refreshdirname)
|
||||
Z_Free(refreshdirname);
|
||||
refreshdirname = NULL;
|
||||
}
|
||||
|
||||
void searchfilemenu(char *tempname)
|
||||
{
|
||||
size_t i, first;
|
||||
char localmenusearch[MAXSTRINGLENGTH] = "";
|
||||
|
||||
if (dirmenu)
|
||||
{
|
||||
if (dirmenu != coredirmenu)
|
||||
{
|
||||
if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS))
|
||||
{
|
||||
Z_Free(dirmenu[0]);
|
||||
dirmenu[0] = NULL;
|
||||
}
|
||||
//Z_Free(dirmenu); -- Z_Realloc later tho...
|
||||
}
|
||||
else
|
||||
dirmenu = NULL;
|
||||
}
|
||||
|
||||
first = (((UINT8)(coredirmenu[0][DIR_TYPE]) == EXT_UP) ? 1 : 0); // skip UP...
|
||||
|
||||
if (!menusearch[0])
|
||||
{
|
||||
if (dirmenu)
|
||||
Z_Free(dirmenu);
|
||||
dirmenu = coredirmenu;
|
||||
sizedirmenu = sizecoredirmenu;
|
||||
|
||||
if (tempname)
|
||||
{
|
||||
for (i = first; i < sizedirmenu; i++)
|
||||
{
|
||||
if (!strcmp(dirmenu[i]+DIR_STRING, tempname))
|
||||
{
|
||||
dir_on[menudepthleft] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == sizedirmenu)
|
||||
dir_on[menudepthleft] = first;
|
||||
|
||||
Z_Free(tempname);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(localmenusearch, menusearch+1);
|
||||
if (!cv_addons_search_case.value)
|
||||
strupr(localmenusearch);
|
||||
|
||||
sizedirmenu = 0;
|
||||
for (i = first; i < sizecoredirmenu; i++)
|
||||
{
|
||||
if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch))
|
||||
sizedirmenu++;
|
||||
}
|
||||
|
||||
if (!sizedirmenu) // no results...
|
||||
{
|
||||
if ((!(dirmenu = Z_Realloc(dirmenu, sizeof(char *), PU_STATIC, NULL)))
|
||||
|| !(dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS))))
|
||||
I_Error("searchfilemenu(): could not create \"No results...\".");
|
||||
sizedirmenu = 1;
|
||||
dir_on[menudepthleft] = 0;
|
||||
if (tempname)
|
||||
Z_Free(tempname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
|
||||
I_Error("searchfilemenu(): could not reallocate dirmenu.");
|
||||
|
||||
sizedirmenu = 0;
|
||||
for (i = first; i < sizecoredirmenu; i++)
|
||||
{
|
||||
if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch))
|
||||
{
|
||||
if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname))
|
||||
{
|
||||
dir_on[menudepthleft] = sizedirmenu;
|
||||
Z_Free(tempname);
|
||||
tempname = NULL;
|
||||
}
|
||||
dirmenu[sizedirmenu++] = coredirmenu[i]; // pointer reuse
|
||||
}
|
||||
}
|
||||
|
||||
if (tempname)
|
||||
{
|
||||
dir_on[menudepthleft] = 0; //first; -- can't be first, causes problems
|
||||
Z_Free(tempname);
|
||||
}
|
||||
}
|
||||
|
||||
boolean preparefilemenu(boolean samedepth)
|
||||
{
|
||||
DIR *dirhandle;
|
||||
struct dirent *dent;
|
||||
struct stat fsstat;
|
||||
size_t pos = 0, folderpos = 0, numfolders = 0;
|
||||
char *tempname = NULL;
|
||||
|
||||
if (samedepth)
|
||||
{
|
||||
if (dirmenu && dirmenu[dir_on[menudepthleft]])
|
||||
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
|
||||
}
|
||||
else
|
||||
menusearch[0] = menusearch[1] = 0; // clear search
|
||||
|
||||
if (!(dirhandle = opendir(menupath))) // get directory
|
||||
{
|
||||
closefilemenu(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items
|
||||
{
|
||||
Z_Free(coredirmenu[sizecoredirmenu-1]);
|
||||
coredirmenu[sizecoredirmenu-1] = NULL;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
dent = readdir(dirhandle);
|
||||
|
||||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
||||
if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
; // was the file (re)moved? can't stat it
|
||||
else // is a file or directory
|
||||
{
|
||||
if (!S_ISDIR(fsstat.st_mode)) // file
|
||||
{
|
||||
if (!cv_addons_showall.value)
|
||||
{
|
||||
size_t len = strlen(dent->d_name)+1;
|
||||
UINT8 ext;
|
||||
for (ext = 0; ext < NUM_EXT_TABLE; ext++)
|
||||
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
|
||||
if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
|
||||
}
|
||||
}
|
||||
else // directory
|
||||
numfolders++;
|
||||
|
||||
sizecoredirmenu++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sizecoredirmenu)
|
||||
{
|
||||
closedir(dirhandle);
|
||||
closefilemenu(false);
|
||||
if (tempname)
|
||||
Z_Free(tempname);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (menudepthleft != menudepth-1) // Make room for UP...
|
||||
{
|
||||
sizecoredirmenu++;
|
||||
numfolders++;
|
||||
folderpos++;
|
||||
}
|
||||
|
||||
if (dirmenu && dirmenu == coredirmenu)
|
||||
dirmenu = NULL;
|
||||
|
||||
if (!(coredirmenu = Z_Realloc(coredirmenu, sizecoredirmenu*sizeof(char *), PU_STATIC, NULL)))
|
||||
{
|
||||
closedir(dirhandle); // just in case
|
||||
I_Error("preparefilemenu(): could not reallocate coredirmenu.");
|
||||
}
|
||||
|
||||
rewinddir(dirhandle);
|
||||
|
||||
while ((pos+folderpos) < sizecoredirmenu)
|
||||
{
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
dent = readdir(dirhandle);
|
||||
|
||||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
||||
if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
; // was the file (re)moved? can't stat it
|
||||
else // is a file or directory
|
||||
{
|
||||
char *temp;
|
||||
size_t len = strlen(dent->d_name)+1;
|
||||
UINT8 ext = EXT_FOLDER;
|
||||
UINT8 folder;
|
||||
|
||||
if (!S_ISDIR(fsstat.st_mode)) // file
|
||||
{
|
||||
if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention
|
||||
for (; ext < NUM_EXT_TABLE; ext++)
|
||||
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
|
||||
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
|
||||
ext += EXT_START; // moving to be appropriate position
|
||||
|
||||
if (ext >= EXT_LOADSTART)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (!filenamebuf[i][0])
|
||||
{
|
||||
strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
|
||||
filenamebuf[i][MAX_WADPATH - 1] = '\0';
|
||||
nameonly(filenamebuf[i]);
|
||||
}
|
||||
|
||||
if (strcmp(dent->d_name, filenamebuf[i]))
|
||||
continue;
|
||||
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
|
||||
continue;
|
||||
|
||||
ext |= EXT_LOADED;
|
||||
}
|
||||
}
|
||||
else if (ext == EXT_TXT)
|
||||
{
|
||||
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
|
||||
ext |= EXT_LOADED;
|
||||
}
|
||||
|
||||
if (!strcmp(dent->d_name, configfile))
|
||||
ext |= EXT_LOADED;
|
||||
|
||||
folder = 0;
|
||||
}
|
||||
else // directory
|
||||
len += (folder = 1);
|
||||
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL)))
|
||||
I_Error("preparefilemenu(): could not create file entry.");
|
||||
temp[DIR_TYPE] = ext;
|
||||
temp[DIR_LEN] = (UINT8)(len);
|
||||
strlcpy(temp+DIR_STRING, dent->d_name, len);
|
||||
if (folder)
|
||||
{
|
||||
strcpy(temp+len, PATHSEP);
|
||||
coredirmenu[folderpos++] = temp;
|
||||
}
|
||||
else
|
||||
coredirmenu[numfolders + pos++] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirhandle);
|
||||
|
||||
if ((menudepthleft != menudepth-1) // now for UP... entry
|
||||
&& !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP))))
|
||||
I_Error("preparefilemenu(): could not create \"UP...\".");
|
||||
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind
|
||||
|
||||
if (!sizecoredirmenu)
|
||||
{
|
||||
dir_on[menudepthleft] = 0;
|
||||
closefilemenu(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
searchfilemenu(tempname);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
|
||||
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
|
||||
|
||||
/** \brief The filesearch function
|
||||
|
||||
|
@ -25,4 +28,71 @@
|
|||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth);
|
||||
|
||||
#define menudepth 20
|
||||
|
||||
extern char menupath[1024];
|
||||
extern size_t menupathindex[menudepth];
|
||||
extern size_t menudepthleft;
|
||||
|
||||
extern char menusearch[MAXSTRINGLENGTH+1];
|
||||
|
||||
extern char **dirmenu;
|
||||
extern size_t sizedirmenu;
|
||||
extern size_t dir_on[menudepth];
|
||||
extern UINT8 refreshdirmenu;
|
||||
extern char *refreshdirname;
|
||||
|
||||
extern size_t packetsizetally;
|
||||
extern size_t mainwadstally;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EXT_FOLDER = 0,
|
||||
EXT_UP,
|
||||
EXT_NORESULTS,
|
||||
EXT_START,
|
||||
EXT_TXT = EXT_START,
|
||||
EXT_CFG,
|
||||
EXT_LOADSTART,
|
||||
EXT_WAD = EXT_LOADSTART,
|
||||
#ifdef USE_KART
|
||||
EXT_KART,
|
||||
#endif
|
||||
EXT_PK3,
|
||||
EXT_SOC,
|
||||
EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt
|
||||
NUM_EXT,
|
||||
NUM_EXT_TABLE = NUM_EXT-EXT_START,
|
||||
EXT_LOADED = 0x80
|
||||
/*
|
||||
obviously there can only be 0x7F supported extensions in
|
||||
addons menu because we're cramming this into a char out of
|
||||
laziness/easy memory allocation (what's the difference?)
|
||||
and have stolen a bit to show whether it's loaded or not
|
||||
in practice the size of the data type is probably overkill
|
||||
toast 02/05/17
|
||||
*/
|
||||
} ext_enum;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIR_TYPE = 0,
|
||||
DIR_LEN,
|
||||
DIR_STRING
|
||||
} dirname_enum;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REFRESHDIR_NORMAL = 1,
|
||||
REFRESHDIR_ADDFILE = 2,
|
||||
REFRESHDIR_WARNING = 4,
|
||||
REFRESHDIR_ERROR = 8,
|
||||
REFRESHDIR_NOTLOADED = 16,
|
||||
REFRESHDIR_MAX = 32
|
||||
} refreshdir_enum;
|
||||
|
||||
void closefilemenu(boolean validsize);
|
||||
void searchfilemenu(char *tempname);
|
||||
boolean preparefilemenu(boolean samedepth);
|
||||
|
||||
#endif // __FILESRCH_H__
|
||||
|
|
145
src/g_game.c
145
src/g_game.c
|
@ -347,6 +347,37 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler.
|
||||
|
||||
// it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on!
|
||||
consvar_t cv_compactscoreboard= {"compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// chat timer thingy
|
||||
static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// chatwidth
|
||||
static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_chatwidth = {"chatwidth", "128", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// chatheight
|
||||
static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_chatheight= {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// chat notifications (do you want to hear beeps? I'd understand if you didn't.)
|
||||
consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// chat spam protection (why would you want to disable that???)
|
||||
consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// minichat text background
|
||||
consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.)
|
||||
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
|
||||
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
||||
consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -375,6 +406,8 @@ typedef enum
|
|||
AXISLOOK,
|
||||
AXISSTRAFE,
|
||||
AXISDEAD, //Axises that don't want deadzones
|
||||
AXISJUMP,
|
||||
AXISSPIN,
|
||||
AXISFIRE,
|
||||
AXISFIRENORMAL,
|
||||
} axis_input_e;
|
||||
|
@ -384,6 +417,8 @@ consvar_t cv_turnaxis = {"joyaxis_turn", "LStick.X", CV_SAVE, joyaxis_cons_t, NU
|
|||
consvar_t cv_moveaxis = {"joyaxis_move", "LStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_sideaxis = {"joyaxis_side", "RStick.X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lookaxis = {"joyaxis_look", "RStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_jumpaxis = {"joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spinaxis = {"joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis = {"joyaxis_fire", "LAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_firenaxis = {"joyaxis_firenormal", "RAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#else
|
||||
|
@ -410,6 +445,8 @@ consvar_t cv_lookaxis = {"joyaxis_look", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL
|
|||
consvar_t cv_lookaxis = {"joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
#endif
|
||||
consvar_t cv_jumpaxis = {"joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spinaxis = {"joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_firenaxis = {"joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
|
@ -419,6 +456,8 @@ consvar_t cv_turnaxis2 = {"joyaxis2_turn", "LStick.X", CV_SAVE, joyaxis_cons_t,
|
|||
consvar_t cv_moveaxis2 = {"joyaxis2_move", "LStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_sideaxis2 = {"joyaxis2_side", "RStick.X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lookaxis2 = {"joyaxis2_look", "RStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_jumpaxis2 = {"joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "LAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "RAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#else
|
||||
|
@ -437,6 +476,8 @@ consvar_t cv_sideaxis2 = {"joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NU
|
|||
#ifndef _XBOX
|
||||
consvar_t cv_lookaxis2 = {"joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
consvar_t cv_jumpaxis2 = {"joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
|
@ -804,6 +845,12 @@ static INT32 JoyAxis(axis_input_e axissel)
|
|||
case AXISSTRAFE:
|
||||
axisval = cv_sideaxis.value;
|
||||
break;
|
||||
case AXISJUMP:
|
||||
axisval = cv_jumpaxis.value;
|
||||
break;
|
||||
case AXISSPIN:
|
||||
axisval = cv_spinaxis.value;
|
||||
break;
|
||||
case AXISFIRE:
|
||||
axisval = cv_fireaxis.value;
|
||||
break;
|
||||
|
@ -881,6 +928,12 @@ static INT32 Joy2Axis(axis_input_e axissel)
|
|||
case AXISSTRAFE:
|
||||
axisval = cv_sideaxis2.value;
|
||||
break;
|
||||
case AXISJUMP:
|
||||
axisval = cv_jumpaxis2.value;
|
||||
break;
|
||||
case AXISSPIN:
|
||||
axisval = cv_spinaxis2.value;
|
||||
break;
|
||||
case AXISFIRE:
|
||||
axisval = cv_fireaxis2.value;
|
||||
break;
|
||||
|
@ -957,7 +1010,7 @@ static fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
|
|||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
||||
{
|
||||
boolean forcestrafe = false;
|
||||
INT32 tspeed, forward, side, axis, i;
|
||||
INT32 tspeed, forward, side, axis, altaxis, i;
|
||||
const INT32 speed = 1;
|
||||
// these ones used for multiple conditions
|
||||
boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove, thisjoyaiming;
|
||||
|
@ -1072,9 +1125,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
|
||||
// forward with key or button
|
||||
axis = JoyAxis(AXISMOVE);
|
||||
if (PLAYER1INPUTDOWN(gc_forward) || (gamepadjoystickmove && axis < 0))
|
||||
altaxis = JoyAxis(AXISLOOK);
|
||||
if (PLAYER1INPUTDOWN(gc_forward) || (gamepadjoystickmove && axis < 0)
|
||||
|| ((player->pflags & PF_NIGHTSMODE)
|
||||
&& (PLAYER1INPUTDOWN(gc_lookup) || (gamepadjoystickmove && altaxis < 0))))
|
||||
forward = forwardmove[speed];
|
||||
if (PLAYER1INPUTDOWN(gc_backward) || (gamepadjoystickmove && axis > 0))
|
||||
if (PLAYER1INPUTDOWN(gc_backward) || (gamepadjoystickmove && axis > 0)
|
||||
|| ((player->pflags & PF_NIGHTSMODE)
|
||||
&& (PLAYER1INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && altaxis > 0))))
|
||||
forward -= forwardmove[speed];
|
||||
|
||||
if (analogjoystickmove && axis != 0)
|
||||
|
@ -1126,7 +1184,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
cmd->buttons |= BT_CUSTOM3;
|
||||
|
||||
// use with any button/key
|
||||
if (PLAYER1INPUTDOWN(gc_use))
|
||||
axis = JoyAxis(AXISSPIN);
|
||||
if (PLAYER1INPUTDOWN(gc_use) || (cv_usejoystick.value && axis > 0))
|
||||
cmd->buttons |= BT_USE;
|
||||
|
||||
// Camera Controls
|
||||
|
@ -1148,7 +1207,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
resetdown = false;
|
||||
|
||||
// jump button
|
||||
if (PLAYER1INPUTDOWN(gc_jump))
|
||||
axis = JoyAxis(AXISJUMP);
|
||||
if (PLAYER1INPUTDOWN(gc_jump) || (cv_usejoystick.value && axis > 0))
|
||||
cmd->buttons |= BT_JUMP;
|
||||
|
||||
// player aiming shit, ahhhh...
|
||||
|
@ -1176,18 +1236,21 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
if (!keyboard_look && cv_lookaxis.value == 0 && !joyaiming && !mouseaiming)
|
||||
localaiming = 0;
|
||||
|
||||
if (PLAYER1INPUTDOWN(gc_lookup) || (gamepadjoystickmove && axis < 0))
|
||||
if (!(player->pflags & PF_NIGHTSMODE))
|
||||
{
|
||||
localaiming += KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
if (PLAYER1INPUTDOWN(gc_lookup) || (gamepadjoystickmove && axis < 0))
|
||||
{
|
||||
localaiming += KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
}
|
||||
else if (PLAYER1INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && axis > 0))
|
||||
{
|
||||
localaiming -= KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
}
|
||||
else if (PLAYER1INPUTDOWN(gc_centerview))
|
||||
localaiming = 0;
|
||||
}
|
||||
else if (PLAYER1INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && axis > 0))
|
||||
{
|
||||
localaiming -= KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
}
|
||||
else if (PLAYER1INPUTDOWN(gc_centerview))
|
||||
localaiming = 0;
|
||||
|
||||
// accept no mlook for network games
|
||||
if (!cv_allowmlook.value)
|
||||
|
@ -1257,7 +1320,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
|
||||
{
|
||||
boolean forcestrafe = false;
|
||||
INT32 tspeed, forward, side, axis, i;
|
||||
INT32 tspeed, forward, side, axis, altaxis, i;
|
||||
const INT32 speed = 1;
|
||||
// these ones used for multiple conditions
|
||||
boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove, thisjoyaiming;
|
||||
|
@ -1372,9 +1435,14 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
|
|||
|
||||
// forward with key or button
|
||||
axis = Joy2Axis(AXISMOVE);
|
||||
if (PLAYER2INPUTDOWN(gc_forward) || (gamepadjoystickmove && axis < 0))
|
||||
altaxis = Joy2Axis(AXISLOOK);
|
||||
if (PLAYER2INPUTDOWN(gc_forward) || (gamepadjoystickmove && axis < 0)
|
||||
|| ((player->pflags & PF_NIGHTSMODE)
|
||||
&& (PLAYER2INPUTDOWN(gc_lookup) || (gamepadjoystickmove && altaxis < 0))))
|
||||
forward = forwardmove[speed];
|
||||
if (PLAYER2INPUTDOWN(gc_backward) || (gamepadjoystickmove && axis > 0))
|
||||
if (PLAYER2INPUTDOWN(gc_backward) || (gamepadjoystickmove && axis > 0)
|
||||
|| ((player->pflags & PF_NIGHTSMODE)
|
||||
&& (PLAYER2INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && altaxis > 0))))
|
||||
forward -= forwardmove[speed];
|
||||
|
||||
if (analogjoystickmove && axis != 0)
|
||||
|
@ -1423,7 +1491,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
|
|||
cmd->buttons |= BT_CUSTOM3;
|
||||
|
||||
// use with any button/key
|
||||
if (PLAYER2INPUTDOWN(gc_use))
|
||||
axis = Joy2Axis(AXISSPIN);
|
||||
if (PLAYER2INPUTDOWN(gc_use) || (cv_usejoystick2.value && axis > 0))
|
||||
cmd->buttons |= BT_USE;
|
||||
|
||||
// Camera Controls
|
||||
|
@ -1445,7 +1514,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
|
|||
resetdown = false;
|
||||
|
||||
// jump button
|
||||
if (PLAYER2INPUTDOWN(gc_jump))
|
||||
axis = Joy2Axis(AXISJUMP);
|
||||
if (PLAYER2INPUTDOWN(gc_jump) || (cv_usejoystick2.value && axis > 0))
|
||||
cmd->buttons |= BT_JUMP;
|
||||
|
||||
// player aiming shit, ahhhh...
|
||||
|
@ -1473,18 +1543,21 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
|
|||
if (!keyboard_look && cv_lookaxis2.value == 0 && !joyaiming && !mouseaiming)
|
||||
localaiming2 = 0;
|
||||
|
||||
if (PLAYER2INPUTDOWN(gc_lookup) || (gamepadjoystickmove && axis < 0))
|
||||
if (!(player->pflags & PF_NIGHTSMODE))
|
||||
{
|
||||
localaiming2 += KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
if (PLAYER2INPUTDOWN(gc_lookup) || (gamepadjoystickmove && axis < 0))
|
||||
{
|
||||
localaiming2 += KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
}
|
||||
else if (PLAYER2INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && axis > 0))
|
||||
{
|
||||
localaiming2 -= KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
}
|
||||
else if (PLAYER2INPUTDOWN(gc_centerview))
|
||||
localaiming2 = 0;
|
||||
}
|
||||
else if (PLAYER2INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && axis > 0))
|
||||
{
|
||||
localaiming2 -= KB_LOOKSPEED * screen_invert;
|
||||
keyboard_look = true;
|
||||
}
|
||||
else if (PLAYER2INPUTDOWN(gc_centerview))
|
||||
localaiming2 = 0;
|
||||
|
||||
// accept no mlook for network games
|
||||
if (!cv_allowmlook.value)
|
||||
|
@ -1585,11 +1658,6 @@ static void Analog_OnChange(void)
|
|||
|
||||
// cameras are not initialized at this point
|
||||
|
||||
if (leveltime > 1)
|
||||
CV_SetValue(&cv_cam_dist, 128);
|
||||
if (cv_analog.value || demoplayback)
|
||||
CV_SetValue(&cv_cam_dist, 192);
|
||||
|
||||
if (!cv_chasecam.value && cv_analog.value) {
|
||||
CV_SetValue(&cv_analog, 0);
|
||||
return;
|
||||
|
@ -1605,11 +1673,6 @@ static void Analog2_OnChange(void)
|
|||
|
||||
// cameras are not initialized at this point
|
||||
|
||||
if (leveltime > 1)
|
||||
CV_SetValue(&cv_cam2_dist, 128);
|
||||
if (cv_analog2.value)
|
||||
CV_SetValue(&cv_cam2_dist, 192);
|
||||
|
||||
if (!cv_chasecam2.value && cv_analog2.value) {
|
||||
CV_SetValue(&cv_analog2, 0);
|
||||
return;
|
||||
|
@ -3630,7 +3693,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
unlocktriggers = 0;
|
||||
|
||||
// clear itemfinder, just in case
|
||||
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
|
||||
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
|
||||
CV_StealthSetValue(&cv_itemfinder, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,13 +54,14 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di
|
|||
extern INT16 rw_maximums[NUM_WEAPONS];
|
||||
|
||||
// used in game menu
|
||||
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
|
||||
extern consvar_t cv_crosshair, cv_crosshair2;
|
||||
extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove;
|
||||
extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2;
|
||||
extern consvar_t cv_useranalog, cv_useranalog2;
|
||||
extern consvar_t cv_analog, cv_analog2;
|
||||
extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis;
|
||||
extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_fireaxis2,cv_firenaxis2;
|
||||
extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_jumpaxis,cv_spinaxis,cv_fireaxis,cv_firenaxis;
|
||||
extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_fireaxis2,cv_firenaxis2;
|
||||
extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
|
||||
|
||||
// mouseaiming (looking up/down with the mouse or keyboard)
|
||||
|
|
238
src/g_input.c
238
src/g_input.c
|
@ -98,6 +98,8 @@ void G_MapEventsToControls(event_t *ev)
|
|||
break;
|
||||
|
||||
case ev_mouse: // buttons are virtual keys
|
||||
if (menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
mousex = (INT32)(ev->data2*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f));
|
||||
mousey = (INT32)(ev->data3*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f));
|
||||
mlooky = (INT32)(ev->data3*((cv_mouseysens.value*cv_mousesens.value)/110.0f + 0.1f));
|
||||
|
@ -105,7 +107,7 @@ void G_MapEventsToControls(event_t *ev)
|
|||
|
||||
case ev_joystick: // buttons are virtual keys
|
||||
i = ev->data1;
|
||||
if (i >= JOYAXISSET)
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
if (ev->data2 != INT32_MAX) joyxmove[i] = ev->data2;
|
||||
if (ev->data3 != INT32_MAX) joyymove[i] = ev->data3;
|
||||
|
@ -113,13 +115,15 @@ void G_MapEventsToControls(event_t *ev)
|
|||
|
||||
case ev_joystick2: // buttons are virtual keys
|
||||
i = ev->data1;
|
||||
if (i >= JOYAXISSET)
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2;
|
||||
if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3;
|
||||
break;
|
||||
|
||||
case ev_mouse2: // buttons are virtual keys
|
||||
if (menuactive || CON_Ready() || chat_on)
|
||||
break;
|
||||
mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f));
|
||||
mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f));
|
||||
mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f));
|
||||
|
@ -1010,6 +1014,16 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control)
|
|||
setupcontrols[control][1] = KEY_NULL;
|
||||
}
|
||||
|
||||
void G_ClearAllControlKeys(void)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
{
|
||||
G_ClearControlKeys(gamecontrol, i);
|
||||
G_ClearControlKeys(gamecontrolbis, i);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the name of a key (or virtual key for mouse and joy)
|
||||
// the input value being an keynum
|
||||
|
@ -1165,7 +1179,9 @@ void G_Controldefault(void)
|
|||
gamecontrol[gc_turnleft ][0] = KEY_LEFTARROW;
|
||||
gamecontrol[gc_turnright ][0] = KEY_RIGHTARROW;
|
||||
gamecontrol[gc_weaponnext ][0] = 'e';
|
||||
gamecontrol[gc_weaponnext ][1] = KEY_JOY1+1; // B
|
||||
gamecontrol[gc_weaponprev ][0] = 'q';
|
||||
gamecontrol[gc_weaponprev ][1] = KEY_JOY1+2; // X
|
||||
gamecontrol[gc_wepslot1 ][0] = '1';
|
||||
gamecontrol[gc_wepslot2 ][0] = '2';
|
||||
gamecontrol[gc_wepslot3 ][0] = '3';
|
||||
|
@ -1180,24 +1196,47 @@ void G_Controldefault(void)
|
|||
gamecontrol[gc_fire ][1] = KEY_MOUSE1+0;
|
||||
gamecontrol[gc_firenormal ][0] = 'c';
|
||||
gamecontrol[gc_tossflag ][0] = '\'';
|
||||
gamecontrol[gc_tossflag ][1] = KEY_JOY1+0; // A
|
||||
gamecontrol[gc_use ][0] = KEY_LSHIFT;
|
||||
gamecontrol[gc_use ][1] = KEY_JOY1+4; // LB
|
||||
gamecontrol[gc_camtoggle ][0] = 'v';
|
||||
gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up
|
||||
gamecontrol[gc_camleft ][0] = '[';
|
||||
gamecontrol[gc_camright ][0] = ']';
|
||||
gamecontrol[gc_camreset ][0] = 'r';
|
||||
gamecontrol[gc_camreset ][1] = KEY_JOY1+3; // Y
|
||||
gamecontrol[gc_lookup ][0] = KEY_UPARROW;
|
||||
gamecontrol[gc_lookdown ][0] = KEY_DOWNARROW;
|
||||
gamecontrol[gc_centerview ][0] = KEY_END;
|
||||
gamecontrol[gc_centerview ][1] = KEY_JOY1+9; // Right Stick
|
||||
gamecontrol[gc_talkkey ][0] = 't';
|
||||
gamecontrol[gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left
|
||||
gamecontrol[gc_teamkey ][0] = 'y';
|
||||
gamecontrol[gc_scores ][0] = KEY_TAB;
|
||||
gamecontrol[gc_scores ][1] = KEY_HAT1+3; // D-Pad Right
|
||||
gamecontrol[gc_jump ][0] = KEY_SPACE;
|
||||
gamecontrol[gc_jump ][1] = KEY_JOY1+5; // RB
|
||||
gamecontrol[gc_console ][0] = KEY_CONSOLE;
|
||||
gamecontrol[gc_pause ][0] = 'p';
|
||||
gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back
|
||||
gamecontrol[gc_screenshot ][0] = KEY_F8;
|
||||
gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down
|
||||
gamecontrol[gc_recordgif ][0] = KEY_F9;
|
||||
gamecontrol[gc_viewpoint ][0] = KEY_F12;
|
||||
gamecontrol[gc_systemmenu ][0] = KEY_JOY1+7; // Start
|
||||
gamecontrolbis[gc_weaponnext][0] = KEY_2JOY1+1; // B
|
||||
gamecontrolbis[gc_weaponprev][0] = KEY_2JOY1+2; // X
|
||||
gamecontrolbis[gc_tossflag ][0] = KEY_2JOY1+0; // A
|
||||
gamecontrolbis[gc_use ][0] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbis[gc_camreset ][0] = KEY_2JOY1+3; // Y
|
||||
gamecontrolbis[gc_centerview][0] = KEY_2JOY1+9; // Right Stick
|
||||
gamecontrolbis[gc_jump ][0] = KEY_2JOY1+5; // RB
|
||||
//gamecontrolbis[gc_pause ][0] = KEY_2JOY1+6; // Back
|
||||
//gamecontrolbis[gc_systemmenu][0] = KEY_2JOY1+7; // Start
|
||||
gamecontrolbis[gc_camtoggle ][0] = KEY_2HAT1+0; // D-Pad Up
|
||||
gamecontrolbis[gc_screenshot][0] = KEY_2HAT1+1; // D-Pad Down
|
||||
//gamecontrolbis[gc_talkkey ][0] = KEY_2HAT1+2; // D-Pad Left
|
||||
//gamecontrolbis[gc_scores ][0] = KEY_2HAT1+3; // D-Pad Right
|
||||
#ifdef WMINPUT
|
||||
gamecontrol[gc_forward ][0] = KEY_JOY1+02; //UP
|
||||
gamecontrol[gc_backward ][0] = KEY_JOY1+03; //DOWN
|
||||
|
@ -1300,30 +1339,166 @@ void G_SaveKeySetting(FILE *f)
|
|||
}
|
||||
}
|
||||
|
||||
void G_CheckDoubleUsage(INT32 keynum)
|
||||
INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify)
|
||||
{
|
||||
INT32 result = gc_null;
|
||||
if (cv_controlperkey.value == 1)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
{
|
||||
if (gamecontrol[i][0] == keynum)
|
||||
gamecontrol[i][0] = KEY_NULL;
|
||||
{
|
||||
result = i;
|
||||
if (modify) gamecontrol[i][0] = KEY_NULL;
|
||||
}
|
||||
if (gamecontrol[i][1] == keynum)
|
||||
gamecontrol[i][1] = KEY_NULL;
|
||||
{
|
||||
result = i;
|
||||
if (modify) gamecontrol[i][1] = KEY_NULL;
|
||||
}
|
||||
if (gamecontrolbis[i][0] == keynum)
|
||||
gamecontrolbis[i][0] = KEY_NULL;
|
||||
{
|
||||
result = i;
|
||||
if (modify) gamecontrolbis[i][0] = KEY_NULL;
|
||||
}
|
||||
if (gamecontrolbis[i][1] == keynum)
|
||||
gamecontrolbis[i][1] = KEY_NULL;
|
||||
{
|
||||
result = i;
|
||||
if (modify) gamecontrolbis[i][1] = KEY_NULL;
|
||||
}
|
||||
if (result && !modify)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setcontrol(INT32 (*gc)[2], INT32 na)
|
||||
static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT32 *keynum1, INT32 *keynum2, boolean *nestedoverride)
|
||||
{
|
||||
// Special case: ignore KEY_PAUSE because it's hardcoded
|
||||
if (keyidx == 0 && *keynum1 == KEY_PAUSE)
|
||||
{
|
||||
if (*keynum2 != KEY_PAUSE)
|
||||
{
|
||||
*keynum1 = *keynum2; // shift down keynum2 and continue
|
||||
*keynum2 = 0;
|
||||
}
|
||||
else
|
||||
return -1; // skip setting control
|
||||
}
|
||||
else if (keyidx == 1 && *keynum2 == KEY_PAUSE)
|
||||
return -1; // skip setting control
|
||||
|
||||
#if !defined (DC) && !defined (_PSP) && !defined (GP2X) && !defined (_NDS) && !defined(WMINPUT) && !defined(_WII)
|
||||
if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22
|
||||
numctrl == gc_weaponnext || numctrl == gc_weaponprev || numctrl == gc_tossflag ||
|
||||
numctrl == gc_use || numctrl == gc_camreset || numctrl == gc_jump ||
|
||||
numctrl == gc_pause || numctrl == gc_systemmenu || numctrl == gc_camtoggle ||
|
||||
numctrl == gc_screenshot || numctrl == gc_talkkey || numctrl == gc_scores ||
|
||||
numctrl == gc_centerview
|
||||
))
|
||||
{
|
||||
INT32 keynum = 0, existingctrl = 0;
|
||||
INT32 defaultkey;
|
||||
boolean defaultoverride = false;
|
||||
|
||||
// get the default gamecontrol
|
||||
if (player == 0 && numctrl == gc_systemmenu)
|
||||
defaultkey = gamecontrol[numctrl][0];
|
||||
else
|
||||
defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]);
|
||||
|
||||
// Assign joypad button defaults if there is an open slot.
|
||||
// At this point, gamecontrol/bis should have the default controls
|
||||
// (unless LOADCONFIG is being run)
|
||||
//
|
||||
// If the player runs SETCONTROL in-game, this block should not be reached
|
||||
// because EXECVERSION is locked onto the latest version.
|
||||
if (keyidx == 0 && !*keynum1)
|
||||
{
|
||||
if (*keynum2) // push keynum2 down; this is an edge case
|
||||
{
|
||||
*keynum1 = *keynum2;
|
||||
*keynum2 = 0;
|
||||
keynum = *keynum1;
|
||||
}
|
||||
else
|
||||
{
|
||||
keynum = defaultkey;
|
||||
defaultoverride = true;
|
||||
}
|
||||
}
|
||||
else if (keyidx == 1 && (!*keynum2 || (!*keynum1 && *keynum2))) // last one is the same edge case as above
|
||||
{
|
||||
keynum = defaultkey;
|
||||
defaultoverride = true;
|
||||
}
|
||||
else // default to the specified keynum
|
||||
keynum = (keyidx == 1 ? *keynum2 : *keynum1);
|
||||
|
||||
// Did our last call override keynum2?
|
||||
if (*nestedoverride)
|
||||
{
|
||||
defaultoverride = true;
|
||||
*nestedoverride = false;
|
||||
}
|
||||
|
||||
// Fill keynum2 with the default control
|
||||
if (keyidx == 0 && !*keynum2)
|
||||
{
|
||||
*keynum2 = defaultkey;
|
||||
// Tell the next call that this is an override
|
||||
*nestedoverride = true;
|
||||
|
||||
// if keynum2 already matches keynum1, we probably recursed
|
||||
// so unset it
|
||||
if (*keynum1 == *keynum2)
|
||||
{
|
||||
*keynum2 = 0;
|
||||
*nestedoverride = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the key is being used somewhere else before passing it
|
||||
// pass it through if it's the same numctrl. This is an edge case -- when using
|
||||
// LOADCONFIG, gamecontrol is not reset with default.
|
||||
//
|
||||
// Also, only check if we're actually overriding, to preserve behavior where
|
||||
// config'd keys overwrite default keys.
|
||||
if (defaultoverride)
|
||||
existingctrl = G_CheckDoubleUsage(keynum, false);
|
||||
|
||||
if (keynum && (!existingctrl || existingctrl == numctrl))
|
||||
return keynum;
|
||||
else if (keyidx == 0 && *keynum2)
|
||||
{
|
||||
// try it again and push down keynum2
|
||||
*keynum1 = *keynum2;
|
||||
*keynum2 = 0;
|
||||
return G_FilterKeyByVersion(numctrl, keyidx, player, keynum1, keynum2, nestedoverride);
|
||||
// recursion *should* be safe because we only assign keynum2 to a joy default
|
||||
// and then clear it if we find that keynum1 already has the joy default.
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// All's good, so pass the keynum as-is
|
||||
if (keyidx == 1)
|
||||
return *keynum2;
|
||||
else //if (keyidx == 0)
|
||||
return *keynum1;
|
||||
}
|
||||
|
||||
static void setcontrol(INT32 (*gc)[2])
|
||||
{
|
||||
INT32 numctrl;
|
||||
const char *namectrl;
|
||||
INT32 keynum;
|
||||
INT32 keynum, keynum1, keynum2;
|
||||
INT32 player = ((void*)gc == (void*)&gamecontrolbis ? 1 : 0);
|
||||
boolean nestedoverride = false;
|
||||
|
||||
namectrl = COM_Argv(1);
|
||||
for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]);
|
||||
|
@ -1334,31 +1509,38 @@ static void setcontrol(INT32 (*gc)[2], INT32 na)
|
|||
CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl);
|
||||
return;
|
||||
}
|
||||
keynum = G_KeyStringtoNum(COM_Argv(2));
|
||||
keynum1 = G_KeyStringtoNum(COM_Argv(2));
|
||||
keynum2 = G_KeyStringtoNum(COM_Argv(3));
|
||||
keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride);
|
||||
|
||||
if (keynum == KEY_PAUSE) // fail silently; pause is hardcoded
|
||||
if (keynum >= 0)
|
||||
{
|
||||
if (na == 4)
|
||||
(void)G_CheckDoubleUsage(keynum, true);
|
||||
|
||||
// if keynum was rejected, try it again with keynum2
|
||||
if (!keynum && keynum2)
|
||||
{
|
||||
na--;
|
||||
keynum = G_KeyStringtoNum(COM_Argv(3));
|
||||
if (keynum == KEY_PAUSE)
|
||||
return;
|
||||
keynum1 = keynum2; // push down keynum2
|
||||
keynum2 = 0;
|
||||
keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride);
|
||||
if (keynum >= 0)
|
||||
(void)G_CheckDoubleUsage(keynum, true);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
G_CheckDoubleUsage(keynum);
|
||||
gc[numctrl][0] = keynum;
|
||||
if (keynum >= 0)
|
||||
gc[numctrl][0] = keynum;
|
||||
|
||||
if (na == 4)
|
||||
if (keynum2)
|
||||
{
|
||||
keynum = G_KeyStringtoNum(COM_Argv(3));
|
||||
if (keynum != KEY_PAUSE)
|
||||
gc[numctrl][1] = keynum;
|
||||
else
|
||||
gc[numctrl][1] = 0;
|
||||
keynum = G_FilterKeyByVersion(numctrl, 1, player, &keynum1, &keynum2, &nestedoverride);
|
||||
if (keynum >= 0)
|
||||
{
|
||||
if (keynum != gc[numctrl][0])
|
||||
gc[numctrl][1] = keynum;
|
||||
else
|
||||
gc[numctrl][1] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
gc[numctrl][1] = 0;
|
||||
|
@ -1376,7 +1558,7 @@ void Command_Setcontrol_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
setcontrol(gamecontrol, na);
|
||||
setcontrol(gamecontrol);
|
||||
}
|
||||
|
||||
void Command_Setcontrol2_f(void)
|
||||
|
@ -1391,5 +1573,5 @@ void Command_Setcontrol2_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
setcontrol(gamecontrolbis, na);
|
||||
setcontrol(gamecontrolbis);
|
||||
}
|
||||
|
|
|
@ -160,10 +160,11 @@ INT32 G_KeyStringtoNum(const char *keystr);
|
|||
|
||||
// detach any keys associated to the given game control
|
||||
void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);
|
||||
void G_ClearAllControlKeys(void);
|
||||
void Command_Setcontrol_f(void);
|
||||
void Command_Setcontrol2_f(void);
|
||||
void G_Controldefault(void);
|
||||
void G_SaveKeySetting(FILE *f);
|
||||
void G_CheckDoubleUsage(INT32 keynum);
|
||||
INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -193,14 +193,14 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
|
|||
v2dy = bsp->dy;
|
||||
|
||||
den = v2dy*v1dx - v2dx*v1dy;
|
||||
if (den == 0)
|
||||
if (fabsf((float)den) < 1.0E-36f) // avoid checking exactly for 0.0
|
||||
return NULL; // parallel
|
||||
|
||||
// first check the frac along the polygon segment,
|
||||
// (do not accept hit with the extensions)
|
||||
num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
|
||||
frac = num / den;
|
||||
if (frac < 0 || frac > 1)
|
||||
if (frac < 0.0 || frac > 1.0)
|
||||
return NULL;
|
||||
|
||||
// now get the frac along the BSP line
|
||||
|
@ -217,29 +217,6 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
|
|||
return &pt;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//Hurdler: it's not used anymore
|
||||
static boolean NearVertice (polyvertex_t *p1, polyvertex_t *p2)
|
||||
{
|
||||
#if 1
|
||||
float diff;
|
||||
diff = p2->x - p1->x;
|
||||
if (diff < -1.5f || diff > 1.5f)
|
||||
return false;
|
||||
diff = p2->y - p1->y;
|
||||
if (diff < -1.5f || diff > 1.5f)
|
||||
return false;
|
||||
#else
|
||||
if (p1->x != p2->x)
|
||||
return false;
|
||||
if (p1->y != p2->y)
|
||||
return false;
|
||||
#endif
|
||||
// p1 and p2 are considered the same vertex
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if two vertice coords have a x and/or y difference
|
||||
// of less or equal than 1 FRACUNIT, they are considered the same
|
||||
// point. Note: hardcoded value, 1.0f could be anything else.
|
||||
|
@ -253,11 +230,23 @@ static boolean SameVertice (polyvertex_t *p1, polyvertex_t *p2)
|
|||
diff = p2->y - p1->y;
|
||||
if (diff < -1.5f || diff > 1.5f)
|
||||
return false;
|
||||
#else
|
||||
#elif 0
|
||||
if (p1->x != p2->x)
|
||||
return false;
|
||||
if (p1->y != p2->y)
|
||||
return false;
|
||||
#elif 0
|
||||
if (fabsf( p2->x - p1->x ) > 1.0E-36f )
|
||||
return false;
|
||||
if (fabsf( p2->y - p1->y ) > 1.0E-36f )
|
||||
return false;
|
||||
#else
|
||||
#define DIVLINE_VERTEX_DIFF 0.45f
|
||||
float ep = DIVLINE_VERTEX_DIFF;
|
||||
if (fabsf( p2->x - p1->x ) > ep )
|
||||
return false;
|
||||
if (fabsf( p2->y - p1->y ) > ep )
|
||||
return false;
|
||||
#endif
|
||||
// p1 and p2 are considered the same vertex
|
||||
return true;
|
||||
|
@ -294,57 +283,57 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
|
|||
// start & end points
|
||||
pv = fracdivline(bsp, &poly->pts[i], &poly->pts[j]);
|
||||
|
||||
if (pv)
|
||||
if (pv == NULL)
|
||||
continue;
|
||||
|
||||
if (ps < 0)
|
||||
{
|
||||
if (ps < 0)
|
||||
// first point
|
||||
ps = i;
|
||||
vs = *pv;
|
||||
fracs = bspfrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
//the partition line traverse a junction between two segments
|
||||
// or the two points are so close, they can be considered as one
|
||||
// thus, don't accept, since split 2 must be another vertex
|
||||
if (SameVertice(pv, &lastpv))
|
||||
{
|
||||
// first point
|
||||
ps = i;
|
||||
vs = *pv;
|
||||
fracs = bspfrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
//the partition line traverse a junction between two segments
|
||||
// or the two points are so close, they can be considered as one
|
||||
// thus, don't accept, since split 2 must be another vertex
|
||||
if (SameVertice(pv, &lastpv))
|
||||
if (pe < 0)
|
||||
{
|
||||
if (pe < 0)
|
||||
{
|
||||
ps = i;
|
||||
psonline = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pe = i;
|
||||
peonline = 1;
|
||||
}
|
||||
ps = i;
|
||||
psonline = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pe < 0)
|
||||
{
|
||||
pe = i;
|
||||
ve = *pv;
|
||||
frace = bspfrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
// a frac, not same vertice as last one
|
||||
// we already got pt2 so pt 2 is not on the line,
|
||||
// so we probably got back to the start point
|
||||
// which is on the line
|
||||
if (SameVertice(pv, &vs))
|
||||
psonline = 1;
|
||||
break;
|
||||
}
|
||||
pe = i;
|
||||
peonline = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pe < 0)
|
||||
{
|
||||
pe = i;
|
||||
ve = *pv;
|
||||
frace = bspfrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
// a frac, not same vertice as last one
|
||||
// we already got pt2 so pt 2 is not on the line,
|
||||
// so we probably got back to the start point
|
||||
// which is on the line
|
||||
if (SameVertice(pv, &vs))
|
||||
psonline = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remember last point intercept to detect identical points
|
||||
lastpv = *pv;
|
||||
}
|
||||
|
||||
// remember last point intercept to detect identical points
|
||||
lastpv = *pv;
|
||||
}
|
||||
|
||||
// no split: the partition line is either parallel and
|
||||
|
@ -368,7 +357,7 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
|
|||
return;
|
||||
}
|
||||
|
||||
if (ps >= 0 && pe < 0)
|
||||
if (pe < 0)
|
||||
{
|
||||
//I_Error("SplitPoly: only one point for split line (%d %d)", ps, pe);
|
||||
*frontpoly = poly;
|
||||
|
@ -387,7 +376,7 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
|
|||
*backpoly = HWR_AllocPoly(2 + nptback);
|
||||
else
|
||||
*backpoly = NULL;
|
||||
if (nptfront)
|
||||
if (nptfront > 0)
|
||||
*frontpoly = HWR_AllocPoly(2 + nptfront);
|
||||
else
|
||||
*frontpoly = NULL;
|
||||
|
@ -482,42 +471,42 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
|
|||
|
||||
pv = fracdivline(&cutseg, &poly->pts[i], &poly->pts[j]);
|
||||
|
||||
if (pv)
|
||||
if (pv == NULL)
|
||||
continue;
|
||||
|
||||
if (ps < 0)
|
||||
{
|
||||
if (ps < 0)
|
||||
ps = i;
|
||||
vs = *pv;
|
||||
fracs = bspfrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
//frac 1 on previous segment,
|
||||
// 0 on the next,
|
||||
//the split line goes through one of the convex poly
|
||||
// vertices, happens quite often since the convex
|
||||
// poly is already adjacent to the subsector segs
|
||||
// on most borders
|
||||
if (SameVertice(pv, &vs))
|
||||
continue;
|
||||
|
||||
if (fracs <= bspfrac)
|
||||
{
|
||||
nump = 2 + poly->numpts - (i-ps);
|
||||
pe = ps;
|
||||
ps = i;
|
||||
vs = *pv;
|
||||
fracs = bspfrac;
|
||||
ve = *pv;
|
||||
}
|
||||
else
|
||||
{
|
||||
//frac 1 on previous segment,
|
||||
// 0 on the next,
|
||||
//the split line goes through one of the convex poly
|
||||
// vertices, happens quite often since the convex
|
||||
// poly is already adjacent to the subsector segs
|
||||
// on most borders
|
||||
if (SameVertice(pv, &vs))
|
||||
continue;
|
||||
|
||||
if (fracs <= bspfrac)
|
||||
{
|
||||
nump = 2 + poly->numpts - (i-ps);
|
||||
pe = ps;
|
||||
ps = i;
|
||||
ve = *pv;
|
||||
}
|
||||
else
|
||||
{
|
||||
nump = 2 + (i-ps);
|
||||
pe = i;
|
||||
ve = vs;
|
||||
vs = *pv;
|
||||
}
|
||||
//found 2nd point
|
||||
break;
|
||||
nump = 2 + (i-ps);
|
||||
pe = i;
|
||||
ve = vs;
|
||||
vs = *pv;
|
||||
}
|
||||
//found 2nd point
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -581,18 +570,42 @@ static inline void HWR_SubsecPoly(INT32 num, poly_t *poly)
|
|||
// search for the segs source of this divline
|
||||
static inline void SearchDivline(node_t *bsp, fdivline_t *divline)
|
||||
{
|
||||
#if 0 // MAR - If you don't use the same partition line that the BSP uses, the front/back polys won't match the subsectors in the BSP!
|
||||
#endif
|
||||
divline->x = FIXED_TO_FLOAT(bsp->x);
|
||||
divline->y = FIXED_TO_FLOAT(bsp->y);
|
||||
divline->dx = FIXED_TO_FLOAT(bsp->dx);
|
||||
divline->dy = FIXED_TO_FLOAT(bsp->dy);
|
||||
}
|
||||
|
||||
#ifdef HWR_LOADING_SCREEN
|
||||
//Hurdler: implement a loading status
|
||||
static size_t ls_count = 0;
|
||||
static UINT8 ls_percent = 0;
|
||||
|
||||
static void loading_status(void)
|
||||
{
|
||||
char s[16];
|
||||
int x, y;
|
||||
|
||||
I_OsPolling();
|
||||
CON_Drawer();
|
||||
sprintf(s, "%d%%", (++ls_percent)<<1);
|
||||
x = BASEVIDWIDTH/2;
|
||||
y = BASEVIDHEIGHT/2;
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect
|
||||
//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
|
||||
M_DrawTextBox(x-58, y-8, 13, 1);
|
||||
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");
|
||||
V_DrawRightAlignedString(x+50, y, V_YELLOWMAP, s);
|
||||
|
||||
// Is this really necessary at this point..?
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 40, V_YELLOWMAP, "OPENGL MODE IS INCOMPLETE AND MAY");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 50, V_YELLOWMAP, "NOT DISPLAY SOME SURFACES.");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 70, V_YELLOWMAP, "USE AT SONIC'S RISK.");
|
||||
|
||||
I_UpdateNoVsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
// poly : the convex polygon that encloses all child subsectors
|
||||
static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *bbox)
|
||||
{
|
||||
|
@ -630,38 +643,19 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
|
|||
}
|
||||
else
|
||||
{
|
||||
HWR_SubsecPoly(bspnum&(~NF_SUBSECTOR), poly);
|
||||
//Hurdler: implement a loading status
|
||||
HWR_SubsecPoly(bspnum & ~NF_SUBSECTOR, poly);
|
||||
|
||||
//Hurdler: implement a loading status
|
||||
#ifdef HWR_LOADING_SCREEN
|
||||
if (ls_count-- <= 0)
|
||||
{
|
||||
char s[16];
|
||||
int x, y;
|
||||
|
||||
I_OsPolling();
|
||||
ls_count = numsubsectors/50;
|
||||
CON_Drawer();
|
||||
sprintf(s, "%d%%", (++ls_percent)<<1);
|
||||
x = BASEVIDWIDTH/2;
|
||||
y = BASEVIDHEIGHT/2;
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect
|
||||
//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
|
||||
M_DrawTextBox(x-58, y-8, 13, 1);
|
||||
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");
|
||||
V_DrawRightAlignedString(x+50, y, V_YELLOWMAP, s);
|
||||
|
||||
// Is this really necessary at this point..?
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 40, V_YELLOWMAP, "OPENGL MODE IS INCOMPLETE AND MAY");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 50, V_YELLOWMAP, "NOT DISPLAY SOME SURFACES.");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 70, V_YELLOWMAP, "USE AT SONIC'S RISK.");
|
||||
|
||||
I_UpdateNoVsync();
|
||||
loading_status();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
M_ClearBox(bbox);
|
||||
poly = extrasubsectors[bspnum&~NF_SUBSECTOR].planepoly;
|
||||
poly = extrasubsectors[bspnum & ~NF_SUBSECTOR].planepoly;
|
||||
|
||||
for (i = 0, pt = poly->pts; i < poly->numpts; i++,pt++)
|
||||
M_AddToBox(bbox, FLOAT_TO_FIXED(pt->x), FLOAT_TO_FIXED(pt->y));
|
||||
|
@ -693,14 +687,13 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
|
|||
if (backpoly)
|
||||
{
|
||||
// Correct back bbox to include floor/ceiling convex polygon
|
||||
WalkBSPNode(bsp->children[1], backpoly, &bsp->children[1],
|
||||
bsp->bbox[1]);
|
||||
WalkBSPNode(bsp->children[1], backpoly, &bsp->children[1], bsp->bbox[1]);
|
||||
|
||||
// enlarge bbox with seconde child
|
||||
// enlarge bbox with second child
|
||||
M_AddToBox(bbox, bsp->bbox[1][BOXLEFT ],
|
||||
bsp->bbox[1][BOXTOP ]);
|
||||
bsp->bbox[1][BOXTOP ]);
|
||||
M_AddToBox(bbox, bsp->bbox[1][BOXRIGHT ],
|
||||
bsp->bbox[1][BOXBOTTOM]);
|
||||
bsp->bbox[1][BOXBOTTOM]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,9 +773,9 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
|
|||
|
||||
if (bspnum & NF_SUBSECTOR)
|
||||
{
|
||||
if (bspnum!=-1)
|
||||
if (bspnum != -1)
|
||||
{
|
||||
bspnum&=~NF_SUBSECTOR;
|
||||
bspnum &= ~NF_SUBSECTOR;
|
||||
q = extrasubsectors[bspnum].planepoly;
|
||||
if (poly == q || !q)
|
||||
return;
|
||||
|
@ -968,7 +961,9 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
|
|||
fixed_t rootbbox[4];
|
||||
|
||||
CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n");
|
||||
#ifdef HWR_LOADING_SCREEN
|
||||
ls_count = ls_percent = 0; // reset the loading status
|
||||
#endif
|
||||
CON_Drawer(); //let the user know what we are doing
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
|
||||
|
|
|
@ -227,14 +227,14 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
Z_Free(realpatch);
|
||||
}
|
||||
// centre screen
|
||||
if ((float)vid.width != (float)BASEVIDWIDTH * dupx)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
|
||||
}
|
||||
if ((float)vid.height != (float)BASEVIDHEIGHT * dupy)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if ((option & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM))
|
||||
cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy));
|
||||
|
@ -375,14 +375,14 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
|||
Z_Free(realpatch);
|
||||
}
|
||||
// centre screen
|
||||
if ((float)vid.width != (float)BASEVIDWIDTH * dupx)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
|
||||
}
|
||||
if ((float)vid.height != (float)BASEVIDHEIGHT * dupy)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if ((option & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM))
|
||||
cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy));
|
||||
|
@ -770,18 +770,6 @@ void HWR_DrawViewBorder(INT32 clearlines)
|
|||
// AM_MAP.C DRAWING STUFF
|
||||
// ==========================================================================
|
||||
|
||||
// Clear the automap part of the screen
|
||||
void HWR_clearAutomap(void)
|
||||
{
|
||||
FRGBAFloat fColor = {0, 0, 0, 1};
|
||||
|
||||
// minx,miny,maxx,maxy
|
||||
HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE);
|
||||
HWD.pfnClearBuffer(true, true, &fColor);
|
||||
HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE);
|
||||
}
|
||||
|
||||
|
||||
// -----------------+
|
||||
// HWR_drawAMline : draw a line of the automap (the clipping is already done in automap code)
|
||||
// Arg : color is a RGB 888 value
|
||||
|
@ -802,6 +790,110 @@ void HWR_drawAMline(const fline_t *fl, INT32 color)
|
|||
HWD.pfnDraw2DLine(&v1, &v2, color_rgba);
|
||||
}
|
||||
|
||||
// -------------------+
|
||||
// HWR_DrawConsoleFill : draw flat coloured transparent rectangle because that's cool, and hw sucks less than sw for that.
|
||||
// -------------------+
|
||||
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options)
|
||||
{
|
||||
FOutVector v[4];
|
||||
FSurfaceInfo Surf;
|
||||
float fx, fy, fw, fh;
|
||||
|
||||
if (w < 0 || h < 0)
|
||||
return; // consistency w/ software
|
||||
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
|
||||
fx = (float)x;
|
||||
fy = (float)y;
|
||||
fw = (float)w;
|
||||
fh = (float)h;
|
||||
|
||||
if (!(options & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{
|
||||
RGBA_t rgbaColour = V_GetColor(color);
|
||||
FRGBAFloat clearColour;
|
||||
clearColour.red = (float)rgbaColour.s.red / 255;
|
||||
clearColour.green = (float)rgbaColour.s.green / 255;
|
||||
clearColour.blue = (float)rgbaColour.s.blue / 255;
|
||||
clearColour.alpha = 1;
|
||||
HWD.pfnClearBuffer(true, false, &clearColour);
|
||||
return;
|
||||
}
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f)
|
||||
{
|
||||
if (options & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(options & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
}
|
||||
if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (options & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(options & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (fx >= vid.width || fy >= vid.height)
|
||||
return;
|
||||
if (fx < 0)
|
||||
{
|
||||
fw += fx;
|
||||
fx = 0;
|
||||
}
|
||||
if (fy < 0)
|
||||
{
|
||||
fh += fy;
|
||||
fy = 0;
|
||||
}
|
||||
|
||||
if (fw <= 0 || fh <= 0)
|
||||
return;
|
||||
if (fx + fw > vid.width)
|
||||
fw = (float)vid.width - fx;
|
||||
if (fy + fh > vid.height)
|
||||
fh = (float)vid.height - fy;
|
||||
|
||||
fx = -1 + fx / (vid.width / 2);
|
||||
fy = 1 - fy / (vid.height / 2);
|
||||
fw = fw / (vid.width / 2);
|
||||
fh = fh / (vid.height / 2);
|
||||
|
||||
v[0].x = v[3].x = fx;
|
||||
v[2].x = v[1].x = fx + fw;
|
||||
v[0].y = v[1].y = fy;
|
||||
v[2].y = v[3].y = fy - fh;
|
||||
|
||||
//Hurdler: do we still use this argb color? if not, we should remove it
|
||||
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
v[0].sow = v[3].sow = 0.0f;
|
||||
v[2].sow = v[1].sow = 1.0f;
|
||||
v[0].tow = v[1].tow = 0.0f;
|
||||
v[2].tow = v[3].tow = 1.0f;
|
||||
|
||||
Surf.FlatColor.rgba = UINT2RGBA(color);
|
||||
Surf.FlatColor.s.alpha = 0x80;
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// HWR_DrawFill : draw flat coloured rectangle, with no texture
|
||||
|
@ -846,14 +938,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if ((float)vid.width != (float)BASEVIDWIDTH * dupx)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
}
|
||||
if ((float)vid.height != (float)BASEVIDHEIGHT * dupy)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
|
|
|
@ -4137,7 +4137,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
|
|||
swallVerts[0].z = swallVerts[3].z = spr->z1;
|
||||
swallVerts[2].z = swallVerts[1].z = spr->z2;
|
||||
|
||||
if (spr->mobj && this_scale != 1.0f)
|
||||
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
|
||||
{
|
||||
// Always a pixel above the floor, perfectly flat.
|
||||
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3);
|
||||
|
@ -4305,7 +4305,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
wallVerts[1].z = wallVerts[2].z = spr->z2;
|
||||
|
||||
wallVerts[2].y = wallVerts[3].y = spr->ty;
|
||||
if (spr->mobj && this_scale != 1.0f)
|
||||
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
|
||||
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale;
|
||||
else
|
||||
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height;
|
||||
|
@ -4334,6 +4334,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t;
|
||||
}
|
||||
|
||||
// if it has a dispoffset, push it a little towards the camera
|
||||
if (spr->dispoffset) {
|
||||
float co = -gr_viewcos*(0.05f*spr->dispoffset);
|
||||
float si = -gr_viewsin*(0.05f*spr->dispoffset);
|
||||
wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si;
|
||||
wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si;
|
||||
wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co;
|
||||
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
|
||||
}
|
||||
|
||||
realtop = top = wallVerts[3].y;
|
||||
realbot = bot = wallVerts[0].y;
|
||||
towtop = wallVerts[3].tow;
|
||||
|
@ -4585,7 +4595,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
|||
wallVerts[0].x = wallVerts[3].x = spr->x1;
|
||||
wallVerts[2].x = wallVerts[1].x = spr->x2;
|
||||
wallVerts[2].y = wallVerts[3].y = spr->ty;
|
||||
if (spr->mobj && this_scale != 1.0f)
|
||||
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
|
||||
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale;
|
||||
else
|
||||
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height;
|
||||
|
@ -4635,6 +4645,16 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
|||
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
|
||||
}
|
||||
|
||||
// if it has a dispoffset, push it a little towards the camera
|
||||
if (spr->dispoffset) {
|
||||
float co = -gr_viewcos*(0.05f*spr->dispoffset);
|
||||
float si = -gr_viewsin*(0.05f*spr->dispoffset);
|
||||
wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si;
|
||||
wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si;
|
||||
wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co;
|
||||
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
|
||||
}
|
||||
|
||||
// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
|
||||
// sprite lighting by modulating the RGB components
|
||||
/// \todo coloured
|
||||
|
@ -4831,7 +4851,7 @@ static void HWR_SortVisSprites(void)
|
|||
best = ds;
|
||||
}
|
||||
// order visprites of same scale by dispoffset, smallest first
|
||||
else if (ds->tz == bestdist && ds->dispoffset < bestdispoffset)
|
||||
else if (fabsf(ds->tz - bestdist) < 1.0E-36f && ds->dispoffset < bestdispoffset)
|
||||
{
|
||||
bestdispoffset = ds->dispoffset;
|
||||
best = ds;
|
||||
|
@ -5752,7 +5772,7 @@ void HWR_SetViewSize(void)
|
|||
|
||||
gr_viewwindowx = (vid.width - gr_viewwidth) / 2;
|
||||
gr_windowcenterx = (float)(vid.width / 2);
|
||||
if (gr_viewwidth == vid.width)
|
||||
if (fabsf(gr_viewwidth - vid.width) < 1.0E-36f)
|
||||
{
|
||||
gr_baseviewwindowy = 0;
|
||||
gr_basewindowcentery = gr_viewheight / 2; // window top left corner at 0,0
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
void HWR_Startup(void);
|
||||
void HWR_Shutdown(void);
|
||||
|
||||
void HWR_clearAutomap(void);
|
||||
void HWR_drawAMline(const fline_t *fl, INT32 color);
|
||||
void HWR_FadeScreenMenuBack(UINT32 color, INT32 height);
|
||||
void HWR_DrawConsoleBack(UINT32 color, INT32 height);
|
||||
|
@ -52,6 +51,7 @@ void HWR_CreatePlanePolygons(INT32 bspnum);
|
|||
void HWR_CreateStaticLightmaps(INT32 bspnum);
|
||||
void HWR_PrepLevelCache(size_t pnumtextures);
|
||||
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
|
||||
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right.
|
||||
void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum);
|
||||
|
||||
void HWR_AddCommands(void);
|
||||
|
|
|
@ -541,7 +541,7 @@ boolean SetupGLFunc13(void)
|
|||
pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f");
|
||||
pglClientActiveTexture = GetGLFunc("glClientActiveTexture");
|
||||
pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -574,7 +574,8 @@ static void GLPerspective(GLdouble fovy, GLdouble aspect)
|
|||
const GLdouble deltaZ = zFar - zNear;
|
||||
GLdouble cotangent;
|
||||
|
||||
if ((deltaZ == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) {
|
||||
if ((fabsf((float)deltaZ) < 1.0E-36f) || fpclassify(sine) == FP_ZERO || fpclassify(aspect) == FP_ZERO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cotangent = cos(radians) / sine;
|
||||
|
@ -609,7 +610,7 @@ static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ,
|
|||
out[2] * projMatrix[2*4+i] +
|
||||
out[3] * projMatrix[3*4+i];
|
||||
}
|
||||
if (in[3] == 0.0f) return;
|
||||
if (fpclassify(in[3]) == FP_ZERO) return;
|
||||
in[0] /= in[3];
|
||||
in[1] /= in[3];
|
||||
in[2] /= in[3];
|
||||
|
@ -1806,7 +1807,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
if (nextFrameIndex != -1)
|
||||
nextframe = &mesh->frames[nextFrameIndex % mesh->numFrames];
|
||||
|
||||
if (!nextframe || pol == 0.0f)
|
||||
if (!nextframe || fpclassify(pol) == FP_ZERO)
|
||||
{
|
||||
// Zoom! Take advantage of just shoving the entire arrays to the GPU.
|
||||
pglVertexPointer(3, GL_FLOAT, 0, frame->vertices);
|
||||
|
@ -1865,6 +1866,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
|
|||
pglLoadIdentity();
|
||||
if (stransform)
|
||||
{
|
||||
boolean fovx90;
|
||||
// keep a trace of the transformation for md2
|
||||
memcpy(&md2_transform, stransform, sizeof (md2_transform));
|
||||
|
||||
|
@ -1885,7 +1887,8 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
|
|||
|
||||
pglMatrixMode(GL_PROJECTION);
|
||||
pglLoadIdentity();
|
||||
special_splitscreen = (stransform->splitscreen == 1 && stransform->fovxangle == 90.0f);
|
||||
fovx90 = stransform->fovxangle > 0.0f && fabsf(stransform->fovxangle - 90.0f) < 0.5f;
|
||||
special_splitscreen = (stransform->splitscreen && fovx90);
|
||||
if (special_splitscreen)
|
||||
GLPerspective(53.13l, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
|
||||
else
|
||||
|
@ -1962,7 +1965,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2])
|
|||
// Draw a black square behind the screen texture,
|
||||
// so nothing shows through the edges
|
||||
pglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
|
||||
pglVertexPointer(3, GL_FLOAT, 0, blackBack);
|
||||
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
|
@ -2353,7 +2356,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height)
|
|||
clearColour.alpha = 1;
|
||||
ClearBuffer(true, false, &clearColour);
|
||||
pglBindTexture(GL_TEXTURE_2D, finalScreenTexture);
|
||||
|
||||
|
||||
pglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
pglEnableClientState(GL_VERTEX_ARRAY);
|
||||
pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
@ -2365,7 +2368,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height)
|
|||
|
||||
pglDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
pglDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
|
||||
tex_downloaded = finalScreenTexture;
|
||||
}
|
||||
|
||||
|
|
1495
src/hu_stuff.c
1495
src/hu_stuff.c
File diff suppressed because it is too large
Load diff
|
@ -21,7 +21,7 @@
|
|||
//------------------------------------
|
||||
// heads up font
|
||||
//------------------------------------
|
||||
#define HU_FONTSTART '\x1F' // the first font character
|
||||
#define HU_FONTSTART '\x16' // the first font character
|
||||
#define HU_FONTEND '~'
|
||||
|
||||
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
|
||||
|
@ -57,6 +57,20 @@ typedef struct
|
|||
// chat stuff
|
||||
//------------------------------------
|
||||
#define HU_MAXMSGLEN 224
|
||||
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
|
||||
#ifdef NETSPLITSCREEN
|
||||
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640)
|
||||
#else
|
||||
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640 || splitscreen)
|
||||
#endif
|
||||
#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot.
|
||||
#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted.
|
||||
|
||||
// some functions
|
||||
void HU_AddChatText(const char *text, boolean playsound);
|
||||
|
||||
// set true when entering a chat message
|
||||
extern boolean chat_on;
|
||||
|
||||
extern patch_t *hu_font[HU_FONTSIZE], *tny_font[HU_FONTSIZE];
|
||||
extern patch_t *tallnum[10];
|
||||
|
@ -72,9 +86,6 @@ extern patch_t *bmatcico;
|
|||
extern patch_t *tagico;
|
||||
extern patch_t *tallminus;
|
||||
|
||||
// set true when entering a chat message
|
||||
extern boolean chat_on;
|
||||
|
||||
// set true whenever the tab rankings are being shown for any reason
|
||||
extern boolean hu_showscores;
|
||||
|
||||
|
@ -87,12 +98,12 @@ void HU_LoadGraphics(void);
|
|||
void HU_Start(void);
|
||||
|
||||
boolean HU_Responder(event_t *ev);
|
||||
|
||||
void HU_Ticker(void);
|
||||
void HU_Drawer(void);
|
||||
char HU_dequeueChatChar(void);
|
||||
void HU_Erase(void);
|
||||
void HU_clearChatChars(void);
|
||||
void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // Lat': Ping drawer for scoreboard.
|
||||
void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
|
||||
void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer);
|
||||
void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "hu_stuff.h" // HU_AddChatText
|
||||
#include "console.h"
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
|
||||
|
@ -91,6 +91,51 @@ static int lib_print(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Print stuff in the chat, or in the console if we can't.
|
||||
static int lib_chatprint(lua_State *L)
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 1); // retrieve string
|
||||
boolean sound = lua_optboolean(L, 2); // retrieve sound boolean
|
||||
int len = strlen(str);
|
||||
|
||||
if (str == NULL) // error if we don't have a string!
|
||||
return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint"));
|
||||
|
||||
if (len > 255) // string is too long!!!
|
||||
return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
|
||||
|
||||
HU_AddChatText(str, sound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Same as above, but do it for only one player.
|
||||
static int lib_chatprintf(lua_State *L)
|
||||
{
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
const char *str = luaL_checkstring(L, 2); // retrieve string
|
||||
boolean sound = lua_optboolean(L, 3); // sound?
|
||||
int len = strlen(str);
|
||||
player_t *plr;
|
||||
|
||||
if (n < 2)
|
||||
return luaL_error(L, "chatprintf requires at least two arguments: player and text.");
|
||||
|
||||
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
|
||||
if (!plr)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (plr != &players[consoleplayer])
|
||||
return 0;
|
||||
|
||||
if (str == NULL) // error if we don't have a string!
|
||||
return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf"));
|
||||
|
||||
if (len > 255) // string is too long!!!
|
||||
return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
|
||||
|
||||
HU_AddChatText(str, sound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_evalMath(lua_State *L)
|
||||
{
|
||||
const char *word = luaL_checkstring(L, 1);
|
||||
|
@ -1682,6 +1727,25 @@ static int lib_rSetPlayerSkin(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// R_DATA
|
||||
////////////
|
||||
|
||||
static int lib_rCheckTextureNumForName(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
//HUDSAFE
|
||||
lua_pushinteger(L, R_CheckTextureNumForName(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_rTextureNumForName(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
//HUDSAFE
|
||||
lua_pushinteger(L, R_TextureNumForName(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// S_SOUND
|
||||
////////////
|
||||
|
||||
|
@ -1690,7 +1754,7 @@ static int lib_sStartSound(lua_State *L)
|
|||
const void *origin = NULL;
|
||||
sfxenum_t sound_id = luaL_checkinteger(L, 2);
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
//NOHUD // kys @whoever did this.
|
||||
if (sound_id >= NUMSFX)
|
||||
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
|
||||
if (!lua_isnil(L, 1))
|
||||
|
@ -1706,7 +1770,12 @@ static int lib_sStartSound(lua_State *L)
|
|||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
{
|
||||
if (hud_running)
|
||||
origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error.
|
||||
|
||||
S_StartSound(origin, sound_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1897,28 +1966,45 @@ static int lib_gDoReborn(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_gExitLevel(lua_State *L)
|
||||
// Another Lua function that doesn't actually exist!
|
||||
// Sets nextmapoverride & skipstats without instantly ending the level, for instances where other sources should be exiting the level, like normal signposts.
|
||||
static int lib_gSetCustomExitVars(lua_State *L)
|
||||
{
|
||||
int n = lua_gettop(L); // Num arguments
|
||||
NOHUD
|
||||
|
||||
// LUA EXTENSION: Custom exit like support
|
||||
// Supported:
|
||||
// G_ExitLevel(); [no modifications]
|
||||
// G_ExitLevel(int) [nextmap override only]
|
||||
// G_ExitLevel(bool) [skipstats only]
|
||||
// G_ExitLevel(int, bool) [both of the above]
|
||||
// G_SetCustomExitVars(); [reset to defaults]
|
||||
// G_SetCustomExitVars(int) [nextmap override only]
|
||||
// G_SetCustomExitVars(bool) [skipstats only]
|
||||
// G_SetCustomExitVars(int, bool) [both of the above]
|
||||
if (n >= 1)
|
||||
{
|
||||
if (lua_isnumber(L, 1) || n >= 2)
|
||||
{
|
||||
nextmapoverride = (INT16)luaL_checknumber(L, 1);
|
||||
lua_pop(L, 1); // pop nextmapoverride; skipstats now 1 if available
|
||||
lua_remove(L, 1); // remove nextmapoverride; skipstats now 1 if available
|
||||
}
|
||||
skipstats = lua_optboolean(L, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextmapoverride = 0;
|
||||
skipstats = false;
|
||||
}
|
||||
// ---
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_gExitLevel(lua_State *L)
|
||||
{
|
||||
int n = lua_gettop(L); // Num arguments
|
||||
NOHUD
|
||||
// Moved this bit to G_SetCustomExitVars
|
||||
if (n >= 1) // Don't run the reset to defaults option
|
||||
lib_gSetCustomExitVars(L);
|
||||
G_ExitLevel();
|
||||
return 0;
|
||||
}
|
||||
|
@ -2016,6 +2102,8 @@ static int lib_gTicsToMilliseconds(lua_State *L)
|
|||
|
||||
static luaL_Reg lib[] = {
|
||||
{"print", lib_print},
|
||||
{"chatprint", lib_chatprint},
|
||||
{"chatprintf", lib_chatprintf},
|
||||
{"EvalMath", lib_evalMath},
|
||||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||
|
||||
|
@ -2165,6 +2253,10 @@ static luaL_Reg lib[] = {
|
|||
{"R_Frame2Char",lib_rFrame2Char},
|
||||
{"R_SetPlayerSkin",lib_rSetPlayerSkin},
|
||||
|
||||
// r_data
|
||||
{"R_CheckTextureNumForName",lib_rCheckTextureNumForName},
|
||||
{"R_TextureNumForName",lib_rTextureNumForName},
|
||||
|
||||
// s_sound
|
||||
{"S_StartSound",lib_sStartSound},
|
||||
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
|
||||
|
@ -2179,6 +2271,7 @@ static luaL_Reg lib[] = {
|
|||
// g_game
|
||||
{"G_BuildMapName",lib_gBuildMapName},
|
||||
{"G_DoReborn",lib_gDoReborn},
|
||||
{"G_SetCustomExitVars",lib_gSetCustomExitVars},
|
||||
{"G_ExitLevel",lib_gExitLevel},
|
||||
{"G_IsSpecialStage",lib_gIsSpecialStage},
|
||||
{"G_GametypeUsesLives",lib_gGametypeUsesLives},
|
||||
|
|
|
@ -952,7 +952,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
|
|||
return hooked;
|
||||
}
|
||||
|
||||
// Hook for player chat
|
||||
|
||||
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
|
||||
{
|
||||
hook_p hookp;
|
||||
|
@ -1005,6 +1005,7 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
|
|||
return hooked;
|
||||
}
|
||||
|
||||
|
||||
// Hook for hurt messages
|
||||
boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
|
|
|
@ -795,16 +795,16 @@ static int side_set(lua_State *L)
|
|||
side->rowoffset = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_toptexture:
|
||||
side->toptexture = luaL_checkinteger(L, 3);
|
||||
side->toptexture = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case side_bottomtexture:
|
||||
side->bottomtexture = luaL_checkinteger(L, 3);
|
||||
side->bottomtexture = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case side_midtexture:
|
||||
side->midtexture = luaL_checkinteger(L, 3);
|
||||
side->midtexture = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case side_repeatcnt:
|
||||
side->repeatcnt = luaL_checkinteger(L, 3);
|
||||
side->repeatcnt = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1090,6 +1090,7 @@ static int ffloor_get(lua_State *L)
|
|||
{
|
||||
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
|
||||
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
|
||||
INT16 i;
|
||||
|
||||
if (!ffloor)
|
||||
{
|
||||
|
@ -1109,11 +1110,11 @@ static int ffloor_get(lua_State *L)
|
|||
lua_pushfixed(L, *ffloor->topheight);
|
||||
return 1;
|
||||
case ffloor_toppic: { // toppic
|
||||
levelflat_t *levelflat;
|
||||
INT16 i;
|
||||
for (i = 0, levelflat = levelflats; i != *ffloor->toppic; i++, levelflat++)
|
||||
;
|
||||
lua_pushlstring(L, levelflat->name, 8);
|
||||
levelflat_t *levelflat = &levelflats[*ffloor->toppic];
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!levelflat->name[i])
|
||||
break;
|
||||
lua_pushlstring(L, levelflat->name, i);
|
||||
return 1;
|
||||
}
|
||||
case ffloor_toplightlevel:
|
||||
|
@ -1123,11 +1124,11 @@ static int ffloor_get(lua_State *L)
|
|||
lua_pushfixed(L, *ffloor->bottomheight);
|
||||
return 1;
|
||||
case ffloor_bottompic: { // bottompic
|
||||
levelflat_t *levelflat;
|
||||
INT16 i;
|
||||
for (i = 0, levelflat = levelflats; i != *ffloor->bottompic; i++, levelflat++)
|
||||
;
|
||||
lua_pushlstring(L, levelflat->name, 8);
|
||||
levelflat_t *levelflat = &levelflats[*ffloor->bottompic];
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!levelflat->name[i])
|
||||
break;
|
||||
lua_pushlstring(L, levelflat->name, i);
|
||||
return 1;
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
|
@ -1504,6 +1505,8 @@ static int mapheaderinfo_get(lua_State *L)
|
|||
lua_pushinteger(L, header->levelselect);
|
||||
else if (fastcmp(field,"bonustype"))
|
||||
lua_pushinteger(L, header->bonustype);
|
||||
else if (fastcmp(field,"saveoverride"))
|
||||
lua_pushinteger(L, header->saveoverride);
|
||||
else if (fastcmp(field,"levelflags"))
|
||||
lua_pushinteger(L, header->levelflags);
|
||||
else if (fastcmp(field,"menuflags"))
|
||||
|
|
688
src/m_menu.c
688
src/m_menu.c
|
@ -33,6 +33,9 @@
|
|||
#include "s_sound.h"
|
||||
#include "i_system.h"
|
||||
|
||||
// Addfile
|
||||
#include "filesrch.h"
|
||||
|
||||
#include "v_video.h"
|
||||
#include "i_video.h"
|
||||
#include "keys.h"
|
||||
|
@ -75,7 +78,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#define SMALLLINEHEIGHT 8
|
||||
#define SLIDER_RANGE 10
|
||||
#define SLIDER_WIDTH (8*SLIDER_RANGE+6)
|
||||
#define MAXSTRINGLENGTH 32
|
||||
#define SERVERS_PER_PAGE 11
|
||||
|
||||
typedef enum
|
||||
|
@ -205,6 +207,8 @@ menu_t MessageDef;
|
|||
|
||||
menu_t SPauseDef;
|
||||
|
||||
#define lsheadingheight 16
|
||||
|
||||
// Sky Room
|
||||
static void M_CustomLevelSelect(INT32 choice);
|
||||
static void M_CustomWarp(INT32 choice);
|
||||
|
@ -292,15 +296,22 @@ menu_t OP_SoundOptionsDef;
|
|||
|
||||
//Misc
|
||||
menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef;
|
||||
menu_t OP_GameOptionsDef, OP_ServerOptionsDef;
|
||||
menu_t OP_GameOptionsDef, OP_ChatOptionsDef, OP_ServerOptionsDef;
|
||||
menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef;
|
||||
menu_t OP_MonitorToggleDef;
|
||||
static void M_ScreenshotOptions(INT32 choice);
|
||||
static void M_EraseData(INT32 choice);
|
||||
|
||||
static void M_Addons(INT32 choice);
|
||||
static void M_AddonsOptions(INT32 choice);
|
||||
static patch_t *addonsp[NUM_EXT+5];
|
||||
|
||||
#define numaddonsshown 4
|
||||
|
||||
// Drawing functions
|
||||
static void M_DrawGenericMenu(void);
|
||||
static void M_DrawCenteredMenu(void);
|
||||
static void M_DrawAddons(void);
|
||||
static void M_DrawSkyRoom(void);
|
||||
static void M_DrawChecklist(void);
|
||||
static void M_DrawEmblemHints(void);
|
||||
|
@ -335,6 +346,7 @@ static boolean M_CancelConnect(void);
|
|||
#endif
|
||||
static boolean M_ExitPandorasBox(void);
|
||||
static boolean M_QuitMultiPlayerMenu(void);
|
||||
static void M_HandleAddons(INT32 choice);
|
||||
static void M_HandleSoundTest(INT32 choice);
|
||||
static void M_HandleImageDef(INT32 choice);
|
||||
static void M_HandleLoadSave(INT32 choice);
|
||||
|
@ -442,10 +454,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum
|
|||
// ---------
|
||||
static menuitem_t MainMenu[] =
|
||||
{
|
||||
{IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84},
|
||||
{IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100},
|
||||
{IT_CALL |IT_STRING, NULL, "options", M_Options, 108},
|
||||
{IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76},
|
||||
{IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92},
|
||||
{IT_CALL |IT_STRING, NULL, "options", M_Options, 100},
|
||||
{IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108},
|
||||
{IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116},
|
||||
};
|
||||
|
||||
|
@ -455,9 +468,15 @@ typedef enum
|
|||
singleplr,
|
||||
multiplr,
|
||||
options,
|
||||
addons,
|
||||
quitdoom
|
||||
} main_e;
|
||||
|
||||
static menuitem_t MISC_AddonsMenu[] =
|
||||
{
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func
|
||||
};
|
||||
|
||||
// ---------------------------------
|
||||
// Pause Menu Mode Attacking Edition
|
||||
// ---------------------------------
|
||||
|
@ -480,6 +499,7 @@ typedef enum
|
|||
// ---------------------
|
||||
static menuitem_t MPauseMenu[] =
|
||||
{
|
||||
{IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8},
|
||||
{IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
|
||||
{IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24},
|
||||
|
||||
|
@ -499,7 +519,8 @@ static menuitem_t MPauseMenu[] =
|
|||
|
||||
typedef enum
|
||||
{
|
||||
mpause_scramble = 0,
|
||||
mpause_addons = 0,
|
||||
mpause_scramble,
|
||||
mpause_switchmap,
|
||||
|
||||
mpause_continue,
|
||||
|
@ -985,6 +1006,7 @@ static menuitem_t OP_MainMenu[] =
|
|||
|
||||
{IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70},
|
||||
{IT_SUBMENU | IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80},
|
||||
{IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 90},
|
||||
};
|
||||
|
||||
static menuitem_t OP_ControlsMenu[] =
|
||||
|
@ -1089,25 +1111,29 @@ static menuitem_t OP_Joystick1Menu[] =
|
|||
{IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis , 40},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis , 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis , 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis , 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis , 80},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Jumping" , &cv_jumpaxis , 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Spinning" , &cv_spinaxis , 80},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis , 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis , 100},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 110},
|
||||
{IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 130},
|
||||
};
|
||||
|
||||
static menuitem_t OP_Joystick2Menu[] =
|
||||
{
|
||||
{IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Turning" , &cv_turnaxis2 , 30},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis2 , 40},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis2 , 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis2 , 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis2 , 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis2 , 80},
|
||||
{IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Turning" , &cv_turnaxis2 , 30},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis2 , 40},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis2 , 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis2 , 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Jumping" , &cv_jumpaxis2 , 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Spinning" , &cv_spinaxis2 , 80},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis2 , 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis2 , 100},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 110},
|
||||
{IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2,120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 130},
|
||||
};
|
||||
|
||||
static menuitem_t OP_JoystickSetMenu[] =
|
||||
|
@ -1289,28 +1315,60 @@ static menuitem_t OP_EraseDataMenu[] =
|
|||
{IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40},
|
||||
};
|
||||
|
||||
static menuitem_t OP_AddonsOptionsMenu[] =
|
||||
{
|
||||
{IT_HEADER, NULL, "Menu", NULL, 0},
|
||||
{IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 10},
|
||||
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 20},
|
||||
{IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 48},
|
||||
{IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 58},
|
||||
|
||||
{IT_HEADER, NULL, "Search", NULL, 76},
|
||||
{IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 86},
|
||||
{IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 96},
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
op_addons_folder = 2,
|
||||
};
|
||||
|
||||
static menuitem_t OP_GameOptionsMenu[] =
|
||||
{
|
||||
#ifndef NONET
|
||||
{IT_STRING | IT_CVAR | IT_CV_STRING,
|
||||
NULL, "Master server", &cv_masterserver, 10},
|
||||
{IT_STRING | IT_SUBMENU, NULL, "Chat Options...", &OP_ChatOptionsDef, 40},
|
||||
#endif
|
||||
{IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40},
|
||||
{IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 50},
|
||||
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
|
||||
NULL, "HUD Visibility", &cv_translucenthud, 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 60},
|
||||
NULL, "HUD Visibility", &cv_translucenthud, 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Always Compact Rankings", &cv_compactscoreboard, 80},
|
||||
#ifdef SEENAMES
|
||||
{IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 80},
|
||||
{IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 90},
|
||||
#endif
|
||||
{IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 100},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,110},
|
||||
{IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 110},
|
||||
{IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 130},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 140},
|
||||
};
|
||||
|
||||
static menuitem_t OP_ChatOptionsMenu[] =
|
||||
{
|
||||
{IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 10},
|
||||
|
||||
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 30},
|
||||
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 40},
|
||||
{IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 80},
|
||||
};
|
||||
|
||||
static menuitem_t OP_ServerOptionsMenu[] =
|
||||
{
|
||||
{IT_STRING | IT_SUBMENU, NULL, "General netgame options...", &OP_NetgameOptionsDef, 10},
|
||||
|
@ -1403,6 +1461,18 @@ static menuitem_t OP_MonitorToggleMenu[] =
|
|||
// Main Menu and related
|
||||
menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72);
|
||||
|
||||
menu_t MISC_AddonsDef =
|
||||
{
|
||||
NULL,
|
||||
sizeof (MISC_AddonsMenu)/sizeof (menuitem_t),
|
||||
&MainDef,
|
||||
MISC_AddonsMenu,
|
||||
M_DrawAddons,
|
||||
50, 28,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
|
||||
menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72);
|
||||
menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72);
|
||||
menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72);
|
||||
|
@ -1413,6 +1483,9 @@ menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseD
|
|||
menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef);
|
||||
menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu);
|
||||
|
||||
static INT32 highlightflags, recommendedflags, warningflags;
|
||||
|
||||
|
||||
// Sky Room
|
||||
menu_t SR_PandoraDef =
|
||||
{
|
||||
|
@ -1705,6 +1778,7 @@ menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu,
|
|||
|
||||
menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30);
|
||||
menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30);
|
||||
menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 30, 30);
|
||||
menu_t OP_MonitorToggleDef =
|
||||
{
|
||||
"M_SERVER",
|
||||
|
@ -1747,6 +1821,7 @@ menu_t OP_OpenGLColorDef =
|
|||
#endif
|
||||
menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30);
|
||||
menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30);
|
||||
menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_MainDef, 30, 30);
|
||||
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30);
|
||||
|
||||
// ==========================================================================
|
||||
|
@ -1972,6 +2047,12 @@ void Moviemode_mode_Onchange(void)
|
|||
OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR;
|
||||
}
|
||||
|
||||
void Addons_option_Onchange(void)
|
||||
{
|
||||
OP_AddonsOptionsMenu[op_addons_folder].status =
|
||||
(cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// END ORGANIZATION STUFF.
|
||||
// ==========================================================================
|
||||
|
@ -2602,6 +2683,7 @@ void M_StartControlPanel(void)
|
|||
else // multiplayer
|
||||
{
|
||||
MPauseMenu[mpause_switchmap].status = IT_DISABLED;
|
||||
MPauseMenu[mpause_addons].status = IT_DISABLED;
|
||||
MPauseMenu[mpause_scramble].status = IT_DISABLED;
|
||||
MPauseMenu[mpause_psetupsplit].status = IT_DISABLED;
|
||||
MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED;
|
||||
|
@ -2613,6 +2695,7 @@ void M_StartControlPanel(void)
|
|||
if ((server || IsPlayerAdmin(consoleplayer)))
|
||||
{
|
||||
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
|
||||
MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL;
|
||||
if (G_GametypeHasTeams())
|
||||
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
|
||||
}
|
||||
|
@ -3852,6 +3935,548 @@ static void M_HandleImageDef(INT32 choice)
|
|||
// MISC MAIN MENU OPTIONS
|
||||
// ======================
|
||||
|
||||
static void M_AddonsOptions(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
Addons_option_Onchange();
|
||||
|
||||
M_SetupNextMenu(&OP_AddonsOptionsDef);
|
||||
}
|
||||
|
||||
#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!"
|
||||
//#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!"
|
||||
|
||||
static void M_Addons(INT32 choice)
|
||||
{
|
||||
const char *pathname = ".";
|
||||
|
||||
(void)choice;
|
||||
|
||||
// If M_GetGameypeColor() is ever ported from Kart, then remove this.
|
||||
highlightflags = V_YELLOWMAP;
|
||||
recommendedflags = V_GREENMAP;
|
||||
warningflags = V_REDMAP;
|
||||
|
||||
#if 1
|
||||
if (cv_addons_option.value == 0)
|
||||
pathname = usehome ? srb2home : srb2path;
|
||||
else if (cv_addons_option.value == 1)
|
||||
pathname = srb2home;
|
||||
else if (cv_addons_option.value == 2)
|
||||
pathname = srb2path;
|
||||
else
|
||||
#endif
|
||||
if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
|
||||
pathname = cv_addons_folder.string;
|
||||
|
||||
strlcpy(menupath, pathname, 1024);
|
||||
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
|
||||
|
||||
if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0])
|
||||
{
|
||||
menupath[menupathindex[menudepthleft]-1] = PATHSEP[0];
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
}
|
||||
else
|
||||
--menupathindex[menudepthleft];
|
||||
|
||||
if (!preparefilemenu(false))
|
||||
{
|
||||
M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n",LOCATIONSTRING1),NULL,MM_NOTHING);
|
||||
// (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1))
|
||||
return;
|
||||
}
|
||||
else
|
||||
dir_on[menudepthleft] = 0;
|
||||
|
||||
if (addonsp[0]) // never going to have some provided but not all, saves individually checking
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < NUM_EXT+5; i++)
|
||||
W_UnlockCachedPatch(addonsp[i]);
|
||||
}
|
||||
|
||||
addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC);
|
||||
addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC);
|
||||
addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC);
|
||||
addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC);
|
||||
addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC);
|
||||
addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC);
|
||||
#ifdef USE_KART
|
||||
addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC);
|
||||
#endif
|
||||
addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC);
|
||||
addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC);
|
||||
addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC);
|
||||
addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC);
|
||||
addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_STATIC);
|
||||
addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC);
|
||||
addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC);
|
||||
addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC);
|
||||
|
||||
MISC_AddonsDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&MISC_AddonsDef);
|
||||
}
|
||||
|
||||
#define width 4
|
||||
#define vpadding 27
|
||||
#define h (BASEVIDHEIGHT-(2*vpadding))
|
||||
#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker
|
||||
static void M_DrawTemperature(INT32 x, fixed_t t)
|
||||
{
|
||||
INT32 y;
|
||||
|
||||
// bounds check
|
||||
if (t > FRACUNIT)
|
||||
t = FRACUNIT;
|
||||
/*else if (t < 0) -- not needed
|
||||
t = 0;*/
|
||||
|
||||
// scale
|
||||
if (t > 1)
|
||||
t = (FixedMul(h<<FRACBITS, t)>>FRACBITS);
|
||||
|
||||
// border
|
||||
V_DrawFill(x - 1, vpadding, 1, h, 120);
|
||||
V_DrawFill(x + width, vpadding, 1, h, 120);
|
||||
V_DrawFill(x - 1, vpadding-1, width+2, 1, 120);
|
||||
V_DrawFill(x - 1, vpadding+h, width+2, 1, 120);
|
||||
|
||||
// bar itself
|
||||
y = h;
|
||||
if (t)
|
||||
for (t = h - t; y > 0; y--)
|
||||
{
|
||||
UINT8 colours[NUMCOLOURS] = {135, 133, 92, 77, 114, 178, 161, 162};
|
||||
UINT8 c;
|
||||
if (y <= t) break;
|
||||
if (y+vpadding >= BASEVIDHEIGHT/2)
|
||||
c = 185;
|
||||
else
|
||||
c = colours[(NUMCOLOURS*(y-1))/(h/2)];
|
||||
V_DrawFill(x, y-1 + vpadding, width, 1, c);
|
||||
}
|
||||
|
||||
// fill the rest of the backing
|
||||
if (y)
|
||||
V_DrawFill(x, vpadding, width, y, 30);
|
||||
}
|
||||
#undef width
|
||||
#undef vpadding
|
||||
#undef h
|
||||
#undef NUMCOLOURS
|
||||
|
||||
static char *M_AddonsHeaderPath(void)
|
||||
{
|
||||
UINT32 len;
|
||||
static char header[1024];
|
||||
|
||||
strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024);
|
||||
len = strlen(header);
|
||||
if (len > 34)
|
||||
{
|
||||
len = len-34;
|
||||
header[len] = header[len+1] = header[len+2] = '.';
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
|
||||
return header+len;
|
||||
}
|
||||
|
||||
#define UNEXIST S_StartSound(NULL, sfx_lose);\
|
||||
M_SetupNextMenu(MISC_AddonsDef.prevMenu);\
|
||||
M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
|
||||
|
||||
#define CLEARNAME Z_Free(refreshdirname);\
|
||||
refreshdirname = NULL
|
||||
|
||||
static void M_AddonsClearName(INT32 choice)
|
||||
{
|
||||
CLEARNAME;
|
||||
M_StopMessage(choice);
|
||||
}
|
||||
|
||||
// returns whether to do message draw
|
||||
static boolean M_AddonsRefresh(void)
|
||||
{
|
||||
if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true))
|
||||
{
|
||||
UNEXIST;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (refreshdirmenu & REFRESHDIR_ADDFILE)
|
||||
{
|
||||
char *message = NULL;
|
||||
|
||||
if (refreshdirmenu & REFRESHDIR_NOTLOADED)
|
||||
{
|
||||
S_StartSound(NULL, sfx_lose);
|
||||
if (refreshdirmenu & REFRESHDIR_MAX)
|
||||
message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
else
|
||||
message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
}
|
||||
else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
|
||||
{
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings"));
|
||||
}
|
||||
|
||||
if (message)
|
||||
{
|
||||
M_StartMessage(message,M_AddonsClearName,MM_EVENTHANDLER);
|
||||
return true;
|
||||
}
|
||||
|
||||
S_StartSound(NULL, sfx_strpst);
|
||||
CLEARNAME;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void M_DrawAddons(void)
|
||||
{
|
||||
INT32 x, y;
|
||||
ssize_t i, m;
|
||||
const UINT8 *flashcol = NULL;
|
||||
UINT8 hilicol;
|
||||
|
||||
// hack - need to refresh at end of frame to handle addfile...
|
||||
if (refreshdirmenu & M_AddonsRefresh())
|
||||
{
|
||||
M_DrawMessageMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Playing())
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems.");
|
||||
else
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, LOCATIONSTRING1);
|
||||
// (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)
|
||||
|
||||
if (numwadfiles <= mainwads+1)
|
||||
y = 0;
|
||||
else if (numwadfiles >= MAX_WADFILES)
|
||||
y = FRACUNIT;
|
||||
else
|
||||
{
|
||||
x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))<<FRACBITS, ((ssize_t)MAX_WADFILES - (ssize_t)(mainwads+1))<<FRACBITS);
|
||||
y = FixedDiv((((ssize_t)packetsizetally-(ssize_t)mainwadstally)<<FRACBITS), ((((ssize_t)MAXFILENEEDED*sizeof(UINT8)-(ssize_t)mainwadstally)-(5+22))<<FRACBITS)); // 5+22 = (a.ext + checksum length) is minimum addition to packet size tally
|
||||
if (x > y)
|
||||
y = x;
|
||||
if (y > FRACUNIT) // happens because of how we're shrinkin' it a little
|
||||
y = FRACUNIT;
|
||||
}
|
||||
|
||||
M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y);
|
||||
|
||||
// DRAW MENU
|
||||
x = currentMenu->x;
|
||||
y = currentMenu->y + 1;
|
||||
|
||||
hilicol = V_GetStringColormap(highlightflags)[120];
|
||||
|
||||
V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), highlightflags|V_ALLOWLOWERCASE, M_AddonsHeaderPath());
|
||||
V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), MAXSTRINGLENGTH*8+6, 1, hilicol);
|
||||
V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 30);
|
||||
|
||||
m = (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1);
|
||||
V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 239);
|
||||
|
||||
// scrollbar!
|
||||
if (sizedirmenu <= (2*numaddonsshown + 1))
|
||||
i = 0;
|
||||
else
|
||||
{
|
||||
ssize_t q = m;
|
||||
m = ((2*numaddonsshown + 1) * m)/sizedirmenu;
|
||||
if (dir_on[menudepthleft] <= numaddonsshown) // all the way up
|
||||
i = 0;
|
||||
else if (sizedirmenu <= (dir_on[menudepthleft] + numaddonsshown + 1)) // all the way down
|
||||
i = q-m;
|
||||
else
|
||||
i = ((dir_on[menudepthleft] - numaddonsshown) * (q-m))/(sizedirmenu - (2*numaddonsshown + 1));
|
||||
}
|
||||
|
||||
V_DrawFill(x + MAXSTRINGLENGTH*8+5 - 21, (y - 1) + i, 1, m, hilicol);
|
||||
|
||||
// get bottom...
|
||||
m = dir_on[menudepthleft] + numaddonsshown + 1;
|
||||
if (m > (ssize_t)sizedirmenu)
|
||||
m = sizedirmenu;
|
||||
|
||||
// then compute top and adjust bottom if needed!
|
||||
if (m < (2*numaddonsshown + 1))
|
||||
{
|
||||
m = min(sizedirmenu, 2*numaddonsshown + 1);
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
i = m - (2*numaddonsshown + 1);
|
||||
|
||||
if (i != 0)
|
||||
V_DrawString(19, y+4 - (skullAnimCounter/5), highlightflags, "\x1A");
|
||||
|
||||
if (skullAnimCounter < 4)
|
||||
flashcol = V_GetStringColormap(highlightflags);
|
||||
|
||||
for (; i < m; i++)
|
||||
{
|
||||
UINT32 flags = V_ALLOWLOWERCASE;
|
||||
if (y > BASEVIDHEIGHT) break;
|
||||
if (dirmenu[i])
|
||||
#define type (UINT8)(dirmenu[i][DIR_TYPE])
|
||||
{
|
||||
if (type & EXT_LOADED)
|
||||
{
|
||||
flags |= V_TRANSLUCENT;
|
||||
V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, addonsp[(type & ~EXT_LOADED)]);
|
||||
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]);
|
||||
}
|
||||
else
|
||||
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]);
|
||||
|
||||
if ((size_t)i == dir_on[menudepthleft])
|
||||
{
|
||||
V_DrawFixedPatch((x-(16+4))<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, 0, addonsp[NUM_EXT+1], flashcol);
|
||||
flags = V_ALLOWLOWERCASE|highlightflags;
|
||||
}
|
||||
|
||||
#define charsonside 14
|
||||
if (dirmenu[i][DIR_LEN] > (charsonside*2 + 3))
|
||||
V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1)));
|
||||
#undef charsonside
|
||||
else
|
||||
V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING);
|
||||
}
|
||||
#undef type
|
||||
y += 16;
|
||||
}
|
||||
|
||||
if (m != (ssize_t)sizedirmenu)
|
||||
V_DrawString(19, y-12 + (skullAnimCounter/5), highlightflags, "\x1B");
|
||||
|
||||
y = BASEVIDHEIGHT - currentMenu->y + 1;
|
||||
|
||||
M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
|
||||
if (menusearch[0])
|
||||
V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1);
|
||||
else
|
||||
V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search...");
|
||||
if (skullAnimCounter < 4)
|
||||
V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8,
|
||||
'_' | 0x80, false);
|
||||
|
||||
x -= (21 + 5 + 16);
|
||||
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]);
|
||||
|
||||
x = BASEVIDWIDTH - x - 16;
|
||||
V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
|
||||
|
||||
if (modifiedgame)
|
||||
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]);
|
||||
}
|
||||
|
||||
static void M_AddonExec(INT32 ch)
|
||||
{
|
||||
if (ch != 'y' && ch != KEY_ENTER)
|
||||
return;
|
||||
|
||||
S_StartSound(NULL, sfx_zoom);
|
||||
COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
|
||||
}
|
||||
|
||||
#define len menusearch[0]
|
||||
static boolean M_ChangeStringAddons(INT32 choice)
|
||||
{
|
||||
if (shiftdown && choice >= 32 && choice <= 127)
|
||||
choice = shiftxform[choice];
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
case KEY_DEL:
|
||||
if (len)
|
||||
{
|
||||
len = menusearch[1] = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case KEY_BACKSPACE:
|
||||
if (len)
|
||||
{
|
||||
menusearch[1+--len] = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (choice >= 32 && choice <= 127)
|
||||
{
|
||||
if (len < MAXSTRINGLENGTH - 1)
|
||||
{
|
||||
menusearch[1+len++] = (char)choice;
|
||||
menusearch[1+len] = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#undef len
|
||||
|
||||
static void M_HandleAddons(INT32 choice)
|
||||
{
|
||||
boolean exitmenu = false; // exit to previous menu
|
||||
|
||||
if (M_ChangeStringAddons(choice))
|
||||
{
|
||||
char *tempname = NULL;
|
||||
if (dirmenu && dirmenu[dir_on[menudepthleft]])
|
||||
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
|
||||
#if 0 // much slower
|
||||
if (!preparefilemenu(true))
|
||||
{
|
||||
UNEXIST;
|
||||
return;
|
||||
}
|
||||
#else // streamlined
|
||||
searchfilemenu(tempname);
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
case KEY_DOWNARROW:
|
||||
if (dir_on[menudepthleft] < sizedirmenu-1)
|
||||
dir_on[menudepthleft]++;
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
break;
|
||||
case KEY_UPARROW:
|
||||
if (dir_on[menudepthleft])
|
||||
dir_on[menudepthleft]--;
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
break;
|
||||
case KEY_PGDN:
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--)
|
||||
dir_on[menudepthleft]++;
|
||||
}
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
break;
|
||||
case KEY_PGUP:
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--)
|
||||
dir_on[menudepthleft]--;
|
||||
}
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
{
|
||||
boolean refresh = true;
|
||||
if (!dirmenu[dir_on[menudepthleft]])
|
||||
S_StartSound(NULL, sfx_lose);
|
||||
else
|
||||
{
|
||||
switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
|
||||
{
|
||||
case EXT_FOLDER:
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING);
|
||||
if (menudepthleft)
|
||||
{
|
||||
menupathindex[--menudepthleft] = strlen(menupath);
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
|
||||
if (!preparefilemenu(false))
|
||||
{
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[++menudepthleft]] = 0;
|
||||
|
||||
if (!preparefilemenu(true))
|
||||
{
|
||||
UNEXIST;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
dir_on[menudepthleft] = 1;
|
||||
}
|
||||
refresh = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_lose);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
}
|
||||
break;
|
||||
case EXT_UP:
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
menupath[menupathindex[++menudepthleft]] = 0;
|
||||
if (!preparefilemenu(false))
|
||||
{
|
||||
UNEXIST;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case EXT_TXT:
|
||||
M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO);
|
||||
break;
|
||||
case EXT_CFG:
|
||||
M_AddonExec(KEY_ENTER);
|
||||
break;
|
||||
case EXT_LUA:
|
||||
#ifndef HAVE_BLUA
|
||||
S_StartSound(NULL, sfx_lose);
|
||||
M_StartMessage(va("%c%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
|
||||
break;
|
||||
#endif
|
||||
// else intentional fallthrough
|
||||
case EXT_SOC:
|
||||
case EXT_WAD:
|
||||
#ifdef USE_KART
|
||||
case EXT_KART:
|
||||
#endif
|
||||
case EXT_PK3:
|
||||
COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
|
||||
break;
|
||||
default:
|
||||
S_StartSound(NULL, sfx_lose);
|
||||
}
|
||||
}
|
||||
if (refresh)
|
||||
refreshdirmenu |= REFRESHDIR_NORMAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_ESCAPE:
|
||||
exitmenu = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (exitmenu)
|
||||
{
|
||||
closefilemenu(true);
|
||||
|
||||
// Secret menu!
|
||||
MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
|
||||
|
||||
if (currentMenu->prevMenu)
|
||||
M_SetupNextMenu(currentMenu->prevMenu);
|
||||
else
|
||||
M_ClearMenus(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_PandorasBox(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
@ -6837,9 +7462,10 @@ static void M_Setup2PControlsMenu(INT32 choice)
|
|||
OP_MPControlsMenu[0].status = IT_GRAYEDOUT2;
|
||||
OP_MPControlsMenu[1].status = IT_GRAYEDOUT2;
|
||||
OP_MPControlsMenu[2].status = IT_GRAYEDOUT2;
|
||||
// Hide the pause/console controls too
|
||||
// Hide the pause/console and system menu controls too
|
||||
OP_MiscControlsMenu[3].status = IT_GRAYEDOUT2;
|
||||
OP_MiscControlsMenu[4].status = IT_GRAYEDOUT2;
|
||||
OP_MiscControlsMenu[6].status = IT_GRAYEDOUT2;
|
||||
OP_MiscControlsMenu[8].status = IT_GRAYEDOUT2;
|
||||
|
||||
OP_ControlListDef.prevMenu = &OP_P2ControlsDef;
|
||||
M_SetupNextMenu(&OP_ControlListDef);
|
||||
|
@ -6955,7 +7581,7 @@ static void M_ChangecontrolResponse(event_t *ev)
|
|||
found = 0;
|
||||
setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2
|
||||
}
|
||||
G_CheckDoubleUsage(ch);
|
||||
(void)G_CheckDoubleUsage(ch, true);
|
||||
setupcontrols[control][found] = ch;
|
||||
}
|
||||
S_StartSound(NULL, sfx_strpst);
|
||||
|
|
|
@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
|
|||
#define IT_HEADER (IT_SPACE +IT_HEADERTEXT)
|
||||
#define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS)
|
||||
|
||||
#define MAXSTRINGLENGTH 32
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct menu_s *submenu; // IT_SUBMENU
|
||||
|
@ -223,6 +225,9 @@ void M_CheatActivationResponder(INT32 ch);
|
|||
void Moviemode_mode_Onchange(void);
|
||||
void Screenshot_option_Onchange(void);
|
||||
|
||||
// Addons menu updating
|
||||
void Addons_option_Onchange(void);
|
||||
|
||||
// These defines make it a little easier to make menus
|
||||
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
|
||||
{\
|
||||
|
|
38
src/m_misc.c
38
src/m_misc.c
|
@ -442,8 +442,12 @@ void Command_LoadConfig_f(void)
|
|||
strcpy(configfile, COM_Argv(1));
|
||||
FIL_ForceExtension(configfile, ".cfg");
|
||||
|
||||
// load default control
|
||||
G_ClearAllControlKeys();
|
||||
G_Controldefault();
|
||||
|
||||
// temporarily reset execversion to default
|
||||
cv_execversion.flags &= ~CV_HIDEN;
|
||||
CV_ToggleExecVersion(true);
|
||||
COM_BufInsertText(va("%s \"%s\"\n", cv_execversion.name, cv_execversion.defaultvalue));
|
||||
CV_InitFilterVar();
|
||||
|
||||
|
@ -451,8 +455,8 @@ void Command_LoadConfig_f(void)
|
|||
COM_BufInsertText(va("exec \"%s\"\n", configfile));
|
||||
|
||||
// don't filter anymore vars and don't let this convsvar be changed
|
||||
COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, MODVERSION));
|
||||
cv_execversion.flags |= CV_HIDEN;
|
||||
COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION));
|
||||
CV_ToggleExecVersion(false);
|
||||
}
|
||||
|
||||
/** Saves the current configuration and loads another.
|
||||
|
@ -494,7 +498,7 @@ void M_FirstLoadConfig(void)
|
|||
|
||||
// temporarily reset execversion to default
|
||||
// we shouldn't need to do this, but JUST in case...
|
||||
cv_execversion.flags &= ~CV_HIDEN;
|
||||
CV_ToggleExecVersion(true);
|
||||
COM_BufInsertText(va("%s \"%s\"\n", cv_execversion.name, cv_execversion.defaultvalue));
|
||||
CV_InitFilterVar();
|
||||
|
||||
|
@ -503,8 +507,8 @@ void M_FirstLoadConfig(void)
|
|||
// no COM_BufExecute() needed; that does it right away
|
||||
|
||||
// don't filter anymore vars and don't let this convsvar be changed
|
||||
COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, MODVERSION));
|
||||
cv_execversion.flags |= CV_HIDEN;
|
||||
COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION));
|
||||
CV_ToggleExecVersion(false);
|
||||
|
||||
// make sure I_Quit() will write back the correct config
|
||||
// (do not write back the config if it crash before)
|
||||
|
@ -518,6 +522,7 @@ void M_FirstLoadConfig(void)
|
|||
void M_SaveConfig(const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char *filepath;
|
||||
|
||||
// make sure not to write back the config until it's been correctly loaded
|
||||
if (!gameconfig_loaded)
|
||||
|
@ -532,13 +537,20 @@ void M_SaveConfig(const char *filename)
|
|||
return;
|
||||
}
|
||||
|
||||
f = fopen(filename, "w");
|
||||
// append srb2home to beginning of filename
|
||||
// but check if srb2home isn't already there, first
|
||||
if (!strstr(filename, srb2home))
|
||||
filepath = va(pandf,srb2home, filename);
|
||||
else
|
||||
filepath = Z_StrDup(filename);
|
||||
|
||||
f = fopen(filepath, "w");
|
||||
// change it only if valid
|
||||
if (f)
|
||||
strcpy(configfile, filename);
|
||||
strcpy(configfile, filepath);
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Couldn't save game config file %s\n"), filename);
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Couldn't save game config file %s\n"), filepath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -562,8 +574,8 @@ void M_SaveConfig(const char *filename)
|
|||
fprintf(f, "// SRB2 configuration file.\n");
|
||||
|
||||
// print execversion FIRST, because subsequent consvars need to be filtered
|
||||
// always print current MODVERSION
|
||||
fprintf(f, "%s \"%d\"\n", cv_execversion.name, MODVERSION);
|
||||
// always print current EXECVERSION
|
||||
fprintf(f, "%s \"%d\"\n", cv_execversion.name, EXECVERSION);
|
||||
|
||||
// FIXME: save key aliases if ever implemented..
|
||||
|
||||
|
@ -1523,6 +1535,10 @@ boolean M_ScreenshotResponder(event_t *ev)
|
|||
return false;
|
||||
|
||||
ch = ev->data1;
|
||||
|
||||
if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus!
|
||||
return false;
|
||||
|
||||
if (ch == KEY_F8 || ch == gamecontrol[gc_screenshot][0] || ch == gamecontrol[gc_screenshot][1]) // remappable F8
|
||||
M_ScreenShot();
|
||||
else if (ch == KEY_F9 || ch == gamecontrol[gc_recordgif][0] || ch == gamecontrol[gc_recordgif][1]) // remappable F9
|
||||
|
|
|
@ -41,9 +41,6 @@
|
|||
// Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red
|
||||
#define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;}
|
||||
|
||||
// player radius used only in am_map.c
|
||||
#define PLAYERRADIUS (16*FRACUNIT)
|
||||
|
||||
// MAXRADIUS is for precalculated sector block boxes
|
||||
// the spider demon is larger,
|
||||
// but we do not have any moving sectors nearby
|
||||
|
|
|
@ -3506,7 +3506,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
|
|||
|
||||
if (player->pflags & PF_FLIPCAM && !(player->pflags & PF_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP)
|
||||
postimg = postimg_flip;
|
||||
else if (player->awayviewtics && player->awayviewmobj != NULL) // Camera must obviously exist
|
||||
else if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist
|
||||
{
|
||||
camera_t dummycam;
|
||||
dummycam.subsector = player->awayviewmobj->subsector;
|
||||
|
@ -7274,6 +7274,8 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
// Assumedly in splitscreen players will be on opposing teams
|
||||
if (players[consoleplayer].ctfteam == 1 || splitscreen)
|
||||
S_StartSound(NULL, sfx_hoop1);
|
||||
else if (players[consoleplayer].ctfteam == 2)
|
||||
S_StartSound(NULL, sfx_hoop3);
|
||||
|
||||
redflag = flagmo;
|
||||
}
|
||||
|
@ -7285,6 +7287,8 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
// Assumedly in splitscreen players will be on opposing teams
|
||||
if (players[consoleplayer].ctfteam == 2 || splitscreen)
|
||||
S_StartSound(NULL, sfx_hoop1);
|
||||
else if (players[consoleplayer].ctfteam == 1)
|
||||
S_StartSound(NULL, sfx_hoop3);
|
||||
|
||||
blueflag = flagmo;
|
||||
}
|
||||
|
|
|
@ -1859,6 +1859,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
diffz = po->lines[0]->backsector->floorheight - (target->z - amtz);
|
||||
po->lines[0]->backsector->floorheight = target->z - amtz;
|
||||
po->lines[0]->backsector->ceilingheight = target->z + amtz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage));
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
// Apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -1870,6 +1873,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
// TODO: use T_MovePlane
|
||||
po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did
|
||||
po->lines[0]->backsector->ceilingheight += diffz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage));
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
}
|
||||
|
||||
po = oldpo;
|
||||
|
@ -2030,6 +2036,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
// TODO: use T_MovePlane
|
||||
po->lines[0]->backsector->floorheight += momz;
|
||||
po->lines[0]->backsector->ceilingheight += momz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // backsector may not be necessary, but just in case
|
||||
|
||||
// Apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
|
@ -2042,6 +2051,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
// TODO: use T_MovePlane
|
||||
po->lines[0]->backsector->floorheight += momz;
|
||||
po->lines[0]->backsector->ceilingheight += momz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage));
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
|
||||
#include "v_video.h"
|
||||
|
||||
#include "filesrch.h" // refreshdirmenu
|
||||
|
||||
// wipes
|
||||
#include "f_finale.h"
|
||||
|
||||
|
@ -219,6 +221,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
|||
mapheaderinfo[num]->levelselect = 0;
|
||||
DEH_WriteUndoline("BONUSTYPE", va("%d", mapheaderinfo[num]->bonustype), UNDO_NONE);
|
||||
mapheaderinfo[num]->bonustype = 0;
|
||||
DEH_WriteUndoline("SAVEOVERRIDE", va("%d", mapheaderinfo[num]->saveoverride), UNDO_NONE);
|
||||
mapheaderinfo[num]->saveoverride = SAVE_DEFAULT;
|
||||
DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE);
|
||||
mapheaderinfo[num]->levelflags = 0;
|
||||
DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE);
|
||||
|
@ -380,30 +384,26 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum)
|
|||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Computes the line length in fracunits, the OpenGL render needs this
|
||||
//
|
||||
|
||||
/** Computes the length of a seg in fracunits.
|
||||
* This is needed for splats.
|
||||
*
|
||||
* \param seg Seg to compute length for.
|
||||
* \return Length in fracunits.
|
||||
*/
|
||||
fixed_t P_SegLength(seg_t *seg)
|
||||
{
|
||||
fixed_t dx, dy;
|
||||
|
||||
// make a vector (start at origin)
|
||||
dx = seg->v2->x - seg->v1->x;
|
||||
dy = seg->v2->y - seg->v1->y;
|
||||
|
||||
return FixedHypot(dx, dy);
|
||||
INT64 dx = (seg->v2->x - seg->v1->x)>>1;
|
||||
INT64 dy = (seg->v2->y - seg->v1->y)>>1;
|
||||
return FixedHypot(dx, dy)<<1;
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
static inline float P_SegLengthf(seg_t *seg)
|
||||
/** Computes the length of a seg as a float.
|
||||
* This is needed for OpenGL.
|
||||
*
|
||||
* \param seg Seg to compute length for.
|
||||
* \return Length as a float.
|
||||
*/
|
||||
static inline float P_SegLengthFloat(seg_t *seg)
|
||||
{
|
||||
float dx, dy;
|
||||
|
||||
|
@ -439,11 +439,11 @@ static void P_LoadRawSegs(UINT8 *data, size_t i)
|
|||
li->v1 = &vertexes[SHORT(ml->v1)];
|
||||
li->v2 = &vertexes[SHORT(ml->v2)];
|
||||
|
||||
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
||||
// used for the hardware render
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
li->length = P_SegLength(li);
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
li->flength = P_SegLengthf(li);
|
||||
li->flength = P_SegLengthFloat(li);
|
||||
//Hurdler: 04/12/2000: for now, only used in hardware mode
|
||||
li->lightmaps = NULL; // list of static lightmap for this seg
|
||||
}
|
||||
|
@ -2000,7 +2000,7 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname
|
|||
if (!count || count >= 0x20000)
|
||||
return false;
|
||||
|
||||
CONS_Printf("Reading blockmap lump for pk3...\n");
|
||||
//CONS_Printf("Reading blockmap lump for pk3...\n");
|
||||
|
||||
// no need to malloc anything, assume the data is uncompressed for now
|
||||
count /= 2;
|
||||
|
@ -2626,6 +2626,28 @@ static void P_SetupCamera(void)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean P_CanSave(void)
|
||||
{
|
||||
// Saving is completely ignored under these conditions:
|
||||
if ((cursaveslot < 0) // Playing without saving
|
||||
|| (modifiedgame && !savemoddata) // Game is modified
|
||||
|| (netgame || multiplayer) // Not in single-player
|
||||
|| (demoplayback || demorecording || metalrecording) // Currently in demo
|
||||
|| (players[consoleplayer].lives <= 0) // Completely dead
|
||||
|| (modeattacking || ultimatemode || G_IsSpecialStage(gamemap))) // Specialized instances
|
||||
return false;
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_ALWAYS)
|
||||
return true; // Saving should ALWAYS happen!
|
||||
else if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_NEVER)
|
||||
return false; // Saving should NEVER happen!
|
||||
|
||||
// Default condition: In a non-hidden map, at the beginning of a zone or on a completed save-file, and not on save reload.
|
||||
return (!(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
|
||||
&& (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete)
|
||||
&& (gamemap != lastmapsaved));
|
||||
}
|
||||
|
||||
/** Loads a level from a lump or external wad.
|
||||
*
|
||||
* \param skipprecip If true, don't spawn precipitation.
|
||||
|
@ -2689,8 +2711,9 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
|
||||
if (!dedicated)
|
||||
{
|
||||
if (!cv_cam_speed.changed)
|
||||
CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);
|
||||
// Salt: CV_ClearChangedFlags() messes with your settings :(
|
||||
/*if (!cv_cam_speed.changed)
|
||||
CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/
|
||||
|
||||
if (!cv_chasecam.changed)
|
||||
CV_SetValue(&cv_chasecam, chase);
|
||||
|
@ -3025,20 +3048,22 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
{
|
||||
P_SetupCamera();
|
||||
|
||||
if (!cv_cam_height.changed)
|
||||
// Salt: CV_ClearChangedFlags() messes with your settings :(
|
||||
/*if (!cv_cam_height.changed)
|
||||
CV_Set(&cv_cam_height, cv_cam_height.defaultvalue);
|
||||
|
||||
if (!cv_cam_dist.changed)
|
||||
CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue);
|
||||
|
||||
if (!cv_cam_rotate.changed)
|
||||
CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
|
||||
|
||||
if (!cv_cam2_height.changed)
|
||||
CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue);
|
||||
|
||||
if (!cv_cam2_dist.changed)
|
||||
CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);
|
||||
CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/
|
||||
|
||||
// Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P
|
||||
if (!cv_cam_rotate.changed)
|
||||
CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
|
||||
|
||||
if (!cv_cam2_rotate.changed)
|
||||
CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue);
|
||||
|
@ -3103,10 +3128,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
|
||||
P_RunCachedActions();
|
||||
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0)
|
||||
&& (!modifiedgame || savemoddata) && cursaveslot >= 0 && !ultimatemode
|
||||
&& !(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
|
||||
&& (!G_IsSpecialStage(gamemap)) && gamemap != lastmapsaved && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete))
|
||||
if (P_CanSave())
|
||||
G_SaveGame((UINT32)cursaveslot);
|
||||
|
||||
if (savedata.lives > 0)
|
||||
|
@ -3177,6 +3199,7 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
|
||||
if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename);
|
||||
return false;
|
||||
}
|
||||
|
|
61
src/p_user.c
61
src/p_user.c
|
@ -7630,6 +7630,9 @@ static void P_DeathThink(player_t *player)
|
|||
if (player->deadtimer < INT32_MAX)
|
||||
player->deadtimer++;
|
||||
|
||||
if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already
|
||||
goto notrealplayer;
|
||||
|
||||
// continue logic
|
||||
if (!(netgame || multiplayer) && player->lives <= 0)
|
||||
{
|
||||
|
@ -7749,6 +7752,8 @@ static void P_DeathThink(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
notrealplayer:
|
||||
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
||||
|
@ -7781,18 +7786,18 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0,
|
|||
static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_cam_dist = {"cam_dist", "128", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_height = {"cam_height", "20", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_height = {"cam_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_speed = {"cam_speed", "0.25", CV_FLOAT, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", 0, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_dist = {"cam2_dist", "128", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_height = {"cam2_height", "20", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_speed = {"cam2_speed", "0.25", CV_FLOAT, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", 0, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
fixed_t t_cam_dist = -42;
|
||||
fixed_t t_cam_height = -42;
|
||||
|
@ -8048,6 +8053,20 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
{
|
||||
dist = camdist;
|
||||
|
||||
// x1.5 dist for splitscreen
|
||||
if (splitscreen)
|
||||
{
|
||||
dist = FixedMul(dist, 3*FRACUNIT/2);
|
||||
camheight = FixedMul(camheight, 3*FRACUNIT/2);
|
||||
}
|
||||
|
||||
// x1.2 dist for analog
|
||||
if (P_AnalogMove(player))
|
||||
{
|
||||
dist = FixedMul(dist, 6*FRACUNIT/5);
|
||||
camheight = FixedMul(camheight, 6*FRACUNIT/5);
|
||||
}
|
||||
|
||||
if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG)))
|
||||
dist <<= 1;
|
||||
}
|
||||
|
@ -8372,7 +8391,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
if (!(multiplayer || netgame) && !splitscreen)
|
||||
{
|
||||
fixed_t vx = thiscam->x, vy = thiscam->y;
|
||||
if (player->awayviewtics && player->awayviewmobj != NULL) // Camera must obviously exist
|
||||
if (player->awayviewtics && player->awayviewmobj != NULL && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist
|
||||
{
|
||||
vx = player->awayviewmobj->x;
|
||||
vy = player->awayviewmobj->y;
|
||||
|
@ -8534,7 +8553,7 @@ static void P_CalcPostImg(player_t *player)
|
|||
else
|
||||
pviewheight = player->mo->z + player->viewheight;
|
||||
|
||||
if (player->awayviewtics)
|
||||
if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj))
|
||||
{
|
||||
sector = player->awayviewmobj->subsector->sector;
|
||||
pviewheight = player->awayviewmobj->z + 20*FRACUNIT;
|
||||
|
@ -8701,6 +8720,13 @@ void P_PlayerThink(player_t *player)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj))
|
||||
{
|
||||
P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid
|
||||
player->awayviewtics = 0; // reset to zero
|
||||
}
|
||||
|
||||
if (player->pflags & PF_GLIDING)
|
||||
{
|
||||
if (player->panim != PA_ABILITY)
|
||||
|
@ -8712,9 +8738,14 @@ void P_PlayerThink(player_t *player)
|
|||
if (player->flashcount)
|
||||
player->flashcount--;
|
||||
|
||||
// By the time P_MoveChaseCamera is called, this might be zero. Do not do it here.
|
||||
//if (player->awayviewtics)
|
||||
// player->awayviewtics--;
|
||||
// Re-fixed by Jimita (11-12-2018)
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
player->awayviewtics--;
|
||||
if (!player->awayviewtics)
|
||||
player->awayviewtics = -1;
|
||||
// The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1.
|
||||
}
|
||||
|
||||
/// \note do this in the cheat code
|
||||
if (player->pflags & PF_NOCLIP)
|
||||
|
@ -9492,8 +9523,8 @@ void P_PlayerAfterThink(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->awayviewtics)
|
||||
player->awayviewtics--;
|
||||
if (player->awayviewtics < 0)
|
||||
player->awayviewtics = 0;
|
||||
|
||||
// spectator invisibility and nogravity.
|
||||
if ((netgame || multiplayer) && player->spectator)
|
||||
|
|
88
src/r_bsp.c
88
src/r_bsp.c
|
@ -403,17 +403,17 @@ static void R_AddLine(seg_t *line)
|
|||
{
|
||||
INT32 x1, x2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
static sector_t tempsec; // ceiling/water hack
|
||||
static sector_t tempsec;
|
||||
|
||||
portalline = false;
|
||||
|
||||
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
|
||||
return;
|
||||
|
||||
// big room fix
|
||||
angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y);
|
||||
angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y);
|
||||
curline = line;
|
||||
portalline = false;
|
||||
|
||||
// OPTIMIZE: quickly reject orthogonal back sides.
|
||||
angle1 = R_PointToAngle(line->v1->x, line->v1->y);
|
||||
angle2 = R_PointToAngle(line->v2->x, line->v2->y);
|
||||
|
||||
// Clip to view edges.
|
||||
span = angle1 - angle2;
|
||||
|
@ -592,69 +592,35 @@ INT32 checkcoord[12][4] =
|
|||
{2, 1, 3, 0}
|
||||
};
|
||||
|
||||
static boolean R_CheckBBox(fixed_t *bspcoord)
|
||||
static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
{
|
||||
INT32 boxpos, sx1, sx2;
|
||||
fixed_t px1, py1, px2, py2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
angle_t angle1, angle2;
|
||||
INT32 sx1, sx2, boxpos;
|
||||
const INT32* check;
|
||||
cliprange_t *start;
|
||||
|
||||
// Find the corners of the box that define the edges from current viewpoint.
|
||||
if (viewx <= bspcoord[BOXLEFT])
|
||||
boxpos = 0;
|
||||
else if (viewx < bspcoord[BOXRIGHT])
|
||||
boxpos = 1;
|
||||
else
|
||||
boxpos = 2;
|
||||
|
||||
if (viewy >= bspcoord[BOXTOP])
|
||||
boxpos |= 0;
|
||||
else if (viewy > bspcoord[BOXBOTTOM])
|
||||
boxpos |= 1<<2;
|
||||
else
|
||||
boxpos |= 2<<2;
|
||||
|
||||
if (boxpos == 5)
|
||||
if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
|
||||
return true;
|
||||
|
||||
px1 = bspcoord[checkcoord[boxpos][0]];
|
||||
py1 = bspcoord[checkcoord[boxpos][1]];
|
||||
px2 = bspcoord[checkcoord[boxpos][2]];
|
||||
py2 = bspcoord[checkcoord[boxpos][3]];
|
||||
check = checkcoord[boxpos];
|
||||
|
||||
// check clip list for an open space
|
||||
angle1 = R_PointToAngle2(viewx>>1, viewy>>1, px1>>1, py1>>1) - viewangle;
|
||||
angle2 = R_PointToAngle2(viewx>>1, viewy>>1, px2>>1, py2>>1) - viewangle;
|
||||
// big room fix
|
||||
angle1 = R_PointToAngleEx(viewx, viewy, bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
|
||||
angle2 = R_PointToAngleEx(viewx, viewy, bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
|
||||
|
||||
span = angle1 - angle2;
|
||||
|
||||
// Sitting on a line?
|
||||
if (span >= ANGLE_180)
|
||||
return true;
|
||||
|
||||
tspan = angle1 + clipangle;
|
||||
|
||||
if (tspan > doubleclipangle)
|
||||
if ((signed)angle1 < (signed)angle2)
|
||||
{
|
||||
tspan -= doubleclipangle;
|
||||
|
||||
// Totally off the left edge?
|
||||
if (tspan >= span)
|
||||
return false;
|
||||
|
||||
angle1 = clipangle;
|
||||
if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270))
|
||||
angle1 = ANGLE_180-1;
|
||||
else
|
||||
angle2 = ANGLE_180;
|
||||
}
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > doubleclipangle)
|
||||
{
|
||||
tspan -= doubleclipangle;
|
||||
|
||||
// Totally off the left edge?
|
||||
if (tspan >= span)
|
||||
return false;
|
||||
|
||||
angle2 = -(signed)clipangle;
|
||||
}
|
||||
if ((signed)angle2 >= (signed)clipangle) return false;
|
||||
if ((signed)angle1 <= -(signed)clipangle) return false;
|
||||
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle;
|
||||
if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle;
|
||||
|
||||
// Find the first clippost that touches the source post (adjacent pixels are touching).
|
||||
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
|
@ -663,9 +629,7 @@ static boolean R_CheckBBox(fixed_t *bspcoord)
|
|||
sx2 = viewangletox[angle2];
|
||||
|
||||
// Does not cross a pixel.
|
||||
if (sx1 == sx2)
|
||||
return false;
|
||||
sx2--;
|
||||
if (sx1 >= sx2) return false;
|
||||
|
||||
start = solidsegs;
|
||||
while (start->last < sx2)
|
||||
|
@ -1119,7 +1083,6 @@ static void R_Subsector(size_t num)
|
|||
}
|
||||
|
||||
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
|
||||
light = 0;
|
||||
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
|
||||
polysec->lightlevel, xoff, yoff,
|
||||
polysec->floorpic_angle-po->angle,
|
||||
|
@ -1167,7 +1130,6 @@ static void R_Subsector(size_t num)
|
|||
}
|
||||
|
||||
light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight);
|
||||
light = 0;
|
||||
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
|
||||
polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
|
||||
NULL, NULL
|
||||
|
|
|
@ -1220,7 +1220,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
|
|||
continue;
|
||||
if (maskcolor == extra_colormaps[i].maskcolor
|
||||
&& fadecolor == extra_colormaps[i].fadecolor
|
||||
&& (float)maskamt == (float)extra_colormaps[i].maskamt
|
||||
&& fabs(maskamt - extra_colormaps[i].maskamt) < DBL_EPSILON
|
||||
&& fadestart == extra_colormaps[i].fadestart
|
||||
&& fadeend == extra_colormaps[i].fadeend
|
||||
&& fog == extra_colormaps[i].fog)
|
||||
|
|
|
@ -573,6 +573,7 @@ typedef struct seg_s
|
|||
sector_t *frontsector;
|
||||
sector_t *backsector;
|
||||
|
||||
fixed_t length; // precalculated seg length
|
||||
#ifdef HWRENDER
|
||||
// new pointers so that AdjustSegs doesn't mess with v1/v2
|
||||
void *pv1; // polyvertex_t
|
||||
|
|
312
src/r_main.c
312
src/r_main.c
|
@ -355,6 +355,29 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y)
|
|||
return R_PointToDist2(viewx, viewy, x, y);
|
||||
}
|
||||
|
||||
angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
|
||||
{
|
||||
INT64 dx = x1-x2;
|
||||
INT64 dy = y1-y2;
|
||||
if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX)
|
||||
{
|
||||
x1 = (int)(dx / 2 + x2);
|
||||
y1 = (int)(dy / 2 + y2);
|
||||
}
|
||||
return (y1 -= y2, (x1 -= x2) || y1) ?
|
||||
x1 >= 0 ?
|
||||
y1 >= 0 ?
|
||||
(x1 > y1) ? tantoangle[SlopeDivEx(y1,x1)] : // octant 0
|
||||
ANGLE_90-tantoangle[SlopeDivEx(x1,y1)] : // octant 1
|
||||
x1 > (y1 = -y1) ? 0-tantoangle[SlopeDivEx(y1,x1)] : // octant 8
|
||||
ANGLE_270+tantoangle[SlopeDivEx(x1,y1)] : // octant 7
|
||||
y1 >= 0 ? (x1 = -x1) > y1 ? ANGLE_180-tantoangle[SlopeDivEx(y1,x1)] : // octant 3
|
||||
ANGLE_90 + tantoangle[SlopeDivEx(x1,y1)] : // octant 2
|
||||
(x1 = -x1) > (y1 = -y1) ? ANGLE_180+tantoangle[SlopeDivEx(y1,x1)] : // octant 4
|
||||
ANGLE_270-tantoangle[SlopeDivEx(x1,y1)] : // octant 5
|
||||
0;
|
||||
}
|
||||
|
||||
//
|
||||
// R_ScaleFromGlobalAngle
|
||||
// Returns the texture mapping scale for the current line (horizontal span)
|
||||
|
@ -551,13 +574,11 @@ void R_SetViewSize(void)
|
|||
//
|
||||
void R_ExecuteSetViewSize(void)
|
||||
{
|
||||
fixed_t cosadj;
|
||||
fixed_t dy;
|
||||
INT32 i;
|
||||
INT32 j;
|
||||
INT32 level;
|
||||
INT32 startmapl;
|
||||
INT32 aspectx; //added : 02-02-98 : for aspect ratio calc. below...
|
||||
|
||||
setsizeneeded = false;
|
||||
|
||||
|
@ -597,31 +618,22 @@ void R_ExecuteSetViewSize(void)
|
|||
for (i = 0; i < viewwidth; i++)
|
||||
screenheightarray[i] = (INT16)viewheight;
|
||||
|
||||
// setup sky scaling (uses pspriteyscale)
|
||||
// setup sky scaling
|
||||
R_SetSkyScale();
|
||||
|
||||
// planes
|
||||
//aspectx = (((vid.height*centerx*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width);
|
||||
aspectx = centerx;
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// this is only used for planes rendering in software mode
|
||||
j = viewheight*8;
|
||||
j = viewheight*16;
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
dy = ((i - viewheight*2)<<FRACBITS) + FRACUNIT/2;
|
||||
dy = ((i - viewheight*8)<<FRACBITS) + FRACUNIT/2;
|
||||
dy = abs(dy);
|
||||
yslopetab[i] = FixedDiv(aspectx*FRACUNIT, dy);
|
||||
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < viewwidth; i++)
|
||||
{
|
||||
cosadj = abs(FINECOSINE(xtoviewangle[i]>>ANGLETOFINESHIFT));
|
||||
distscale[i] = FixedDiv(FRACUNIT, cosadj);
|
||||
}
|
||||
|
||||
memset(scalelight, 0xFF, sizeof(scalelight));
|
||||
|
||||
// Calculate the light levels to use for each level/scale combination.
|
||||
|
@ -734,9 +746,136 @@ static mobj_t *viewmobj;
|
|||
// WARNING: a should be unsigned but to add with 2048, it isn't!
|
||||
#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS)
|
||||
|
||||
void R_SkyboxFrame(player_t *player)
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
static void R_SetupFreelook(void)
|
||||
{
|
||||
INT32 dy = 0;
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH;
|
||||
yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
|
||||
}
|
||||
centery = (viewheight/2) + dy;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
}
|
||||
|
||||
#undef AIMINGTODY
|
||||
|
||||
void R_SetupFrame(player_t *player, boolean skybox)
|
||||
{
|
||||
camera_t *thiscam;
|
||||
boolean chasecam = false;
|
||||
|
||||
if (splitscreen && player == &players[secondarydisplayplayer]
|
||||
&& player != &players[consoleplayer])
|
||||
{
|
||||
thiscam = &camera2;
|
||||
chasecam = (cv_chasecam2.value != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
thiscam = &camera;
|
||||
chasecam = (cv_chasecam.value != 0);
|
||||
}
|
||||
|
||||
if (player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)
|
||||
chasecam = true; // force chasecam on
|
||||
else if (player->spectator) // no spectator chasecam
|
||||
chasecam = false; // force chasecam off
|
||||
|
||||
if (chasecam && !thiscam->chase)
|
||||
{
|
||||
P_ResetCamera(player, thiscam);
|
||||
thiscam->chase = true;
|
||||
}
|
||||
else if (!chasecam)
|
||||
thiscam->chase = false;
|
||||
|
||||
viewsky = !skybox;
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
// cut-away view stuff
|
||||
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
|
||||
I_Assert(viewmobj != NULL);
|
||||
viewz = viewmobj->z + 20*FRACUNIT;
|
||||
aimingangle = player->awayviewaiming;
|
||||
viewangle = viewmobj->angle;
|
||||
}
|
||||
else if (!player->spectator && chasecam)
|
||||
// use outside cam view
|
||||
{
|
||||
viewmobj = NULL;
|
||||
viewz = thiscam->z + (thiscam->height>>1);
|
||||
aimingangle = thiscam->aiming;
|
||||
viewangle = thiscam->angle;
|
||||
}
|
||||
else
|
||||
// use the player's eyes view
|
||||
{
|
||||
viewz = player->viewz;
|
||||
|
||||
viewmobj = player->mo;
|
||||
I_Assert(viewmobj != NULL);
|
||||
|
||||
aimingangle = player->aiming;
|
||||
viewangle = viewmobj->angle;
|
||||
|
||||
if (!demoplayback && player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
viewangle = localangle; // WARNING: camera uses this
|
||||
aimingangle = localaiming;
|
||||
}
|
||||
else if (player == &players[secondarydisplayplayer])
|
||||
{
|
||||
viewangle = localangle2;
|
||||
aimingangle = localaiming2;
|
||||
}
|
||||
}
|
||||
}
|
||||
viewz += quake.z;
|
||||
|
||||
viewplayer = player;
|
||||
|
||||
if (chasecam && !player->awayviewtics && !player->spectator)
|
||||
{
|
||||
viewx = thiscam->x;
|
||||
viewy = thiscam->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
|
||||
if (thiscam->subsector)
|
||||
viewsector = thiscam->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewx = viewmobj->x;
|
||||
viewy = viewmobj->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
|
||||
if (viewmobj->subsector)
|
||||
viewsector = viewmobj->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
}
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_SetupFreelook();
|
||||
}
|
||||
|
||||
void R_SkyboxFrame(player_t *player)
|
||||
{
|
||||
camera_t *thiscam;
|
||||
|
||||
if (splitscreen && player == &players[secondarydisplayplayer]
|
||||
|
@ -950,146 +1089,7 @@ void R_SkyboxFrame(player_t *player)
|
|||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 8*viewheight, thanks MPC aka Jimita for finding this out)
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
|
||||
dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH;
|
||||
|
||||
yslope = &yslopetab[(3*viewheight/2) - dy];
|
||||
}
|
||||
centery = (viewheight/2) + dy;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
}
|
||||
|
||||
void R_SetupFrame(player_t *player, boolean skybox)
|
||||
{
|
||||
INT32 dy = 0;
|
||||
camera_t *thiscam;
|
||||
boolean chasecam = false;
|
||||
|
||||
if (splitscreen && player == &players[secondarydisplayplayer]
|
||||
&& player != &players[consoleplayer])
|
||||
{
|
||||
thiscam = &camera2;
|
||||
chasecam = (cv_chasecam2.value != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
thiscam = &camera;
|
||||
chasecam = (cv_chasecam.value != 0);
|
||||
}
|
||||
|
||||
if (player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)
|
||||
chasecam = true; // force chasecam on
|
||||
else if (player->spectator) // no spectator chasecam
|
||||
chasecam = false; // force chasecam off
|
||||
|
||||
if (chasecam && !thiscam->chase)
|
||||
{
|
||||
P_ResetCamera(player, thiscam);
|
||||
thiscam->chase = true;
|
||||
}
|
||||
else if (!chasecam)
|
||||
thiscam->chase = false;
|
||||
|
||||
viewsky = !skybox;
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
// cut-away view stuff
|
||||
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
|
||||
I_Assert(viewmobj != NULL);
|
||||
viewz = viewmobj->z + 20*FRACUNIT;
|
||||
aimingangle = player->awayviewaiming;
|
||||
viewangle = viewmobj->angle;
|
||||
}
|
||||
else if (!player->spectator && chasecam)
|
||||
// use outside cam view
|
||||
{
|
||||
viewmobj = NULL;
|
||||
viewz = thiscam->z + (thiscam->height>>1);
|
||||
aimingangle = thiscam->aiming;
|
||||
viewangle = thiscam->angle;
|
||||
}
|
||||
else
|
||||
// use the player's eyes view
|
||||
{
|
||||
viewz = player->viewz;
|
||||
|
||||
viewmobj = player->mo;
|
||||
I_Assert(viewmobj != NULL);
|
||||
|
||||
aimingangle = player->aiming;
|
||||
viewangle = viewmobj->angle;
|
||||
|
||||
if (!demoplayback && player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
viewangle = localangle; // WARNING: camera uses this
|
||||
aimingangle = localaiming;
|
||||
}
|
||||
else if (player == &players[secondarydisplayplayer])
|
||||
{
|
||||
viewangle = localangle2;
|
||||
aimingangle = localaiming2;
|
||||
}
|
||||
}
|
||||
}
|
||||
viewz += quake.z;
|
||||
|
||||
viewplayer = player;
|
||||
|
||||
if (chasecam && !player->awayviewtics && !player->spectator)
|
||||
{
|
||||
viewx = thiscam->x;
|
||||
viewy = thiscam->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
|
||||
if (thiscam->subsector)
|
||||
viewsector = thiscam->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewx = viewmobj->x;
|
||||
viewy = viewmobj->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
|
||||
if (viewmobj->subsector)
|
||||
viewsector = viewmobj->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
}
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 8*viewheight, thanks MPC aka Jimita for finding this out)
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
|
||||
dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH;
|
||||
|
||||
yslope = &yslopetab[(3*viewheight/2) - dy];
|
||||
}
|
||||
centery = (viewheight/2) + dy;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
R_SetupFreelook();
|
||||
}
|
||||
|
||||
#define ANGLED_PORTALS
|
||||
|
|
|
@ -58,6 +58,7 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
|
|||
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
|
||||
angle_t R_PointToAngle(fixed_t x, fixed_t y);
|
||||
angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
|
||||
angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1);
|
||||
fixed_t R_PointToDist(fixed_t x, fixed_t y);
|
||||
fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "doomdef.h"
|
||||
#include "console.h"
|
||||
#include "g_game.h"
|
||||
#include "p_setup.h" // levelflats
|
||||
#include "p_slopes.h"
|
||||
#include "r_data.h"
|
||||
#include "r_local.h"
|
||||
#include "r_state.h"
|
||||
|
@ -26,9 +28,12 @@
|
|||
#include "z_zone.h"
|
||||
#include "p_tick.h"
|
||||
|
||||
#include "p_setup.h" // levelflats
|
||||
|
||||
#include "p_slopes.h"
|
||||
#ifdef TIMING
|
||||
#include "p5prof.h"
|
||||
INT64 mycount;
|
||||
INT64 mytotal = 0;
|
||||
UINT32 nombre = 100000;
|
||||
#endif
|
||||
|
||||
//
|
||||
// opening
|
||||
|
@ -51,7 +56,7 @@ visplane_t *floorplane;
|
|||
visplane_t *ceilingplane;
|
||||
static visplane_t *currentplane;
|
||||
|
||||
planemgr_t ffloor[MAXFFLOORS];
|
||||
visffloor_t ffloor[MAXFFLOORS];
|
||||
INT32 numffloors;
|
||||
|
||||
//SoM: 3/23/2000: Boom visplane hashing routine.
|
||||
|
@ -89,10 +94,9 @@ static fixed_t planeheight;
|
|||
// (this is to calculate yslopes only when really needed)
|
||||
// (when mouselookin', yslope is moving into yslopetab)
|
||||
// Check R_SetupFrame, R_SetViewSize for more...
|
||||
fixed_t yslopetab[MAXVIDHEIGHT*8];
|
||||
fixed_t yslopetab[MAXVIDHEIGHT*16];
|
||||
fixed_t *yslope;
|
||||
|
||||
fixed_t distscale[MAXVIDWIDTH];
|
||||
fixed_t basexscale, baseyscale;
|
||||
|
||||
fixed_t cachedheight[MAXVIDHEIGHT];
|
||||
|
@ -155,34 +159,19 @@ void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//profile stuff ---------------------------------------------------------
|
||||
//#define TIMING
|
||||
#ifdef TIMING
|
||||
#include "p5prof.h"
|
||||
INT64 mycount;
|
||||
INT64 mytotal = 0;
|
||||
UINT32 nombre = 100000;
|
||||
#endif
|
||||
//profile stuff ---------------------------------------------------------
|
||||
|
||||
|
||||
//
|
||||
// R_MapPlane
|
||||
//
|
||||
// Uses global vars:
|
||||
// planeheight
|
||||
// ds_source
|
||||
// basexscale
|
||||
// baseyscale
|
||||
// centerx
|
||||
// viewx
|
||||
// viewy
|
||||
// xoffs
|
||||
// yoffs
|
||||
// planeangle
|
||||
//
|
||||
// BASIC PRIMITIVE
|
||||
//
|
||||
// viewsin
|
||||
// viewcos
|
||||
// viewheight
|
||||
|
||||
#ifndef NOWATER
|
||||
static INT32 bgofs;
|
||||
static INT32 wtofs=0;
|
||||
|
@ -190,10 +179,6 @@ static INT32 waterofs;
|
|||
static boolean itswater;
|
||||
#endif
|
||||
|
||||
#ifdef __mips__
|
||||
//#define NOWATER
|
||||
#endif
|
||||
|
||||
#ifndef NOWATER
|
||||
static void R_DrawTranslucentWaterSpan_8(void)
|
||||
{
|
||||
|
@ -275,8 +260,8 @@ static void R_DrawTranslucentWaterSpan_8(void)
|
|||
|
||||
void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
||||
{
|
||||
angle_t angle;
|
||||
fixed_t distance, length;
|
||||
angle_t angle, planecos, planesin;
|
||||
fixed_t distance, span;
|
||||
size_t pindex;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
|
@ -287,12 +272,22 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
// from r_splats's R_RenderFloorSplat
|
||||
if (x1 >= vid.width) x1 = vid.width - 1;
|
||||
|
||||
angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT;
|
||||
planecos = FINECOSINE(angle);
|
||||
planesin = FINESINE(angle);
|
||||
|
||||
if (planeheight != cachedheight[y])
|
||||
{
|
||||
cachedheight[y] = planeheight;
|
||||
distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
|
||||
ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale);
|
||||
ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale);
|
||||
|
||||
if ((span = abs(centery-y)))
|
||||
{
|
||||
ds_xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span;
|
||||
ds_ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -301,13 +296,8 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
ds_ystep = cachedystep[y];
|
||||
}
|
||||
|
||||
length = FixedMul (distance,distscale[x1]);
|
||||
angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
|
||||
/// \note Wouldn't it be faster just to add viewx and viewy
|
||||
// to the plane's x/yoffs anyway??
|
||||
|
||||
ds_xfrac = FixedMul(FINECOSINE(angle), length) + xoffs;
|
||||
ds_yfrac = yoffs - FixedMul(FINESINE(angle), length);
|
||||
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep;
|
||||
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep;
|
||||
|
||||
#ifndef NOWATER
|
||||
if (itswater)
|
||||
|
@ -315,8 +305,9 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
const INT32 yay = (wtofs + (distance>>9) ) & 8191;
|
||||
// ripples da water texture
|
||||
bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS;
|
||||
angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
|
||||
|
||||
angle = (angle + 2048) & 8191; //90<EFBFBD>
|
||||
angle = (angle + 2048) & 8191; // 90 degrees
|
||||
ds_xfrac += FixedMul(FINECOSINE(angle), (bgofs<<FRACBITS));
|
||||
ds_yfrac += FixedMul(FINESINE(angle), (bgofs<<FRACBITS));
|
||||
|
||||
|
@ -328,7 +319,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
#endif
|
||||
|
||||
pindex = distance >> LIGHTZSHIFT;
|
||||
|
||||
if (pindex >= MAXLIGHTZ)
|
||||
pindex = MAXLIGHTZ - 1;
|
||||
|
||||
|
@ -365,8 +355,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
// R_ClearPlanes
|
||||
// At begining of frame.
|
||||
//
|
||||
// NOTE: Uses con_clipviewtop, so that when console is on,
|
||||
// we don't draw the part of the view hidden under the console.
|
||||
void R_ClearPlanes(void)
|
||||
{
|
||||
INT32 i, p;
|
||||
|
@ -376,12 +364,12 @@ void R_ClearPlanes(void)
|
|||
for (i = 0; i < viewwidth; i++)
|
||||
{
|
||||
floorclip[i] = (INT16)viewheight;
|
||||
ceilingclip[i] = (INT16)con_clipviewtop;
|
||||
ceilingclip[i] = -1;
|
||||
frontscale[i] = INT32_MAX;
|
||||
for (p = 0; p < MAXFFLOORS; p++)
|
||||
{
|
||||
ffloor[p].f_clip[i] = (INT16)viewheight;
|
||||
ffloor[p].c_clip[i] = (INT16)con_clipviewtop;
|
||||
ffloor[p].c_clip[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
//
|
||||
// Now what is a visplane, anyway?
|
||||
// Simple: kinda floor/ceiling polygon optimised for SRB2 rendering.
|
||||
// 7764 bytes! (for win32, anyway)
|
||||
//
|
||||
typedef struct visplane_s
|
||||
{
|
||||
|
@ -39,25 +38,12 @@ typedef struct visplane_s
|
|||
extracolormap_t *extra_colormap;
|
||||
|
||||
// leave pads for [minx-1]/[maxx+1]
|
||||
|
||||
// words sucks .. should get rid of that.. but eats memory
|
||||
// THIS IS UNSIGNED! VERY IMPORTANT!!
|
||||
UINT16 pad1;
|
||||
UINT16 top[MAXVIDWIDTH];
|
||||
UINT16 pad2;
|
||||
UINT16 pad3;
|
||||
UINT16 bottom[MAXVIDWIDTH];
|
||||
UINT16 pad4;
|
||||
|
||||
UINT16 padtopstart, top[MAXVIDWIDTH], padtopend;
|
||||
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
|
||||
INT32 high, low; // R_PlaneBounds should set these.
|
||||
|
||||
fixed_t xoffs, yoffs; // Scrolling flats.
|
||||
|
||||
// SoM: frontscale should be stored in the first seg of the subsector
|
||||
// where the planes themselves are stored. I'm doing this now because
|
||||
// the old way caused trouble with the drawseg array was re-sized.
|
||||
INT32 scaleseg;
|
||||
|
||||
struct ffloor_s *ffloor;
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
polyobj_t *polyobj;
|
||||
|
@ -75,17 +61,15 @@ extern INT16 *lastopening, *openings;
|
|||
extern size_t maxopenings;
|
||||
|
||||
extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
|
||||
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*8];
|
||||
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16];
|
||||
extern fixed_t cachedheight[MAXVIDHEIGHT];
|
||||
extern fixed_t cacheddistance[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedxstep[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedystep[MAXVIDHEIGHT];
|
||||
extern fixed_t basexscale, baseyscale;
|
||||
|
||||
extern lighttable_t **planezlight;
|
||||
|
||||
extern fixed_t *yslope;
|
||||
extern fixed_t distscale[MAXVIDWIDTH];
|
||||
extern lighttable_t **planezlight;
|
||||
|
||||
void R_InitPlanes(void);
|
||||
void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale);
|
||||
|
@ -134,8 +118,8 @@ typedef struct planemgr_s
|
|||
#ifdef POLYOBJECTS_PLANES
|
||||
polyobj_t *polyobj;
|
||||
#endif
|
||||
} planemgr_t;
|
||||
} visffloor_t;
|
||||
|
||||
extern planemgr_t ffloor[MAXFFLOORS];
|
||||
extern visffloor_t ffloor[MAXFFLOORS];
|
||||
extern INT32 numffloors;
|
||||
#endif
|
||||
|
|
89
src/r_segs.c
89
src/r_segs.c
|
@ -1344,24 +1344,12 @@ static void R_RenderSegLoop (void)
|
|||
|
||||
if (markfloor)
|
||||
{
|
||||
#if 0 // Old Doom Legacy code
|
||||
bottom = floorclip[rw_x]-1;
|
||||
if (top <= ceilingclip[rw_x])
|
||||
top = ceilingclip[rw_x]+1;
|
||||
if (top <= bottom && floorplane)
|
||||
{
|
||||
floorplane->top[rw_x] = (INT16)top;
|
||||
floorplane->bottom[rw_x] = (INT16)bottom;
|
||||
}
|
||||
#else // Spiffy new PRBoom code
|
||||
top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
|
||||
|
||||
top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
|
||||
if (++top <= bottom && floorplane)
|
||||
{
|
||||
floorplane->top[rw_x] = (INT16)top;
|
||||
floorplane->bottom[rw_x] = (INT16)bottom;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (numffloors)
|
||||
|
@ -1645,26 +1633,11 @@ static void R_RenderSegLoop (void)
|
|||
}
|
||||
|
||||
for (i = 0; i < numffloors; i++)
|
||||
{
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
ffloor[i].f_frac += ffloor[i].f_step;
|
||||
}
|
||||
|
||||
for (i = 0; i < numbackffloors; i++)
|
||||
{
|
||||
INT32 y_w;
|
||||
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
|
||||
continue;
|
||||
#endif
|
||||
y_w = ffloor[i].b_frac >> HEIGHTBITS;
|
||||
|
||||
ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)(y_w & 0xFFFF);
|
||||
ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF);
|
||||
ffloor[i].b_frac += ffloor[i].b_step;
|
||||
}
|
||||
|
||||
|
@ -1674,6 +1647,23 @@ static void R_RenderSegLoop (void)
|
|||
}
|
||||
}
|
||||
|
||||
// Uses precalculated seg->length
|
||||
static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
|
||||
{
|
||||
if (!seg->linedef->dy)
|
||||
return llabs(y2 - seg->v1->y);
|
||||
else if (!seg->linedef->dx)
|
||||
return llabs(x2 - seg->v1->x);
|
||||
else
|
||||
{
|
||||
INT64 dx = (seg->v2->x)-(seg->v1->x);
|
||||
INT64 dy = (seg->v2->y)-(seg->v1->y);
|
||||
INT64 vdx = x2-(seg->v1->x);
|
||||
INT64 vdy = y2-(seg->v1->y);
|
||||
return ((dy*vdx)-(dx*vdy))/(seg->length);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_StoreWallRange
|
||||
// A wall segment will be drawn
|
||||
|
@ -1684,6 +1674,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
fixed_t hyp;
|
||||
fixed_t sineval;
|
||||
angle_t distangle, offsetangle;
|
||||
boolean longboi;
|
||||
#ifndef ESLOPE
|
||||
fixed_t vtop;
|
||||
#endif
|
||||
|
@ -1729,10 +1720,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
offsetangle = ANGLE_90;
|
||||
|
||||
distangle = ANGLE_90 - offsetangle;
|
||||
hyp = R_PointToDist (curline->v1->x, curline->v1->y);
|
||||
sineval = FINESINE(distangle>>ANGLETOFINESHIFT);
|
||||
rw_distance = FixedMul (hyp, sineval);
|
||||
|
||||
hyp = R_PointToDist(curline->v1->x, curline->v1->y);
|
||||
rw_distance = FixedMul(hyp, sineval);
|
||||
longboi = (hyp >= INT32_MAX);
|
||||
|
||||
// big room fix
|
||||
if (longboi)
|
||||
rw_distance = (fixed_t)R_CalcSegDist(curline,viewx,viewy);
|
||||
|
||||
ds_p->x1 = rw_x = start;
|
||||
ds_p->x2 = stop;
|
||||
|
@ -2589,8 +2585,18 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
if (offsetangle > ANGLE_90)
|
||||
offsetangle = ANGLE_90;
|
||||
|
||||
sineval = FINESINE(offsetangle >>ANGLETOFINESHIFT);
|
||||
rw_offset = FixedMul (hyp, sineval);
|
||||
sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT);
|
||||
rw_offset = FixedMul(hyp, sineval);
|
||||
|
||||
// big room fix
|
||||
if (longboi)
|
||||
{
|
||||
INT64 dx = (curline->v2->x)-(curline->v1->x);
|
||||
INT64 dy = (curline->v2->y)-(curline->v1->y);
|
||||
INT64 vdx = viewx-(curline->v1->x);
|
||||
INT64 vdy = viewy-(curline->v1->y);
|
||||
rw_offset = ((dx*vdx-dy*vdy))/(curline->length);
|
||||
}
|
||||
|
||||
if (rw_normalangle-rw_angle1 < ANGLE_180)
|
||||
rw_offset = -rw_offset;
|
||||
|
@ -2775,11 +2781,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
{
|
||||
for (i = 0; i < numffloors; i++)
|
||||
{
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
ffloor[i].f_pos >>= 4;
|
||||
#ifdef ESLOPE
|
||||
ffloor[i].f_pos_slope >>= 4;
|
||||
|
@ -3060,7 +3061,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
if (ceilingplane) //SoM: 3/29/2000: Check for null ceiling planes
|
||||
ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
|
||||
else
|
||||
markceiling = 0;
|
||||
markceiling = false;
|
||||
|
||||
// Don't render the ceiling again when rendering polyobjects
|
||||
if (curline->polyseg)
|
||||
markceiling = false;
|
||||
}
|
||||
|
||||
// get a new or use the same visplane
|
||||
|
@ -3069,7 +3074,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
if (floorplane) //SoM: 3/29/2000: Check for null planes
|
||||
floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
|
||||
else
|
||||
markfloor = 0;
|
||||
markfloor = false;
|
||||
|
||||
// Don't render the floor again when rendering polyobjects
|
||||
if (curline->polyseg)
|
||||
markfloor = false;
|
||||
}
|
||||
|
||||
ds_p->numffloorplanes = 0;
|
||||
|
|
|
@ -365,9 +365,8 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe
|
|||
#else
|
||||
lighttable_t **planezlight;
|
||||
fixed_t planeheight;
|
||||
angle_t angle;
|
||||
fixed_t distance;
|
||||
fixed_t length;
|
||||
angle_t angle, planecos, planesin;
|
||||
fixed_t distance, span;
|
||||
size_t indexr;
|
||||
INT32 light;
|
||||
#endif
|
||||
|
@ -473,12 +472,22 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe
|
|||
if (x2 >= vid.width)
|
||||
x2 = vid.width - 1;
|
||||
|
||||
angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT;
|
||||
planecos = FINECOSINE(angle);
|
||||
planesin = FINESINE(angle);
|
||||
|
||||
if (planeheight != cachedheight[y])
|
||||
{
|
||||
cachedheight[y] = planeheight;
|
||||
distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
|
||||
ds_xstep = cachedxstep[y] = FixedMul(distance,basexscale);
|
||||
ds_ystep = cachedystep[y] = FixedMul(distance,baseyscale);
|
||||
|
||||
if ((span = abs(centery-y)))
|
||||
{
|
||||
ds_xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span;
|
||||
ds_ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -486,10 +495,9 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe
|
|||
ds_xstep = cachedxstep[y];
|
||||
ds_ystep = cachedystep[y];
|
||||
}
|
||||
length = FixedMul(distance, distscale[x1]);
|
||||
angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
|
||||
ds_xfrac = viewx + FixedMul(FINECOSINE(angle), length);
|
||||
ds_yfrac = -viewy - FixedMul(FINESINE(angle), length);
|
||||
|
||||
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep;
|
||||
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep;
|
||||
ds_xfrac -= offsetx;
|
||||
ds_yfrac += offsety;
|
||||
|
||||
|
|
|
@ -1733,7 +1733,7 @@ static void R_CreateDrawNodes(void)
|
|||
plane = ds->curline->polyseg->visplane;
|
||||
R_PlaneBounds(plane);
|
||||
|
||||
if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low)
|
||||
if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low)
|
||||
;
|
||||
else {
|
||||
// Put it in!
|
||||
|
@ -1762,7 +1762,7 @@ static void R_CreateDrawNodes(void)
|
|||
plane = ds->ffloorplanes[p];
|
||||
R_PlaneBounds(plane);
|
||||
|
||||
if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low || plane->polyobj)
|
||||
if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low || plane->polyobj)
|
||||
{
|
||||
ds->ffloorplanes[p] = NULL;
|
||||
continue;
|
||||
|
@ -1799,7 +1799,7 @@ static void R_CreateDrawNodes(void)
|
|||
plane = PolyObjects[i].visplane;
|
||||
R_PlaneBounds(plane);
|
||||
|
||||
if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low)
|
||||
if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low)
|
||||
{
|
||||
PolyObjects[i].visplane = NULL;
|
||||
continue;
|
||||
|
|
|
@ -219,6 +219,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
|
|||
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead
|
||||
return cn - 'A';
|
||||
#else
|
||||
if (cn >= 'A' && cn <= 'Z') return cn - 'A';
|
||||
|
|
|
@ -309,14 +309,6 @@ void SCR_Recalc(void)
|
|||
if (automapactive)
|
||||
AM_Stop();
|
||||
|
||||
// r_plane stuff: visplanes, openings, floorclip, ceilingclip, spanstart,
|
||||
// spanstop, yslope, distscale, cachedheight, cacheddistance,
|
||||
// cachedxstep, cachedystep
|
||||
// -> allocated at the maximum vidsize, static.
|
||||
|
||||
// r_main: xtoviewangle, allocated at the maximum size.
|
||||
// r_things: negonearray, screenheightarray allocated max. size.
|
||||
|
||||
// set the screen[x] ptrs on the new vidbuffers
|
||||
V_Init();
|
||||
|
||||
|
|
|
@ -278,13 +278,13 @@ if(${SDL2_FOUND})
|
|||
if (${CMAKE_GENERATOR} STREQUAL "MinGW Makefiles")
|
||||
if(${SRB2_SYSTEM_BITS} EQUAL 64)
|
||||
find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}"
|
||||
HINTS ${CMAKE_SOURCE_DIR}/Bin/Resources/x86_64
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/x86_64
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/bin
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/x86_64-w64-mingw32/bin
|
||||
)
|
||||
else()
|
||||
find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}"
|
||||
HINTS ${CMAKE_SOURCE_DIR}/Bin/Resources/i686
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/i686
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/bin
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/i686-w64-mingw32/bin
|
||||
)
|
||||
|
@ -292,13 +292,13 @@ if(${SDL2_FOUND})
|
|||
else()
|
||||
if(${SRB2_SYSTEM_BITS} EQUAL 64)
|
||||
find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}"
|
||||
HINTS ${CMAKE_SOURCE_DIR}/Bin/Resources/x86_64
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/x86_64
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x64
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x64
|
||||
)
|
||||
else()
|
||||
find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}"
|
||||
HINTS ${CMAKE_SOURCE_DIR}/Bin/Resources/i686
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/i686
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x86
|
||||
HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x86
|
||||
)
|
||||
|
|
|
@ -200,7 +200,10 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
|
|||
}
|
||||
// Reposition window only in windowed mode
|
||||
SDL_SetWindowSize(window, width, height);
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
SDL_SetWindowPosition(window,
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -357,6 +360,7 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
|
|||
|
||||
static void SDLdoUngrabMouse(void)
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_SetWindowGrab(window, SDL_FALSE);
|
||||
wrapmouseok = SDL_FALSE;
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
@ -366,6 +370,7 @@ void SDLforceUngrabMouse(void)
|
|||
{
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO && window != NULL)
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_SetWindowGrab(window, SDL_FALSE);
|
||||
wrapmouseok = SDL_FALSE;
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
@ -1547,9 +1552,18 @@ void I_StartupGraphics(void)
|
|||
realheight = (Uint16)vid.height;
|
||||
|
||||
VID_Command_Info_f();
|
||||
if (!disable_mouse) SDL_ShowCursor(SDL_DISABLE);
|
||||
SDLdoUngrabMouse();
|
||||
|
||||
SDL_RaiseWindow(window);
|
||||
|
||||
if (mousegrabok && !disable_mouse)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
wrapmouseok = SDL_TRUE;
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
}
|
||||
|
||||
graphics_started = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1214,7 +1214,7 @@
|
|||
C01FCF4B08A954540054247B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CURRENT_PROJECT_VERSION = 2.1.21;
|
||||
CURRENT_PROJECT_VERSION = 2.1.23;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
NORMALSRB2,
|
||||
|
@ -1226,7 +1226,7 @@
|
|||
C01FCF4C08A954540054247B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CURRENT_PROJECT_VERSION = 2.1.21;
|
||||
CURRENT_PROJECT_VERSION = 2.1.23;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
|
|
@ -92,6 +92,12 @@ void I_StartupSound(void)
|
|||
{
|
||||
I_Assert(!sound_started);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Force DirectSound instead of WASAPI
|
||||
// SDL 2.0.6+ defaults to the latter and it screws up our sound effects
|
||||
SDL_setenv("SDL_AUDIODRIVER", "directsound", 1);
|
||||
#endif
|
||||
|
||||
// EE inits audio first so we're following along.
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO) == SDL_INIT_AUDIO)
|
||||
{
|
||||
|
@ -759,6 +765,7 @@ void I_UnloadSong(void)
|
|||
|
||||
boolean I_PlaySong(boolean looping)
|
||||
{
|
||||
boolean lpz = fpclassify(loop_point) == FP_ZERO;
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
|
@ -772,14 +779,15 @@ boolean I_PlaySong(boolean looping)
|
|||
if (!music)
|
||||
return false;
|
||||
|
||||
if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1)
|
||||
|
||||
if (Mix_PlayMusic(music, looping && lpz ? -1 : 0) == -1)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
Mix_VolumeMusic((UINT32)music_volume*128/31);
|
||||
|
||||
if (loop_point != 0.0f)
|
||||
if (!lpz)
|
||||
Mix_HookMusicFinished(music_loop);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1186,6 +1186,12 @@ void I_StartupSound(void)
|
|||
// Configure sound device
|
||||
CONS_Printf("I_StartupSound:\n");
|
||||
|
||||
#ifdef _WIN32
|
||||
// Force DirectSound instead of WASAPI
|
||||
// SDL 2.0.6+ defaults to the latter and it screws up our sound effects
|
||||
SDL_setenv("SDL_AUDIODRIVER", "directsound", 1);
|
||||
#endif
|
||||
|
||||
// EE inits audio first so we're following along.
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO) == SDL_INIT_AUDIO)
|
||||
CONS_Printf("SDL Audio already started\n");
|
||||
|
|
|
@ -1214,7 +1214,7 @@
|
|||
C01FCF4B08A954540054247B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CURRENT_PROJECT_VERSION = 2.1.21;
|
||||
CURRENT_PROJECT_VERSION = 2.1.23;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
NORMALSRB2,
|
||||
|
@ -1226,7 +1226,7 @@
|
|||
C01FCF4C08A954540054247B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CURRENT_PROJECT_VERSION = 2.1.21;
|
||||
CURRENT_PROJECT_VERSION = 2.1.23;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
|
|
@ -37,6 +37,15 @@ unsigned SlopeDiv(unsigned num, unsigned den)
|
|||
return ans <= SLOPERANGE ? ans : SLOPERANGE;
|
||||
}
|
||||
|
||||
UINT64 SlopeDivEx(unsigned int num, unsigned int den)
|
||||
{
|
||||
UINT64 ans;
|
||||
if (den < 512)
|
||||
return SLOPERANGE;
|
||||
ans = ((UINT64)num<<3)/(den>>8);
|
||||
return ans <= SLOPERANGE ? ans : SLOPERANGE;
|
||||
}
|
||||
|
||||
fixed_t AngleFixed(angle_t af)
|
||||
{
|
||||
angle_t wa = ANGLE_180;
|
||||
|
|
|
@ -83,6 +83,8 @@ extern angle_t tantoangle[SLOPERANGE+1];
|
|||
|
||||
// Utility function, called by R_PointToAngle.
|
||||
FUNCMATH unsigned SlopeDiv(unsigned num, unsigned den);
|
||||
// Only called by R_PointToAngleEx
|
||||
UINT64 SlopeDivEx(unsigned int num, unsigned int den);
|
||||
|
||||
// 360 - angle_t(ANGLE_45) = ANGLE_315
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE angle_t InvAngle(angle_t a)
|
||||
|
|
183
src/v_video.c
183
src/v_video.c
|
@ -841,6 +841,145 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
memset(dest, c, w * vid.bpp);
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
// This is now a function since it's otherwise repeated 2 times and honestly looks retarded:
|
||||
static UINT32 V_GetHWConsBackColor(void)
|
||||
{
|
||||
UINT32 hwcolor;
|
||||
switch (cons_backcolor.value)
|
||||
{
|
||||
case 0: hwcolor = 0xffffff00; break; // White
|
||||
case 1: hwcolor = 0x80808000; break; // Gray
|
||||
case 2: hwcolor = 0xdeb88700; break; // Sepia
|
||||
case 3: hwcolor = 0x40201000; break; // Brown
|
||||
case 4: hwcolor = 0xfa807200; break; // Pink
|
||||
case 5: hwcolor = 0xff69b400; break; // Raspberry
|
||||
case 6: hwcolor = 0xff000000; break; // Red
|
||||
case 7: hwcolor = 0xffd68300; break; // Creamsicle
|
||||
case 8: hwcolor = 0xff800000; break; // Orange
|
||||
case 9: hwcolor = 0xdaa52000; break; // Gold
|
||||
case 10: hwcolor = 0x80800000; break; // Yellow
|
||||
case 11: hwcolor = 0x00ff0000; break; // Emerald
|
||||
case 12: hwcolor = 0x00800000; break; // Green
|
||||
case 13: hwcolor = 0x4080ff00; break; // Cyan
|
||||
case 14: hwcolor = 0x4682b400; break; // Steel
|
||||
case 15: hwcolor = 0x1e90ff00; break; // Periwinkle
|
||||
case 16: hwcolor = 0x0000ff00; break; // Blue
|
||||
case 17: hwcolor = 0xff00ff00; break; // Purple
|
||||
case 18: hwcolor = 0xee82ee00; break; // Lavender
|
||||
// Default green
|
||||
default: hwcolor = 0x00800000; break;
|
||||
}
|
||||
return hwcolor;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// THANK YOU MPC!!!
|
||||
|
||||
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
||||
{
|
||||
UINT8 *dest;
|
||||
INT32 u, v;
|
||||
UINT8 *fadetable;
|
||||
UINT32 alphalevel = 0;
|
||||
|
||||
if (rendermode == render_none)
|
||||
return;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
UINT32 hwcolor = V_GetHWConsBackColor();
|
||||
HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(c & V_NOSCALESTART))
|
||||
{
|
||||
INT32 dupx = vid.dupx, dupy = vid.dupy;
|
||||
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
|
||||
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp);
|
||||
return;
|
||||
}
|
||||
|
||||
x *= dupx;
|
||||
y *= dupy;
|
||||
w *= dupx;
|
||||
h *= dupy;
|
||||
|
||||
// Center it if necessary
|
||||
if (vid.width != BASEVIDWIDTH * dupx)
|
||||
{
|
||||
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
||||
// so center this imaginary screen
|
||||
if (c & V_SNAPTORIGHT)
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx));
|
||||
else if (!(c & V_SNAPTOLEFT))
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
||||
}
|
||||
if (vid.height != BASEVIDHEIGHT * dupy)
|
||||
{
|
||||
// same thing here
|
||||
if (c & V_SNAPTOBOTTOM)
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
||||
else if (!(c & V_SNAPTOTOP))
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (x >= vid.width || y >= vid.height)
|
||||
return; // off the screen
|
||||
if (x < 0) {
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0)
|
||||
return; // zero width/height wouldn't draw anything
|
||||
if (x + w > vid.width)
|
||||
w = vid.width-x;
|
||||
if (y + h > vid.height)
|
||||
h = vid.height-y;
|
||||
|
||||
dest = screens[0] + y*vid.width + x;
|
||||
|
||||
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
|
||||
{
|
||||
if (alphalevel == 13)
|
||||
alphalevel = hudminusalpha[cv_translucenthud.value];
|
||||
else if (alphalevel == 14)
|
||||
alphalevel = 10 - cv_translucenthud.value;
|
||||
else if (alphalevel == 15)
|
||||
alphalevel = hudplusalpha[cv_translucenthud.value];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
return; // invis
|
||||
}
|
||||
|
||||
c &= 255;
|
||||
|
||||
// Jimita (12-04-2018)
|
||||
w = min(w, vid.width);
|
||||
h = min(h, vid.height);
|
||||
fadetable = ((UINT8 *)transtables + ((alphalevel-1)<<FF_TRANSSHIFT) + (c*256));
|
||||
for (v = 0; v < h; v++, dest += vid.width)
|
||||
for (u = 0; u < w; u++)
|
||||
{
|
||||
if (!alphalevel)
|
||||
dest[u] = consolebgmap[dest[u]];
|
||||
else
|
||||
dest[u] = fadetable[consolebgmap[dest[u]]];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Fills a box of pixels using a flat texture as a pattern, scaled to screen size.
|
||||
//
|
||||
|
@ -983,21 +1122,7 @@ void V_DrawFadeConsBack(INT32 plines)
|
|||
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
UINT32 hwcolor;
|
||||
switch (cons_backcolor.value)
|
||||
{
|
||||
case 0: hwcolor = 0xffffff00; break; // White
|
||||
case 1: hwcolor = 0x80808000; break; // Gray
|
||||
case 2: hwcolor = 0x40201000; break; // Brown
|
||||
case 3: hwcolor = 0xff000000; break; // Red
|
||||
case 4: hwcolor = 0xff800000; break; // Orange
|
||||
case 5: hwcolor = 0x80800000; break; // Yellow
|
||||
case 6: hwcolor = 0x00800000; break; // Green
|
||||
case 7: hwcolor = 0x0000ff00; break; // Blue
|
||||
case 8: hwcolor = 0x4080ff00; break; // Cyan
|
||||
// Default green
|
||||
default: hwcolor = 0x00800000; break;
|
||||
}
|
||||
UINT32 hwcolor = V_GetHWConsBackColor();
|
||||
HWR_DrawConsoleBack(hwcolor, plines);
|
||||
return;
|
||||
}
|
||||
|
@ -1012,7 +1137,7 @@ void V_DrawFadeConsBack(INT32 plines)
|
|||
|
||||
// Gets string colormap, used for 0x80 color codes
|
||||
//
|
||||
static const UINT8 *V_GetStringColormap(INT32 colorflags)
|
||||
UINT8 *V_GetStringColormap(INT32 colorflags)
|
||||
{
|
||||
switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT)
|
||||
{
|
||||
|
@ -1061,6 +1186,32 @@ void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed)
|
|||
V_DrawScaledPatch(x, y, flags, hu_font[c]);
|
||||
}
|
||||
|
||||
// Writes a single character for the chat. (draw WHITE if bit 7 set)
|
||||
// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge..
|
||||
//
|
||||
void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap)
|
||||
{
|
||||
INT32 w, flags;
|
||||
//const UINT8 *colormap = V_GetStringColormap(c);
|
||||
|
||||
flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
|
||||
c &= 0x7f;
|
||||
if (lowercaseallowed)
|
||||
c -= HU_FONTSTART;
|
||||
else
|
||||
c = toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
||||
return;
|
||||
|
||||
w = (vid.width < 640 ) ? (SHORT(hu_font[c]->width)/2) : (SHORT(hu_font[c]->width)); // use normal sized characters if we're using a terribly low resolution.
|
||||
if (x + w > vid.width)
|
||||
return;
|
||||
|
||||
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Precompile a wordwrapped string to any given width.
|
||||
// This is a muuuch better method than V_WORDWRAP.
|
||||
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
||||
|
|
|
@ -139,6 +139,7 @@ void V_DrawScaledPic (INT32 px1, INT32 py1, INT32 scrn, INT32 lumpnum);
|
|||
|
||||
// fill a box with a single color
|
||||
void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c);
|
||||
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c);
|
||||
// fill a box with a flat as a pattern
|
||||
void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
|
||||
|
||||
|
@ -149,11 +150,16 @@ void V_DrawFadeConsBack(INT32 plines);
|
|||
|
||||
// draw a single character
|
||||
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
|
||||
// draw a single character, but for the chat
|
||||
void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap);
|
||||
|
||||
UINT8 *V_GetStringColormap(INT32 colorflags);
|
||||
|
||||
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
|
||||
// wordwrap a string using the hu_font
|
||||
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string);
|
||||
UINT8 *V_GetStringColormap(INT32 colorflags);
|
||||
|
||||
// draw a string using the hu_font
|
||||
void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
|
|
46
src/w_wad.c
46
src/w_wad.c
|
@ -34,6 +34,8 @@
|
|||
#include "z_zone.h"
|
||||
#include "fastcmp.h"
|
||||
|
||||
#include "filesrch.h"
|
||||
|
||||
#include "i_video.h" // rendermode
|
||||
#include "d_netfil.h"
|
||||
#include "dehacked.h"
|
||||
|
@ -647,12 +649,22 @@ UINT16 W_InitFile(const char *filename)
|
|||
restype_t type;
|
||||
UINT16 numlumps = 0;
|
||||
size_t i;
|
||||
size_t packetsize = 0;
|
||||
serverinfo_pak *dummycheck = NULL;
|
||||
size_t packetsize;
|
||||
UINT8 md5sum[16];
|
||||
boolean important;
|
||||
|
||||
// Shut the compiler up.
|
||||
(void)dummycheck;
|
||||
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
|
||||
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
|
||||
|
||||
if (refreshdirname)
|
||||
Z_Free(refreshdirname);
|
||||
if (dirmenu)
|
||||
{
|
||||
refreshdirname = Z_StrDup(filename);
|
||||
nameonly(refreshdirname);
|
||||
}
|
||||
else
|
||||
refreshdirname = NULL;
|
||||
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
|
||||
//
|
||||
|
@ -661,6 +673,7 @@ UINT16 W_InitFile(const char *filename)
|
|||
if (numwadfiles >= MAX_WADFILES)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
refreshdirmenu |= REFRESHDIR_MAX;
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
|
@ -670,21 +683,21 @@ UINT16 W_InitFile(const char *filename)
|
|||
|
||||
// Check if wad files will overflow fileneededbuffer. Only the filename part
|
||||
// is send in the packet; cf.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
// see PutFileNeeded in d_netfil.c
|
||||
if ((important = !W_VerifyNMUSlumps(filename)))
|
||||
{
|
||||
packetsize += nameonlylength(wadfiles[i]->filename);
|
||||
packetsize += 22; // MD5, etc.
|
||||
}
|
||||
packetsize = packetsizetally + nameonlylength(filename) + 22;
|
||||
|
||||
packetsize += nameonlylength(filename);
|
||||
packetsize += 22;
|
||||
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
refreshdirmenu |= REFRESHDIR_MAX;
|
||||
if (handle)
|
||||
fclose(handle);
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
if (packetsize > sizeof(dummycheck->fileneeded))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
if (handle)
|
||||
fclose(handle);
|
||||
return INT16_MAX;
|
||||
packetsizetally = packetsize;
|
||||
}
|
||||
|
||||
#ifndef NOMD5
|
||||
|
@ -741,6 +754,7 @@ UINT16 W_InitFile(const char *filename)
|
|||
wadfile->handle = handle;
|
||||
wadfile->numlumps = (UINT16)numlumps;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
fseek(handle, 0, SEEK_END);
|
||||
wadfile->filesize = (unsigned)ftell(handle);
|
||||
wadfile->type = type;
|
||||
|
|
|
@ -110,6 +110,7 @@ typedef struct wadfile_s
|
|||
FILE *handle;
|
||||
UINT32 filesize; // for network
|
||||
UINT8 md5sum[16];
|
||||
boolean important;
|
||||
} wadfile_t;
|
||||
|
||||
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word
|
||||
|
|
|
@ -996,7 +996,7 @@ static INT32 WINAPI VID_SetDirectDrawMode(viddef_t *lvid, vmode_t *currentmode)
|
|||
// but rather render to memory bitmap buffer
|
||||
lvid->direct = NULL;
|
||||
|
||||
if (!cv_stretch.value && (float)vid.width/vid.height != ((float)BASEVIDWIDTH/BASEVIDHEIGHT))
|
||||
if (!cv_stretch.value && fabsf((float)vid.width/vid.height - ((float)BASEVIDWIDTH/BASEVIDHEIGHT)) > 1.0E-36f)
|
||||
vid.height = (int)(vid.width * ((float)BASEVIDHEIGHT/BASEVIDWIDTH));// Adjust the height to match
|
||||
|
||||
return 1;
|
||||
|
|
10
windows-installer/.gitignore
vendored
10
windows-installer/.gitignore
vendored
|
@ -1,10 +0,0 @@
|
|||
*
|
||||
*.*
|
||||
!staging
|
||||
!sfx
|
||||
!uninstaller
|
||||
!! MAKE SURE FILES ARE IN new-install ARCHIVE FOLDER !.txt
|
||||
!BuildInstaller.bat
|
||||
!README.txt
|
||||
!VersionFileName.txt
|
||||
!.gitignore
|
|
@ -1,76 +0,0 @@
|
|||
@echo off
|
||||
|
||||
set "SCRIPTDIR=%~dp0"
|
||||
set "SCRIPTDIR=%SCRIPTDIR:~0,-1%"
|
||||
|
||||
IF [%SRB2VERSIONNAME%] == [] set /p SRB2VERSIONNAME=<"%SCRIPTDIR%\VersionFileName.txt"
|
||||
|
||||
:: Find 7z
|
||||
|
||||
set SVZIP=
|
||||
|
||||
if NOT [%1] == [] (
|
||||
echo.%~1 | findstr /C:"7z" 1>nul
|
||||
if NOT errorlevel 1 (
|
||||
if exist "%~1" set "SVZIP=%~1"
|
||||
)
|
||||
)
|
||||
|
||||
if ["%SVZIP%"] == [""] (
|
||||
if exist "%ProgramFiles(x86)%\7-Zip\7z.exe" set "SVZIP=%ProgramFiles(x86)%\7-Zip\7z.exe"
|
||||
if exist "%ProgramFiles%\7-Zip\7z.exe" set "SVZIP=%ProgramFiles%\7-Zip\7z.exe"
|
||||
if exist "%ProgramW6432%\7-Zip\7z.exe" set "SVZIP=%ProgramW6432%\7-Zip\7z.exe"
|
||||
)
|
||||
|
||||
:: Is it in PATH?
|
||||
|
||||
if ["%SVZIP%"] == [""] (
|
||||
"7z.exe" --help > NUL 2> NUL
|
||||
if NOT errorlevel 1 (
|
||||
set "SVZIP=7z.exe"
|
||||
)
|
||||
)
|
||||
|
||||
:: Create the uninstaller
|
||||
|
||||
if NOT ["%SVZIP%"] == [""] (
|
||||
del /f /q "%SCRIPTDIR%\Uninstaller.7z" 2> NUL
|
||||
"%SVZIP%" a -t7z "%SCRIPTDIR%\Uninstaller.7z" "%SCRIPTDIR%\uninstaller\*" -m5=LZMA2
|
||||
copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-uninstaller.txt" + "%SCRIPTDIR%\Uninstaller.7z" "%SCRIPTDIR%\staging\new-install\uninstall.exe"
|
||||
del /f /q "%SCRIPTDIR%\uninstaller.7z"
|
||||
)
|
||||
|
||||
:: Operate on install archives
|
||||
|
||||
type NUL > "%SCRIPTDIR%\staging\new-install\staging.txt"
|
||||
|
||||
if exist "%SCRIPTDIR%\Installer.7z" (
|
||||
if NOT ["%SVZIP%"] == [""] (
|
||||
"%SVZIP%" a "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\staging\*"
|
||||
)
|
||||
copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-installer.txt" + "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-Installer.exe"
|
||||
)
|
||||
|
||||
if exist "%SCRIPTDIR%\Patch.7z" (
|
||||
if NOT ["%SVZIP%"] == [""] (
|
||||
"%SVZIP%" a "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\staging\*"
|
||||
)
|
||||
copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-patch.txt" + "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-Patch.exe"
|
||||
)
|
||||
|
||||
if exist "%SCRIPTDIR%\Installer_x64.7z" (
|
||||
if NOT ["%SVZIP%"] == [""] (
|
||||
"%SVZIP%" a "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\staging\*"
|
||||
)
|
||||
copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2_x64.sfx" + "%SCRIPTDIR%\sfx\config-installer.txt" + "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-x64-Installer.exe"
|
||||
)
|
||||
|
||||
if exist "%SCRIPTDIR%\Patch_x64.7z" (
|
||||
if NOT ["%SVZIP%"] == [""] (
|
||||
"%SVZIP%" a "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\staging\*"
|
||||
)
|
||||
copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2_x64.sfx" + "%SCRIPTDIR%\sfx\config-patch.txt" + "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-x64-Patch.exe"
|
||||
)
|
||||
|
||||
del /f /q "%SCRIPTDIR%\staging\new-install\staging.txt"
|
||||
del /f /q "%SCRIPTDIR%\staging\new-install\uninstall.exe"
|
|
@ -1,48 +0,0 @@
|
|||
Windows Install Builder
|
||||
for SRB2
|
||||
|
||||
This installer is much like the 7-Zip self-extracting archive, except
|
||||
this allows for scripting the post-install step.
|
||||
|
||||
This also allows for some light customization, including dialog messages
|
||||
and program shortcuts.
|
||||
|
||||
The included install scripts manage the game data location depending on the
|
||||
install location -- if installed in Program Files or AppData\Local, the
|
||||
game data location is set to %UserProfile%\SRB2.
|
||||
|
||||
Program shortcuts are also added, as well as an uninstaller that
|
||||
will remove the icons and also selectively uninstall the core game files.
|
||||
The uninstaller gives you the option to preserve your game data and mods.
|
||||
|
||||
How to Use
|
||||
----------
|
||||
|
||||
1. Zip up the install contents in 7z format.
|
||||
* ALL FILES MUST BE IN THE `new-install/` ARCHIVE SUBFOLDER, OR THE
|
||||
POST-INSTALL SCRIPT WILL NOT WORK!
|
||||
* Make sure you are using the LZMA2 algorithm, which is 7-Zip's default.
|
||||
|
||||
2. Copy the 7z archive to this folder using the following names:
|
||||
* Installer.7z - 32-bit full installer
|
||||
* Patch.7z - 32-bit patch
|
||||
* Installer_x64.7z - 64-bit full installer
|
||||
* Patch_x64.7z - 64-bit patch
|
||||
|
||||
3. Set the text in VersionFilename.txt to the version identifier for the
|
||||
installer's filename.
|
||||
* e.g., v2121 for v2.1.21, from "SRB2-v2121-Installer.exe"
|
||||
* Also look through sfx/config-installer.txt and sfx/config-patch.txt
|
||||
and update the version strings. Templating is TODO.
|
||||
|
||||
4. Run BuildInstaller.bat [7z.exe install path]
|
||||
* First argument is the path to 7z.exe. If this is not specified, the
|
||||
script will try to look for it in C:\Program Files [(x86)]
|
||||
* This script will automatically add the install scripts to each
|
||||
installer.
|
||||
|
||||
Credit
|
||||
------
|
||||
|
||||
OlegScherbakov/7zSFX
|
||||
https://github.com/OlegScherbakov/7zSFX
|
|
@ -1 +0,0 @@
|
|||
v2121
|
Binary file not shown.
Binary file not shown.
|
@ -1,24 +0,0 @@
|
|||
;!@Install@!UTF-8!
|
||||
|
||||
GUIFlags="8+32+64+4096"
|
||||
GUIMode="1"
|
||||
|
||||
Title="Sonic Robo Blast 2 v2.1.21"
|
||||
BeginPrompt="Sonic Robo Blast 2 v2.1.21\nFull Installer\n\nSelect a folder to install SRB2 in.\n\nIf you install in \"AppData\\Local\" or \"Program Files\", your game data will be saved to:\n%UserProfile%\\SRB2\n\nOtherwise, your game data will be in the installation folder.\n\nShortcuts will be created in your Start Menu."
|
||||
|
||||
ExtractPathText="Installation folder: (no exclamation points, please!)"
|
||||
InstallPath="%LocalAppData%\\SRB2"
|
||||
ExtractTitle="Installing..."
|
||||
ExtractDialogText="Installing SRB2 v2.1.21...\n\nCheck out our modding community!\nWe make levels, characters, and much more!\n\nVisit http://www.srb2.org/mods"
|
||||
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{-opengl},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL)},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{-opengl -win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL, Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2dd.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw)},{%%T\\},{%%T\\srb2dd.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2dd.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw, Windowed)},{%%T\\},{%%T\\srb2dd.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\uninstall.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{Uninstall SRB2},{%%T\\},{shell32.dll},{31}"
|
||||
|
||||
RunProgram="nowait:\"%%T\\new-install\\staging.bat\""
|
||||
|
||||
;!@InstallEnd@!
|
|
@ -1,24 +0,0 @@
|
|||
;!@Install@!UTF-8!
|
||||
|
||||
GUIFlags="8+32+64+4096"
|
||||
GUIMode="1"
|
||||
|
||||
Title="Sonic Robo Blast 2 v2.1.21"
|
||||
BeginPrompt="Sonic Robo Blast 2 v2.1.21\nPatch Installer\n\nYou must have at least v2.1.15 to use this patch.\n\nSelect your current SRB2 folder.\n\nShortcuts will be created in your Start Menu."
|
||||
|
||||
ExtractPathText="Current SRB2 folder: (no exclamation points, please!)"
|
||||
InstallPath="%LocalAppData%\\SRB2"
|
||||
ExtractTitle="Installing..."
|
||||
ExtractDialogText="Installing SRB2 v2.1.21...\n\nCheck out our modding community!\nWe make levels, characters, and much more!\n\nVisit http://www.srb2.org/mods"
|
||||
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{-opengl},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL)},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2win.exe},{-opengl -win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL, Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2dd.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw)},{%%T\\},{%%T\\srb2dd.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\srb2dd.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw, Windowed)},{%%T\\},{%%T\\srb2dd.exe},{0}"
|
||||
Shortcut="Pu,{%%T\\uninstall.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{Uninstall SRB2},{%%T\\},{shell32.dll},{31}"
|
||||
|
||||
RunProgram="nowait:\"%%T\\new-install\\staging.bat\""
|
||||
|
||||
;!@InstallEnd@!
|
|
@ -1,13 +0,0 @@
|
|||
;!@Install@!UTF-8!
|
||||
|
||||
GUIFlags="1+2+8"
|
||||
GUIMode="2"
|
||||
|
||||
Title="Uninstall SRB2"
|
||||
BeginPrompt="Are you sure you want to uninstall Sonic Robo Blast 2?\n\nYour game data and mods will be preserved, as well as\nany extra files in your install folder."
|
||||
|
||||
InstallPath="%%S"
|
||||
|
||||
RunProgram="nowait:\"%%S\\uninstall.bat\" /y"
|
||||
|
||||
;!@InstallEnd@!
|
|
@ -1,11 +0,0 @@
|
|||
SRB2 Install Instructions
|
||||
|
||||
1. Move every file from the "new-install" folder to this main install folder.
|
||||
|
||||
2. DELETE "staging.bat" and "staging.txt"! These can mess up your installation if run by accident!
|
||||
|
||||
3. Optionally, create a folder in your user profile named "SRB2". This is where your game data and addons may live. For example,
|
||||
|
||||
C:\Users\[User]\SRB2
|
||||
|
||||
4. Run the game! Double-click srb2win.exe -- or see if you have Start Menu icons under "Sonic Robo Blast 2".
|
|
@ -1,15 +0,0 @@
|
|||
exchndl.dll
|
||||
fmodex.dll
|
||||
libFLAC-8.dll
|
||||
libgme.dll
|
||||
libintl-8.dll
|
||||
libmikmod-2.dll
|
||||
libogg-0.dll
|
||||
libvorbis-0.dll
|
||||
libvorbisfile-3.dll
|
||||
r_opengl.dll
|
||||
SDL2.dll
|
||||
SDL2_mixer.dll
|
||||
smpeg2.dll
|
||||
srb2dd.exe
|
||||
srb2win.exe
|
|
@ -1,363 +0,0 @@
|
|||
@echo off
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
cls
|
||||
|
||||
:: SRB2 Install Staging
|
||||
::
|
||||
:: This accomplishes the following tasks:
|
||||
::
|
||||
:: 1. Creates a user profile folder if SRB2 is installed in AppData or Program Files, and config.cfg is not already in the install folder
|
||||
::
|
||||
:: 2. Moves old installation files into old-install
|
||||
::
|
||||
:: 3. Moves new installaton files into install folder
|
||||
::
|
||||
|
||||
:: Get Parent folder (the SRB2 install folder)
|
||||
::
|
||||
:: https://wiert.me/2011/08/30/batch-file-to-get-parent-directory-not-the-directory-of-the-batch-file-but-the-parent-of-that-directory/
|
||||
|
||||
set "STAGINGDIR=%~dp0"
|
||||
:: strip trailing backslash
|
||||
set "STAGINGDIR=!STAGINGDIR:~0,-1!"
|
||||
:: ~dp only works for batch file parameters and loop indexes
|
||||
for %%d in ("!STAGINGDIR!") do set "INSTALLDIR=%%~dpd"
|
||||
set "INSTALLDIR=!INSTALLDIR:~0,-1!"
|
||||
|
||||
:: Find 7z
|
||||
|
||||
set SVZIP=
|
||||
if ["%SVZIP%"] == [""] (
|
||||
if exist "!ProgramFiles(x86)!\7-Zip\7z.exe" set "SVZIP=!ProgramFiles(x86)!\7-Zip\7z.exe"
|
||||
if exist "!ProgramFiles!\7-Zip\7z.exe" set "SVZIP=!ProgramFiles!\7-Zip\7z.exe"
|
||||
if exist "!ProgramW6432!\7-Zip\7z.exe" set "SVZIP=!ProgramW6432!\7-Zip\7z.exe"
|
||||
)
|
||||
|
||||
:: Is it in PATH?
|
||||
|
||||
if ["%SVZIP%"] == [""] (
|
||||
"7z.exe" --help > NUL 2> NUL
|
||||
if NOT errorlevel 1 (
|
||||
set "SVZIP=7z.exe"
|
||||
)
|
||||
)
|
||||
|
||||
:: FAILSAFE: Check if staging.txt exists in the directory
|
||||
:: If not, exit, so we don't mess up anything by accident.
|
||||
|
||||
if NOT exist "!STAGINGDIR!\staging.txt" (
|
||||
exit
|
||||
)
|
||||
|
||||
: CheckPermissionsInstall
|
||||
|
||||
:: Write a dummy file and check for an error. If error, we need administrator rights
|
||||
|
||||
:: NOTE: We should never have to deal with this because the main installer should
|
||||
:: already have the rights.
|
||||
|
||||
mkdir "!INSTALLDIR!\install-dummy"
|
||||
|
||||
:: TODO elevate automatically
|
||||
if errorlevel 1 (
|
||||
echo Finish installing SRB2 with these steps:
|
||||
echo.
|
||||
echo 1. Go to your SRB2 install folder
|
||||
echo.
|
||||
echo !INSTALLDIR!
|
||||
echo.
|
||||
echo 2. Copy all files from the "new-install" subfolder into the main folder
|
||||
echo and DELETE staging.bat and staging.txt!!!
|
||||
echo.
|
||||
echo 3. Optionally, create a folder in your user profile named "SRB2".
|
||||
echo This is where your game data and addons may live.
|
||||
echo To create the folder, go here:
|
||||
echo.
|
||||
echo !USERPROFILE!
|
||||
echo.
|
||||
echo If anything fails, you may delete the files and try to run the installer
|
||||
echo again with Administrator Rights: Right-click on the icon and click
|
||||
echo "Run as administrator."
|
||||
echo.
|
||||
"!SystemRoot!\explorer.exe" "!INSTALLDIR!"
|
||||
set /p ADMINFINAL="Press Enter key to exit. "
|
||||
|
||||
exit
|
||||
) else (
|
||||
rmdir /s /q "!INSTALLDIR!\install-dummy"
|
||||
goto CheckUserDir
|
||||
)
|
||||
|
||||
: CheckUserDir
|
||||
|
||||
:: Check if we need to create !userprofile!\SRB2
|
||||
|
||||
set "USERDIR=!INSTALLDIR!"
|
||||
|
||||
:: Is config.cfg in our install dir?
|
||||
if exist "!INSTALLDIR!\config.cfg" goto MoveOldInstall
|
||||
|
||||
:: Are we in AppData?
|
||||
echo.!STAGINGDIR! | findstr /C:"!LocalAppData!" 1>nul
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
) else (
|
||||
goto SetUserDir
|
||||
)
|
||||
|
||||
: Are we in Program Files?
|
||||
echo.!STAGINGDIR! | findstr /C:"!ProgramFiles!" 1>nul
|
||||
if NOT errorlevel 1 (
|
||||
goto SetUserDir
|
||||
)
|
||||
|
||||
:: Are we in Program Files (x86)?
|
||||
echo.!STAGINGDIR! | findstr /C:"!ProgramFiles(X86)!" 1>nul
|
||||
if NOT errorlevel 1 (
|
||||
goto SetUserDir
|
||||
)
|
||||
|
||||
:: Are we 32-bit and actually in Program Files?
|
||||
echo.!STAGINGDIR! | findstr /C:"!ProgramW6432!" 1>nul
|
||||
if NOT errorlevel 1 (
|
||||
goto SetUserDir
|
||||
)
|
||||
|
||||
goto MoveOldInstall
|
||||
|
||||
: SetUserDir
|
||||
: CheckPermissionsUserDir
|
||||
|
||||
set "USERDIR=!UserProfile!\SRB2"
|
||||
|
||||
:: Check for permissions and create the folder
|
||||
if exist "!USERDIR!\*" (
|
||||
mkdir "!USERDIR!\install-dummy"
|
||||
|
||||
if errorlevel 1 (
|
||||
echo User profile folder exists, but we won't operate on it.
|
||||
echo.
|
||||
goto MoveOldInstall
|
||||
) else (
|
||||
rmdir /s /q "!USERDIR!\install-dummy"
|
||||
)
|
||||
) else (
|
||||
mkdir "!USERDIR!"
|
||||
|
||||
if errorlevel 1 (
|
||||
echo Could not create user profile folder
|
||||
echo Defaulting to install dir: "!INSTALLDIR!"
|
||||
echo.
|
||||
set "USERDIR=!INSTALLDIR!"
|
||||
goto MoveOldInstall
|
||||
)
|
||||
)
|
||||
|
||||
:: Now copy READMEs
|
||||
:: echo f answers xcopy's prompt as to whether the destination is a file or a folder
|
||||
echo f | xcopy /y "!STAGINGDIR!\README.txt" "!USERDIR!\README.txt"
|
||||
echo f | xcopy /y "!STAGINGDIR!\LICENSE.txt" "!USERDIR!\LICENSE.txt"
|
||||
echo f | xcopy /y "!STAGINGDIR!\LICENSE-3RD-PARTY.txt" "!USERDIR!\LICENSE-3RD-PARTY.txt"
|
||||
echo Your game data and mods folder is: > "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo !USERDIR! >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo Your install folder is: >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo !INSTALLDIR! >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo To run SRB2, go to: >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
echo Start Menu ^> Programs ^> Sonic Robo Blast 2 >> "!USERDIR!\^! Data and Mods Go Here ^!.txt"
|
||||
|
||||
:: Copy path to install folder
|
||||
|
||||
set "SCRIPT=!TEMP!\!RANDOM!-!RANDOM!-!RANDOM!-!RANDOM!.vbs"
|
||||
echo Set oWS = WScript.CreateObject("WScript.Shell") >> "!SCRIPT!"
|
||||
echo sLinkFile = "!USERDIR!\^! SRB2 Install Folder ^!.lnk" >> "!SCRIPT!"
|
||||
echo Set oLink = oWS.CreateShortcut(sLinkFile) >> "!SCRIPT!"
|
||||
echo oLink.TargetPath = "!INSTALLDIR!" >> "!SCRIPT!"
|
||||
echo oLink.WorkingDirectory = "!INSTALLDIR!" >> "!SCRIPT!"
|
||||
echo oLink.Arguments = "" >> "!SCRIPT!"
|
||||
echo oLink.IconLocation = "!INSTALLDIR!\srb2win.exe,0" >> "!SCRIPT!"
|
||||
echo oLink.Save >> "!SCRIPT!"
|
||||
cscript /nologo "!SCRIPT!"
|
||||
del "!SCRIPT!"
|
||||
|
||||
:: Also do it the other way around
|
||||
|
||||
set "SCRIPT=!TEMP!\!RANDOM!-!RANDOM!-!RANDOM!-!RANDOM!.vbs"
|
||||
echo Set oWS = WScript.CreateObject("WScript.Shell") >> "!SCRIPT!"
|
||||
echo sLinkFile = "!INSTALLDIR!\^! SRB2 Data Folder ^!.lnk" >> "!SCRIPT!"
|
||||
echo Set oLink = oWS.CreateShortcut(sLinkFile) >> "!SCRIPT!"
|
||||
echo oLink.TargetPath = "!USERDIR!" >> "!SCRIPT!"
|
||||
echo oLink.WorkingDirectory = "!USERDIR!" >> "!SCRIPT!"
|
||||
echo oLink.Arguments = "" >> "!SCRIPT!"
|
||||
echo oLink.IconLocation = "!INSTALLDIR!\srb2win.exe,0" >> "!SCRIPT!"
|
||||
echo oLink.Save >> "!SCRIPT!"
|
||||
cscript /nologo "!SCRIPT!"
|
||||
del "!SCRIPT!"
|
||||
|
||||
: MoveOldInstall
|
||||
|
||||
if exist "!INSTALLDIR!\old-install\*" (
|
||||
set "OLDINSTALLDIR=!INSTALLDIR!\old-install-!RANDOM!"
|
||||
) else (
|
||||
set "OLDINSTALLDIR=!INSTALLDIR!\old-install"
|
||||
)
|
||||
|
||||
mkdir "!OLDINSTALLDIR!"
|
||||
|
||||
::
|
||||
:: Move all old install files
|
||||
:: We support a list of explicit files to copy to old-install
|
||||
:: And later, we also loop through our staging files, look for the pre-existing copy in
|
||||
:: install root, then copy that also to old-install
|
||||
::
|
||||
|
||||
:: Extract the uninstall-list.txt and uninstall-userdir.txt files from uninstaller.exe
|
||||
:: if it exists
|
||||
|
||||
if exist "!INSTALLDIR!\uninstall.exe" (
|
||||
if NOT ["!SVZIP!"] == [""] (
|
||||
"!SVZIP!" x "!INSTALLDIR!\uninstall.exe" "uninstall-list.txt" -o"!INSTALLDIR!"
|
||||
"!SVZIP!" x "!INSTALLDIR!\uninstall.exe" "uninstall-userdir.txt" -o"!INSTALLDIR!"
|
||||
)
|
||||
)
|
||||
|
||||
set OLDINSTALLCHANGED=
|
||||
|
||||
if exist "!STAGINGDIR!\old-install-list.txt" (
|
||||
goto MoveOldInstallOldFiles
|
||||
) else (
|
||||
goto MoveOldInstallNewFiles
|
||||
)
|
||||
|
||||
: MoveOldInstallOldFiles
|
||||
|
||||
set "TESTFILE=!TEMP!\!RANDOM!.txt"
|
||||
|
||||
:: Do our failsafes before copying the file in the list
|
||||
:: See uninstall.bat for details
|
||||
for /F "usebackq tokens=*" %%A in ("!STAGINGDIR!\old-install-list.txt") do (
|
||||
if exist "!INSTALLDIR!\%%A" (
|
||||
if NOT ["%%A"] == [""] (
|
||||
if NOT ["%%A"] == ["%~nx0"] (
|
||||
echo %%A> "!TESTFILE!"
|
||||
findstr /r ".*[<>:\"\"/\\|?*%%].*" "!TESTFILE!" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo %%A has invalid characters, skipping...
|
||||
) else (
|
||||
if exist "!INSTALLDIR!\%%A\*" (
|
||||
echo %%A is a folder, skipping...
|
||||
) else (
|
||||
echo Moving !INSTALLDIR!\%%A to "old-install" folder
|
||||
echo f | xcopy /y /v "!INSTALLDIR!\%%A" "!OLDINSTALLDIR!\%%A"
|
||||
if errorlevel 0 del /f /q "!INSTALLDIR!\%%A"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
del /q /f "!STAGINGDIR!\old-install-list.txt"
|
||||
|
||||
for %%F in ("!OLDINSTALLDIR!\*") DO (
|
||||
set OLDINSTALLCHANGED=1
|
||||
goto MoveOldInstallNewFiles
|
||||
)
|
||||
|
||||
: MoveOldInstallNewFiles
|
||||
|
||||
:: Save a list of standard files
|
||||
:: So the uninstall script will know what to remove
|
||||
:: Append to any existing file, in case we are a patch
|
||||
|
||||
dir /b /a-d "!STAGINGDIR!" >> "!INSTALLDIR!\uninstall-list.txt"
|
||||
|
||||
:: Overwrite the last known gamedata folder
|
||||
|
||||
echo !USERDIR! > "!INSTALLDIR!\uninstall-userdir.txt"
|
||||
|
||||
:: Add the install-generated to the uninstall list
|
||||
:: NO FOLLOWING SPACES AFTER THE FILENAME!!!
|
||||
|
||||
echo uninstall.bat>> "!INSTALLDIR!\uninstall-list.txt"
|
||||
echo uninstall-list.txt>> "!INSTALLDIR!\uninstall-list.txt"
|
||||
echo uninstall-userdir.txt>> "!INSTALLDIR!\uninstall-list.txt"
|
||||
:: *ahem* Prints as ^! SRB2 Data Folder ^!.lnk
|
||||
:: We need to escape the exclamations (^^!) and the carets themselves (^^^^)
|
||||
echo ^^^^^^! SRB2 Data Folder ^^^^^^!.lnk>> "!INSTALLDIR!\uninstall-list.txt"
|
||||
|
||||
:: Add the uninstall list files to the uninstall EXE
|
||||
|
||||
if NOT ["!SVZIP!"] == [""] (
|
||||
if exist "!INSTALLDIR!\new-install\uninstall.exe" (
|
||||
"!SVZIP!" a "!INSTALLDIR!\new-install\uninstall.exe" "!INSTALLDIR!\uninstall-list.txt" -sdel
|
||||
"!SVZIP!" a "!INSTALLDIR!\new-install\uninstall.exe" "!INSTALLDIR!\uninstall-userdir.txt" -sdel
|
||||
)
|
||||
)
|
||||
|
||||
:: Start moving files
|
||||
|
||||
for %%F in ("!STAGINGDIR!\*") DO (
|
||||
if exist "!INSTALLDIR!\%%~nxF" (
|
||||
set OLDINSTALLCHANGED=1
|
||||
move "!INSTALLDIR!\%%~nxF" "!OLDINSTALLDIR!\%%~nxF"
|
||||
)
|
||||
if NOT ["%%~nxF"] == ["staging.bat"] (
|
||||
if NOT ["%%~nxF"] == ["staging.txt"] (
|
||||
move "!STAGINGDIR!\%%~nxF" "!INSTALLDIR!\%%~nxF"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
: Finished
|
||||
|
||||
del /q /f "!INSTALLDIR!\^! SRB2 INSTALL INSTRUCTIONS ^!.txt"
|
||||
|
||||
set MSGEXE=
|
||||
if exist "!SystemRoot!\System32\msg.exe" (
|
||||
set MSGEXE=!SystemRoot!\System32\msg.exe
|
||||
) else (
|
||||
if exist "!SystemRoot!\Sysnative\msg.exe" (
|
||||
set MSGEXE=!SystemRoot!\Sysnative\msg.exe
|
||||
)
|
||||
)
|
||||
|
||||
if ["!OLDINSTALLCHANGED!"] == ["1"] (
|
||||
"!systemroot!\explorer.exe" /select, "!OLDINSTALLDIR!"
|
||||
echo Finished^^! Some of your old installation files were moved to the "old-install" folder. > !TEMP!\srb2msgprompt.txt
|
||||
echo. >> !TEMP!\srb2msgprompt.txt
|
||||
echo If you no longer need these files, you may delete the folder safely. >> !TEMP!\srb2msgprompt.txt
|
||||
echo. >> !TEMP!\srb2msgprompt.txt
|
||||
echo To run SRB2, go to: Start Menu ^> Programs ^> Sonic Robo Blast 2. >> !TEMP!\srb2msgprompt.txt
|
||||
!MSGEXE! "!username!" < !TEMP!\srb2msgprompt.txt
|
||||
del !TEMP!\srb2msgprompt.txt
|
||||
) else (
|
||||
if /I ["!USERDIR!"] == ["!INSTALLDIR!"] (
|
||||
"!systemroot!\explorer.exe" "!INSTALLDIR!"
|
||||
echo Finished^^! > !TEMP!\srb2msgprompt.txt
|
||||
echo. >> !TEMP!\srb2msgprompt.txt
|
||||
echo To run SRB2, go to: Start Menu ^> Programs ^> Sonic Robo Blast 2. >> !TEMP!\srb2msgprompt.txt
|
||||
!MSGEXE! "!username!" < !TEMP!\srb2msgprompt.txt
|
||||
del !TEMP!\srb2msgprompt.txt
|
||||
) else (
|
||||
"!systemroot!\explorer.exe" "!USERDIR!"
|
||||
echo Finished^^! You may find your game data in this folder: > !TEMP!\srb2msgprompt.txt
|
||||
echo. >> !TEMP!\srb2msgprompt.txt
|
||||
echo !USERDIR! >> !TEMP!\srb2msgprompt.txt
|
||||
echo. >> !TEMP!\srb2msgprompt.txt
|
||||
echo To run SRB2, go to: Start Menu ^> Programs ^> Sonic Robo Blast 2. >> !TEMP!\srb2msgprompt.txt
|
||||
!MSGEXE! "!username!" < !TEMP!\srb2msgprompt.txt
|
||||
del !TEMP!\srb2msgprompt.txt
|
||||
)
|
||||
)
|
||||
|
||||
: Attempt to remove OLDINSTALLDIR, in case it's empty
|
||||
rmdir /q "!OLDINSTALLDIR!"
|
||||
cd \
|
||||
start "" /b "cmd" /s /c " del /f /q "%STAGINGDIR%\*"&rmdir /s /q "%STAGINGDIR%"&exit /b "
|
|
@ -1,183 +0,0 @@
|
|||
@echo off
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
cls
|
||||
|
||||
set "INSTALLDIR=%~dp0"
|
||||
set "INSTALLDIR=!INSTALLDIR:~0,-1!"
|
||||
set /p USERDIR=<"!INSTALLDIR!\uninstall-userdir.txt"
|
||||
set "USERDIR=!USERDIR:~0,-1!"
|
||||
|
||||
: ProceedPrompt
|
||||
|
||||
if ["%1"] == ["/y"] (
|
||||
set "PROCEED=1"
|
||||
) else (
|
||||
set PROCEED=
|
||||
set /p PROCEED="Are you sure you want to uninstall SRB2? [yes/no] "
|
||||
|
||||
if /I ["!PROCEED:~0,1!"] == ["n"] exit
|
||||
if /I ["!PROCEED!"] == ["y"] (
|
||||
echo Type Yes or No
|
||||
echo.
|
||||
goto ProceedPrompt
|
||||
) else (
|
||||
if /I ["!PROCEED!"] == ["yes"] (
|
||||
set PROCEED=1
|
||||
) else (
|
||||
echo.
|
||||
goto ProceedPrompt
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:: Failsafe, in case we Ctrl+C and decline "Terminate batch file?"
|
||||
|
||||
if NOT ["!PROCEED!"] == ["1"] (
|
||||
exit
|
||||
)
|
||||
|
||||
: CheckPermissions
|
||||
|
||||
:: Write a dummy file and check for an error. If error, we need administrator rights
|
||||
|
||||
mkdir "!INSTALLDIR!\uninstall-dummy"
|
||||
|
||||
:: TODO elevate automatically
|
||||
if errorlevel 1 (
|
||||
echo We need Administrator Rights to uninstall SRB2.
|
||||
echo.
|
||||
echo Try running this uninstaller by right-clicking on the icon
|
||||
echo and click "Run as administrator"
|
||||
echo.
|
||||
set /p ADMINFINAL="Press Enter key to exit. "
|
||||
exit
|
||||
) else (
|
||||
rmdir /s /q "!INSTALLDIR!\uninstall-dummy"
|
||||
goto DeleteFiles
|
||||
)
|
||||
|
||||
: DeleteFiles
|
||||
|
||||
:: Our deletion list is a list of filenames, no paths, in the current folder
|
||||
::
|
||||
:: We apply the following failsafes:
|
||||
:: 1. Is filename the script itself?
|
||||
:: 2. Does filename have illegal characters? https://stackoverflow.com/a/33625339/241046
|
||||
:: 3. Is filename a directory?
|
||||
::
|
||||
:: TODO hack this to support .\file.txt relative paths
|
||||
:: Can %%A be substring'd to get only the filename and extension?
|
||||
:: If so, print that to the temp file instead of the whole line
|
||||
:: And possibly do the folder check before the invalid char check.
|
||||
:: ALSO: Don't honor upward relative paths! (..\)
|
||||
::
|
||||
set "TESTFILE=!TEMP!\!RANDOM!.txt"
|
||||
|
||||
for /F "usebackq tokens=*" %%A in ("!INSTALLDIR!\uninstall-list.txt") do (
|
||||
if exist "!INSTALLDIR!\%%A" (
|
||||
if NOT ["%%A"] == [""] (
|
||||
if NOT ["%%A"] == ["%~nx0"] (
|
||||
echo %%A> "!TESTFILE!"
|
||||
findstr /r ".*[<>:\"\"/\\|?*%%].*" "!TESTFILE!" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo %%A has invalid characters, skipping...
|
||||
) else (
|
||||
if exist "!INSTALLDIR!\%%A\*" (
|
||||
echo %%A is a folder, skipping...
|
||||
) else (
|
||||
echo Deleting !INSTALLDIR!\%%A
|
||||
del /q /f "!INSTALLDIR!\%%A"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
del /q /f "!TESTFILE!"
|
||||
|
||||
: AllDone
|
||||
|
||||
:: Delete the program icons
|
||||
echo Deleting your program icons...
|
||||
echo.
|
||||
|
||||
cd \
|
||||
rmdir /s /q "!AppData!\Microsoft\Windows\Start Menu\Programs\Sonic Robo Blast 2"
|
||||
|
||||
:: Check if our install folder is non-empty
|
||||
|
||||
set USERDIRFILLED=
|
||||
set INSTALLDIRFILLED=
|
||||
for /F %%i in ('dir /b /a "!USERDIR!\*"') do (
|
||||
if NOT ["%%i"] == ["%~nx0"] (
|
||||
set USERDIRFILLED=1
|
||||
goto InstallFilledCheck
|
||||
)
|
||||
)
|
||||
|
||||
: InstallFilledCheck
|
||||
|
||||
if /I NOT ["!USERDIR!"] == ["!INSTALLDIR!"] (
|
||||
for /F %%i in ('dir /b /a "!INSTALLDIR!\*"') do (
|
||||
if ["%%i"] == ["%~nx0"] (
|
||||
echo.
|
||||
) else (
|
||||
set INSTALLDIRFILLED=1
|
||||
goto Final
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
: Final
|
||||
|
||||
echo All done^^! Visit http://www.srb2.org if you want to play SRB2 again^^!
|
||||
echo.
|
||||
|
||||
set "FINALPROMPT=Press Enter key to exit."
|
||||
if ["!USERDIRFILLED!"] == ["1"] (
|
||||
echo We left your game data and mods alone, so you may delete those manually.
|
||||
echo.
|
||||
echo !USERDIR!
|
||||
echo.
|
||||
set "FINALPROMPT=Do you want to view your data? [yes/no]"
|
||||
)
|
||||
|
||||
if ["!INSTALLDIRFILLED!"] == ["1"] (
|
||||
echo We left some extra files alone in your install folder.
|
||||
echo.
|
||||
echo !INSTALLDIR!
|
||||
echo.
|
||||
set "FINALPROMPT=Do you want to view your data? [yes/no]"
|
||||
)
|
||||
|
||||
set FINALRESPONSE=
|
||||
set /p FINALRESPONSE="!FINALPROMPT! "
|
||||
|
||||
if NOT ["!FINALPROMPT!"] == ["Press Enter key to exit."] (
|
||||
if /I ["!FINALRESPONSE:~0,1!"] == ["y"] (
|
||||
if ["!USERDIRFILLED!"] == ["1"] (
|
||||
"!SystemRoot!\explorer.exe" "!USERDIR!"
|
||||
)
|
||||
if ["!INSTALLDIRFILLED!"] == ["1"] (
|
||||
"!SystemRoot!\explorer.exe" "!INSTALLDIR!"
|
||||
)
|
||||
) else (
|
||||
if ["!FINALRESPONSE!"] == [""] (
|
||||
if ["!USERDIRFILLED!"] == ["1"] (
|
||||
"!SystemRoot!\explorer.exe" "!USERDIR!"
|
||||
)
|
||||
if ["!INSTALLDIRFILLED!"] == ["1"] (
|
||||
"!SystemRoot!\explorer.exe" "!INSTALLDIR!"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
: DeferredDelete
|
||||
|
||||
:: Now let's delete our installation folder!
|
||||
cd \
|
||||
start "" /b "cmd" /s /c " del /q /f "%INSTALLDIR%\uninstall.bat"&timeout /t 2 > NUL&rmdir "%INSTALLDIR%"&exit /b "
|
Loading…
Reference in a new issue