Merge next

This commit is contained in:
Sally Cochenour 2020-01-07 07:35:39 -05:00
commit ca5b56181b
86 changed files with 3869 additions and 2042 deletions

View File

@ -9,7 +9,7 @@ environment:
# c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead
MINGW_SDK: c:\msys64\mingw32
# c:\msys64 x86_64 has gcc 8.2.0, so use c:\mingw-w64 7.3.0 instead
MINGW_SDK_64: C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64
MINGW_SDK_64: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64
CFLAGS: -Wall -W -Werror -Wno-error=implicit-fallthrough -Wimplicit-fallthrough=3 -Wno-tautological-compare -Wno-error=suggest-attribute=noreturn
NASM_ZIP: nasm-2.12.01
NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip
@ -55,8 +55,6 @@ cache:
install:
- if [%CONFIGURATION%] == [SDL64] ( set "X86_64=1" )
- if [%CONFIGURATION%] == [SDL64] ( set "CONFIGURATION=SDL" )
- if [%CONFIGURATION%] == [DD64] ( set "X86_64=1" )
- if [%CONFIGURATION%] == [DD64] ( set "CONFIGURATION=DD" )
- if [%X86_64%] == [1] ( set "MINGW_SDK=%MINGW_SDK_64%" )
- if [%X86_64%] == [1] ( set "CCACHE_CC=%CCACHE_CC_64%" )
@ -75,13 +73,6 @@ install:
configuration:
- SDL
- SDL64
- DD
- DD64
matrix:
allow_failures:
- configuration: DD
- configuration: DD64
before_build:
- set "Path=%MINGW_SDK%\bin;%Path%"
@ -92,8 +83,8 @@ before_build:
- ccache -V
- ccache -s
- if [%NOUPX%] == [1] ( set "NOUPX=NOUPX=1" ) else ( set "NOUPX=" )
- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 GCC73=1 NOOBJDUMP=1 %NOUPX%"
- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1" ) else ( set "MINGW_FLAGS=MINGW=1 GCC91=1" )
- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX%"
- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1 GCC81=1" ) else ( set "MINGW_FLAGS=MINGW=1 GCC91=1" )
- set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1"
build_script:

View File

@ -245,6 +245,8 @@ void I_GetJoystick2Events(void){}
void I_GetMouseEvents(void){}
void I_UpdateMouseGrab(void){}
char *I_GetEnv(const char *name)
{
LOGW("I_GetEnv() called?!");

View File

@ -19,6 +19,7 @@ boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
void I_StartupGraphics(void){}
void I_StartupHardwareGraphics(void){}
void I_ShutdownGraphics(void){}
@ -51,6 +52,11 @@ INT32 VID_SetMode(INT32 modenum)
return 0;
}
void VID_CheckRenderer(void)
{
// ..............
}
const char *VID_GetModeName(INT32 modenum)
{
return "A320x240";

View File

@ -335,27 +335,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
jump_last = jump;
spin_last = spin;
// ********
// Thinkfly overlay
if (thinkfly)
{
if (!tails->hnext)
{
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
if (tails->hnext)
{
P_SetTarget(&tails->hnext->target, tails);
P_SetTarget(&tails->hnext->hprev, tails);
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
}
}
}
else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
{
P_RemoveMobj(tails->hnext);
P_SetTarget(&tails->hnext, NULL);
}
// Turn the virtual keypresses into ticcmd_t.
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin);
@ -565,3 +544,30 @@ void B_RespawnBot(INT32 playernum)
P_SetScale(tails, sonic->scale);
tails->destscale = sonic->destscale;
}
void B_HandleFlightIndicator(player_t *player)
{
mobj_t *tails = player->mo;
if (!tails)
return;
if (thinkfly && player->bot == 1 && tails->health)
{
if (!tails->hnext)
{
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
if (tails->hnext)
{
P_SetTarget(&tails->hnext->target, tails);
P_SetTarget(&tails->hnext->hprev, tails);
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
}
}
}
else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
{
P_RemoveMobj(tails->hnext);
P_SetTarget(&tails->hnext, NULL);
}
}

View File

@ -15,3 +15,4 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
boolean B_CheckRespawn(player_t *player);
void B_MoveBlocked(player_t *player);
void B_RespawnBot(INT32 playernum);
void B_HandleFlightIndicator(player_t *player);

View File

@ -54,13 +54,15 @@ static void COM_Add_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);
consvar_t *CV_FindVar(const char *name);
static const char *CV_StringValue(const char *var_name);
static consvar_t *consvar_vars; // list of registered console variables
static char com_token[1024];
static char *COM_Parse(char *data);
static char * COM_Purge (char *text, int *lenp);
CV_PossibleValue_t CV_OnOff[] = {{0, "Off"}, {1, "On"}, {0, NULL}};
CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}};
CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}};
@ -100,31 +102,61 @@ static cmdalias_t *com_alias; // aliases list
static vsbuf_t com_text; // variable sized buffer
/** Purges control characters out of some text.
*
* \param s The text.
* \param np Optionally a pointer to fill with the new string length.
* \return The text.
* \sa COM_ExecuteString
*/
static char *
COM_Purge (char *s, int *np)
{
char *t;
char *p;
int n;
n = strlen(s);
t = s + n + 1;
p = s;
while (( p = strchr(p, '\033') ))
{
memmove(p, &p[1], t - p - 1);
n--;
}
if (np)
(*np) = n;
return s;
}
/** Adds text into the command buffer for later execution.
*
* \param ptext The text to add.
* \sa COM_BufInsertText
* \sa COM_BufInsertTextEx
*/
void COM_BufAddText(const char *ptext)
void COM_BufAddTextEx(const char *ptext, int flags)
{
size_t l;
int l;
char *text;
l = strlen(ptext);
text = COM_Purge(Z_StrDup(ptext), &l);
if (com_text.cursize + l >= com_text.maxsize)
if (com_text.cursize + 2 + l >= com_text.maxsize)
{
CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n"));
return;
}
VS_Write(&com_text, ptext, l);
VS_WriteEx(&com_text, text, l, flags);
Z_Free(text);
}
/** Adds command text and executes it immediately.
*
* \param ptext The text to execute. A newline is automatically added.
* \sa COM_BufAddText
* \sa COM_BufAddTextEx
*/
void COM_BufInsertText(const char *ptext)
void COM_BufInsertTextEx(const char *ptext, int flags)
{
char *temp = NULL;
size_t templen;
@ -138,7 +170,7 @@ void COM_BufInsertText(const char *ptext)
}
// add the entire text of the file (or alias)
COM_BufAddText(ptext);
COM_BufAddTextEx(ptext, flags);
COM_BufExecute(); // do it right away
// add the copied off data
@ -272,6 +304,7 @@ static size_t com_argc;
static char *com_argv[MAX_ARGS];
static const char *com_null_string = "";
static char *com_args = NULL; // current command args or NULL
static int com_flags;
static void Got_NetVar(UINT8 **p, INT32 playernum);
@ -394,12 +427,21 @@ static void COM_TokenizeString(char *ptext)
com_argc = 0;
com_args = NULL;
com_flags = 0;
while (com_argc < MAX_ARGS)
{
// Skip whitespace up to a newline.
while (*ptext != '\0' && *ptext <= ' ' && *ptext != '\n')
ptext++;
{
if (ptext[0] == '\033')
{
com_flags = (unsigned)ptext[1];
ptext += 2;
}
else
ptext++;
}
// A newline means end of command in buffer,
// thus end of this command's args too.
@ -1016,6 +1058,15 @@ void VS_Write(vsbuf_t *buf, const void *data, size_t length)
M_Memcpy(VS_GetSpace(buf, length), data, length);
}
void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, int flags)
{
char *p;
p = VS_GetSpace(buf, 2 + length);
p[0] = '\033';
p[1] = flags;
M_Memcpy(&p[2], data, length);
}
/** Prints text in a variable buffer. Like VS_Write() plus a
* trailing NUL.
*
@ -1055,7 +1106,7 @@ static const char *cv_null_string = "";
* \return Pointer to the variable if found, or NULL.
* \sa CV_FindNetVar
*/
static consvar_t *CV_FindVar(const char *name)
consvar_t *CV_FindVar(const char *name)
{
consvar_t *cvar;
@ -2015,6 +2066,9 @@ static boolean CV_Command(void)
if (!v)
return false;
if (( com_flags & COM_SAFE ) && ( v->flags & CV_NOLUA ))
return false;
// perform a variable print or set
if (COM_Argc() == 1)
{
@ -2116,8 +2170,13 @@ skipwhite:
com_token[len] = 0;
return data;
}
com_token[len] = c;
len++;
if (c == '\033')
data++;
else
{
com_token[len] = c;
len++;
}
}
}
@ -2133,10 +2192,22 @@ skipwhite:
// parse a regular word
do
{
com_token[len] = c;
data++;
len++;
c = *data;
if (c == '\033')
{
do
{
data += 2;
c = *data;
}
while (c == '\033') ;
}
else
{
com_token[len] = c;
data++;
len++;
c = *data;
}
if (c == '{' || c == '}' || c == ')'|| c == '(' || c == '\'')
break;
} while (c > 32);

View File

@ -20,6 +20,11 @@
// Command buffer & command execution
//===================================
enum
{
COM_SAFE = 1,
};
typedef void (*com_func_t)(void);
void COM_AddCommand(const char *name, com_func_t func);
@ -36,10 +41,12 @@ size_t COM_FirstOption(void);
const char *COM_CompleteCommand(const char *partial, INT32 skips);
// insert at queu (at end of other command)
void COM_BufAddText(const char *btext);
#define COM_BufAddText(s) COM_BufAddTextEx(s, 0)
void COM_BufAddTextEx(const char *btext, int flags);
// insert in head (before other command)
void COM_BufInsertText(const char *btext);
#define COM_BufInsertText(s) COM_BufInsertTextEx(s, 0)
void COM_BufInsertTextEx(const char *btext, int flags);
// don't bother inserting, just do immediately
void COM_ImmedExecute(const char *ptext);
@ -71,6 +78,7 @@ void VS_Free(vsbuf_t *buf);
void VS_Clear(vsbuf_t *buf);
void *VS_GetSpace(vsbuf_t *buf, size_t length);
void VS_Write(vsbuf_t *buf, const void *data, size_t length);
void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, int flags);
void VS_Print(vsbuf_t *buf, const char *data); // strcats onto the sizebuf
//==================
@ -100,7 +108,8 @@ typedef enum
CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console
// can only be set when we have the pointer to it
// used on menus
CV_CHEAT = 2048 // Don't let this be used in multiplayer unless cheats are on.
CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on.
CV_NOLUA = 4096,/* don't let this be called from Lua */
} cvflags_t;
typedef struct CV_PossibleValue_s
@ -140,6 +149,9 @@ void CV_ToggleExecVersion(boolean enable);
// register a variable for use at the console
void CV_RegisterVar(consvar_t *variable);
// returns a console variable by name
consvar_t *CV_FindVar(const char *name);
// sets changed to 0 for every console variable
void CV_ClearChangedFlags(void);

View File

@ -20,6 +20,7 @@
#include "g_input.h"
#include "hu_stuff.h"
#include "keys.h"
#include "r_main.h"
#include "r_defs.h"
#include "sounds.h"
#include "st_stuff.h"
@ -591,6 +592,8 @@ void CON_ToggleOff(void)
CON_ClearHUD();
con_forcepic = 0;
con_clipviewtop = -1; // remove console clipping of view
I_UpdateMouseGrab();
}
boolean CON_Ready(void)
@ -615,6 +618,7 @@ void CON_Ticker(void)
consoletoggle = false;
con_destlines = 0;
CON_ClearHUD();
I_UpdateMouseGrab();
}
// console key was pushed
@ -627,6 +631,7 @@ void CON_Ticker(void)
{
con_destlines = 0;
CON_ClearHUD();
I_UpdateMouseGrab();
}
else
CON_ChangeHeight();
@ -1285,10 +1290,10 @@ void CONS_Printf(const char *fmt, ...)
con_scrollup = 0;
// if not in display loop, force screen update
if (con_startup)
if (con_startup && (!setrenderneeded))
{
#ifdef _WINDOWS
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_CACHE);
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawScaledPatch(0, 0, 0, con_backpic);
@ -1545,7 +1550,7 @@ static void CON_DrawConsole(void)
// draw console background
if (cons_backpic.value || con_forcepic)
{
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_CACHE);
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawScaledPatch(0, 0, 0, con_backpic);
@ -1602,8 +1607,18 @@ void CON_Drawer(void)
if (!con_started || !graphics_started)
return;
if (needpatchrecache)
{
W_FlushCachedPatches();
HU_LoadGraphics();
}
if (con_recalc)
{
CON_RecalcSize();
if (con_curlines <= 0)
CON_ClearHUD();
}
if (con_curlines > 0)
CON_DrawConsole();

View File

@ -1265,8 +1265,12 @@ static boolean CL_SendJoin(void)
if (splitscreen || botingame)
localplayers++;
netbuffer->u.clientcfg.localplayers = localplayers;
netbuffer->u.clientcfg._255 = 255;
netbuffer->u.clientcfg.packetversion = PACKETVERSION;
netbuffer->u.clientcfg.version = VERSION;
netbuffer->u.clientcfg.subversion = SUBVERSION;
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
sizeof netbuffer->u.clientcfg.application);
strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME);
strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME);
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
@ -1277,15 +1281,20 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
UINT8 *p;
netbuffer->packettype = PT_SERVERINFO;
netbuffer->u.serverinfo._255 = 255;
netbuffer->u.serverinfo.packetversion = PACKETVERSION;
netbuffer->u.serverinfo.version = VERSION;
netbuffer->u.serverinfo.subversion = SUBVERSION;
strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION,
sizeof netbuffer->u.serverinfo.application);
// return back the time value so client can compute their ping
netbuffer->u.serverinfo.time = (tic_t)LONG(servertime);
netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime);
netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value;
netbuffer->u.serverinfo.gametype = (UINT8)gametype;
strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
sizeof netbuffer->u.serverinfo.gametypename);
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated;
@ -1712,12 +1721,21 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
if (serverlistcount >= MAXSERVERLIST)
return; // list full
if (info->_255 != 255)
return;/* old packet format */
if (info->packetversion != PACKETVERSION)
return;/* old new packet format */
if (info->version != VERSION)
return; // Not same version.
if (info->subversion != SUBVERSION)
return; // Close, but no cigar.
if (strcmp(info->application, SRB2APPLICATION))
return;/* that's a different mod */
i = serverlistcount++;
}
@ -2105,13 +2123,10 @@ static void CL_ConnectToServer(boolean viams)
if (i != -1)
{
UINT16 num = serverlist[i].info.gametype;
const char *gametypestr = NULL;
char *gametypestr = serverlist[i].info.gametypename;
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
if (num < gametypecount)
gametypestr = Gametype_Names[num];
if (gametypestr)
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0';
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100,
serverlist[i].info.version%100, serverlist[i].info.subversion);
}
@ -2987,8 +3002,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_RemovePlayer(pnum, kickreason);
}
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}};
@ -3509,6 +3524,12 @@ static void HandleConnect(SINT8 node)
if (bannednode && bannednode[node])
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
else if (netbuffer->u.clientcfg._255 != 255 ||
netbuffer->u.clientcfg.packetversion != PACKETVERSION)
SV_SendRefuse(node, "Incompatible packet formats.");
else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION,
sizeof netbuffer->u.clientcfg.application))
SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible.");
else if (netbuffer->u.clientcfg.version != VERSION
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
@ -3631,6 +3652,10 @@ static void HandleServerInfo(SINT8 node)
const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE;
netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff);
netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0;
netbuffer->u.serverinfo.application
[sizeof netbuffer->u.serverinfo.application - 1] = '\0';
netbuffer->u.serverinfo.gametypename
[sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0';
SL_InsertServer(&netbuffer->u.serverinfo, node);
}

View File

@ -19,6 +19,16 @@
#include "tables.h"
#include "d_player.h"
/*
The 'packet version' may be used with packets whose
format is expected to change between versions.
This version is independent of the mod name, and standard
version and subversion. It should only account for the
basic fields of the packet, and change infrequently.
*/
#define PACKETVERSION 1
// Network play related stuff.
// There is a data struct that stores network
// communication related stuff, and another
@ -320,8 +330,13 @@ typedef struct {
#pragma warning(default : 4200)
#endif
#define MAXAPPLICATION 16
typedef struct
{
UINT8 _255;/* see serverinfo_pak */
UINT8 packetversion;
char application[MAXAPPLICATION];
UINT8 version; // Different versions don't work
UINT8 subversion; // Contains build version
UINT8 localplayers;
@ -334,11 +349,19 @@ typedef struct
// This packet is too large
typedef struct
{
/*
In the old packet, 'version' is the first field. Now that field is set
to 255 always, so older versions won't be confused with the new
versions or vice-versa.
*/
UINT8 _255;
UINT8 packetversion;
char application[MAXAPPLICATION];
UINT8 version;
UINT8 subversion;
UINT8 numberofplayer;
UINT8 maxplayer;
UINT8 gametype;
char gametypename[24];
UINT8 modifiedgame;
UINT8 cheatsenabled;
UINT8 isdedicated;

View File

@ -108,6 +108,8 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo
boolean lastdraw = false;
static void D_CheckRendererState(void);
postimg_t postimgtype = postimg_none;
INT32 postimgparam;
postimg_t postimgtype2 = postimg_none;
@ -212,6 +214,7 @@ INT16 wipetypepost = -1;
static void D_Display(void)
{
INT32 setrenderstillneeded = 0;
boolean forcerefresh = false;
static boolean wipe = false;
INT32 wipedefindex = 0;
@ -222,11 +225,38 @@ static void D_Display(void)
if (nodrawers)
return; // for comparative timing/profiling
// check for change of screen size (video mode)
if (setmodeneeded && !wipe)
SCR_SetMode(); // change video mode
// Lactozilla: Switching renderers works by checking
// if the game has to do it right when the frame
// needs to render. If so, five things will happen:
// 1. Interface functions will be called so
// that switching to OpenGL creates a
// GL context, and switching to Software
// allocates screen buffers.
// 2. Software will set drawer functions,
// and OpenGL will load textures and
// create plane polygons, if necessary.
// 3. Functions related to switching video
// modes (resolution) are called.
// 4. Patch data is freed from memory,
// and recached if necessary.
// 5. The frame is ready to be drawn!
if (vid.recalc)
// stop movie if needs to change renderer
if (setrenderneeded && (moviemode == MM_APNG))
M_StopMovie();
// check for change of renderer or screen size (video mode)
if ((setrenderneeded || setmodeneeded) && !wipe)
{
if (setrenderneeded)
{
CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded);
setrenderstillneeded = setrenderneeded;
}
SCR_SetMode(); // change video mode
}
if (vid.recalc || setrenderstillneeded)
{
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
#ifdef HWRENDER
@ -237,12 +267,15 @@ static void D_Display(void)
}
// change the view size if needed
if (setsizeneeded)
if (setsizeneeded || setrenderstillneeded)
{
R_ExecuteSetViewSize();
forcerefresh = true; // force background redraw
}
// Lactozilla: Renderer switching
D_CheckRendererState();
// draw buffered stuff to screen
// Used only by linux GGI version
I_UpdateNoBlit();
@ -457,7 +490,7 @@ static void D_Display(void)
py = 4;
else
py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_CACHE);
patch = W_CachePatchName("M_PAUSE", PU_PATCH);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch);
#else
INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2));
@ -557,6 +590,25 @@ static void D_Display(void)
I_FinishUpdate(); // page flip or blit buffer
}
needpatchflush = false;
needpatchrecache = false;
}
// Lactozilla: Check the renderer's state
// after a possible renderer switch.
void D_CheckRendererState(void)
{
// flush all patches from memory
// (also frees memory tagged with PU_CACHE)
// (which are not necessarily patches but I don't care)
if (needpatchflush)
Z_FlushCachedPatches();
// some patches have been freed,
// so cache them again
if (needpatchrecache)
R_ReloadHUDGraphics();
}
// =========================================================================
@ -600,8 +652,7 @@ void D_SRB2Loop(void)
// hack to start on a nice clear console screen.
COM_ImmedExecute("cls;version");
if (rendermode == render_soft)
V_DrawScaledPatch(0, 0, 0, (patch_t *)W_CacheLumpNum(W_GetNumForName("CONSBACK"), PU_CACHE));
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE));
I_FinishUpdate(); // page flip or blit buffer
for (;;)
@ -715,7 +766,7 @@ void D_StartTitle(void)
if (netgame)
{
if (gametype == GT_COOP)
if (gametyperules & GTR_CAMPAIGN)
{
G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat
@ -1118,26 +1169,6 @@ void D_SRB2Main(void)
if (M_CheckParm("-server") || dedicated)
netgame = server = true;
if (M_CheckParm("-warp") && M_IsNextParm())
{
const char *word = M_GetNextParm();
char ch; // use this with sscanf to catch non-digits with
if (fastncmp(word, "MAP", 3)) // MAPxx name
pstartmap = M_MapNumber(word[3], word[4]);
else if (sscanf(word, "%d%c", &pstartmap, &ch) != 1) // a plain number
I_Error("Cannot warp to map %s (invalid map name)\n", word);
// Don't check if lump exists just yet because the wads haven't been loaded!
// Just do a basic range check here.
if (pstartmap < 1 || pstartmap > NUMMAPS)
I_Error("Cannot warp to map %d (out of range)\n", pstartmap);
else
{
if (!M_CheckParm("-server"))
G_SetGameModified(true);
autostart = true;
}
}
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
Z_Init();
@ -1194,6 +1225,20 @@ void D_SRB2Main(void)
mainwadstally = packetsizetally; // technically not accurate atm, remember to port the two-stage -file process from kart in 2.2.x
if (M_CheckParm("-warp") && M_IsNextParm())
{
const char *word = M_GetNextParm();
pstartmap = G_FindMapByNameOrCode(word, 0);
if (! pstartmap)
I_Error("Cannot find a map remotely named '%s'\n", word);
else
{
if (!M_CheckParm("-server"))
G_SetGameModified(true);
autostart = true;
}
}
cht_Init();
//---------------------------------------------------- READY SCREEN
@ -1239,6 +1284,16 @@ void D_SRB2Main(void)
// set user default mode or mode set at cmdline
SCR_CheckDefaultMode();
// Lactozilla: Does the render mode need to change?
if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
{
needpatchflush = true;
needpatchrecache = true;
VID_CheckRenderer();
SCR_ChangeRendererCVars(setrenderneeded);
}
D_CheckRendererState();
wipegamestate = gamestate;
savedata.lives = 0; // flag this as not-used

View File

@ -848,6 +848,10 @@ void D_RegisterClientCommands(void)
// screen.c
CV_RegisterVar(&cv_fullscreen);
CV_RegisterVar(&cv_renderview);
CV_RegisterVar(&cv_renderer);
#ifdef HWRENDER
CV_RegisterVar(&cv_newrenderer);
#endif
CV_RegisterVar(&cv_scr_depth);
CV_RegisterVar(&cv_scr_width);
CV_RegisterVar(&cv_scr_height);
@ -1809,18 +1813,15 @@ static void Command_Map_f(void)
boolean newresetplayers;
boolean mustmodifygame;
boolean usemapcode = false;
INT32 newmapnum;
char * mapname;
size_t mapnamelen;
char *realmapname = NULL;
INT32 newgametype = gametype;
INT32 d;
char *p;
if (client && !IsPlayerAdmin(consoleplayer))
{
@ -1880,43 +1881,8 @@ static void Command_Map_f(void)
}
mapname = ConcatCommandArgv(1, first_option);
mapnamelen = strlen(mapname);
if (mapnamelen == 2)/* maybe two digit code */
{
if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) ))
usemapcode = true;
}
else if (mapnamelen == 5 && strnicmp(mapname, "MAP", 3) == 0)
{
if (( newmapnum = M_MapNumber(mapname[3], mapname[4]) ) == 0)
{
CONS_Alert(CONS_ERROR, M_GetText("Invalid map code '%s'.\n"), mapname);
Z_Free(mapname);
return;
}
usemapcode = true;
}
if (!usemapcode)
{
/* Now detect map number in base 10, which no one asked for. */
newmapnum = strtol(mapname, &p, 10);
if (*p == '\0')/* we got it */
{
if (newmapnum < 1 || newmapnum > NUMMAPS)
{
CONS_Alert(CONS_ERROR, M_GetText("Invalid map number %d.\n"), newmapnum);
Z_Free(mapname);
return;
}
usemapcode = true;
}
else
{
newmapnum = G_FindMap(mapname, &realmapname, NULL, NULL);
}
}
newmapnum = G_FindMapByNameOrCode(mapname, &realmapname);
if (newmapnum == 0)
{
@ -1925,11 +1891,6 @@ static void Command_Map_f(void)
return;
}
if (usemapcode)
{
realmapname = G_BuildMapTitle(newmapnum);
}
if (mustmodifygame && option_force)
{
G_SetGameModified(false);
@ -2209,6 +2170,8 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
else
S_ResumeAudio();
}
I_UpdateMouseGrab();
}
// Command for stuck characters in netgames, griefing, etc.
@ -3745,7 +3708,7 @@ static void CoopStarposts_OnChange(void)
{
INT32 i;
if (!(netgame || multiplayer) || gametype != GT_COOP)
if (!(netgame || multiplayer) || !G_GametypeUsesCoopStarposts())
return;
switch (cv_coopstarposts.value)
@ -3800,7 +3763,7 @@ static void CoopLives_OnChange(void)
{
INT32 i;
if (!(netgame || multiplayer) || gametype != GT_COOP)
if (!(netgame || multiplayer) || !G_GametypeUsesCoopLives())
return;
switch (cv_cooplives.value)

View File

@ -4804,11 +4804,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
if (introchanged)
{
menuactive = false;
I_UpdateMouseGrab();
COM_BufAddText("playintro");
}
else if (titlechanged)
{
menuactive = false;
I_UpdateMouseGrab();
COM_BufAddText("exitgame"); // Command_ExitGame_f() but delayed
}
}
@ -8824,9 +8826,11 @@ static const char *const MOBJEFLAG_LIST[] = {
"JUSTSTEPPEDDOWN", // used for ramp sectors
"VERTICALFLIP", // Vertically flip sprite/allow upside-down physics
"GOOWATER", // Goo water
"TOUCHLAVA", // The mobj is touching a lava block
"PUSHED", // Mobj was already pushed this tic
"SPRUNG", // Mobj was already sprung this tic
"APPLYPMOMZ", // Platform movement
"TRACERANGLE", // Compute and trigger on mobj angle relative to tracer
NULL
};
@ -8902,32 +8906,35 @@ static const char *const GAMETYPERULE_LIST[] = {
"CAMPAIGN",
"RINGSLINGER",
"SPECTATORS",
"FRIENDLYFIRE",
"LIVES",
"TEAMS",
"FIRSTPERSON",
"POWERSTONES",
"TEAMFLAGS",
"FRIENDLY",
"SPECIALSTAGES",
"EMERALDTOKENS",
"EMERALDHUNT",
"RACE",
"TAG",
"POINTLIMIT",
"TIMELIMIT",
"HIDETIME",
"OVERTIME",
"HURTMESSAGES",
"FRIENDLYFIRE",
"STARTCOUNTDOWN",
"HIDEFROZEN",
"BLINDFOLDED",
"FIRSTPERSON",
"MATCHEMERALDS",
"TEAMFLAGS",
"RESPAWNDELAY",
"PITYSHIELD",
"DEATHPENALTY",
"NOSPECTATORSPAWN",
"DEATHMATCHSTARTS",
"SPECIALSTAGES",
"EMERALDTOKENS",
"EMERALDHUNT",
"SPAWNINVUL",
"SPAWNENEMIES",
"ALLOWEXIT",
"NOTITLECARD",
"OVERTIME",
"HURTMESSAGES",
"SPAWNINVUL",
"CUTSCENES",
NULL
};
@ -9744,6 +9751,7 @@ struct {
{"CV_HIDEN",CV_HIDEN},
{"CV_HIDDEN",CV_HIDEN},
{"CV_CHEAT",CV_CHEAT},
{"CV_NOLUA",CV_NOLUA},
// v_video flags
{"V_NOSCALEPATCH",V_NOSCALEPATCH},

View File

@ -338,3 +338,8 @@ void I_StartupGraphics(void)
graphics_started = true;
}
void I_StartupHardwareGraphics(void)
{
// oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y
}

View File

@ -378,6 +378,11 @@ INT32 VID_SetMode (INT32 modenum) //, UINT8 *palette)
return 1;
}
void VID_CheckRenderer(void)
{
// ..............
}
// converts a segm:offs 32bit pair to a 32bit flat ptr

View File

@ -130,6 +130,9 @@ extern FILE *logstream;
extern char logfilename[1024];
#endif
/* A mod name to further distinguish versions. */
#define SRB2APPLICATION "SRB2"
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
#ifdef DEVELOP
#define VERSION 0 // Game version
@ -461,6 +464,8 @@ extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
char *va(const char *format, ...) FUNCPRINTF;
char *M_GetToken(const char *inputString);
void M_UnGetToken(void);
UINT32 M_GetTokenPos(void);
void M_SetTokenPos(UINT32 newPos);
char *sizeu1(size_t num);
char *sizeu2(size_t num);
char *sizeu3(size_t num);
@ -623,6 +628,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
#define SECTORSPECIALSAFTERTHINK
/// Cache patches in Lua in a way that renderer switching will work flawlessly.
//#define LUA_PATCH_SAFETY
/// Sprite rotation
#define ROTSPRITE
#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...)

View File

@ -397,32 +397,35 @@ enum GameTypeRules
GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps
GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger)
GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race
GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire
GTR_LIVES = 1<<4, // Co-op and Competition
GTR_TEAMS = 1<<5, // Team Match, CTF
GTR_RACE = 1<<6, // Race and Competition
GTR_TAG = 1<<7, // Tag and Hide and Seek
GTR_POINTLIMIT = 1<<8, // Ringslinger point limit
GTR_TIMELIMIT = 1<<9, // Ringslinger time limit
GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek)
GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag)
GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek)
GTR_FIRSTPERSON = 1<<13, // First person camera
GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF)
GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF)
GTR_PITYSHIELD = 1<<16, // Award pity shield
GTR_DEATHPENALTY = 1<<17, // Death score penalty
GTR_NOSPECTATORSPAWN = 1<<18, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators
GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts
GTR_SPECIALSTAGES = 1<<20, // Allow special stages
GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens
GTR_EMERALDHUNT = 1<<22, // Emerald Hunt
GTR_SPAWNENEMIES = 1<<23, // Spawn enemies
GTR_ALLOWEXIT = 1<<24, // Allow exit sectors
GTR_NOTITLECARD = 1<<25, // Don't show the title card
GTR_OVERTIME = 1<<26, // Allow overtime
GTR_HURTMESSAGES = 1<<27, // Hit and death messages
GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent
GTR_LIVES = 1<<3, // Co-op and Competition
GTR_TEAMS = 1<<4, // Team Match, CTF
GTR_FIRSTPERSON = 1<<5, // First person camera
GTR_POWERSTONES = 1<<6, // Power stones (Match and CTF)
GTR_TEAMFLAGS = 1<<7, // Gametype has team flags (CTF)
GTR_FRIENDLY = 1<<8, // Co-op
GTR_SPECIALSTAGES = 1<<9, // Allow special stages
GTR_EMERALDTOKENS = 1<<10, // Spawn emerald tokens
GTR_EMERALDHUNT = 1<<11, // Emerald Hunt
GTR_RACE = 1<<12, // Race and Competition
GTR_TAG = 1<<13, // Tag and Hide and Seek
GTR_POINTLIMIT = 1<<14, // Ringslinger point limit
GTR_TIMELIMIT = 1<<15, // Ringslinger time limit
GTR_OVERTIME = 1<<16, // Allow overtime
GTR_HURTMESSAGES = 1<<17, // Hit and death messages
GTR_FRIENDLYFIRE = 1<<18, // Always allow friendly fire
GTR_STARTCOUNTDOWN = 1<<19, // Hide time countdown (Tag and Hide and Seek)
GTR_HIDEFROZEN = 1<<20, // Frozen after hide time (Hide and Seek, but not Tag)
GTR_BLINDFOLDED = 1<<21, // Blindfolded view (Tag and Hide and Seek)
GTR_RESPAWNDELAY = 1<<22, // Respawn delay
GTR_PITYSHIELD = 1<<23, // Award pity shield
GTR_DEATHPENALTY = 1<<24, // Death score penalty
GTR_NOSPECTATORSPAWN = 1<<25, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators
GTR_DEATHMATCHSTARTS = 1<<26, // Use deathmatch starts
GTR_SPAWNINVUL = 1<<27, // Babysitting deterrent
GTR_SPAWNENEMIES = 1<<28, // Spawn enemies
GTR_ALLOWEXIT = 1<<29, // Allow exit sectors
GTR_NOTITLECARD = 1<<30, // Don't show the title card
GTR_CUTSCENES = 1<<31, // Play cutscenes, ending, credits, and evaluation
};
// String names for gametypes

View File

@ -150,6 +150,8 @@ void I_GetJoystick2Events(void){}
void I_GetMouseEvents(void){}
void I_UpdateMouseGrab(void){}
char *I_GetEnv(const char *name)
{
(void)name;

View File

@ -11,6 +11,7 @@ boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
void I_StartupGraphics(void){}
void I_StartupHardwareGraphics(void){}
void I_ShutdownGraphics(void){}
@ -39,6 +40,11 @@ INT32 VID_SetMode(INT32 modenum)
return 0;
}
void VID_CheckRenderer(void)
{
// ..............
}
const char *VID_GetModeName(INT32 modenum)
{
(void)modenum;

View File

@ -530,78 +530,78 @@ static void F_IntroDrawScene(void)
case 0:
break;
case 1:
background = W_CachePatchName("INTRO1", PU_CACHE);
background = W_CachePatchName("INTRO1", PU_PATCH);
break;
case 2:
background = W_CachePatchName("INTRO2", PU_CACHE);
background = W_CachePatchName("INTRO2", PU_PATCH);
break;
case 3:
background = W_CachePatchName("INTRO3", PU_CACHE);
background = W_CachePatchName("INTRO3", PU_PATCH);
break;
case 4:
background = W_CachePatchName("INTRO4", PU_CACHE);
background = W_CachePatchName("INTRO4", PU_PATCH);
break;
case 5:
if (intro_curtime >= 5*TICRATE)
background = W_CachePatchName("RADAR", PU_CACHE);
background = W_CachePatchName("RADAR", PU_PATCH);
else
background = W_CachePatchName("DRAT", PU_CACHE);
background = W_CachePatchName("DRAT", PU_PATCH);
break;
case 6:
background = W_CachePatchName("INTRO6", PU_CACHE);
background = W_CachePatchName("INTRO6", PU_PATCH);
cx = 180;
cy = 8;
break;
case 7:
{
if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2))
background = W_CachePatchName("SGRASS5", PU_CACHE);
background = W_CachePatchName("SGRASS5", PU_PATCH);
else if (intro_curtime >= 7*TICRATE + (TICRATE/7))
background = W_CachePatchName("SGRASS4", PU_CACHE);
background = W_CachePatchName("SGRASS4", PU_PATCH);
else if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SGRASS3", PU_CACHE);
background = W_CachePatchName("SGRASS3", PU_PATCH);
else if (intro_curtime >= 6*TICRATE)
background = W_CachePatchName("SGRASS2", PU_CACHE);
background = W_CachePatchName("SGRASS2", PU_PATCH);
else
background = W_CachePatchName("SGRASS1", PU_CACHE);
background = W_CachePatchName("SGRASS1", PU_PATCH);
break;
}
case 8:
background = W_CachePatchName("WATCHING", PU_CACHE);
background = W_CachePatchName("WATCHING", PU_PATCH);
break;
case 9:
background = W_CachePatchName("ZOOMING", PU_CACHE);
background = W_CachePatchName("ZOOMING", PU_PATCH);
break;
case 10:
break;
case 11:
background = W_CachePatchName("INTRO5", PU_CACHE);
background = W_CachePatchName("INTRO5", PU_PATCH);
break;
case 12:
background = W_CachePatchName("REVENGE", PU_CACHE);
background = W_CachePatchName("REVENGE", PU_PATCH);
cx = 208;
cy = 8;
break;
case 13:
background = W_CachePatchName("CONFRONT", PU_CACHE);
background = W_CachePatchName("CONFRONT", PU_PATCH);
cy += 48;
break;
case 14:
background = W_CachePatchName("TAILSSAD", PU_CACHE);
background = W_CachePatchName("TAILSSAD", PU_PATCH);
bgxoffs = 144;
cx = 8;
cy = 8;
break;
case 15:
if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SONICDO2", PU_CACHE);
background = W_CachePatchName("SONICDO2", PU_PATCH);
else
background = W_CachePatchName("SONICDO1", PU_CACHE);
background = W_CachePatchName("SONICDO1", PU_PATCH);
cx = 224;
cy = 8;
break;
case 16:
background = W_CachePatchName("INTRO7", PU_CACHE);
background = W_CachePatchName("INTRO7", PU_PATCH);
break;
default:
break;
@ -631,30 +631,30 @@ static void F_IntroDrawScene(void)
S_ChangeMusicInternal("_stjr", false);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(334<<FRACBITS, aspect)/2;
y = (BASEVIDHEIGHT<<FRACBITS)/2 - FixedMul(358<<FRACBITS, aspect)/2;
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH1", PU_CACHE)), aspect);
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH1", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
if (finalecount > 6) {
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_CACHE)), aspect);
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
if (finalecount > 10) {
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_CACHE)), aspect);
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
if (finalecount > 14) {
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_CACHE)), aspect);
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
}
else if (finalecount-30 < 20) { // Big eggy
background = W_CachePatchName("FEEDIN", PU_CACHE);
background = W_CachePatchName("FEEDIN", PU_PATCH);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(560<<FRACBITS, aspect)/2;
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(477<<FRACBITS, aspect);
V_DrawSciencePatch(x, y, V_SNAPTOBOTTOM, background, aspect);
}
else if (finalecount-50 < 30) { // Zoom out
fixed_t scale = FixedDiv(aspect, FixedDiv((finalecount-50)<<FRACBITS, (15<<FRACBITS))+FRACUNIT);
background = W_CachePatchName("FEEDIN", PU_CACHE);
background = W_CachePatchName("FEEDIN", PU_PATCH);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(560<<FRACBITS, aspect)/2 + (FixedMul(560<<FRACBITS, aspect) - FixedMul(560<<FRACBITS, scale));
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(477<<FRACBITS, scale);
V_DrawSciencePatch(x, y, V_SNAPTOBOTTOM, background, scale);
@ -664,7 +664,7 @@ static void F_IntroDrawScene(void)
{
// Draw tiny eggy
fixed_t scale = FixedMul(FRACUNIT/3, aspect);
background = W_CachePatchName("FEEDIN", PU_CACHE);
background = W_CachePatchName("FEEDIN", PU_PATCH);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(560<<FRACBITS, aspect)/2 + (FixedMul(560<<FRACBITS, aspect) - FixedMul(560<<FRACBITS, scale));
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(477<<FRACBITS, scale);
V_DrawSciencePatch(x, y, V_SNAPTOBOTTOM, background, scale);
@ -675,34 +675,34 @@ static void F_IntroDrawScene(void)
x = (-189*FRACUNIT) + (FixedMul((6<<FRACBITS)+FRACUNIT/3, ftime<<FRACBITS) - FixedMul((6<<FRACBITS)+FRACUNIT/3, FixedDiv(FixedMul(ftime<<FRACBITS, ftime<<FRACBITS), 120<<FRACBITS)));
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(417<<FRACBITS, aspect);
// Draw the body
V_DrawSciencePatch(x, y, V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT1", PU_CACHE)), aspect);
V_DrawSciencePatch(x, y, V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT1", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the door
V_DrawSciencePatch(x+FixedMul(344<<FRACBITS, aspect), y+FixedMul(292<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT2", PU_CACHE)), aspect);
V_DrawSciencePatch(x+FixedMul(344<<FRACBITS, aspect), y+FixedMul(292<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT2", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel
V_DrawSciencePatch(x+FixedMul(178<<FRACBITS, aspect), y+FixedMul(344<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName(va("TYRE%02u",(abs(finalecount-144)/3)%16), PU_CACHE)), aspect);
V_DrawSciencePatch(x+FixedMul(178<<FRACBITS, aspect), y+FixedMul(344<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName(va("TYRE%02u",(abs(finalecount-144)/3)%16), PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel cover
V_DrawSciencePatch(x+FixedMul(88<<FRACBITS, aspect), y+FixedMul(238<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT3", PU_CACHE)), aspect);
V_DrawSciencePatch(x+FixedMul(88<<FRACBITS, aspect), y+FixedMul(238<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT3", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
} else { // Pure Fat has stopped!
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(417<<FRACBITS, aspect);
// Draw the body
V_DrawSciencePatch(0, y, V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT1", PU_CACHE)), aspect);
V_DrawSciencePatch(0, y, V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT1", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel
V_DrawSciencePatch(FixedMul(178<<FRACBITS, aspect), y+FixedMul(344<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("TYRE00", PU_CACHE)), aspect);
V_DrawSciencePatch(FixedMul(178<<FRACBITS, aspect), y+FixedMul(344<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("TYRE00", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel cover
V_DrawSciencePatch(FixedMul(88<<FRACBITS, aspect), y+FixedMul(238<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT3", PU_CACHE)), aspect);
V_DrawSciencePatch(FixedMul(88<<FRACBITS, aspect), y+FixedMul(238<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT3", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the door
if (finalecount-TICRATE/2 > 4*TICRATE) { // Door is being raised!
int ftime = (finalecount-TICRATE/2-4*TICRATE);
y -= FixedDiv((ftime*ftime)<<FRACBITS, 23<<FRACBITS);
}
V_DrawSciencePatch(FixedMul(344<<FRACBITS, aspect), y+FixedMul(292<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT2", PU_CACHE)), aspect);
V_DrawSciencePatch(FixedMul(344<<FRACBITS, aspect), y+FixedMul(292<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT2", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
}
@ -716,27 +716,27 @@ static void F_IntroDrawScene(void)
if (timetonext > 5*TICRATE && timetonext < 6*TICRATE)
{
if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG1", PU_CACHE);
background = W_CachePatchName("BRITEGG1", PU_PATCH);
else
background = W_CachePatchName("DARKEGG1", PU_CACHE);
background = W_CachePatchName("DARKEGG1", PU_PATCH);
V_DrawSmallScaledPatch(0, 0, 0, background);
}
else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE)
{
if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG2", PU_CACHE);
background = W_CachePatchName("BRITEGG2", PU_PATCH);
else
background = W_CachePatchName("DARKEGG2", PU_CACHE);
background = W_CachePatchName("DARKEGG2", PU_PATCH);
V_DrawSmallScaledPatch(0, 0, 0, background);
}
else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE)
{
if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG3", PU_CACHE);
background = W_CachePatchName("BRITEGG3", PU_PATCH);
else
background = W_CachePatchName("DARKEGG3", PU_CACHE);
background = W_CachePatchName("DARKEGG3", PU_PATCH);
V_DrawSmallScaledPatch(0, 0, 0, background);
}
@ -768,79 +768,79 @@ static void F_IntroDrawScene(void)
knucklesx += sonicx;
sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3);
V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_CACHE)));
V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH)));
V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch);
V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_CACHE)));
V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH)));
V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch);
if (finalecount & 1)
{
// Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_CACHE)));
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Appendages
if (finalecount & 2)
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_CACHE)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_CACHE)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH)));
W_UnlockCachedPatch(patch);
}
else
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_CACHE)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_CACHE)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH)));
W_UnlockCachedPatch(patch);
}
// Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_CACHE)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_CACHE)));
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH)));
W_UnlockCachedPatch(patch);
}
else
{
// Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_CACHE)));
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Appendages
if (finalecount & 2)
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_CACHE)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_CACHE)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH)));
W_UnlockCachedPatch(patch);
}
else
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_CACHE)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_CACHE)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH)));
W_UnlockCachedPatch(patch);
}
// Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_CACHE)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH)));
W_UnlockCachedPatch(patch);
// Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_CACHE)));
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH)));
W_UnlockCachedPatch(patch);
}
@ -873,8 +873,8 @@ static void F_IntroDrawScene(void)
y += (30*(FRACUNIT-scale));
}
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_LEVEL);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_LEVEL);
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH);
if (worktics >= 5)
trans = (worktics-5)>>1;
@ -988,7 +988,7 @@ void F_IntroDrawer(void)
{
if (intro_scenenum == 5 && intro_curtime == 5*TICRATE)
{
patch_t *radar = W_CachePatchName("RADAR", PU_CACHE);
patch_t *radar = W_CachePatchName("RADAR", PU_PATCH);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -1001,7 +1001,7 @@ void F_IntroDrawer(void)
}
else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here
{
patch_t *grass = W_CachePatchName("SGRASS2", PU_CACHE);
patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -1014,7 +1014,7 @@ void F_IntroDrawer(void)
}
/*else if (intro_scenenum == 12 && intro_curtime == 7*TICRATE)
{
patch_t *confront = W_CachePatchName("CONFRONT", PU_CACHE);
patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -1027,7 +1027,7 @@ void F_IntroDrawer(void)
}*/
if (intro_scenenum == 15 && intro_curtime == 7*TICRATE)
{
patch_t *sdo = W_CachePatchName("SONICDO2", PU_CACHE);
patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -1359,14 +1359,14 @@ void F_CreditDrawer(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Zig Zagz
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_CACHE));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_CACHE));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_CACHE));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_CACHE));
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH));
// Draw background pictures first
for (i = 0; credits_pics[i].patch; i++)
V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_CACHE), FRACUNIT>>1);
V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH), FRACUNIT>>1);
// Dim the background
V_DrawFadeScreen(0xFF00, 16);
@ -1574,14 +1574,14 @@ void F_GameEvaluationDrawer(void)
if (goodending)
{
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_LEVEL);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_LEVEL);
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH);
x -= FRACUNIT;
}
else
{
rockpat = W_CachePatchName("ROID0000", PU_LEVEL);
glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_LEVEL);
glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH);
}
if (finalecount >= 5)
@ -1613,20 +1613,20 @@ void F_GameEvaluationDrawer(void)
// if j == 0 - alternate between 0 and 1
// 1 - 1 and 2
// 2 - 2 and not rendered
V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_LEVEL), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE));
V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE));
}
j--;
}
}
else
{
patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_LEVEL);
patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH);
V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]);
if (trans < 10)
V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, eggrock, colormap[1]);
else if (sparklloop)
V_DrawFixedPatch(x, y, scale, (10-sparklloop)<<V_ALPHASHIFT,
W_CachePatchName("ENDEGRK0", PU_LEVEL), colormap[1]);
W_CachePatchName("ENDEGRK0", PU_PATCH), colormap[1]);
}
}
@ -1640,7 +1640,7 @@ void F_GameEvaluationDrawer(void)
eemeralds_cur += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_LEVEL), NULL);
V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH), NULL);
}
V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext);
@ -1753,6 +1753,83 @@ void F_GameEvaluationTicker(void)
#define STOPPINGPOINT (14*TICRATE)
#define SPARKLLOOPTIME 15 // must be odd
static void F_CacheEnding(void)
{
endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH);
endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH);
endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH);
endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH);
endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH);
endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH);
endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH);
endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH);
endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH);
endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH);
endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH);
endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH);
endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH);
endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH);
endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH);
endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH);
endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH);
endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH);
endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH);
endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH);
// so we only need to check once
if ((goodending = ALL7EMERALDS(emeralds)))
{
UINT8 skinnum = players[consoleplayer].skin;
spritedef_t *sprdef;
spriteframe_t *sprframe;
if (skins[skinnum].sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2))
{
sprdef = &skins[skinnum].sprites[SPR2_XTRA];
// character head, skin specific
sprframe = &sprdef->spriteframes[XTRA_ENDING];
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
}
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH);
}
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH);
}
else
{
// eggman, skin nonspecific
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH);
endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL);
}
}
static void F_CacheGoodEnding(void)
{
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH);
endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH);
endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH);
endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH);
endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH);
}
void F_StartEnding(void)
{
G_SetGamestate(GS_ENDING);
@ -1768,7 +1845,7 @@ void F_StartEnding(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
S_StopMusic();
S_StopMusic(); // todo: placeholder
S_StopSounds();
finalecount = -10; // what? this totally isn't a hack. why are you asking?
@ -1776,68 +1853,7 @@ void F_StartEnding(void)
memset(sparkloffs, 0, sizeof(INT32)*3*2);
sparklloop = 0;
endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_LEVEL);
endegrk[0] = W_CachePatchName("ENDEGRK0", PU_LEVEL);
endegrk[1] = W_CachePatchName("ENDEGRK1", PU_LEVEL);
endglow[0] = W_CachePatchName("ENDGLOW0", PU_LEVEL);
endglow[1] = W_CachePatchName("ENDGLOW1", PU_LEVEL);
endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_LEVEL);
endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_LEVEL);
endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_LEVEL);
endspkl[0] = W_CachePatchName("ENDSPKL0", PU_LEVEL);
endspkl[1] = W_CachePatchName("ENDSPKL1", PU_LEVEL);
endspkl[2] = W_CachePatchName("ENDSPKL2", PU_LEVEL);
endxpld[0] = W_CachePatchName("ENDXPLD0", PU_LEVEL);
endxpld[1] = W_CachePatchName("ENDXPLD1", PU_LEVEL);
endxpld[2] = W_CachePatchName("ENDXPLD2", PU_LEVEL);
endxpld[3] = W_CachePatchName("ENDXPLD3", PU_LEVEL);
endescp[0] = W_CachePatchName("ENDESCP0", PU_LEVEL);
endescp[1] = W_CachePatchName("ENDESCP1", PU_LEVEL);
endescp[2] = W_CachePatchName("ENDESCP2", PU_LEVEL);
endescp[3] = W_CachePatchName("ENDESCP3", PU_LEVEL);
endescp[4] = W_CachePatchName("ENDESCP4", PU_LEVEL);
// so we only need to check once
if ((goodending = ALL7EMERALDS(emeralds)))
{
UINT8 skinnum = players[consoleplayer].skin;
spritedef_t *sprdef;
spriteframe_t *sprframe;
if (skins[skinnum].sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2))
{
sprdef = &skins[skinnum].sprites[SPR2_XTRA];
// character head, skin specific
sprframe = &sprdef->spriteframes[XTRA_ENDING];
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
}
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_LEVEL);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_LEVEL);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_LEVEL);
}
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL);
}
else
{
// eggman, skin nonspecific
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL);
endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL);
}
F_CacheEnding();
}
void F_EndingTicker(void)
@ -1853,15 +1869,7 @@ void F_EndingTicker(void)
S_ChangeMusicInternal((goodending ? "_endg" : "_endb"), false);
if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets
{
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL);
endegrk[1] = W_CachePatchName("ENDEGRK3", PU_LEVEL);
endglow[0] = W_CachePatchName("ENDGLOW2", PU_LEVEL);
endglow[1] = W_CachePatchName("ENDGLOW3", PU_LEVEL);
endxpld[0] = W_CachePatchName("ENDEGRK4", PU_LEVEL);
}
F_CacheGoodEnding();
if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again
{
@ -1880,10 +1888,17 @@ void F_EndingDrawer(void)
INT32 x, y, i, j, parallaxticker;
patch_t *rockpat;
if (needpatchrecache)
{
F_CacheEnding();
if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets
F_CacheGoodEnding();
}
if (!goodending || finalecount < INFLECTIONPOINT)
rockpat = W_CachePatchName("ROID0000", PU_LEVEL);
rockpat = W_CachePatchName("ROID0000", PU_PATCH);
else
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_LEVEL);
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
@ -2367,11 +2382,11 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
if (!scrollxspeed && !scrollyspeed)
{
V_DrawPatchFill(W_CachePatchName(patchname, PU_CACHE));
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH));
return;
}
pat = W_CachePatchName(patchname, PU_CACHE);
pat = W_CachePatchName(patchname, PU_PATCH);
patwidth = SHORT(pat->width);
patheight = SHORT(pat->height);
@ -2432,6 +2447,45 @@ else if (strlen(name) <= 6) \
else \
arr[0] = 0;
static void F_CacheTitleScreen(void)
{
switch(curttmode)
{
case TTMODE_OLD:
case TTMODE_NONE:
ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL);
ttwing = W_CachePatchName("TTWING", PU_LEVEL);
ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL);
ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL);
ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL);
ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL);
ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL);
ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL);
ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL);
ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL);
ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL);
ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL);
ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL);
ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL);
ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL);
break;
// don't load alacroix gfx yet; we do that upon first draw.
case TTMODE_ALACROIX:
break;
case TTMODE_USER:
{
UINT16 i;
lumpnum_t lumpnum;
char lumpname[9];
LOADTTGFX(ttuser, curttname, TTMAX_USER)
break;
}
}
}
void F_StartTitleScreen(void)
{
if (menupres[MN_MAIN].musname[0])
@ -2493,7 +2547,7 @@ void F_StartTitleScreen(void)
camera.x = startpos->x << FRACBITS;
camera.y = startpos->y << FRACBITS;
camera.subsector = R_PointInSubsector(camera.x, camera.y);
camera.z = camera.subsector->sector->floorheight + ((startpos->options >> ZSHIFT) << FRACBITS);
camera.z = camera.subsector->sector->floorheight + (startpos->z << FRACBITS);
camera.angle = (startpos->angle % 360)*ANG1;
camera.aiming = 0;
}
@ -2528,41 +2582,7 @@ void F_StartTitleScreen(void)
demoDelayLeft = demoDelayTime;
demoIdleLeft = demoIdleTime;
switch(curttmode)
{
case TTMODE_OLD:
case TTMODE_NONE:
ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL);
ttwing = W_CachePatchName("TTWING", PU_LEVEL);
ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL);
ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL);
ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL);
ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL);
ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL);
ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL);
ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL);
ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL);
ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL);
ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL);
ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL);
ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL);
ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL);
break;
// don't load alacroix gfx yet; we do that upon first draw.
case TTMODE_ALACROIX:
break;
case TTMODE_USER:
{
UINT16 i;
lumpnum_t lumpnum;
char lumpname[9];
LOADTTGFX(ttuser, curttname, TTMAX_USER)
break;
}
}
F_CacheTitleScreen();
}
static void F_UnloadAlacroixGraphics(SINT8 oldttscale)
@ -2711,6 +2731,9 @@ void F_TitleScreenDrawer(void)
if (modeattacking)
return; // We likely came here from retrying. Don't do a damn thing.
if (needpatchrecache && (curttmode != TTMODE_ALACROIX))
F_CacheTitleScreen();
// Draw that sky!
if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
@ -2734,6 +2757,12 @@ void F_TitleScreenDrawer(void)
return;
#endif
if (needpatchrecache && (curttmode == TTMODE_ALACROIX))
{
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0;
F_LoadAlacroixGraphics(activettscale);
}
switch(curttmode)
{
case TTMODE_OLD:
@ -3681,7 +3710,7 @@ void F_ContinueDrawer(void)
V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?");
// Two stars...
patch = W_CachePatchName("CONTSTAR", PU_CACHE);
patch = W_CachePatchName("CONTSTAR", PU_PATCH);
V_DrawScaledPatch(x-32, 160, 0, patch);
V_DrawScaledPatch(x+32, 160, 0, patch);
@ -3689,14 +3718,14 @@ void F_ContinueDrawer(void)
if (timeleft > 9)
{
numbuf[7] = '1';
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE));
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH));
numbuf[7] = '0';
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE));
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH));
}
else
{
numbuf[7] = '0'+timeleft;
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_CACHE));
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH));
}
// Draw the continue markers! Show continues.
@ -3723,7 +3752,7 @@ void F_ContinueDrawer(void)
}
// Spotlight
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_CACHE));
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH));
// warping laser
if (continuetime)
@ -3760,7 +3789,7 @@ void F_ContinueDrawer(void)
#define drawchar(dx, dy, n) {\
sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\
sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_CACHE);\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH);\
V_DrawFixedPatch((dx), (dy), FRACUNIT, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
}
@ -4024,10 +4053,10 @@ void F_CutsceneDrawer(void)
{
if (cutscenes[cutnum]->scene[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE));
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH));
else
V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE));
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH));
}
if (dofadenow && rendermode != render_none)
@ -4513,10 +4542,10 @@ void F_TextPromptDrawer(void)
{
if (textprompts[cutnum]->page[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_CACHE));
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH));
else
V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_CACHE));
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH));
}
// Draw background
@ -4526,7 +4555,7 @@ void F_TextPromptDrawer(void)
if (iconlump != LUMPERROR)
{
INT32 iconx, icony, scale, scaledsize;
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_CACHE);
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH);
// scale and center
if (patch->width > patch->height)

View File

@ -1718,6 +1718,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver
B_BuildTiccmd(player, cmd);
}
B_HandleFlightIndicator(player);
}
if (cv_analog2.value) {
@ -1839,6 +1840,7 @@ void G_DoLoadLevel(boolean resetplayer)
titlemapinaction = TITLEMAP_OFF;
G_SetGamestate(GS_LEVEL);
I_UpdateMouseGrab();
for (i = 0; i < MAXPLAYERS; i++)
{
@ -1854,8 +1856,7 @@ void G_DoLoadLevel(boolean resetplayer)
return;
}
if (!resetplayer)
P_FindEmerald();
P_FindEmerald();
displayplayer = consoleplayer; // view the guy you are playing
if (!splitscreen && !botingame)
@ -2689,8 +2690,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
// -- DM/Tag/CTF-spectator/etc --
// Order: DM->CTF->Coop
else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF
|| ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT)))
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT))
{
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
@ -2891,11 +2891,11 @@ void G_DoReborn(INT32 playernum)
if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP))
resetlevel = true;
else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
{
boolean notgameover = true;
if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first
if (G_GametypeUsesCoopLives() && (cv_cooplives.value != 0 && player->lives <= 0)) // consider game over first
{
for (i = 0; i < MAXPLAYERS; i++)
{
@ -2930,7 +2930,7 @@ void G_DoReborn(INT32 playernum)
}
}
if (notgameover && cv_coopstarposts.value == 2)
if (G_GametypeUsesCoopStarposts() && (notgameover && cv_coopstarposts.value == 2))
{
for (i = 0; i < MAXPLAYERS; i++)
{
@ -2965,7 +2965,7 @@ void G_DoReborn(INT32 playernum)
}
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD))
{
P_LoadThingsOnly();
P_RespawnThings();
for (i = 0; i < MAXPLAYERS; i++)
{
@ -3006,7 +3006,7 @@ void G_DoReborn(INT32 playernum)
}
// restore time in netgame (see also p_setup.c)
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2)
{
// is this a hack? maybe
tic_t maxstarposttime = 0;
@ -3077,7 +3077,7 @@ void G_AddPlayer(INT32 playernum)
if (!players[i].exiting)
notexiting++;
if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
if (!(cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (p->starpostnum < players[i].starpostnum)))
continue;
p->starpostscale = players[i].starpostscale;
@ -3194,24 +3194,24 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] =
UINT32 gametypedefaultrules[NUMGAMETYPES] =
{
// Co-op
GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES,
GTR_CAMPAIGN|GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES|GTR_CUTSCENES,
// Competition
GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
// Race
GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
// Match
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY,
// Team Match
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
// Tag
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
// Hide and Seek
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
// CTF
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
};
//
@ -3252,50 +3252,68 @@ INT16 G_AddGametype(UINT32 rules)
//
void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
{
char *gtconst = Z_Malloc(strlen(newgtconst) + 3, PU_STATIC, NULL);
// Copy GT_ and the gametype name.
strcpy(gtconst, "GT_");
strcat(gtconst, newgtconst);
size_t r = 0; // read
size_t w = 0; // write
char *gtconst = Z_Calloc(strlen(newgtconst) + 3, PU_STATIC, NULL);
char *tmpconst = Z_Calloc(strlen(newgtconst), PU_STATIC, NULL);
// Copy the gametype name.
strcpy(tmpconst, newgtconst);
// Make uppercase.
strupr(gtconst);
// Remove characters.
#define REMOVECHAR(chr) \
{ \
char *chrfind = strchr(gtconst, chr); \
while (chrfind) \
{ \
*chrfind = '_'; \
chrfind = strchr(chrfind, chr); \
} \
strupr(tmpconst);
// Prepare to write the new constant string now.
strcpy(gtconst, "GT_");
// Remove characters that will not be allowed in the constant string.
for (; r < strlen(tmpconst); r++)
{
boolean writechar = true;
char rc = tmpconst[r];
switch (rc)
{
// Space, at sign and question mark
case ' ':
case '@':
case '?':
// Used for operations
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
case '&':
case '!':
// Part of Lua's syntax
case '#':
case '=':
case '~':
case '<':
case '>':
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case ':':
case ';':
case ',':
case '.':
writechar = false;
break;
}
if (writechar)
{
gtconst[3 + w] = rc;
w++;
}
}
// Space
REMOVECHAR(' ')
// Used for operations
REMOVECHAR('+')
REMOVECHAR('-')
REMOVECHAR('*')
REMOVECHAR('/')
REMOVECHAR('%')
REMOVECHAR('^')
// Part of Lua's syntax
REMOVECHAR('#')
REMOVECHAR('=')
REMOVECHAR('~')
REMOVECHAR('<')
REMOVECHAR('>')
REMOVECHAR('(')
REMOVECHAR(')')
REMOVECHAR('{')
REMOVECHAR('}')
REMOVECHAR('[')
REMOVECHAR(']')
REMOVECHAR(':')
REMOVECHAR(';')
REMOVECHAR(',')
REMOVECHAR('.')
#undef REMOVECHAR
// Free the temporary string.
Z_Free(tmpconst);
// Finally, set the constant string.
Gametype_ConstantNames[gtype] = gtconst;
@ -3398,7 +3416,7 @@ INT32 G_GetGametypeByName(const char *gametypestr)
{
INT32 i;
for (i = 0; i < NUMGAMETYPES; i++)
for (i = 0; i < gametypecount; i++)
if (!stricmp(gametypestr, Gametype_Names[i]))
return i;
@ -3440,6 +3458,28 @@ boolean G_GametypeUsesLives(void)
return false;
}
//
// G_GametypeUsesCoopLives
//
// Returns true if the current gametype uses
// the cooplives CVAR. False otherwise.
//
boolean G_GametypeUsesCoopLives(void)
{
return (gametyperules & (GTR_LIVES|GTR_FRIENDLY)) == (GTR_LIVES|GTR_FRIENDLY);
}
//
// G_GametypeUsesCoopStarposts
//
// Returns true if the current gametype uses
// the coopstarposts CVAR. False otherwise.
//
boolean G_GametypeUsesCoopStarposts(void)
{
return (gametyperules & GTR_FRIENDLY);
}
//
// G_GametypeHasTeams
//
@ -3493,6 +3533,16 @@ boolean G_TagGametype(void)
return (gametyperules & GTR_TAG);
}
//
// G_CompetitionGametype
//
// For gametypes that are race gametypes, and have lives.
//
boolean G_CompetitionGametype(void)
{
return ((gametyperules & GTR_RACE) && (gametyperules & GTR_LIVES));
}
/** Get the typeoflevel flag needed to indicate support of a gametype.
* In single-player, this always returns TOL_SP.
* \param gametype The gametype for which support is desired.
@ -3734,7 +3784,7 @@ void G_AfterIntermission(void)
HU_ClearCEcho();
if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene.
if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
else
{
@ -3844,7 +3894,7 @@ static void G_DoContinued(void)
void G_EndGame(void)
{
// Only do evaluation and credits in coop games.
if (gametype == GT_COOP)
if (gametyperules & GTR_CUTSCENES)
{
if (nextmap == 1103-1) // end game with ending
{
@ -4547,7 +4597,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
automapactive = false;
imcontinuing = false;
if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene.
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer);
else
G_DoLoadLevel(resetplayer);
@ -4780,6 +4830,61 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc)
Z_Free(freq);
}
INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep)
{
boolean usemapcode = false;
INT32 newmapnum;
size_t mapnamelen;
char *p;
mapnamelen = strlen(mapname);
if (mapnamelen == 2)/* maybe two digit code */
{
if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) ))
usemapcode = true;
}
else if (mapnamelen == 5 && strnicmp(mapname, "MAP", 3) == 0)
{
if (( newmapnum = M_MapNumber(mapname[3], mapname[4]) ))
usemapcode = true;
}
if (!usemapcode)
{
/* Now detect map number in base 10, which no one asked for. */
newmapnum = strtol(mapname, &p, 10);
if (*p == '\0')/* we got it */
{
if (newmapnum < 1 || newmapnum > NUMMAPS)
{
CONS_Alert(CONS_ERROR, M_GetText("Invalid map number %d.\n"), newmapnum);
return 0;
}
usemapcode = true;
}
else
{
newmapnum = G_FindMap(mapname, realmapnamep, NULL, NULL);
}
}
if (usemapcode)
{
/* we can't check mapheaderinfo for this hahahaha */
if (W_CheckNumForName(G_BuildMapName(newmapnum)) == LUMPERROR)
return 0;
if (realmapnamep)
(*realmapnamep) = G_BuildMapTitle(newmapnum);
}
return newmapnum;
}
//
// DEMO RECORDING
//
@ -6873,23 +6978,20 @@ void G_AddGhost(char *defdemoname)
I_Assert(mthing);
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t z,f,c;
fixed_t offset = mthing->z << FRACBITS;
gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
gh->mo->angle = FixedAngle(mthing->angle << FRACBITS);
f = gh->mo->floorz;
c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;
if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
{
z = c;
if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS);
z = c - offset;
if (z < f)
z = f;
}
else
{
z = f;
if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS);
z = f + offset;
if (z > c)
z = c;
}

View File

@ -130,6 +130,9 @@ INT32 G_FindMap(const char *query, char **foundmapnamep,
mapsearchfreq_t **freqp, INT32 *freqc);
void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc);
/* Match map name by search + 2 digit map code or map number. */
INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
// XMOD spawning
mapthing_t *G_FindCTFStart(INT32 playernum);
mapthing_t *G_FindMatchStart(INT32 playernum);
@ -218,11 +221,14 @@ void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolo
INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeUsesCoopLives(void);
boolean G_GametypeUsesCoopStarposts(void);
boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void);
boolean G_RingSlingerGametype(void);
boolean G_PlatformGametype(void);
boolean G_TagGametype(void);
boolean G_CompetitionGametype(void);
boolean G_EnoughPlayersFinished(void);
void G_ExitLevel(void);
void G_NextLevel(void);

View File

@ -449,8 +449,12 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
// for each seg of the subsector
for (; count--; lseg++)
{
//x,y,dx,dy (like a divline)
line_t *line = lseg->linedef;
if (lseg->glseg)
continue;
//x,y,dx,dy (like a divline)
p1.x = FIXED_TO_FLOAT(lseg->side ? line->v2->x : line->v1->x);
p1.y = FIXED_TO_FLOAT(lseg->side ? line->v2->y : line->v1->y);
p2.x = FIXED_TO_FLOAT(lseg->side ? line->v1->x : line->v2->x);
@ -836,8 +840,10 @@ static INT32 SolveTProblem(void)
return 0;
CONS_Debug(DBG_RENDER, "Solving T-joins. This may take a while. Please wait...\n");
#ifdef HWR_LOADING_SCREEN
CON_Drawer(); //let the user know what we are doing
I_FinishUpdate(); // page flip or blit buffer
#endif
numsplitpoly = 0;
@ -964,9 +970,9 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
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
#endif
HWR_ClearPolys();

View File

@ -764,13 +764,12 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
// CACHING HANDLING
// =================================================
static size_t gr_numtextures; // Texture count
static size_t gr_numtextures = 0; // Texture count
static GLTexture_t *gr_textures; // For all textures
static GLTexture_t *gr_flats; // For all (texture) flats, as normal flats don't need to be cached
void HWR_InitTextureCache(void)
{
gr_numtextures = 0;
gr_textures = NULL;
gr_flats = NULL;
}
@ -958,6 +957,9 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
UINT8 *flat;
if (needpatchflush)
W_FlushCachedPatches();
// setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
@ -983,6 +985,9 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
if (flatlumpnum == LUMPERROR)
return;
if (needpatchflush)
W_FlushCachedPatches();
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFlat(grmip, flatlumpnum);
@ -1061,6 +1066,9 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
// -----------------+
void HWR_GetPatch(GLPatch_t *gpatch)
{
if (needpatchflush)
W_FlushCachedPatches();
// is it in hardware cache
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data)
{
@ -1091,6 +1099,9 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
{
GLMipmap_t *grmip, *newmip;
if (needpatchflush)
W_FlushCachedPatches();
if (colormap == colormaps || colormap == NULL)
{
// Load the default (green) color in doom cache (temporary?) AND hardware cache
@ -1216,6 +1227,9 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
{
GLPatch_t *grpatch;
if (needpatchflush)
W_FlushCachedPatches();
grpatch = HWR_GetCachedGLPatch(lumpnum);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data)
@ -1419,6 +1433,9 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
{
GLMipmap_t *grmip;
if (needpatchflush)
W_FlushCachedPatches();
grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)

View File

@ -980,7 +980,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// top edge
if (clearlines > basewindowy - 8)
{
patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_CACHE);
patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH);
for (x = 0; x < baseviewwidth; x += 8)
HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8,
0);
@ -989,7 +989,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// bottom edge
if (clearlines > basewindowy + baseviewheight)
{
patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_CACHE);
patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH);
for (x = 0; x < baseviewwidth; x += 8)
HWR_DrawPatch(patch, basewindowx + x,
basewindowy + baseviewheight, 0);
@ -998,7 +998,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// left edge
if (clearlines > basewindowy)
{
patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_CACHE);
patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH);
for (y = 0; y < baseviewheight && basewindowy + y < clearlines;
y += 8)
{
@ -1010,7 +1010,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// right edge
if (clearlines > basewindowy)
{
patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_CACHE);
patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH);
for (y = 0; y < baseviewheight && basewindowy+y < clearlines;
y += 8)
{
@ -1022,22 +1022,22 @@ void HWR_DrawViewBorder(INT32 clearlines)
// Draw beveled corners.
if (clearlines > basewindowy - 8)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL],
PU_CACHE),
PU_PATCH),
basewindowx - 8, basewindowy - 8, 0);
if (clearlines > basewindowy - 8)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR],
PU_CACHE),
PU_PATCH),
basewindowx + baseviewwidth, basewindowy - 8, 0);
if (clearlines > basewindowy+baseviewheight)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL],
PU_CACHE),
PU_PATCH),
basewindowx - 8, basewindowy + baseviewheight, 0);
if (clearlines > basewindowy + baseviewheight)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR],
PU_CACHE),
PU_PATCH),
basewindowx + baseviewwidth,
basewindowy + baseviewheight, 0);
}

View File

@ -374,7 +374,6 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_ADST
&lspr[NOLIGHT], // SPR_MCRT
&lspr[NOLIGHT], // SPR_MCSP
&lspr[NOLIGHT], // SPR_NON2
&lspr[NOLIGHT], // SPR_SALD
&lspr[NOLIGHT], // SPR_TRAE
&lspr[NOLIGHT], // SPR_TRAI

View File

@ -556,7 +556,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
if (!M_PointInBox(segbbox,splat->v1.x,splat->v1.y) && !M_PointInBox(segbbox,splat->v2.x,splat->v2.y))
continue;
gpatch = W_CachePatchNum(splat->patch, PU_CACHE);
gpatch = W_CachePatchNum(splat->patch, PU_PATCH);
HWR_GetPatch(gpatch);
wallVerts[0].x = wallVerts[3].x = FIXED_TO_FLOAT(splat->v1.x);
@ -3404,11 +3404,16 @@ static void HWR_Subsector(size_t num)
while (count--)
{
if (!line->glseg
#ifdef POLYOBJECTS
if (!line->polyseg) // ignore segs that belong to polyobjects
&& !line->polyseg // ignore segs that belong to polyobjects
#endif
)
{
HWR_AddLine(line);
line++;
}
line++;
}
}
@ -6282,7 +6287,13 @@ void HWR_AddCommands(void)
void HWR_AddSessionCommands(void)
{
static boolean alreadycalled = false;
if (alreadycalled)
return;
CV_RegisterVar(&cv_granisotropicmode);
alreadycalled = true;
}
// --------------------------------------------------------------------------
@ -6315,6 +6326,17 @@ void HWR_Startup(void)
HWD.pfnLoadShaders();
}
// --------------------------------------------------------------------------
// Called after switching to the hardware renderer
// --------------------------------------------------------------------------
void HWR_Switch(void)
{
// Set special states from CVARs
HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value);
HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value);
HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value);
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value);
}
// --------------------------------------------------------------------------
// Free resources allocated by the hardware renderer

View File

@ -29,6 +29,7 @@
// Startup & Shutdown the hardware mode renderer
void HWR_Startup(void);
void HWR_Switch(void);
void HWR_Shutdown(void);
void HWR_drawAMline(const fline_t *fl, INT32 color);

View File

@ -1173,6 +1173,8 @@ void HU_clearChatChars(void)
w_chat[i] = 0; // reset this.
chat_on = false;
c_input = 0;
I_UpdateMouseGrab();
}
#ifndef NONET
@ -1323,6 +1325,7 @@ boolean HU_Responder(event_t *ev)
chat_on = false;
c_input = 0; // reset input cursor
chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :)
I_UpdateMouseGrab();
}
else if (c == KEY_ESCAPE
|| ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1]
@ -1331,6 +1334,7 @@ boolean HU_Responder(event_t *ev)
{
chat_on = false;
c_input = 0; // reset input cursor
I_UpdateMouseGrab();
}
else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0 && !OLDCHAT) // CHAT SCROLLING YAYS!
{
@ -2117,6 +2121,9 @@ static void HU_DrawDemoInfo(void)
//
void HU_Drawer(void)
{
if (needpatchrecache)
R_ReloadHUDGraphics();
#ifndef NONET
// draw chat string plus cursor
if (chat_on)
@ -2434,7 +2441,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
}
}
if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
{
@ -2743,7 +2750,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
| (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);

View File

@ -288,6 +288,10 @@ void I_GetJoystick2Events(void);
*/
void I_GetMouseEvents(void);
/** \brief Checks if the mouse needs to be grabbed
*/
void I_UpdateMouseGrab(void);
char *I_GetEnv(const char *name);
INT32 I_PutEnv(char *variable);

View File

@ -44,6 +44,7 @@ extern boolean highcolor;
/** \brief setup video mode
*/
void I_StartupGraphics(void);
void I_StartupHardwareGraphics(void);
/** \brief restore old video mode
*/
@ -84,6 +85,7 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h);
\return currect video mode
*/
INT32 VID_SetMode(INT32 modenum);
void VID_CheckRenderer(void);
/** \brief The VID_GetModeName function

View File

@ -2854,6 +2854,22 @@ static int lib_gGametypeUsesLives(lua_State *L)
return 1;
}
static int lib_gGametypeUsesCoopLives(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeUsesCoopLives());
return 1;
}
static int lib_gGametypeUsesCoopStarposts(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeUsesCoopStarposts());
return 1;
}
static int lib_gGametypeHasTeams(lua_State *L)
{
//HUDSAFE
@ -2894,6 +2910,14 @@ static int lib_gTagGametype(lua_State *L)
return 1;
}
static int lib_gCompetitionGametype(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_CompetitionGametype());
return 1;
}
static int lib_gTicsToHours(lua_State *L)
{
tic_t rtic = luaL_checkinteger(L, 1);
@ -3139,11 +3163,14 @@ static luaL_Reg lib[] = {
{"G_ExitLevel",lib_gExitLevel},
{"G_IsSpecialStage",lib_gIsSpecialStage},
{"G_GametypeUsesLives",lib_gGametypeUsesLives},
{"G_GametypeUsesCoopLives",lib_gGametypeUsesCoopLives},
{"G_GametypeUsesCoopStarposts",lib_gGametypeUsesCoopStarposts},
{"G_GametypeHasTeams",lib_gGametypeHasTeams},
{"G_GametypeHasSpectators",lib_gGametypeHasSpectators},
{"G_RingSlingerGametype",lib_gRingSlingerGametype},
{"G_PlatformGametype",lib_gPlatformGametype},
{"G_TagGametype",lib_gTagGametype},
{"G_CompetitionGametype",lib_gCompetitionGametype},
{"G_TicsToHours",lib_gTicsToHours},
{"G_TicsToMinutes",lib_gTicsToMinutes},
{"G_TicsToSeconds",lib_gTicsToSeconds},

View File

@ -245,7 +245,7 @@ static int lib_comBufAddText(lua_State *L)
return LUA_ErrInvalid(L, "player_t");
if (plr != &players[consoleplayer])
return 0;
COM_BufAddText(va("%s\n", luaL_checkstring(L, 2)));
COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE);
return 0;
}
@ -262,7 +262,7 @@ static int lib_comBufInsertText(lua_State *L)
return LUA_ErrInvalid(L, "player_t");
if (plr != &players[consoleplayer])
return 0;
COM_BufInsertText(va("%s\n", luaL_checkstring(L, 2)));
COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE);
return 0;
}
@ -427,6 +427,26 @@ static int lib_cvRegisterVar(lua_State *L)
return 1;
}
static int lib_cvFindVar(lua_State *L)
{
consvar_t *cv;
if (( cv = CV_FindVar(luaL_checkstring(L,1)) ))
{
lua_settop(L,1);/* We only want one argument in the stack. */
lua_pushlightuserdata(L, cv);/* Now the second value on stack. */
luaL_getmetatable(L, META_CVAR);
/*
The metatable is the last value on the stack, so this
applies it to the second value, which is the cvar.
*/
lua_setmetatable(L,2);
lua_pushvalue(L,2);
return 1;
}
else
return 0;
}
// CONS_Printf for a single player
// Use 'print' in baselib for a global message.
static int lib_consPrintf(lua_State *L)
@ -466,6 +486,7 @@ static luaL_Reg lib[] = {
{"COM_BufAddText", lib_comBufAddText},
{"COM_BufInsertText", lib_comBufInsertText},
{"CV_RegisterVar", lib_cvRegisterVar},
{"CV_FindVar", lib_cvFindVar},
{"CONS_Printf", lib_consPrintf},
{NULL, NULL}
};

View File

@ -20,9 +20,12 @@ enum hook {
hook_MapChange,
hook_MapLoad,
hook_PlayerJoin,
hook_PreThinkFrame,
hook_ThinkFrame,
hook_PostThinkFrame,
hook_MobjSpawn,
hook_MobjCollide,
hook_MobjLineCollide,
hook_MobjMoveCollide,
hook_TouchSpecial,
hook_MobjFuse,
@ -53,6 +56,7 @@ enum hook {
hook_IntermissionThinker,
hook_TeamSwitch,
hook_ViewpointSwitch,
hook_SeenPlayer,
hook_MAX // last hook
};
@ -61,12 +65,16 @@ extern const char *const hookNames[];
void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load)
void LUAh_MapLoad(void); // Hook for map load
void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer
void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers)
void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers)
void LUAh_PostThinkFrame(void); // Hook for frame (at end of tick, ie after overlays, precipitation, specials)
boolean LUAh_MobjHook(mobj_t *mo, enum hook which);
boolean LUAh_PlayerHook(player_t *plr, enum hook which);
#define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which);
UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which);
#define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type
#define LUAh_MobjLineCollide(thing, line) LUAh_MobjLineCollideHook(thing, line, hook_MobjLineCollide) // Hook for PIT_CheckThing by (thing) mobj type
#define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type
boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type
#define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type
@ -97,5 +105,8 @@ void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
#endif
#endif

View File

@ -31,9 +31,12 @@ const char *const hookNames[hook_MAX+1] = {
"MapChange",
"MapLoad",
"PlayerJoin",
"PreThinkFrame",
"ThinkFrame",
"PostThinkFrame",
"MobjSpawn",
"MobjCollide",
"MobjLineCollide",
"MobjMoveCollide",
"TouchSpecial",
"MobjFuse",
@ -64,6 +67,7 @@ const char *const hookNames[hook_MAX+1] = {
"IntermissionThinker",
"TeamSwitch",
"ViewpointSwitch",
"SeenPlayer",
NULL
};
@ -123,6 +127,7 @@ static int lib_addHook(lua_State *L)
// Take a mobjtype enum which this hook is specifically for.
case hook_MobjSpawn:
case hook_MobjCollide:
case hook_MobjLineCollide:
case hook_MobjMoveCollide:
case hook_TouchSpecial:
case hook_MobjFuse:
@ -182,6 +187,7 @@ static int lib_addHook(lua_State *L)
lastp = &mobjthinkerhooks[hook.s.mt];
break;
case hook_MobjCollide:
case hook_MobjLineCollide:
case hook_MobjMoveCollide:
lastp = &mobjcollidehooks[hook.s.mt];
break;
@ -207,6 +213,7 @@ static int lib_addHook(lua_State *L)
case hook_PlayerCanDamage:
case hook_TeamSwitch:
case hook_ViewpointSwitch:
case hook_SeenPlayer:
case hook_ShieldSpawn:
case hook_ShieldSpecial:
lastp = &playerhooks;
@ -411,6 +418,29 @@ void LUAh_PlayerJoin(int playernum)
lua_settop(gL, 0);
}
// Hook for frame (before mobj and player thinkers)
void LUAh_PreThinkFrame(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_PreThinkFrame/8] & (1<<(hook_PreThinkFrame%8))))
return;
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PreThinkFrame)
continue;
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
if (lua_pcall(gL, 0, 0, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
}
}
}
// Hook for frame (after mobj and player thinkers)
void LUAh_ThinkFrame(void)
{
@ -434,6 +464,30 @@ void LUAh_ThinkFrame(void)
}
}
// Hook for frame (at end of tick, ie after overlays, precipitation, specials)
void LUAh_PostThinkFrame(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_PostThinkFrame/8] & (1<<(hook_PostThinkFrame%8))))
return;
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PostThinkFrame)
continue;
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
if (lua_pcall(gL, 0, 0, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
}
}
}
// Hook for mobj collisions
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
{
@ -513,6 +567,84 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
return shouldCollide;
}
UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
{
hook_p hookp;
UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
return 0;
I_Assert(thing->type < NUMMOBJTYPES);
lua_settop(gL, 0);
// Look for all generic mobj collision hooks
for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next)
{
if (hookp->type != which)
continue;
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, thing, META_MOBJ);
LUA_PushUserdata(gL, line, META_LINE);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave shouldCollide = 0.
if (lua_toboolean(gL, -1))
shouldCollide = 1; // Force yes
else
shouldCollide = 2; // Force no
}
lua_pop(gL, 1);
}
for (hookp = mobjcollidehooks[thing->type]; hookp; hookp = hookp->next)
{
if (hookp->type != which)
continue;
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, thing, META_MOBJ);
LUA_PushUserdata(gL, line, META_LINE);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave shouldCollide = 0.
if (lua_toboolean(gL, -1))
shouldCollide = 1; // Force yes
else
shouldCollide = 2; // Force no
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return shouldCollide;
}
// Hook for mobj thinkers
boolean LUAh_MobjThinker(mobj_t *mo)
{
@ -1412,7 +1544,7 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
return 0;
lua_settop(gL, 0);
hud_running = true;
hud_running = true; // local hook
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
@ -1453,4 +1585,49 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
return canSwitchView;
}
// Hook for MT_NAMECHECK
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
{
hook_p hookp;
boolean hasSeenPlayer = true;
if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8))))
return 0;
lua_settop(gL, 0);
hud_running = true; // local hook
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
if (hookp->type != hook_SeenPlayer)
continue;
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, seenfriend, META_PLAYER);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1))
hasSeenPlayer = false; // Hasn't seen player
lua_pop(gL, 1);
}
lua_settop(gL, 0);
hud_running = false;
return hasSeenPlayer;
}
#endif // SEENAMES
#endif

View File

@ -36,6 +36,11 @@ static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field
#ifdef LUA_PATCH_SAFETY
static patchinfo_t *patchinfo, *patchinfohead;
static int numluapatches;
#endif
// must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = {
"stagetitle",
@ -256,12 +261,17 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L)
{
#ifdef LUA_PATCH_SAFETY
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
#else
patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH));
#endif
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are CURRENTLY always valid, expected to be cached with PU_STATIC
// this may change in the future, so patch.valid still exists
I_Assert(patch != NULL);
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
switch (field)
{
@ -358,8 +368,59 @@ static int libd_patchExists(lua_State *L)
static int libd_cachePatch(lua_State *L)
{
#ifdef LUA_PATCH_SAFETY
int i;
lumpnum_t lumpnum;
patchinfo_t *luapat;
patch_t *realpatch;
HUDONLY
LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_STATIC), META_PATCH);
luapat = patchinfohead;
lumpnum = W_CheckNumForName(luaL_checkstring(L, 1));
if (lumpnum == LUMPERROR)
lumpnum = W_GetNumForName("MISSING");
for (i = 0; i < numluapatches; i++)
{
// check if already cached
if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum))
{
LUA_PushUserdata(L, luapat, META_PATCH);
return 1;
}
luapat = luapat->next;
if (!luapat)
break;
}
if (numluapatches > 0)
{
patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfo = patchinfo->next;
}
else
{
patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfohead = patchinfo;
}
realpatch = W_CachePatchNum(lumpnum, PU_PATCH);
patchinfo->width = realpatch->width;
patchinfo->height = realpatch->height;
patchinfo->leftoffset = realpatch->leftoffset;
patchinfo->topoffset = realpatch->topoffset;
patchinfo->wadnum = WADFILENUM(lumpnum);
patchinfo->lumpnum = LUMPNUM(lumpnum);
LUA_PushUserdata(L, patchinfo, META_PATCH);
numluapatches++;
#else
HUDONLY
LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
#endif
return 1;
}
@ -415,7 +476,7 @@ static int libd_getSpritePatch(lua_State *L)
return 0;
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH);
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
@ -510,7 +571,7 @@ static int libd_getSprite2Patch(lua_State *L)
return 0;
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH);
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
@ -519,12 +580,22 @@ static int libd_draw(lua_State *L)
{
INT32 x, y, flags;
patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 4, 0);
if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
@ -540,6 +611,9 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale;
INT32 flags;
patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL;
HUDONLY
@ -548,7 +622,14 @@ static int libd_drawScaled(lua_State *L)
scale = luaL_checkinteger(L, 3);
if (scale < 0)
return luaL_error(L, "negative scale");
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 5, 0);
if (!lua_isnoneornil(L, 6))
colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP));
@ -1047,6 +1128,10 @@ int LUA_HudLib(lua_State *L)
{
memset(hud_enabled, 0xff, (hud_MAX/8)+1);
#ifdef LUA_PATCH_SAFETY
numluapatches = 0;
#endif
lua_newtable(L); // HUD registry table
lua_newtable(L);
luaL_register(L, NULL, lib_draw);

View File

@ -134,6 +134,7 @@ enum side_e {
side_toptexture,
side_bottomtexture,
side_midtexture,
side_line,
side_sector,
side_special,
side_repeatcnt,
@ -156,15 +157,13 @@ static const char *const side_opt[] = {
enum vertex_e {
vertex_valid = 0,
vertex_x,
vertex_y,
vertex_z
vertex_y
};
static const char *const vertex_opt[] = {
"valid",
"x",
"y",
"z",
NULL};
enum ffloor_e {
@ -869,6 +868,9 @@ static int side_get(lua_State *L)
case side_midtexture:
lua_pushinteger(L, side->midtexture);
return 1;
case side_line:
LUA_PushUserdata(L, side->line, META_LINE);
return 1;
case side_sector:
LUA_PushUserdata(L, side->sector, META_SECTOR);
return 1;
@ -902,6 +904,7 @@ static int side_set(lua_State *L)
switch(field)
{
case side_valid: // valid
case side_line:
case side_sector:
case side_special:
case side_text:
@ -965,9 +968,6 @@ static int vertex_get(lua_State *L)
case vertex_y:
lua_pushfixed(L, vertex->y);
return 1;
case vertex_z:
lua_pushfixed(L, vertex->z);
return 1;
}
return 0;
}

View File

@ -299,9 +299,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
// See the above.
int LUA_CheckGlobals(lua_State *L, const char *word)
{
if (fastcmp(word, "gametyperules"))
gametyperules = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "redscore"))
if (fastcmp(word, "redscore"))
redscore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "bluescore"))
bluescore = (UINT32)luaL_checkinteger(L, 2);

View File

@ -517,6 +517,7 @@ void Command_Teleport_f(void)
if (!starpostnum) // spawnpoints...
{
mapthing_t *mt;
fixed_t offset;
if (starpostpath >= numcoopstarts)
{
@ -527,6 +528,7 @@ void Command_Teleport_f(void)
mt = playerstarts[starpostpath]; // Given above check, should never be NULL.
intx = mt->x<<FRACBITS;
inty = mt->y<<FRACBITS;
offset = mt->z<<FRACBITS;
ss = R_IsPointInSubsector(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
@ -538,17 +540,9 @@ void Command_Teleport_f(void)
// Flagging a player's ambush will make them start on the ceiling
// Objectflip inverts
if (!!(mt->options & MTF_AMBUSH) ^ !!(mt->options & MTF_OBJECTFLIP))
{
intz = ss->sector->ceilingheight - p->mo->height;
if (mt->options >> ZSHIFT)
intz -= ((mt->options >> ZSHIFT) << FRACBITS);
}
intz = ss->sector->ceilingheight - p->mo->height - offset;
else
{
intz = ss->sector->floorheight;
if (mt->options >> ZSHIFT)
intz += ((mt->options >> ZSHIFT) << FRACBITS);
}
intz = ss->sector->floorheight + offset;
if (mt->options & MTF_OBJECTFLIP) // flip the player!
{
@ -1193,14 +1187,14 @@ void OP_NightsObjectplace(player_t *player)
if (cmd->buttons & BT_TOSSFLAG)
{
UINT16 vertangle = (UINT16)(player->anotherflyangle % 360);
UINT16 newflags, newz;
UINT16 newflags;
player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false))
return;
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSBUMPER].doomednum, false);
newz = min((mt->options >> ZSHIFT) - (mobjinfo[MT_NIGHTSBUMPER].height/4), 0);
mt->z = min(mt->z - (mobjinfo[MT_NIGHTSBUMPER].height/4), 0);
// height offset: from P_TouchSpecialThing case MT_NIGHTSBUMPER
// clockwise
@ -1231,7 +1225,7 @@ void OP_NightsObjectplace(player_t *player)
else // forward
newflags = 0;
mt->options = (newz << ZSHIFT) | newflags;
mt->options = (mt->z << ZSHIFT) | newflags;
// if NiGHTS is facing backwards, orient the Thing angle forwards so that the sprite angle
// displays correctly. Backwards movement via the Thing flags is unaffected.
@ -1439,7 +1433,7 @@ void OP_ObjectplaceMovement(player_t *player)
else
P_SpawnMapThing(mt);
CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->options>>ZSHIFT, mt->angle);
CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->z, mt->angle);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -222,13 +222,14 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
// flags for items in the menu
// menu handle (what we do when key is pressed
#define IT_TYPE 14 // (2+4+8)
#define IT_TYPE 15 // (1+2+4+8)
#define IT_CALL 0 // call the function
#define IT_SPACE 1 // no handling
#define IT_ARROWS 2 // call function with 0 for left arrow and 1 for right arrow in param
#define IT_KEYHANDLER 4 // call with the key in param
#define IT_SUBMENU 6 // go to sub menu
#define IT_CVAR 8 // handle as a cvar
#define IT_SPACE 10 // no handling
#define IT_PAIR 11 // no handling, define both sides of text
#define IT_MSGHANDLER 12 // same as key but with event and sometime can handle y/n key (special for message)
#define IT_DISPLAY (48+64+128) // 16+32+64+128

View File

@ -1908,6 +1908,20 @@ void M_UnGetToken(void)
endPos = oldendPos;
}
/** Returns the current token's position.
*/
UINT32 M_GetTokenPos(void)
{
return endPos;
}
/** Sets the current token's position.
*/
void M_SetTokenPos(UINT32 newPos)
{
endPos = newPos;
}
/** Count bits in a number.
*/
UINT8 M_CountBits(UINT32 num, UINT8 size)

View File

@ -14225,7 +14225,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
fixed_t c = FINECOSINE(fa)*locvar2;
fixed_t s = FINESINE(fa)*locvar2;
mobj_t *door;
mobjflag2_t ambush = (actor->flags & MF2_AMBUSH);
mobjflag2_t ambush = (actor->flags2 & MF2_AMBUSH);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SaloonDoorSpawn", actor))

View File

@ -1451,7 +1451,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->starpostnum >= special->health)
return; // Already hit this post
if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer))
if (cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (netgame || multiplayer))
{
for (i = 0; i < MAXPLAYERS; i++)
{
@ -1807,7 +1807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
case MT_MINECARTSPAWNER:
if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART))
if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART)
{
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
P_SetTarget(&mcart->target, toucher);
@ -2481,9 +2481,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
P_SetMobjState(scoremobj, scorestate);
// On ground? No chain starts.
if (source->player->powers[pw_invulnerability] || !P_IsObjectOnGround(source))
source->player->scoreadd = locscoreadd;
source->player->scoreadd = locscoreadd;
}
}
@ -2523,7 +2521,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->colorized = false;
G_GhostAddColor(GHC_NORMAL);
if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0))
if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0))
;
else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES)
&& G_GametypeUsesLives())
@ -2533,7 +2531,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (target->player->lives <= 0) // Tails 03-14-2000
{
boolean gameovermus = false;
if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1))
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value != 1))
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
@ -3201,10 +3199,12 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
player->powers[pw_carry] = CR_NONE;
// Burst weapons and emeralds in Match/CTF only
if (source && (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF))
if (source)
{
P_PlayerRingBurst(player, player->rings);
P_PlayerEmeraldBurst(player, false);
if ((gametyperules & GTR_RINGSLINGER) && !(gametyperules & GTR_TAG))
P_PlayerRingBurst(player, player->rings);
if (gametyperules & GTR_POWERSTONES)
P_PlayerEmeraldBurst(player, false);
}
// Get rid of shield

View File

@ -745,9 +745,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
// So that NOTHING ELSE can see MT_NAMECHECK because it is client-side.
if (tmthing->type == MT_NAMECHECK)
{
// Ignore things that aren't players, ignore spectators, ignore yourself.
// (also don't bother to check that tmthing->target->player is non-NULL because we're not actually using it here.)
if (!thing->player || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player))
// Ignore things that aren't players, ignore spectators, ignore yourself.
if (!thing->player || !(tmthing->target && tmthing->target->player) || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player))
return true;
// Now check that you actually hit them.
@ -760,6 +759,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
#ifdef HAVE_BLUA
// REX HAS SEEN YOU
if (!LUAh_SeenPlayer(tmthing->target->player, thing->player))
return false;
#endif
seenplayer = thing->player;
return false;
}
@ -829,13 +834,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext)
if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(iter, tmthing, tmthing, 0);
return true;
}
else
{
thing->health = 0;
P_KillMobj(thing, tmthing, tmthing, 0);
if (P_DamageMobj(thing, tmthing, tmthing, 1, 0))
return true;
}
return true;
}
// vectorise metal - done in a special case as at this point neither has the right flags for touching
@ -995,7 +1000,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags & MF2_AMBUSH) || ref != tmthing)
if ((thing->flags2 & MF2_AMBUSH) || ref != tmthing)
{
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
@ -1008,7 +1013,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{
if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
if ((thing->flags2 & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true;
}
@ -1943,6 +1948,19 @@ static boolean PIT_CheckLine(line_t *ld)
// this line is out of the if so upper and lower textures can be hit by a splat
blockingline = ld;
#ifdef HAVE_BLUA
{
UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, blockingline); // checks hook for thing's type
if (P_MobjWasRemoved(tmthing))
return true; // one of them was removed???
if (shouldCollide == 1)
return false; // force collide
else if (shouldCollide == 2)
return true; // force no collide
}
#endif
if (!ld->backsector) // one sided line
{
if (P_PointOnLineSide(tmthing->x, tmthing->y, ld))
@ -1987,7 +2005,7 @@ static boolean PIT_CheckLine(line_t *ld)
if (lowfloor < tmdropoffz)
tmdropoffz = lowfloor;
return true;
}

View File

@ -78,68 +78,37 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result)
return;
}
//
// P_ClosestPointOnLine3D
// Finds the closest point on a given line to the supplied point IN 3D!!!
//
void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result)
/// Similar to FV3_ClosestPointOnLine() except it actually works.
void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t *result)
{
fixed_t startx = line->v1->x;
fixed_t starty = line->v1->y;
fixed_t startz = line->v1->z;
fixed_t dx = line->dx;
fixed_t dy = line->dy;
fixed_t dz = line->v2->z - line->v1->z;
const vector3_t* v1 = &Line[0];
const vector3_t* v2 = &Line[1];
vector3_t c, V, n;
fixed_t t, d;
FV3_SubEx(v2, v1, &V);
FV3_SubEx(p, v1, &c);
// Determine t (the length of the vector from <20>Line[0]<5D> to <20>p<EFBFBD>)
fixed_t cx, cy, cz;
fixed_t vx, vy, vz;
fixed_t magnitude;
fixed_t t;
d = R_PointToDist2(0, v2->z, R_PointToDist2(v2->x, v2->y, v1->x, v1->y), v1->z);
FV3_Copy(&n, &V);
FV3_Divide(&n, d);
//Sub (p, &Line[0], &c);
cx = x - startx;
cy = y - starty;
cz = z - startz;
//Sub (&Line[1], &Line[0], &V);
vx = dx;
vy = dy;
vz = dz;
//Normalize (&V, &V);
magnitude = R_PointToDist2(0, line->v2->z, R_PointToDist2(line->v2->x, line->v2->y, startx, starty), startz);
vx = FixedDiv(vx, magnitude);
vy = FixedDiv(vy, magnitude);
vz = FixedDiv(vz, magnitude);
t = (FixedMul(vx, cx) + FixedMul(vy, cy) + FixedMul(vz, cz));
t = FV3_Dot(&n, &c);
// Set closest point to the end if it extends past -Red
if (t <= 0)
{
result->x = line->v1->x;
result->y = line->v1->y;
result->z = line->v1->z;
FV3_Copy(result, v1);
return;
}
else if (t >= magnitude)
else if (t >= d)
{
result->x = line->v2->x;
result->y = line->v2->y;
result->z = line->v2->z;
FV3_Copy(result, v2);
return;
}
// Return the point between <20>Line[0]<5D> and <20>Line[1]<5D>
vx = FixedMul(vx, t);
vy = FixedMul(vy, t);
vz = FixedMul(vz, t);
FV3_Mul(&n, t);
//Add (&Line[0], &V, out);
result->x = startx + vx;
result->y = starty + vy;
result->z = startz + vz;
FV3_AddEx(v1, &n, result);
return;
}

View File

@ -43,7 +43,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy);
void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result);
void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result);
void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result);
INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line);
void P_MakeDivline(line_t *li, divline_t *dl);
void P_CameraLineOpening(line_t *plinedef);

View File

@ -7977,15 +7977,19 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->x = mobj->extravalue1 + P_ReturnThrustX(mobj, mobj->movedir, mobj->cvmem*mobj->scale);
mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale);
P_SetThingPosition(mobj);
if ((--mobj->fuse) < 6)
if (!mobj->fuse)
{
if (!mobj->fuse)
{
#ifdef HAVE_BLUA
if (!LUAh_MobjFuse(mobj))
#endif
P_RemoveMobj(mobj);
return;
}
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT));
return;
}
if (mobj->fuse < 0)
return;
if ((--mobj->fuse) < 6)
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT));
}
break;
case MT_VWREF:
@ -9903,19 +9907,12 @@ static void P_FlagFuseThink(mobj_t *mobj)
x = mobj->spawnpoint->x << FRACBITS;
y = mobj->spawnpoint->y << FRACBITS;
z = mobj->spawnpoint->z << FRACBITS;
ss = R_PointInSubsector(x, y);
if (mobj->spawnpoint->options & MTF_OBJECTFLIP)
{
z = ss->sector->ceilingheight - mobjinfo[mobj->type].height;
if (mobj->spawnpoint->options >> ZSHIFT)
z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS;
}
z = ss->sector->ceilingheight - mobjinfo[mobj->type].height - z;
else
{
z = ss->sector->floorheight;
if (mobj->spawnpoint->options >> ZSHIFT)
z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS;
}
z = ss->sector->floorheight + z;
flagmo = P_SpawnMobj(x, y, z, mobj->type);
flagmo->spawnpoint = mobj->spawnpoint;
if (mobj->spawnpoint->options & MTF_OBJECTFLIP)
@ -11289,9 +11286,6 @@ static mobjtype_t P_GetMobjtype(UINT16 mthingtype)
//
void P_RespawnSpecials(void)
{
fixed_t x, y, z;
subsector_t *ss;
mobj_t *mo = NULL;
mapthing_t *mthing = NULL;
// only respawn items when cv_itemrespawn is on
@ -11321,63 +11315,8 @@ void P_RespawnSpecials(void)
#endif
if (mthing)
{
mobjtype_t i = P_GetMobjtype(mthing->type);
x = mthing->x << FRACBITS;
y = mthing->y << FRACBITS;
ss = R_PointInSubsector(x, y);
P_SpawnMapThing(mthing);
if (i == MT_UNKNOWN) // prevent creation of objects with this type -- Monster Iestyn 17/12/17
{
// 3D Mode start Thing is unlikely to be added to the que,
// so don't bother checking for that specific type
CONS_Alert(CONS_WARNING, M_GetText("P_RespawnSpecials: Unknown thing type %d attempted to respawn at (%d, %d)\n"), mthing->type, mthing->x, mthing->y);
// pull it from the que
iquetail = (iquetail+1)&(ITEMQUESIZE-1);
return;
}
//CTF rings should continue to respawn as normal rings outside of CTF.
if (!(gametyperules & GTR_TEAMFLAGS))
{
if (i == MT_REDTEAMRING || i == MT_BLUETEAMRING)
i = MT_RING;
}
if (mthing->options & MTF_OBJECTFLIP)
{
z = (
#ifdef ESLOPE
ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) :
#endif
ss->sector->ceilingheight) - (mthing->options >> ZSHIFT) * FRACUNIT;
if (mthing->options & MTF_AMBUSH
&& (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || i == MT_NIGHTSSTAR || P_WeaponOrPanel(i)))
z -= 24*FRACUNIT;
z -= mobjinfo[i].height; // Don't forget the height!
}
else
{
z = (
#ifdef ESLOPE
ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) :
#endif
ss->sector->floorheight) + (mthing->options >> ZSHIFT) * FRACUNIT;
if (mthing->options & MTF_AMBUSH
&& (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || i == MT_NIGHTSSTAR || P_WeaponOrPanel(i)))
z += 24*FRACUNIT;
}
mo = P_SpawnMobj(x, y, z, i);
mo->spawnpoint = mthing;
mo->angle = ANGLE_45 * (mthing->angle/45);
if (mthing->options & MTF_OBJECTFLIP)
{
mo->eflags |= MFE_VERTICALFLIP;
mo->flags2 |= MF2_OBJECTFLIP;
}
}
// pull it from the que
iquetail = (iquetail+1)&(ITEMQUESIZE-1);
}
@ -11563,7 +11502,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
fixed_t z;
sector_t *sector;
fixed_t floor, ceiling;
fixed_t floor, ceiling, ceilingspawn;
player_t *p = &players[playernum];
mobj_t *mobj = p->mo;
@ -11590,23 +11529,18 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
sector->c_slope ? P_GetZAt(sector->c_slope, x, y) :
#endif
sector->ceilingheight;
ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height;
if (mthing)
{
fixed_t offset = mthing->z << FRACBITS;
// Flagging a player's ambush will make them start on the ceiling
// Objectflip inverts
if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
{
z = ceiling - mobjinfo[MT_PLAYER].height;
if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS);
}
z = ceilingspawn - offset;
else
{
z = floor;
if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS);
}
z = floor + offset;
if (mthing->options & MTF_OBJECTFLIP) // flip the player!
{
@ -11623,8 +11557,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
if (z < floor)
z = floor;
else if (z > ceiling - mobjinfo[MT_PLAYER].height)
z = ceiling - mobjinfo[MT_PLAYER].height;
else if (z > ceilingspawn)
z = ceilingspawn;
mobj->floorz = floor;
mobj->ceilingz = ceiling;
@ -11893,7 +11827,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
if (!cv_powerstones.value)
return false;
if (!(gametyperules & GTR_MATCHEMERALDS))
if (!(gametyperules & GTR_POWERSTONES))
return false;
runemeraldmanager = true;
@ -12465,7 +12399,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
|| (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1)
ticcount = 3;
numdivisions = (mthing->options >> ZSHIFT);
numdivisions = mthing->z;
if (numdivisions)
{

View File

@ -400,6 +400,8 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg)
// Find backfacings
for (s = 0; s < numsegs; s++)
{
if (segs[s].glseg)
continue;
if (segs[s].linedef == seg->linedef
&& segs[s].side == 1)
{
@ -436,6 +438,8 @@ newseg:
// seg's ending vertex.
for (i = 0; i < numsegs; ++i)
{
if (segs[i].glseg)
continue;
if (segs[i].side != 0) // needs to be frontfacing
continue;
if (segs[i].v1->x == seg->v2->x && segs[i].v1->y == seg->v2->y)
@ -460,6 +464,9 @@ newseg:
// Find backfacings
for (q = 0; q < numsegs; q++)
{
if (segs[q].glseg)
continue;
if (segs[q].linedef == segs[i].linedef
&& segs[q].side == 1)
{
@ -606,6 +613,9 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
INT32 poflags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
INT32 parentID = 0, potrans = 0;
if (seg->glseg)
continue;
if (seg->side != 0) // needs to be frontfacing
continue;
@ -1815,6 +1825,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
if (po->thinker == NULL)
po->thinker = &th->thinker;
/*
// Find out target first.
// We redo this each tic to make savegame compatibility easier.
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
@ -1833,6 +1844,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
break;
}
}
*/
target = th->target;
if (!target)
{
@ -2015,6 +2029,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
target = waypoint;
th->pointnum = target->health;
// Set the mobj as your target! -- Monster Iestyn 27/12/19
P_SetTarget(&th->target, target);
// calculate MOMX/MOMY/MOMZ for next waypoint
// change slope
@ -2641,6 +2657,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// Set pointnum
th->pointnum = target->health;
th->target = NULL; // set to NULL first so the below doesn't go wrong
// Set the mobj as your target! -- Monster Iestyn 27/12/19
P_SetTarget(&th->target, target);
// We don't deal with the mirror crap here, we'll
// handle that in the T_Thinker function.

View File

@ -161,6 +161,8 @@ typedef struct polywaypoint_s
fixed_t diffx;
fixed_t diffy;
fixed_t diffz;
mobj_t *target; // next waypoint mobj
} polywaypoint_t;
typedef struct polyslidedoor_s

View File

@ -2055,6 +2055,7 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
WRITEFIXED(save_p, ht->diffx);
WRITEFIXED(save_p, ht->diffy);
WRITEFIXED(save_p, ht->diffz);
WRITEUINT32(save_p, SaveMobjnum(ht->target));
}
//
@ -3244,6 +3245,7 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
ht->diffx = READFIXED(save_p);
ht->diffy = READFIXED(save_p);
ht->diffz = READFIXED(save_p);
ht->target = LoadMobj(READUINT32(save_p));
return &ht->thinker;
}
@ -3538,6 +3540,7 @@ static void P_NetUnArchiveThinkers(void)
case tc_polywaypoint:
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
restoreNum = true;
break;
case tc_polyslidedoor:
@ -3599,9 +3602,9 @@ static void P_NetUnArchiveThinkers(void)
if (restoreNum)
{
executor_t *delay = NULL;
polywaypoint_t *polywp = NULL;
UINT32 mobjnum;
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN];
currentthinker = currentthinker->next)
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
continue;
@ -3610,6 +3613,15 @@ static void P_NetUnArchiveThinkers(void)
continue;
delay->caller = P_FindNewPosition(mobjnum);
}
for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint)
continue;
polywp = (void *)currentthinker;
if (!(mobjnum = (UINT32)(size_t)polywp->target))
continue;
polywp->target = P_FindNewPosition(mobjnum);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -96,8 +96,11 @@ void P_SetupLevelSky(INT32 skynum, boolean global);
#ifdef SCANTHINGS
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif
void P_LoadThingsOnly(void);
void P_RespawnThings(void);
boolean P_LoadLevel(boolean fromnetsave);
#ifdef HWRENDER
void HWR_SetupLevel(void);
#endif
boolean P_AddWadFile(const char *wadfilename);
boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);

View File

@ -222,6 +222,9 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
fixed_t fracx, fracy;
#endif
if (seg->glseg)
continue;
// already checked other side?
if (line->validcount == validcount)
continue;

View File

@ -50,10 +50,10 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v
// Set some defaults for a non-sloped "slope"
if (vec1.z == 0 && vec2.z == 0)
{
/// \todo Fix fully flat cases.
slope->zangle = slope->xydirection = 0;
slope->zdelta = slope->d.x = slope->d.y = 0;
slope->normal.x = slope->normal.y = 0;
slope->normal.z = FRACUNIT;
}
else
{
@ -445,10 +445,9 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
I_Error("MakeViaMapthings: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1);
vx[i].x = mt->x << FRACBITS;
vx[i].y = mt->y << FRACBITS;
if (mt->extrainfo)
vx[i].z = mt->options << FRACBITS;
else
vx[i].z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight) + ((mt->options >> ZSHIFT) << FRACBITS);
vx[i].z = mt->z << FRACBITS;
if (!mt->extrainfo)
vx[i].z += R_PointInSubsector(vx[i].x, vx[i].y)->sector->floorheight;
}
ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]);
@ -654,7 +653,9 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
// Handles slope ejection for objects
void P_SlopeLaunch(mobj_t *mo)
{
if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching.
if (!(mo->standingslope->flags & SL_NOPHYSICS) // If there's physics, time for launching.
&& (mo->standingslope->normal.x != 0
|| mo->standingslope->normal.y != 0))
{
// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
// vertical launch given from slopes while increasing the horizontal launch
@ -711,8 +712,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope)
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
{
vector3_t mom; // Ditto.
if (slope->flags & SL_NOPHYSICS) { // No physics, no need to make anything complicated.
if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated.
if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope
{
thing->standingslope = slope;

View File

@ -52,9 +52,6 @@ mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
// Amount (dx, dy) vector linedef is shifted right to get scroll amount
#define SCROLL_SHIFT 5
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
#define MAXFLATSIZE (2048<<FRACBITS)
/** Animated texture descriptor
* This keeps track of an animated texture or an animated flat.
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
@ -5041,8 +5038,7 @@ DoneSection2:
mobj_t *waypointlow = NULL;
mobj_t *mo2;
mobj_t *closest = NULL;
line_t junk;
vertex_t v1, v2, resulthigh, resultlow;
vector3_t p, line[2], resulthigh, resultlow;
mobj_t *highest = NULL;
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG)
@ -5189,38 +5185,34 @@ DoneSection2:
// Next, we need to find the closest point on the line between each set, and determine which one we're
// closest to.
p.x = player->mo->x;
p.y = player->mo->y;
p.z = player->mo->z;
// Waypointmid and Waypointlow:
if (waypointlow)
{
v1.x = waypointmid->x;
v1.y = waypointmid->y;
v1.z = waypointmid->z;
v2.x = waypointlow->x;
v2.y = waypointlow->y;
v2.z = waypointlow->z;
junk.v1 = &v1;
junk.v2 = &v2;
junk.dx = v2.x - v1.x;
junk.dy = v2.y - v1.y;
line[0].x = waypointmid->x;
line[0].y = waypointmid->y;
line[0].z = waypointmid->z;
line[1].x = waypointlow->x;
line[1].y = waypointlow->y;
line[1].z = waypointlow->z;
P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resultlow);
P_ClosestPointOnLine3D(&p, line, &resultlow);
}
// Waypointmid and Waypointhigh:
if (waypointhigh)
{
v1.x = waypointmid->x;
v1.y = waypointmid->y;
v1.z = waypointmid->z;
v2.x = waypointhigh->x;
v2.y = waypointhigh->y;
v2.z = waypointhigh->z;
junk.v1 = &v1;
junk.v2 = &v2;
junk.dx = v2.x - v1.x;
junk.dy = v2.y - v1.y;
line[0].x = waypointmid->x;
line[0].y = waypointmid->y;
line[0].z = waypointmid->z;
line[1].x = waypointhigh->x;
line[1].y = waypointhigh->y;
line[1].z = waypointhigh->z;
P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resulthigh);
P_ClosestPointOnLine3D(&p, line, &resulthigh);
}
// 3D support now available. Disregard the previous notice here. -Red
@ -6433,7 +6425,6 @@ void P_SpawnSpecials(boolean fromnetsave)
INT32 j;
thinkerlist_t *secthinkers;
thinker_t *th;
virtres_t* virt = NULL;
// This used to be used, and *should* be used in the future,
// but currently isn't.
(void)fromnetsave;
@ -7179,38 +7170,14 @@ void P_SpawnSpecials(boolean fromnetsave)
EV_AddLaserThinker(&sectors[s], &sectors[sec], lines + i, secthinkers);
break;
case 259: // Make-Your-Own FOF!
case 259: // Custom FOF
if (lines[i].sidenum[1] != 0xffff)
{
UINT8 *data;
UINT16 b;
if (!virt)
virt = vres_GetMap(lastloadedmaplumpnum);
data = (UINT8*) vres_Find(virt, "SIDEDEFS")->data;
for (b = 0; b < (INT16)numsides; b++)
{
register mapsidedef_t *msd = (mapsidedef_t *)data + b;
if (b == lines[i].sidenum[1])
{
if ((msd->toptexture[0] >= '0' && msd->toptexture[0] <= '9')
|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F'))
{
ffloortype_e FOF_Flags = axtoi(msd->toptexture);
P_AddFakeFloorsByLine(i, FOF_Flags, secthinkers);
break;
}
else
I_Error("Make-Your-Own-FOF (tag %d) needs a value in the linedef's second side upper texture field.", lines[i].tag);
}
}
ffloortype_e fofflags = sides[lines[i].sidenum[1]].toptexture;
P_AddFakeFloorsByLine(i, fofflags, secthinkers);
}
else
I_Error("Make-Your-Own FOF (tag %d) found without a 2nd linedef side!", lines[i].tag);
I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag);
break;
case 300: // Linedef executor (combines with sector special 974/975) and commands
@ -7433,9 +7400,6 @@ void P_SpawnSpecials(boolean fromnetsave)
}
}
if (virt)
vres_Free(virt);
// Allocate each list
for (i = 0; i < numsectors; i++)
if(secthinkers[i].thinkers)

View File

@ -27,6 +27,9 @@ extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
//
#define GETSECSPECIAL(i,j) ((i >> ((j-1)*4))&15)
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
#define MAXFLATSIZE (2048<<FRACBITS)
// at game start
void P_InitPicAnims(void);

View File

@ -629,6 +629,10 @@ void P_Ticker(boolean run)
if (demoplayback)
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
#ifdef HAVE_BLUA
LUAh_PreThinkFrame();
#endif
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]);
@ -726,6 +730,10 @@ void P_Ticker(boolean run)
G_ConsGhostTic();
if (modeattacking)
G_GhostTicker();
#ifdef HAVE_BLUA
LUAh_PostThinkFrame();
#endif
}
P_MapEnd();
@ -745,6 +753,9 @@ void P_PreTicker(INT32 frames)
{
P_MapStart();
#ifdef HAVE_BLUA
LUAh_PreThinkFrame();
#endif
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
{
@ -779,6 +790,10 @@ void P_PreTicker(INT32 frames)
P_UpdateSpecials();
P_RespawnSpecials();
#ifdef HAVE_BLUA
LUAh_PostThinkFrame();
#endif
P_MapEnd();
}
}

View File

@ -347,6 +347,11 @@ void P_GiveEmerald(boolean spawnObj)
continue;
P_SetTarget(&emmo->target, players[i].mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
// Make sure we're not being carried before our tracer is changed
if (players[i].powers[pw_carry] != CR_NIGHTSMODE)
players[i].powers[pw_carry] = CR_NONE;
P_SetTarget(&players[i].mo->tracer, emmo);
if (pnum == 255)
@ -1230,13 +1235,13 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
if (gamestate == GS_LEVEL)
{
if (player->lives == INFLIVES || (gametype != GT_COOP && gametype != GT_COMPETITION))
if (player->lives == INFLIVES || !(gametyperules & GTR_LIVES))
{
P_GivePlayerRings(player, 100*numlives);
return;
}
if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0)
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0)
{
P_GivePlayerRings(player, 100*numlives);
if (player->lives - prevlives >= numlives)
@ -1267,7 +1272,7 @@ docooprespawn:
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound)
{
if (!((netgame || multiplayer) && gametype == GT_COOP))
if (!((netgame || multiplayer) && G_GametypeUsesCoopLives()))
{
P_GivePlayerLives(player, numlives);
if (sound)
@ -1395,7 +1400,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
player->score = MAXSCORE;
// check for extra lives every 50000 pts
if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP))
if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametyperules & GTR_LIVES))
{
P_GivePlayerLives(player, (player->score/50000) - (oldscore/50000));
P_PlayLivesJingle(player);
@ -4631,6 +4636,12 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
S_StartSound(player->mo, sfx_spin);
break;
}
if (player->dashspeed < player->mindash)
player->dashspeed = player->mindash;
if (player->dashspeed > player->maxdash)
player->dashspeed = player->maxdash;
if (player->dashspeed < player->maxdash && player->mindash != player->maxdash)
{
#define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash)
@ -7780,6 +7791,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
flame->fuse = TICRATE*7; // takes about an extra second to hit the ground
flame->destscale = player->mo->scale;
P_SetScale(flame, player->mo->scale);
flame->flags2 = (flame->flags2 & ~MF2_OBJECTFLIP)|(player->mo->flags2 & MF2_OBJECTFLIP);
flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP);
P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale));
P_SetObjectMomZ(flame, 3*FRACUNIT, false);
@ -9298,7 +9310,7 @@ boolean P_GetLives(player_t *player)
{
INT32 i, maxlivesplayer = -1, livescheck = 1;
if (!(netgame || multiplayer)
|| (gametype != GT_COOP)
|| !G_GametypeUsesCoopLives()
|| (player->lives == INFLIVES))
return true;
@ -9447,7 +9459,7 @@ static void P_DeathThink(player_t *player)
player->playerstate = PST_REBORN;
else if ((player->lives > 0 || j != MAXPLAYERS) && !(!(netgame || multiplayer) && G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages!
{
if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2)
if (G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2)
{
P_ConsiderAllGone();
if ((player->deadtimer > TICRATE<<1) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))
@ -9462,19 +9474,22 @@ static void P_DeathThink(player_t *player)
// Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes.
if (cmd->buttons & BT_JUMP)
{
if (gametype != GT_COOP && player->spectator)
// You're a spectator, so respawn right away.
if ((gametyperules & GTR_SPECTATORS) && player->spectator)
player->playerstate = PST_REBORN;
else switch(gametype) {
case GT_COOP:
case GT_COMPETITION:
case GT_RACE:
if (player->deadtimer > TICRATE)
player->playerstate = PST_REBORN;
break;
default:
if (player->deadtimer > cv_respawntime.value*TICRATE)
player->playerstate = PST_REBORN;
break;
else
{
// Give me one second.
INT32 respawndelay = TICRATE;
// Non-platform gametypes
if (gametyperules & GTR_RESPAWNDELAY)
respawndelay = (cv_respawntime.value*TICRATE);
// You've been dead for enough time.
// You may now respawn.
if (player->deadtimer > respawndelay)
player->playerstate = PST_REBORN;
}
}
@ -9488,7 +9503,7 @@ static void P_DeathThink(player_t *player)
INT32 i, deadtimercheck = INT32_MAX;
// In a net/multiplayer game, and out of lives
if (gametype == GT_COMPETITION)
if (G_CompetitionGametype())
{
for (i = 0; i < MAXPLAYERS; i++)
{
@ -11244,7 +11259,10 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
if (panim == PA_WALK)
{
if (stat != fume->info->spawnstate)
{
fume->threshold = 0;
P_SetMobjState(fume, fume->info->spawnstate);
}
return;
}
}
@ -11275,6 +11293,12 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
if (underwater)
{
fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10);
fume->threshold = 1;
}
else if (fume->threshold)
{
fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame;
fume->threshold = 0;
}
}
@ -11534,7 +11558,7 @@ void P_PlayerThink(player_t *player)
#else
if (player->spectator &&
#endif
gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2)
G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2)
P_ConsiderAllGone();
if (player->playerstate == PST_DEAD)

View File

@ -1169,9 +1169,11 @@ static void R_Subsector(size_t num)
while (count--)
{
// CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime);
if (!line->glseg
#ifdef POLYOBJECTS
if (!line->polyseg) // ignore segs that belong to polyobjects
&& !line->polyseg // ignore segs that belong to polyobjects
#endif
)
R_AddLine(line);
line++;
curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */

View File

@ -324,8 +324,8 @@ UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 al
else if (style != AST_TRANSLUCENT)
{
RGBA_t texel;
RGBA_t bg = V_GetColor(background);
RGBA_t fg = V_GetColor(foreground);
RGBA_t bg = V_GetMasterColor(background);
RGBA_t fg = V_GetMasterColor(foreground);
texel.rgba = ASTBlendPixel(bg, fg, style, alpha);
return NearestColor(texel.s.red, texel.s.green, texel.s.blue);
}
@ -1664,7 +1664,7 @@ static void R_CreateFadeColormaps(void)
#define GETCOLOR \
px = colormaps[i%256]; \
fade = (i/256) * (256 / FADECOLORMAPROWS); \
rgba = V_GetColor(px);
rgba = V_GetMasterColor(px);
// to black
makeblack:
@ -2095,7 +2095,6 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
/////////////////////
// This code creates the colormap array used by software renderer
/////////////////////
if (rendermode == render_soft)
{
double r, g, b, cbrightness;
int p;
@ -2717,7 +2716,7 @@ void R_PrecacheLevel(void)
lump = sf->lumppat[k];
if (devparm)
spritememory += W_LumpLength(lump);
W_CachePatchNum(lump, PU_CACHE);
W_CachePatchNum(lump, PU_PATCH);
}
}
}

View File

@ -83,7 +83,7 @@ typedef struct extracolormap_s
*/
typedef struct
{
fixed_t x, y, z;
fixed_t x, y;
} vertex_t;
// Forward of linedefs, for sectors.
@ -436,14 +436,10 @@ typedef struct line_s
polyobj_t *polyobj; // Belongs to a polyobject?
#endif
char *text; // a concatination of all front and back texture names, for linedef specials that require a string.
char *text; // a concatenation of all front and back texture names, for linedef specials that require a string.
INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0
} line_t;
//
// The SideDef.
//
typedef struct
{
// add this to the calculated texture column
@ -456,13 +452,16 @@ typedef struct
// We do not maintain names here.
INT32 toptexture, bottomtexture, midtexture;
// Sector the SideDef is facing.
// Linedef the sidedef belongs to
line_t *line;
// Sector the sidedef is facing.
sector_t *sector;
INT16 special; // the special of the linedef this side belongs to
INT16 repeatcnt; // # of times to repeat midtexture
char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string.
char *text; // a concatenation of all top, bottom, and mid texture names, for linedef specials that require a string.
extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors.
} side_t;
@ -587,6 +586,7 @@ typedef struct seg_s
polyobj_t *polyseg;
boolean dontrenderme;
#endif
boolean glseg;
} seg_t;
//
@ -731,9 +731,9 @@ typedef struct
boolean cached[8];
#ifdef HWRENDER
aatree_t *hardware_patch[8];
#endif
#endif/*HWRENDER*/
} rotsprite_t;
#endif
#endif/*ROTSPRITE*/
typedef enum
{
@ -745,6 +745,24 @@ typedef enum
SRF_NONE = 0xff // Initial value
} spriterotateflags_t; // SRF's up!
// Same as a patch_t, except just the header
// and the wadnum/lumpnum combination that points
// to wherever the patch is in memory.
struct patchinfo_s
{
INT16 width; // bounding box size
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
UINT16 wadnum; // the software patch lump num for when the patch
UINT16 lumpnum; // was flushed, and we need to re-create it
// next patchinfo_t in memory
struct patchinfo_s *next;
};
typedef struct patchinfo_s patchinfo_t;
//
// Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites.

View File

@ -19,6 +19,7 @@
#include "r_local.h"
#include "r_splats.h" // faB(21jan): testing
#include "r_sky.h"
#include "hu_stuff.h"
#include "st_stuff.h"
#include "p_local.h"
#include "keys.h"
@ -28,6 +29,7 @@
#include "d_main.h"
#include "v_video.h"
#include "p_spec.h" // skyboxmo
#include "p_setup.h"
#include "z_zone.h"
#include "m_random.h" // quake camera shake
#include "r_portal.h"
@ -691,6 +693,7 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
INT32 side, i;
size_t nodenum;
subsector_t *ret;
seg_t *seg;
// single subsector is a special case
if (numnodes == 0)
@ -706,10 +709,15 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
}
ret = &subsectors[nodenum & ~NF_SUBSECTOR];
for (i = 0; i < ret->numlines; i++)
//if (R_PointOnSegSide(x, y, &segs[ret->firstline + i])) -- breaks in ogl because polyvertex_t cast over vertex pointers
if (P_PointOnLineSide(x, y, segs[ret->firstline + i].linedef) != segs[ret->firstline + i].side)
for (i = 0, seg = &segs[ret->firstline]; i < ret->numlines; i++, seg++)
{
if (seg->glseg)
continue;
//if (R_PointOnSegSide(x, y, seg)) -- breaks in ogl because polyvertex_t cast over vertex pointers
if (P_PointOnLineSide(x, y, seg->linedef) != seg->side)
return 0;
}
return ret;
}
@ -1154,6 +1162,26 @@ void R_RenderPlayerView(player_t *player)
free(masks);
}
// Lactozilla: Renderer switching
#ifdef HWRENDER
void R_InitHardwareMode(void)
{
HWR_AddSessionCommands();
HWR_Switch();
HWR_LoadTextures(numtextures);
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))
HWR_SetupLevel();
}
#endif
void R_ReloadHUDGraphics(void)
{
CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n");
ST_LoadGraphics();
HU_LoadGraphics();
ST_ReloadSkinFaceGraphics();
}
// =========================================================================
// ENGINE COMMANDS & VARS
// =========================================================================

View File

@ -89,6 +89,10 @@ extern consvar_t cv_tailspickup;
// Called by startup code.
void R_Init(void);
#ifdef HWRENDER
void R_InitHardwareMode(void);
#endif
void R_ReloadHUDGraphics(void);
// just sets setsizeneeded true
extern boolean setsizeneeded;

View File

@ -1396,4 +1396,19 @@ void R_FreeSkinRotSprite(size_t skinnum)
skinsprites++;
}
}
//
// R_FreeAllRotSprite
//
// Free ALL sprite rotation data from memory.
//
void R_FreeAllRotSprite(void)
{
INT32 i;
size_t s;
for (s = 0; s < numsprites; s++)
R_FreeSingleRotSprite(&sprites[s]);
for (i = 0; i < numskins; ++i)
R_FreeSkinRotSprite(i);
}
#endif

View File

@ -68,6 +68,7 @@ void R_FreeSingleRotSprite(spritedef_t *spritedef);
void R_FreeSkinRotSprite(size_t skinnum);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
void R_FreeAllRotSprite(void);
#endif
#endif // __R_PATCH__

View File

@ -165,7 +165,7 @@ static void R_DrawWallSplats(void)
mfloorclip = floorclip;
mceilingclip = ceilingclip;
patch = W_CachePatchNum(splat->patch, PU_CACHE);
patch = W_CachePatchNum(splat->patch, PU_PATCH);
dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz;
if (splat->yoffset)
@ -308,6 +308,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// for horizontal / vertical / diagonal. Diagonal?
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
curline = ds->curline;
frontsector = curline->frontsector;
backsector = curline->backsector;
texnum = R_GetTextureNum(curline->sidedef->midtexture);

View File

@ -147,7 +147,7 @@ void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, f
splat->flags = flags;
// bad.. but will be needed for drawing anyway..
patch = W_CachePatchNum(splat->patch, PU_CACHE);
patch = W_CachePatchNum(splat->patch, PU_PATCH);
// offset needed by draw code for texture mapping
linelength = P_SegLength((seg_t *)wallline);

View File

@ -126,11 +126,10 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
for (ang = 0; ang < ROTANGLES; ang++)
sprtemp[frame].rotsprite.patch[r][ang] = NULL;
#ifdef HWRENDER
if (rendermode == render_opengl)
sprtemp[frame].rotsprite.hardware_patch[r] = M_AATreeAlloc(AATREE_ZUSER);
#endif // HWRENDER
sprtemp[frame].rotsprite.hardware_patch[r] = M_AATreeAlloc(AATREE_ZUSER);
#endif/*HWRENDER*/
}
#endif
#endif/*ROTSPRITE*/
if (rotation == 0)
{
@ -988,7 +987,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
//
// R_SplitSprite
// runs through a sector's lightlist and
// runs through a sector's lightlist and Knuckles
static void R_SplitSprite(vissprite_t *sprite)
{
INT32 i, lightnum, lindex;

View File

@ -61,7 +61,9 @@ static void GameMIDIMusic_OnChange(void);
static void GameSounds_OnChange(void);
static void GameDigiMusic_OnChange(void);
#ifdef HAVE_OPENMPT
static void ModFilter_OnChange(void);
#endif
static lumpnum_t S_GetMusicLumpNum(const char *mname);

View File

@ -53,6 +53,7 @@ void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
// ------------------
viddef_t vid;
INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + 1)
UINT8 setrenderneeded = 0;
static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}};
@ -62,7 +63,17 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N
consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static void SCR_ChangeFullscreen (void);
static void SCR_ActuallyChangeRenderer(void);
CV_PossibleValue_t cv_renderer_t[] = {
{1, "Software"},
#ifdef HWRENDER
{2, "OpenGL"},
#endif
{0, NULL}
};
consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL};
static void SCR_ChangeFullscreen(void);
consvar_t cv_fullscreen = {"fullscreen", "Yes", CV_SAVE|CV_CALL, CV_YesNo, SCR_ChangeFullscreen, 0, NULL, NULL, 0, 0, NULL};
@ -87,19 +98,8 @@ boolean R_3DNow = false;
boolean R_MMXExt = false;
boolean R_SSE2 = false;
void SCR_SetMode(void)
void SCR_SetDrawFuncs(void)
{
if (dedicated)
return;
if (!setmodeneeded || WipeInAction)
return; // should never happen and don't change it during a wipe, BAD!
VID_SetMode(--setmodeneeded);
V_SetPalette(0);
//
// setup the right draw routines for either 8bpp or 16bpp
//
@ -193,9 +193,37 @@ void SCR_SetMode(void)
if (SCR_IsAspectCorrect(vid.width, vid.height))
CONS_Alert(CONS_WARNING, M_GetText("Resolution is not aspect-correct!\nUse a multiple of %dx%d\n"), BASEVIDWIDTH, BASEVIDHEIGHT);
*/
}
void SCR_SetMode(void)
{
if (dedicated)
return;
if (!(setmodeneeded || setrenderneeded) || WipeInAction)
return; // should never happen and don't change it during a wipe, BAD!
// Lactozilla: Renderer switching
if (setrenderneeded)
{
Z_PreparePatchFlush();
needpatchflush = true;
needpatchrecache = true;
VID_CheckRenderer();
if (!setmodeneeded)
VID_SetMode(vid.modenum);
}
if (setmodeneeded)
VID_SetMode(--setmodeneeded);
V_SetPalette(0);
SCR_SetDrawFuncs();
// set the apprpriate drawer for the sky (tall or INT16)
setmodeneeded = 0;
setrenderneeded = 0;
}
// do some initial settings for the game loading screen
@ -383,6 +411,8 @@ void SCR_CheckDefaultMode(void)
// see note above
setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1;
}
SCR_ActuallyChangeRenderer();
}
// sets the modenum as the new default video mode to be saved in the config file
@ -412,6 +442,55 @@ void SCR_ChangeFullscreen(void)
#endif
}
static int target_renderer = 0;
void SCR_ActuallyChangeRenderer(void)
{
setrenderneeded = target_renderer;
// setting the same renderer twice WILL crash your game, so let's not, please
if (rendermode == setrenderneeded)
setrenderneeded = 0;
}
// Lactozilla: Renderer switching
void SCR_ChangeRenderer(void)
{
setrenderneeded = 0;
if (con_startup)
{
target_renderer = cv_renderer.value;
#ifdef HWRENDER
if (M_CheckParm("-opengl"))
target_renderer = rendermode = render_opengl;
else
#endif
if (M_CheckParm("-software"))
target_renderer = rendermode = render_soft;
// set cv_renderer back
SCR_ChangeRendererCVars(rendermode);
return;
}
if (cv_renderer.value == 1)
target_renderer = render_soft;
else if (cv_renderer.value == 2)
target_renderer = render_opengl;
SCR_ActuallyChangeRenderer();
}
void SCR_ChangeRendererCVars(INT32 mode)
{
// set cv_renderer back
if (mode == render_soft)
CV_StealthSetValue(&cv_renderer, 1);
else if (mode == render_opengl)
CV_StealthSetValue(&cv_renderer, 2);
#ifdef HWRENDER
CV_StealthSetValue(&cv_newrenderer, cv_renderer.value);
#endif
}
boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
{
return

View File

@ -170,18 +170,29 @@ extern boolean R_SSE2;
// ----------------
// screen variables
// ----------------
extern viddef_t vid;
extern INT32 setmodeneeded; // mode number to set if needed, or 0
void SCR_ChangeRenderer(void);
void SCR_ChangeRendererCVars(INT32 mode);
extern UINT8 setrenderneeded;
extern INT32 scr_bpp;
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen;
extern CV_PossibleValue_t cv_renderer_t[];
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen;
#ifdef HWRENDER
extern consvar_t cv_newrenderer;
#endif
// wait for page flipping to end or not
extern consvar_t cv_vidwait;
// Change video mode, only at the start of a refresh.
void SCR_SetMode(void);
void SCR_SetDrawFuncs(void);
// Recalc screen size dependent stuff
void SCR_Recalc(void);
// Check parms once at startup

View File

@ -67,10 +67,12 @@
#include "../s_sound.h"
#include "../i_joy.h"
#include "../st_stuff.h"
#include "../hu_stuff.h"
#include "../g_game.h"
#include "../i_video.h"
#include "../console.h"
#include "../command.h"
#include "../r_main.h"
#include "sdlmain.h"
#ifdef HWRENDER
#include "../hardware/hw_main.h"
@ -98,6 +100,7 @@ boolean highcolor = false;
// synchronize page flipping with screen refresh
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
UINT8 graphics_started = 0; // Is used in console.c and screen.c
@ -107,6 +110,7 @@ static SDL_bool disable_fullscreen = SDL_FALSE;
#define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value
static SDL_bool disable_mouse = SDL_FALSE;
#define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus)
#define IGNORE_MOUSE (!cv_alwaysgrabmouse.value && (menuactive || paused || con_destlines || chat_on || gamestate != GS_LEVEL))
#define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN)
#define MOUSEBUTTONS_MAX MOUSEBUTTONS
@ -373,12 +377,15 @@ static void SDLdoUngrabMouse(void)
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);
}
SDLdoUngrabMouse();
}
void I_UpdateMouseGrab(void)
{
if (SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO && window != NULL
&& SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window
&& USE_MOUSEINPUT && !IGNORE_MOUSE)
SDLdoGrabMouse();
}
static void VID_Command_NumModes_f (void)
@ -585,7 +592,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
}
//else firsttimeonmouse = SDL_FALSE;
if (USE_MOUSEINPUT)
if (USE_MOUSEINPUT && !IGNORE_MOUSE)
SDLdoGrabMouse();
}
else if (!mousefocus && !kbfocus)
@ -632,11 +639,14 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
{
static boolean firstmove = true;
if (USE_MOUSEINPUT)
{
if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window))
if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window) || (IGNORE_MOUSE && !firstmove))
{
SDLdoUngrabMouse();
firstmove = false;
return;
}
@ -650,6 +660,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
mousemovey += -evt.yrel;
SDL_SetWindowGrab(window, SDL_TRUE);
}
firstmove = false;
return;
}
@ -657,6 +668,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
// of the screen then ignore it.
if ((evt.x == realwidth/2) && (evt.y == realheight/2))
{
firstmove = false;
return;
}
@ -669,6 +681,8 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
SDLdoGrabMouse();
}
}
firstmove = false;
}
static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
@ -682,7 +696,7 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
// this apparently makes a mouse button down event but not a mouse button up event,
// resulting in whatever key was pressed down getting "stuck" if we don't ignore it.
// -- Monster Iestyn (28/05/18)
if (SDL_GetMouseFocus() != window)
if (SDL_GetMouseFocus() != window || IGNORE_MOUSE)
return;
/// \todo inputEvent.button.which
@ -1064,7 +1078,7 @@ void I_StartupMouse(void)
}
else
firsttimeonmouse = SDL_FALSE;
if (cv_usemouse.value)
if (cv_usemouse.value && !IGNORE_MOUSE)
SDLdoGrabMouse();
else
SDLdoUngrabMouse();
@ -1204,7 +1218,6 @@ void I_FinishUpdate(void)
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
#ifdef HWRENDER
else if (rendermode == render_opengl)
{
@ -1404,37 +1417,53 @@ void VID_PrepareModeList(void)
#endif
}
INT32 VID_SetMode(INT32 modeNum)
static SDL_bool Impl_CreateContext(void)
{
SDLdoUngrabMouse();
vid.recalc = 1;
vid.bpp = 1;
if (modeNum >= 0 && modeNum < MAXWINMODES)
// Renderer-specific stuff
#ifdef HWRENDER
if (rendermode == render_opengl)
{
vid.width = windowedModes[modeNum][0];
vid.height = windowedModes[modeNum][1];
vid.modenum = modeNum;
if (!sdlglcontext)
sdlglcontext = SDL_GL_CreateContext(window);
if (sdlglcontext == NULL)
{
SDL_DestroyWindow(window);
I_Error("Failed to create a GL context: %s\n", SDL_GetError());
}
SDL_GL_MakeCurrent(window, sdlglcontext);
}
else
#endif
if (rendermode == render_soft)
{
// just set the desktop resolution as a fallback
SDL_DisplayMode mode;
SDL_GetWindowDisplayMode(window, &mode);
if (mode.w >= 2048)
int flags = 0; // Use this to set SDL_RENDERER_* flags now
if (usesdl2soft)
flags |= SDL_RENDERER_SOFTWARE;
else if (cv_vidwait.value)
flags |= SDL_RENDERER_PRESENTVSYNC;
if (!renderer)
renderer = SDL_CreateRenderer(window, -1, flags);
if (renderer == NULL)
{
vid.width = 1920;
vid.height = 1200;
CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError());
return SDL_FALSE;
}
else
{
vid.width = mode.w;
vid.height = mode.h;
}
vid.modenum = -1;
SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT);
}
return SDL_TRUE;
}
void VID_CheckRenderer(void)
{
if (dedicated)
return;
if (setrenderneeded)
{
rendermode = setrenderneeded;
Impl_CreateContext();
}
//Impl_SetWindowName("SRB2 "VERSIONSTRING);
SDLSetMode(vid.width, vid.height, USE_FULLSCREEN);
Impl_VideoSetupBuffer();
@ -1446,8 +1475,39 @@ INT32 VID_SetMode(INT32 modeNum)
SDL_FreeSurface(bufSurface);
bufSurface = NULL;
}
#ifdef HWRENDER
HWR_FreeTextureCache();
#endif
SCR_SetDrawFuncs();
}
#ifdef HWRENDER
else if (rendermode == render_opengl)
{
I_StartupHardwareGraphics();
R_InitHardwareMode();
HWR_Switch();
}
#endif
}
INT32 VID_SetMode(INT32 modeNum)
{
SDLdoUngrabMouse();
vid.recalc = 1;
vid.bpp = 1;
if (modeNum < 0)
modeNum = 0;
if (modeNum >= MAXWINMODES)
modeNum = MAXWINMODES-1;
vid.width = windowedModes[modeNum][0];
vid.height = windowedModes[modeNum][1];
vid.modenum = modeNum;
//Impl_SetWindowName("SRB2 "VERSIONSTRING);
VID_CheckRenderer();
return SDL_TRUE;
}
@ -1468,8 +1528,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
flags |= SDL_WINDOW_BORDERLESS;
#ifdef HWRENDER
if (rendermode == render_opengl)
flags |= SDL_WINDOW_OPENGL;
flags |= SDL_WINDOW_OPENGL;
#endif
// Create a window
@ -1482,38 +1541,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
return SDL_FALSE;
}
// Renderer-specific stuff
#ifdef HWRENDER
if (rendermode == render_opengl)
{
sdlglcontext = SDL_GL_CreateContext(window);
if (sdlglcontext == NULL)
{
SDL_DestroyWindow(window);
I_Error("Failed to create a GL context: %s\n", SDL_GetError());
}
SDL_GL_MakeCurrent(window, sdlglcontext);
}
else
#endif
if (rendermode == render_soft)
{
flags = 0; // Use this to set SDL_RENDERER_* flags now
if (usesdl2soft)
flags |= SDL_RENDERER_SOFTWARE;
else if (cv_vidwait.value)
flags |= SDL_RENDERER_PRESENTVSYNC;
renderer = SDL_CreateRenderer(window, -1, flags);
if (renderer == NULL)
{
CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError());
return SDL_FALSE;
}
SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT);
}
return SDL_TRUE;
return Impl_CreateContext();
}
/*
@ -1568,17 +1596,14 @@ static void Impl_VideoSetupSDLBuffer(void)
static void Impl_VideoSetupBuffer(void)
{
// Set up game's software render buffer
//if (rendermode == render_soft)
vid.rowbytes = vid.width * vid.bpp;
vid.direct = NULL;
if (vid.buffer)
free(vid.buffer);
vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS);
if (!vid.buffer)
{
vid.rowbytes = vid.width * vid.bpp;
vid.direct = NULL;
if (vid.buffer)
free(vid.buffer);
vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS);
if (!vid.buffer)
{
I_Error("%s", M_GetText("Not enough memory for video buffer\n"));
}
I_Error("%s", M_GetText("Not enough memory for video buffer\n"));
}
}
@ -1598,6 +1623,7 @@ void I_StartupGraphics(void)
COM_AddCommand ("vid_mode", VID_Command_Mode_f);
CV_RegisterVar (&cv_vidwait);
CV_RegisterVar (&cv_stretch);
CV_RegisterVar (&cv_alwaysgrabmouse);
disable_mouse = M_CheckParm("-nomouse");
disable_fullscreen = M_CheckParm("-win") ? 1 : 0;
@ -1623,16 +1649,12 @@ void I_StartupGraphics(void)
framebuffer = SDL_TRUE;
}
if (M_CheckParm("-software"))
{
rendermode = render_soft;
}
#ifdef HWRENDER
else if (M_CheckParm("-opengl"))
{
if (M_CheckParm("-opengl"))
rendermode = render_opengl;
}
else if (M_CheckParm("-software"))
#endif
rendermode = render_soft;
usesdl2soft = M_CheckParm("-softblit");
borderlesswindow = M_CheckParm("-borderless");
@ -1640,48 +1662,7 @@ void I_StartupGraphics(void)
//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
VID_Command_ModeList_f();
#ifdef HWRENDER
if (rendermode == render_opengl)
{
HWD.pfnInit = hwSym("Init",NULL);
HWD.pfnFinishUpdate = NULL;
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL);
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
HWD.pfnReadRect = hwSym("ReadRect",NULL);
HWD.pfnGClipRect = hwSym("GClipRect",NULL);
HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL);
HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL);
HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
HWD.pfnLoadShaders = hwSym("LoadShaders",NULL);
HWD.pfnKillShaders = hwSym("KillShaders",NULL);
HWD.pfnSetShader = hwSym("SetShader",NULL);
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL);
if (!HWD.pfnInit()) // load the OpenGL library
{
rendermode = render_soft;
}
}
I_StartupHardwareGraphics();
#endif
// Fury: we do window initialization after GL setup to allow
@ -1731,16 +1712,65 @@ void I_StartupGraphics(void)
SDL_RaiseWindow(window);
if (mousegrabok && !disable_mouse)
{
SDL_ShowCursor(SDL_DISABLE);
SDL_SetRelativeMouseMode(SDL_TRUE);
wrapmouseok = SDL_TRUE;
SDL_SetWindowGrab(window, SDL_TRUE);
}
SDLdoGrabMouse();
graphics_started = true;
}
void I_StartupHardwareGraphics(void)
{
#ifdef HWRENDER
static boolean glstartup = false;
if (!glstartup)
{
if (rendermode == render_opengl)
{
HWD.pfnInit = hwSym("Init",NULL);
HWD.pfnFinishUpdate = NULL;
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL);
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
HWD.pfnReadRect = hwSym("ReadRect",NULL);
HWD.pfnGClipRect = hwSym("GClipRect",NULL);
HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL);
HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL);
HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
HWD.pfnLoadShaders = hwSym("LoadShaders",NULL);
HWD.pfnKillShaders = hwSym("KillShaders",NULL);
HWD.pfnSetShader = hwSym("SetShader",NULL);
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL);
// check gl renderer lib
if (HWD.pfnGetRenderVersion() != VERSION)
I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
if (!HWD.pfnInit(I_Error)) // let load the OpenGL library
rendermode = render_soft;
else
glstartup = true;
}
#endif
}
void I_ShutdownGraphics(void)
{
const rendermode_t oldrendermode = rendermode;

View File

@ -1432,6 +1432,8 @@ static void I_ResumeGME(void)
boolean I_LoadSong(char *data, size_t len)
{
(void)data;
(void)len;
return false;
}
@ -1493,6 +1495,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms
(void)target_volume;
(void)source_volume;
(void)ms;
(void)callback;
return false;
}
@ -1500,6 +1503,7 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{
(void)target_volume;
(void)ms;
(void)callback;
return false;
}

View File

@ -187,6 +187,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pity Shield"}, // generic GET!
{"wirlsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind Shield"}, // Whirlwind GET!
{"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Force Shield"}, // Force GET!
{"frcssg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weak Force Shield"}, // Force GET...? (consider making a custom shield with this instead of a single-hit force shield!)
{"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Elemental Shield"}, // Elemental GET!
{"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon Shield"}, // Armaggeddon GET!
{"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction Shield"}, // Attract GET!
@ -220,6 +221,9 @@ sfxinfo_t S_sfx[NUMSFX] =
{"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"},
{"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"},
{"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"},
{"iceb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice crack"},
{"shattr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shattering"},
{"antiri", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Depletion"},
// Menu, interface
{"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"},
@ -233,6 +237,9 @@ sfxinfo_t S_sfx[NUMSFX] =
{"wepchg", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weapon change"}, // Weapon switch is identical to menu for now
{"wtrdng", true, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, // make sure you can hear the DING DING! Tails 03-08-2000
{"zelda", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"},
{"adderr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Error"},
{"notadd", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Reject"},
{"addfil", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accept"},
// NiGHTS
{"ideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"},
@ -427,24 +434,9 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
// S3&K sounds
{"s3k2b", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald!
{"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter
{"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous
{"s3k35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"},
@ -566,6 +558,21 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"},
{"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"},
{"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kab9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kaba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kabb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kabc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kabd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kabe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kabf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
{"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Continue"},
{"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "GO!"},
{"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pinball flipper"},
@ -604,7 +611,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto
{"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"},
{"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto
{"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"},
{"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"},
{"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, // ditto
{"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"},
{"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, // ditto
{"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging"},

View File

@ -236,6 +236,7 @@ typedef enum
sfx_shield,
sfx_wirlsg,
sfx_forcsg,
sfx_frcssg,
sfx_elemsg,
sfx_armasg,
sfx_attrsg,
@ -269,6 +270,9 @@ typedef enum
sfx_sprong,
sfx_lvfal1,
sfx_pscree,
sfx_iceb,
sfx_shattr,
sfx_antiri,
// Menu, interface
sfx_chchng,
@ -282,6 +286,9 @@ typedef enum
sfx_wepchg,
sfx_wtrdng,
sfx_zelda,
sfx_adderr,
sfx_notadd,
sfx_addfil,
// NiGHTS
sfx_ideya,
@ -476,24 +483,9 @@ typedef enum
sfx_s25e,
sfx_s25f,
sfx_s260,
sfx_s261,
sfx_s262,
sfx_s263,
sfx_s264,
sfx_s265,
sfx_s266,
sfx_s267,
sfx_s268,
sfx_s269,
sfx_s26a,
sfx_s26b,
sfx_s26c,
sfx_s26d,
sfx_s26e,
sfx_s26f,
sfx_s270,
// S3&K sounds
sfx_s3k2b,
sfx_s3k33,
sfx_s3k34,
sfx_s3k35,
@ -615,6 +607,21 @@ typedef enum
sfx_s3ka9,
sfx_s3kaa,
sfx_s3kab,
sfx_s3kab1,
sfx_s3kab2,
sfx_s3kab3,
sfx_s3kab4,
sfx_s3kab5,
sfx_s3kab6,
sfx_s3kab7,
sfx_s3kab8,
sfx_s3kab9,
sfx_s3kaba,
sfx_s3kabb,
sfx_s3kabc,
sfx_s3kabd,
sfx_s3kabe,
sfx_s3kabf,
sfx_s3kac,
sfx_s3kad,
sfx_s3kae,
@ -653,7 +660,8 @@ typedef enum
sfx_s3kc5l,
sfx_s3kc6s,
sfx_s3kc6l,
sfx_s3kc7,
sfx_s3kc7s,
sfx_s3kc7l,
sfx_s3kc8s,
sfx_s3kc8l,
sfx_s3kc9s,

View File

@ -694,7 +694,7 @@ static void ST_drawTime(void)
else
{
// Counting down the hidetime?
if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE)))
if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime <= (hidetime*TICRATE)))
{
tics = (hidetime*TICRATE - stplyr->realtime);
if (tics < 3*TICRATE)
@ -705,7 +705,7 @@ static void ST_drawTime(void)
else
{
// Hidetime finish!
if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime);
// Time limit?
@ -723,7 +723,7 @@ static void ST_drawTime(void)
downwards = true;
}
// Post-hidetime normal.
else if (gametyperules & GTR_TAG)
else if (gametyperules & GTR_STARTCOUNTDOWN)
tics = stplyr->realtime - hidetime*TICRATE;
// "Shadow! What are you doing? Hurry and get back here
// right now before the island blows up with you on it!"
@ -845,69 +845,13 @@ static void ST_drawLivesArea(void)
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, faceprefix[stplyr->skin], colormap);
}
// Lives number
// Metal Sonic recording
if (metalrecording)
{
if (((2*leveltime)/TICRATE) & 1)
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC");
}
else if (G_GametypeUsesLives() || gametype == GT_RACE)
{
// x
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10,
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex);
// lives number
if (gametype == GT_RACE)
{
livescount = INFLIVES;
notgreyedout = true;
}
else if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3)
{
INT32 i;
livescount = 0;
notgreyedout = (stplyr->lives > 0);
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].lives < 1)
continue;
if (players[i].lives > 1)
notgreyedout = true;
if (players[i].lives == INFLIVES)
{
livescount = INFLIVES;
break;
}
else if (livescount < 99)
livescount += (players[i].lives);
}
}
else
{
livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives);
notgreyedout = true;
}
if (livescount == INFLIVES)
V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8,
'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
else
{
if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)))
livescount++;
if (livescount > 99)
livescount = 99;
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount));
}
}
// Spectator
else if (stplyr->spectator)
v_colmap = V_GRAYMAP;
@ -934,11 +878,89 @@ static void ST_drawLivesArea(void)
v_colmap = V_BLUEMAP;
}
}
// Lives number
else
{
boolean candrawlives = true;
// Co-op and Competition, normal life counter
if (G_GametypeUsesLives())
{
// Handle cooplives here
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 3)
{
INT32 i;
livescount = 0;
notgreyedout = (stplyr->lives > 0);
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].lives < 1)
continue;
if (players[i].lives > 1)
notgreyedout = true;
if (players[i].lives == INFLIVES)
{
livescount = INFLIVES;
break;
}
else if (livescount < 99)
livescount += (players[i].lives);
}
}
else
{
livescount = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives);
notgreyedout = true;
}
}
// Infinity symbol (Race)
else if (G_PlatformGametype() && !(gametyperules & GTR_LIVES))
{
livescount = INFLIVES;
notgreyedout = true;
}
// Otherwise nothing, sorry.
// Special Stages keep not showing lives,
// as G_GametypeUsesLives() returns false in
// Special Stages, and the infinity symbol
// cannot show up because Special Stages
// still have the GTR_LIVES gametype rule
// by default.
else
candrawlives = false;
// Draw the lives counter here.
if (candrawlives)
{
// x
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex);
if (livescount == INFLIVES)
V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8,
'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
else
{
if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)))
livescount++;
if (livescount > 99)
livescount = 99;
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount));
}
}
#undef ST_drawLivesX
}
// name
v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER);
if (strlen(skins[stplyr->skin].hudname) <= 5)
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48)
V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40)
V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
else
@ -2202,7 +2224,7 @@ static void ST_drawTextHUD(void)
donef12 = true;
}
}
else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text.
else if ((gametyperules & GTR_RESPAWNDELAY) && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text.
{
INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE;
@ -2226,7 +2248,7 @@ static void ST_drawTextHUD(void)
textHUDdraw(M_GetText("\x82""Wait for the stage to end..."))
else if (G_PlatformGametype())
{
if (gametype == GT_COOP)
if (G_GametypeUsesCoopLives())
{
if (stplyr->lives <= 0
&& cv_cooplives.value == 2
@ -2637,7 +2659,7 @@ static void ST_overlayDrawer(void)
INT32 i = MAXPLAYERS;
INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1));
if ((gametype == GT_COOP)
if (G_GametypeUsesCoopLives()
&& (netgame || multiplayer)
&& (cv_cooplives.value != 1))
{
@ -2766,6 +2788,9 @@ static void ST_overlayDrawer(void)
void ST_Drawer(void)
{
if (needpatchrecache)
R_ReloadHUDGraphics();
#ifdef SEENAMES
if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo)
{

View File

@ -1045,13 +1045,13 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin
{
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE];
patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE);
V_DrawMappedPatch(x, y, flags, patch, colormap);
}
else
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE));
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_PATCH));
}
//

View File

@ -64,6 +64,7 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
// Retrieve the ARGB value from a palette color index
#define V_GetColor(color) (pLocalPalette[color&0xFF])
#define V_GetMasterColor(color) (pMasterPalette[color&0xFF])
// Bottom 8 bits are used for parameter (screen or character)
#define V_PARAMMASK 0x000000FF

View File

@ -55,6 +55,7 @@
#include "dehacked.h"
#include "d_clisrv.h"
#include "r_defs.h"
#include "r_data.h"
#include "i_system.h"
#include "md5.h"
#include "lua_script.h"
@ -1380,7 +1381,6 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
void *W_CacheLumpNum(lumpnum_t lumpnum, INT32 tag)
{
return W_CacheLumpNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag);
}
@ -1493,12 +1493,31 @@ void *W_CacheLumpName(const char *name, INT32 tag)
// Cache a patch into heap memory, convert the patch format as necessary
//
void W_FlushCachedPatches(void)
{
if (needpatchflush)
{
Z_FreeTag(PU_CACHE);
Z_FreeTag(PU_PATCH);
Z_FreeTag(PU_HUDGFX);
Z_FreeTag(PU_HWRPATCHINFO);
Z_FreeTag(PU_HWRMODELTEXTURE);
Z_FreeTag(PU_HWRCACHE);
Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRPATCHINFO_UNLOCKED);
}
needpatchflush = false;
}
// Software-only compile cache the data without conversion
void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
{
#ifdef HWRENDER
GLPatch_t *grPatch;
#endif
if (needpatchflush)
W_FlushCachedPatches();
if (!TestValidLump(wad, lump))
return NULL;

View File

@ -196,6 +196,7 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch
void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); // return a patch_t
void W_UnlockCachedPatch(void *patch);
void W_FlushCachedPatches(void);
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5);

View File

@ -1354,6 +1354,8 @@ getBufferedData:
}
}
void I_UpdateMouseGrab(void) {}
// ===========================================================================================
// DIRECT INPUT JOYSTICK
// ===========================================================================================

View File

@ -239,6 +239,11 @@ void I_StartupGraphics(void)
if (!dedicated) graphics_started = true;
}
void I_StartupHardwareGraphics(void)
{
// oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y
}
// ------------------
// I_ShutdownGraphics
// Close the screen, restore previous video mode.
@ -946,6 +951,11 @@ INT32 VID_SetMode(INT32 modenum)
return 1;
}
void VID_CheckRenderer(void)
{
// ..............
}
// ========================================================================
// Free the video buffer of the last video mode,
// allocate a new buffer for the video mode to set.

View File

@ -161,6 +161,7 @@ typedef struct
boolean usebuffer = false;
static boolean useinterpic;
static boolean safetorender = true;
static y_buffer_t *y_buffer;
static INT32 intertic;
@ -177,6 +178,7 @@ static void Y_CalculateCompetitionWinners(void);
static void Y_CalculateTimeRaceWinners(void);
static void Y_CalculateMatchWinners(void);
static void Y_UnloadData(void);
static void Y_CleanupData(void);
// Stuff copy+pasted from st_stuff.c
#define ST_DrawNumFromHud(h,n) V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n)
@ -335,8 +337,19 @@ void Y_IntermissionDrawer(void)
}
if (!usebuffer)
// Lactozilla: Renderer switching
if (needpatchrecache)
{
Y_CleanupData();
safetorender = false;
}
if (!usebuffer || !safetorender)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
if (!safetorender)
goto dontdrawbg;
if (useinterpic)
V_DrawScaledPatch(0, 0, 0, interpic);
else if (!usetile)
@ -377,6 +390,7 @@ void Y_IntermissionDrawer(void)
goto skiptallydrawer;
#endif
dontdrawbg:
if (intertype == int_coop)
{
INT32 bonusy;
@ -426,14 +440,17 @@ void Y_IntermissionDrawer(void)
bonusy = 150;
// Total
V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal);
V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total);
if (safetorender)
{
V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal);
V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total);
}
bonusy -= (3*SHORT(tallnum[0]->height)/2) + 1;
// Draw bonuses
for (i = 3; i >= 0; --i)
{
if (data.coop.bonuses[i].display)
if (data.coop.bonuses[i].display && safetorender)
{
V_DrawScaledPatch(152, bonusy, 0, data.coop.bonuspatches[i]);
V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.bonuses[i].points);
@ -662,7 +679,8 @@ void Y_IntermissionDrawer(void)
char strtime[10];
// draw the header
V_DrawScaledPatch(112, 2, 0, data.match.result);
if (safetorender)
V_DrawScaledPatch(112, 2, 0, data.match.result);
// draw the level name
V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring);
@ -1194,6 +1212,8 @@ void Y_StartIntermission(void)
I_Error("endtic is dirty");
#endif
safetorender = true;
if (!multiplayer)
{
timer = 0;
@ -1249,20 +1269,20 @@ void Y_StartIntermission(void)
data.coop.tics = players[consoleplayer].realtime;
for (i = 0; i < 4; ++i)
data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_STATIC);
data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_STATIC);
data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_PATCH);
data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH);
// get act number
data.coop.actnum = mapheaderinfo[gamemap-1]->actnum;
// get background patches
widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC);
bgpatch = W_CachePatchName("INTERSCR", PU_STATIC);
widebgpatch = W_CachePatchName("INTERSCW", PU_PATCH);
bgpatch = W_CachePatchName("INTERSCR", PU_PATCH);
// grab an interscreen if appropriate
if (mapheaderinfo[gamemap-1]->interscreen[0] != '#')
{
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_STATIC);
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH);
useinterpic = true;
usebuffer = false;
}
@ -1320,18 +1340,18 @@ void Y_StartIntermission(void)
Y_AwardSpecialStageBonus();
for (i = 0; i < 2; ++i)
data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_STATIC);
data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH);
data.spec.pscore = W_CachePatchName("YB_SCORE", PU_STATIC);
data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_STATIC);
data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH);
data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH);
// get background tile
bgtile = W_CachePatchName("SPECTILE", PU_STATIC);
bgtile = W_CachePatchName("SPECTILE", PU_PATCH);
// grab an interscreen if appropriate
if (mapheaderinfo[gamemap-1]->interscreen[0] != '#')
{
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_STATIC);
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH);
useinterpic = true;
}
else
@ -1343,14 +1363,14 @@ void Y_StartIntermission(void)
// get special stage specific patches
/* if (!stagefailed && ALL7EMERALDS(emeralds))
{
data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_STATIC);
data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_PATCH);
data.spec.headx = 70;
data.spec.nowsuper = players[consoleplayer].skin
? NULL : W_CachePatchName("NOWSUPER", PU_STATIC);
? NULL : W_CachePatchName("NOWSUPER", PU_PATCH);
}
else
{
data.spec.cemerald = W_CachePatchName("CEMERALD", PU_STATIC);
data.spec.cemerald = W_CachePatchName("CEMERALD", PU_PATCH);
data.spec.headx = 48;
data.spec.nowsuper = NULL;
} */
@ -1428,9 +1448,9 @@ void Y_StartIntermission(void)
// get RESULT header
data.match.result =
W_CachePatchName("RESULT", PU_STATIC);
W_CachePatchName("RESULT", PU_PATCH);
bgtile = W_CachePatchName("SRB2BACK", PU_STATIC);
bgtile = W_CachePatchName("SRB2BACK", PU_PATCH);
usetile = true;
useinterpic = false;
break;
@ -1456,9 +1476,9 @@ void Y_StartIntermission(void)
data.match.levelstring[sizeof data.match.levelstring - 1] = '\0';
// get RESULT header
data.match.result = W_CachePatchName("RESULT", PU_STATIC);
data.match.result = W_CachePatchName("RESULT", PU_PATCH);
bgtile = W_CachePatchName("SRB2BACK", PU_STATIC);
bgtile = W_CachePatchName("SRB2BACK", PU_PATCH);
usetile = true;
useinterpic = false;
break;
@ -1495,7 +1515,7 @@ void Y_StartIntermission(void)
data.match.blueflag = bmatcico;
}
bgtile = W_CachePatchName("SRB2BACK", PU_STATIC);
bgtile = W_CachePatchName("SRB2BACK", PU_PATCH);
usetile = true;
useinterpic = false;
break;
@ -1521,7 +1541,7 @@ void Y_StartIntermission(void)
data.competition.levelstring[sizeof data.competition.levelstring - 1] = '\0';
// get background tile
bgtile = W_CachePatchName("SRB2BACK", PU_STATIC);
bgtile = W_CachePatchName("SRB2BACK", PU_PATCH);
usetile = true;
useinterpic = false;
break;
@ -1977,7 +1997,7 @@ static void Y_AwardCoopBonuses(void)
if (i == consoleplayer)
{
data.coop.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
data.coop.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives);
M_Memcpy(&data.coop.bonuses, &localbonuses, sizeof(data.coop.bonuses));
}
}
@ -2032,7 +2052,7 @@ static void Y_AwardSpecialStageBonus(void)
if (i == consoleplayer)
{
data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
data.spec.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives);
M_Memcpy(&data.spec.bonuses, &localbonuses, sizeof(data.spec.bonuses));
// Continues related
@ -2059,7 +2079,8 @@ void Y_EndIntermission(void)
usebuffer = false;
}
#define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL
#define UNLOAD(x) if (x) {Z_ChangeTag(x, PU_CACHE);} x = NULL;
#define CLEANUP(x) x = NULL;
//
// Y_UnloadData
@ -2110,5 +2131,47 @@ static void Y_UnloadData(void)
//are not handled
break;
}
}
static void Y_CleanupData(void)
{
// unload the background patches
CLEANUP(bgpatch);
CLEANUP(widebgpatch);
CLEANUP(bgtile);
CLEANUP(interpic);
switch (intertype)
{
case int_coop:
// unload the coop and single player patches
CLEANUP(data.coop.bonuspatches[3]);
CLEANUP(data.coop.bonuspatches[2]);
CLEANUP(data.coop.bonuspatches[1]);
CLEANUP(data.coop.bonuspatches[0]);
CLEANUP(data.coop.ptotal);
break;
case int_spec:
// unload the special stage patches
//CLEANUP(data.spec.cemerald);
//CLEANUP(data.spec.nowsuper);
CLEANUP(data.spec.bonuspatches[1]);
CLEANUP(data.spec.bonuspatches[0]);
CLEANUP(data.spec.pscore);
CLEANUP(data.spec.pcontinues);
break;
case int_match:
case int_race:
CLEANUP(data.match.result);
break;
case int_ctf:
CLEANUP(data.match.blueflag);
CLEANUP(data.match.redflag);
break;
default:
//without this default,
//int_none, int_tag, int_chaos, and int_classicrace
//are not handled
break;
}
}

View File

@ -27,6 +27,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "r_patch.h"
#include "i_system.h" // I_GetFreeMem
#include "i_video.h" // rendermode
#include "z_zone.h"
@ -497,6 +498,35 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
// Utility functions
// -----------------
// for renderer switching, free a bunch of stuff
boolean needpatchflush = false;
boolean needpatchrecache = false;
// flush all patches from memory
// (also frees memory tagged with PU_CACHE)
// (which are not necessarily patches but I don't care)
void Z_FlushCachedPatches(void)
{
CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n");
Z_FreeTag(PU_CACHE);
Z_FreeTag(PU_PATCH);
Z_FreeTag(PU_HUDGFX);
Z_FreeTag(PU_HWRPATCHINFO);
Z_FreeTag(PU_HWRMODELTEXTURE);
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
Z_FreeTag(PU_HWRPATCHINFO_UNLOCKED);
}
// happens before a renderer switch
void Z_PreparePatchFlush(void)
{
CONS_Debug(DBG_RENDER, "Z_PreparePatchFlush()...\n");
#ifdef ROTSPRITE
R_FreeAllRotSprite();
#endif
}
// starting value of nextcleanup
#define CLEANUPCOUNT 2000

View File

@ -43,6 +43,7 @@ enum
PU_SOUND = 11, // static while playing
PU_MUSIC = 12, // static while playing
PU_HUDGFX = 13, // static until WAD added
PU_PATCH = 14, // static until renderer change
PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache
PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch
@ -142,4 +143,10 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag);
char *Z_StrDup(const char *in);
#define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed
// For renderer switching
extern boolean needpatchflush;
extern boolean needpatchrecache;
void Z_FlushCachedPatches(void);
void Z_PreparePatchFlush(void);
#endif