diff --git a/SRB2.cbp b/SRB2.cbp
index 88dc400fe..2a1eb87b8 100644
--- a/SRB2.cbp
+++ b/SRB2.cbp
@@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index da8438a59..6a8b7e3f1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -351,6 +351,7 @@ if(${SRB2_CONFIG_HWRENDER})
set(SRB2_HWRENDER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
@@ -359,6 +360,7 @@ if(${SRB2_CONFIG_HWRENDER})
)
set (SRB2_HWRENDER_HEADERS
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
diff --git a/src/Makefile b/src/Makefile
index 426dc2289..27569b36c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -259,7 +259,7 @@ ifndef DC
endif
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
- $(OBJDIR)/hw_main.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
+ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
endif
ifdef NOHS
@@ -703,7 +703,7 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
@@ -711,7 +711,7 @@ else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
@@ -864,7 +864,7 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -872,7 +872,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -880,7 +880,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
diff --git a/src/console.c b/src/console.c
index fff9ba96c..54fde7af7 100644
--- a/src/console.c
+++ b/src/console.c
@@ -33,6 +33,7 @@
#include "i_system.h"
#include "d_main.h"
#include "m_menu.h"
+#include "filesrch.h"
#ifdef _WINDOWS
#include "win32/win_main.h"
@@ -1275,12 +1276,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...)
switch (level)
{
case CONS_NOTICE:
+ // no notice for notices, hehe
CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:"));
break;
case CONS_WARNING:
+ refreshdirmenu |= REFRESHDIR_WARNING;
CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:"));
break;
case CONS_ERROR:
+ refreshdirmenu |= REFRESHDIR_ERROR;
CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:"));
break;
}
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 8af95531c..decc2e74b 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -2527,12 +2527,18 @@ static void Command_Nodes(void)
static void Command_Ban(void)
{
- if (COM_Argc() == 1)
+ if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("Ban : ban and kick a player\n"));
return;
}
+ if (!netgame) // Don't kick Tails in splitscreen!
+ {
+ CONS_Printf(M_GetText("This only works in a netgame.\n"));
+ return;
+ }
+
if (server || adminplayer == consoleplayer)
{
XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
@@ -2542,8 +2548,9 @@ static void Command_Ban(void)
if (pn == -1 || pn == 0)
return;
- else
- WRITEUINT8(p, pn);
+
+ WRITEUINT8(p, pn);
+
if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now
{
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
@@ -2586,21 +2593,27 @@ static void Command_Ban(void)
static void Command_Kick(void)
{
- XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
- UINT8 *p = buf;
-
- if (COM_Argc() == 1)
+ if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("kick : kick a player\n"));
return;
}
+ if (!netgame) // Don't kick Tails in splitscreen!
+ {
+ CONS_Printf(M_GetText("This only works in a netgame.\n"));
+ return;
+ }
+
if (server || adminplayer == consoleplayer)
{
+ XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
+ UINT8 *p = buf;
const SINT8 pn = nametonum(COM_Argv(1));
- WRITESINT8(p, pn);
+
if (pn == -1 || pn == 0)
return;
+
// Special case if we are trying to kick a player who is downloading the game state:
// trigger a timeout instead of kicking them, because a kick would only
// take effect after they have finished downloading
@@ -2609,6 +2622,9 @@ static void Command_Kick(void)
Net_ConnectionTimeout(playernode[pn]);
return;
}
+
+ WRITESINT8(p, pn);
+
if (COM_Argc() == 2)
{
WRITEUINT8(p, KICK_MSG_GO_AWAY);
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 1ca82fdc5..da077c682 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -315,6 +315,7 @@ typedef struct
} ATTRPACK clientconfig_pak;
#define MAXSERVERNAME 32
+#define MAXFILENEEDED 915
// This packet is too large
typedef struct
{
@@ -336,7 +337,7 @@ typedef struct
unsigned char mapmd5[16];
UINT8 actnum;
UINT8 iszone;
- UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h)
+ UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK serverinfo_pak;
typedef struct
diff --git a/src/d_main.c b/src/d_main.c
index 26abcbde3..f01bcb84d 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "m_cond.h" // condition initialization
#include "fastcmp.h"
#include "keys.h"
+#include "filesrch.h" // refreshdirmenu, mainwadstally
#ifdef CMAKECONFIG
#include "config.h"
@@ -107,8 +108,6 @@ UINT8 window_notinfocus = false;
//
// DEMO LOOP
//
-//static INT32 demosequence;
-static const char *pagename = "MAP1PIC";
static char *startupwadfiles[MAX_WADFILES];
boolean devparm = false; // started game with -devparm
@@ -420,10 +419,13 @@ static void D_Display(void)
}
// Image postprocessing effect
- if (postimgtype)
- V_DoPostProcessor(0, postimgtype, postimgparam);
- if (postimgtype2)
- V_DoPostProcessor(1, postimgtype2, postimgparam2);
+ if (rendermode == render_soft)
+ {
+ if (postimgtype)
+ V_DoPostProcessor(0, postimgtype, postimgparam);
+ if (postimgtype2)
+ V_DoPostProcessor(1, postimgtype2, postimgparam2);
+ }
}
if (lastdraw)
@@ -586,6 +588,8 @@ void D_SRB2Loop(void)
realtics = entertic - oldentertics;
oldentertics = entertic;
+ refreshdirmenu = 0; // not sure where to put this, here as good as any?
+
#ifdef DEBUGFILE
if (!realtics)
if (debugload)
@@ -711,6 +715,7 @@ void D_StartTitle(void)
botskin = 0;
cv_debug = 0;
emeralds = 0;
+ lastmaploaded = 0;
// In case someone exits out at the same time they start a time attack run,
// reset modeattacking
@@ -721,7 +726,6 @@ void D_StartTitle(void)
gameaction = ga_nothing;
displayplayer = consoleplayer = 0;
- //demosequence = -1;
gametype = GT_COOP;
paused = false;
advancedemo = false;
@@ -870,7 +874,7 @@ static void IdentifyVersion(void)
}
#endif
-#if 1 // This section can be deleted when music_new is merged with music.dta
+#ifdef DEVELOP // This section can be deleted when music_new is merged with music.dta
{
const char *musicfile = "music_new.dta";
const char *musicpath = va(pandf,srb2waddir,musicfile);
@@ -883,27 +887,10 @@ static void IdentifyVersion(void)
#endif
}
-/* ======================================================================== */
-// Just print the nice red titlebar like the original SRB2 for DOS.
-/* ======================================================================== */
#ifdef PC_DOS
-static inline void D_Titlebar(char *title1, char *title2)
-{
- // SRB2 banner
- clrscr();
- textattr((BLUE<<4)+WHITE);
- clreol();
- cputs(title1);
-
- // standard srb2 banner
- textattr((RED<<4)+WHITE);
- clreol();
- gotoxy((80-strlen(title2))/2, 2);
- cputs(title2);
- normvideo();
- gotoxy(1,3);
-}
-#endif
+/* ======================================================================== */
+// Code for printing SRB2's title bar in DOS
+/* ======================================================================== */
//
// Center the title string, then add the date and time of compilation.
@@ -932,6 +919,31 @@ static inline void D_MakeTitleString(char *s)
strcpy(s, temp);
}
+static inline void D_Titlebar(void)
+{
+ char title1[82]; // srb2 title banner
+ char title2[82];
+
+ strcpy(title1, "Sonic Robo Blast 2");
+ strcpy(title2, "Sonic Robo Blast 2");
+
+ D_MakeTitleString(title1);
+
+ // SRB2 banner
+ clrscr();
+ textattr((BLUE<<4)+WHITE);
+ clreol();
+ cputs(title1);
+
+ // standard srb2 banner
+ textattr((RED<<4)+WHITE);
+ clreol();
+ gotoxy((80-strlen(title2))/2, 2);
+ cputs(title2);
+ normvideo();
+ gotoxy(1,3);
+}
+#endif
//
// D_SRB2Main
@@ -939,8 +951,6 @@ static inline void D_MakeTitleString(char *s)
void D_SRB2Main(void)
{
INT32 p;
- char srb2[82]; // srb2 title banner
- char title[82];
INT32 pstartmap = 1;
boolean autostart = false;
@@ -983,20 +993,8 @@ void D_SRB2Main(void)
dedicated = M_CheckParm("-dedicated") != 0;
#endif
- strcpy(title, "Sonic Robo Blast 2");
- strcpy(srb2, "Sonic Robo Blast 2");
- D_MakeTitleString(srb2);
-
#ifdef PC_DOS
- D_Titlebar(srb2, title);
-#endif
-
-#if defined (__OS2__) && !defined (HAVE_SDL)
- // set PM window title
- snprintf(pmData->title, sizeof (pmData->title),
- "Sonic Robo Blast 2" VERSIONSTRING ": %s",
- title);
- pmData->title[sizeof (pmData->title) - 1] = '\0';
+ D_Titlebar();
#endif
if (devparm)
@@ -1167,6 +1165,11 @@ void D_SRB2Main(void)
#ifdef USE_PATCH_DTA
++mainwads; // patch.dta adds one more
#endif
+#ifdef DEVELOP
+ ++mainwads; // music_new, too
+#endif
+
+ mainwadstally = packetsizetally;
cht_Init();
@@ -1397,7 +1400,6 @@ void D_SRB2Main(void)
if (dedicated && server)
{
- pagename = "TITLESKY";
levelstarttic = gametic;
G_SetGamestate(GS_LEVEL);
if (!P_SetupLevel(false))
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index be1a87a13..d7aabe253 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -37,6 +37,7 @@
#include "d_main.h"
#include "m_random.h"
#include "f_finale.h"
+#include "filesrch.h"
#include "mserv.h"
#include "md5.h"
#include "z_zone.h"
@@ -714,6 +715,14 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_firenaxis);
CV_RegisterVar(&cv_firenaxis2);
+ // filesrch.c
+ CV_RegisterVar(&cv_addons_option);
+ CV_RegisterVar(&cv_addons_folder);
+ CV_RegisterVar(&cv_addons_md5);
+ CV_RegisterVar(&cv_addons_showall);
+ CV_RegisterVar(&cv_addons_search_type);
+ CV_RegisterVar(&cv_addons_search_case);
+
// WARNING: the order is important when initialising mouse2
// we need the mouse2port
CV_RegisterVar(&cv_mouse2port);
diff --git a/src/d_netfil.c b/src/d_netfil.c
index db0bf8055..00a0b0d41 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -104,6 +104,7 @@ INT32 lastfilenum = -1;
/** Fills a serverinfo packet with information about wad files loaded.
*
* \todo Give this function a better name since it is in global scope.
+ * Used to have size limiting built in - now handled via W_LoadWadFile in w_wad.c
*
*/
UINT8 *PutFileNeeded(void)
@@ -112,29 +113,22 @@ UINT8 *PutFileNeeded(void)
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus;
- size_t bytesused = 0;
for (i = 0; i < numwadfiles; i++)
{
- // If it has only music/sound lumps, mark it as unimportant
- if (W_VerifyNMUSlumps(wadfiles[i]->filename))
- filestatus = 0;
- else
- filestatus = 1; // Important
+ // If it has only music/sound lumps, don't put it in the list
+ if (!wadfiles[i]->important)
+ continue;
+
+ filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
// Store in the upper four bits
if (!cv_downloading.value)
filestatus += (2 << 4); // Won't send
- else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024))
- filestatus += (0 << 4); // Won't send
- else
+ else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
filestatus += (1 << 4); // Will send if requested
-
- bytesused += (nameonlylength(wadfilename) + 22);
-
- // Don't write too far...
- if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded))
- I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename);
+ // else
+ // filestatus += (0 << 4); -- Won't send, too big
WRITEUINT8(p, filestatus);
@@ -167,7 +161,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
{
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
filestatus = READUINT8(p); // The first byte is the file status
- fileneeded[i].important = (UINT8)(filestatus & 3);
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
fileneeded[i].file = NULL; // The file isn't open yet
@@ -197,7 +190,7 @@ boolean CL_CheckDownloadable(void)
UINT8 i,dlstatus = 0;
for (i = 0; i < fileneedednum; i++)
- if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
+ if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
{
if (fileneeded[i].willsend == 1)
continue;
@@ -218,7 +211,7 @@ boolean CL_CheckDownloadable(void)
// not downloadable, put reason in console
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
for (i = 0; i < fileneedednum; i++)
- if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
+ if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
{
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
@@ -271,7 +264,7 @@ boolean CL_SendRequestFile(void)
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
- && fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
+ && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
{
I_Error("Attempted to download files that were not sendable");
}
@@ -280,8 +273,7 @@ boolean CL_SendRequestFile(void)
netbuffer->packettype = PT_REQUESTFILE;
p = (char *)netbuffer->u.textcmd;
for (i = 0; i < fileneedednum; i++)
- if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
- && fileneeded[i].important)
+ if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
{
totalfreespaceneeded += fileneeded[i].totalsize;
nameonly(fileneeded[i].filename);
@@ -360,15 +352,9 @@ INT32 CL_CheckFiles(void)
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
{
- if (i < fileneedednum && !fileneeded[i].important)
+ if (j < numwadfiles && !wadfiles[j]->important)
{
- // Eh whatever, don't care
- ++i;
- continue;
- }
- if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename))
- {
- // Unimportant on our side. still don't care.
+ // Unimportant on our side.
++j;
continue;
}
@@ -411,7 +397,7 @@ INT32 CL_CheckFiles(void)
break;
}
}
- if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important)
+ if (fileneeded[i].status != FS_NOTFOUND)
continue;
packetsize += nameonlylength(fileneeded[i].filename) + 22;
@@ -449,27 +435,8 @@ void CL_LoadServerFiles(void)
fileneeded[i].status = FS_OPEN;
}
else if (fileneeded[i].status == FS_MD5SUMBAD)
- {
- // If the file is marked important, don't even bother proceeding.
- if (fileneeded[i].important)
- I_Error("Wrong version of important file %s", fileneeded[i].filename);
-
- // If it isn't, no need to worry the user with a console message,
- // although it can't hurt to put something in the debug file.
-
- // ...but wait a second. What if the local version is "important"?
- if (!W_VerifyNMUSlumps(fileneeded[i].filename))
- I_Error("File %s should only contain music and sound effects!",
- fileneeded[i].filename);
-
- // Okay, NOW we know it's safe. Whew.
- P_AddWadFile(fileneeded[i].filename, NULL);
- if (fileneeded[i].important)
- G_SetGameModified(true);
- fileneeded[i].status = FS_OPEN;
- DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename));
- }
- else if (fileneeded[i].important)
+ I_Error("Wrong version of file %s", fileneeded[i].filename);
+ else
{
const char *s;
switch(fileneeded[i].status)
diff --git a/src/d_netfil.h b/src/d_netfil.h
index b9b7b2f2e..6fdd0a8a1 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -35,7 +35,6 @@ typedef enum
typedef struct
{
- UINT8 important;
UINT8 willsend; // Is the server willing to send it?
char filename[MAX_WADPATH];
UINT8 md5sum[16];
diff --git a/src/dehacked.c b/src/dehacked.c
index aa6f4f7f9..3a40b64a5 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -382,56 +382,6 @@ static void clear_levels(void)
P_AllocMapHeader(gamemap-1);
}
-/*
-// Edits an animated texture slot on the array
-// Tails 12-27-2003
-static void readAnimTex(MYFILE *f, INT32 num)
-{
- char s[MAXLINELEN];
- char *word;
- char *word2;
- INT32 i;
-
- do {
- if (myfgets(s, sizeof s, f) != NULL)
- {
- if (s[0] == '\n') break;
-
- tmp = strchr(s, '#');
- if (tmp)
- *tmp = '\0';
- // set the value in the appropriate field
-
- word = strtok(s, " ");
- if (word)
- strupr(word);
- else
- break;
-
- word2 = strtok(NULL, " = ");
- if (word2)
- strupr(word2);
- else
- break;
-
- if (word2[strlen(word2)-1] == '\n')
- word2[strlen(word2)-1] = '\0';
-
- i = atoi(word2);
-
- if (fastcmp(word, "START"))
- strncpy(harddefs[num].startname, word2, 8);
- if (fastcmp(word, "END"))
- strncpy(harddefs[num].endname, word2, 8);
- else if (fastcmp(word, "SPEED")) harddefs[num].speed = i;
- else if (fastcmp(word, "ISTEXTURE")) harddefs[num].istexture = i;
-
- else deh_warning("readAnimTex %d: unknown word '%s'", num, word);
- }
- } while (s[0] != '\n' && !myfeof(f)); //finish when the line is empty
-}
-*/
-
static boolean findFreeSlot(INT32 *num)
{
// Send the character select entry to a free slot.
@@ -1379,6 +1329,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
else
mapheaderinfo[num-1]->levelflags &= ~LF_NOZONE;
}
+ else if (fastcmp(word, "SAVEGAME"))
+ {
+ if (i || word2[0] == 'T' || word2[0] == 'Y')
+ mapheaderinfo[num-1]->levelflags |= LF_SAVEGAME;
+ else
+ mapheaderinfo[num-1]->levelflags &= ~LF_SAVEGAME;
+ }
// Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN"))
@@ -1826,7 +1783,6 @@ static actionpointer_t actionpointers[] =
{{A_CapeChase}, "A_CAPECHASE"},
{{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"},
{{A_SlingAppear}, "A_SLINGAPPEAR"},
- {{A_MaceRotate}, "A_MACEROTATE"},
{{A_UnidusBall}, "A_UNIDUSBALL"},
{{A_RockSpawn}, "A_ROCKSPAWN"},
{{A_SetFuse}, "A_SETFUSE"},
@@ -2106,7 +2062,7 @@ static void readframe(MYFILE *f, INT32 num)
Z_Free(s);
}
-static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
+static void readsound(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
@@ -2142,21 +2098,7 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
continue;
}
-/* if (fastcmp(word, "OFFSET"))
- {
- value -= 150360;
- if (value <= 64)
- value /= 8;
- else if (value <= 260)
- value = (value+4)/8;
- else
- value = (value+8)/8;
- if (value >= -1 && value < sfx_freeslot0 - 1)
- S_sfx[num].name = savesfxnames[value+1];
- else
- deh_warning("Sound %d: offset out of bounds", num);
- }
- else */if (fastcmp(word, "SINGULAR"))
+ if (fastcmp(word, "SINGULAR"))
{
DEH_WriteUndoline(word, va("%d", S_sfx[num].singularity), UNDO_NONE);
S_sfx[num].singularity = value;
@@ -2182,8 +2124,6 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
} while (!myfeof(f));
Z_Free(s);
-
- (void)savesfxnames;
}
/** Checks if a game data file name for a mod is good.
@@ -2293,12 +2233,12 @@ static void reademblemdata(MYFILE *f, INT32 num)
emblemlocations[num-1].type = ET_TIME;
else if (fastcmp(word2, "RINGS"))
emblemlocations[num-1].type = ET_RINGS;
+ else if (fastcmp(word2, "MAP"))
+ emblemlocations[num-1].type = ET_MAP;
else if (fastcmp(word2, "NGRADE"))
emblemlocations[num-1].type = ET_NGRADE;
else if (fastcmp(word2, "NTIME"))
emblemlocations[num-1].type = ET_NTIME;
- else if (fastcmp(word2, "MAP"))
- emblemlocations[num-1].type = ET_MAP;
else
emblemlocations[num-1].type = (UINT8)value;
}
@@ -2811,190 +2751,6 @@ static void readconditionset(MYFILE *f, UINT8 setnum)
Z_Free(s);
}
-static void readtexture(MYFILE *f, const char *name)
-{
- char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
- char *word;
- char *word2;
- char *tmp;
- INT32 i, j, value;
- UINT16 width = 0, height = 0;
- INT16 patchcount = 0;
- texture_t *texture;
-
- do
- {
- if (myfgets(s, MAXLINELEN, f))
- {
- if (s[0] == '\n')
- break;
-
- tmp = strchr(s, '#');
- if (tmp)
- *tmp = '\0';
-
- value = searchvalue(s);
- word = strtok(s, " ");
- if (word)
- strupr(word);
- else
- break;
-
- word2 = strtok(NULL, " ");
- if (word2)
- strupr(word2);
- else
- break;
-
- // Width of the texture.
- if (fastcmp(word, "WIDTH"))
- {
- DEH_WriteUndoline(word, va("%d", width), UNDO_NONE);
- width = SHORT((UINT16)value);
- }
- // Height of the texture.
- else if (fastcmp(word, "HEIGHT"))
- {
- DEH_WriteUndoline(word, va("%d", height), UNDO_NONE);
- height = SHORT((UINT16)value);
- }
- // Number of patches the texture has.
- else if (fastcmp(word, "NUMPATCHES"))
- {
- DEH_WriteUndoline(word, va("%d", patchcount), UNDO_NONE);
- patchcount = SHORT((UINT16)value);
- }
- else
- deh_warning("readtexture: unknown word '%s'", word);
- }
- } while (!myfeof(f));
-
- // Error checking.
- if (!width)
- I_Error("Texture %s has no width!\n", name);
-
- if (!height)
- I_Error("Texture %s has no height!\n", name);
-
- if (!patchcount)
- I_Error("Texture %s has no patches!\n", name);
-
- // Allocate memory for the texture, and fill in information.
- texture = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * SHORT(patchcount)), PU_STATIC, NULL);
- M_Memcpy(texture->name, name, sizeof(texture->name));
- texture->width = width;
- texture->height = height;
- texture->patchcount = patchcount;
- texture->holes = false;
- // Fill out the texture patches, to allow them to be detected
- // accurately by readpatch.
- for (i = 0; i < patchcount; i++)
- {
- texture->patches[i].originx = 0;
- texture->patches[i].originy = 0;
- texture->patches[i].wad = UINT16_MAX;
- texture->patches[i].lump = UINT16_MAX;
- }
-
- // Jump to the next empty texture entry.
- i = 0;
- while (textures[i])
- i++;
-
- // Fill the global texture buffer entries.
- j = 1;
- while (j << 1 <= texture->width)
- j <<= 1;
-
- textures[i] = texture;
- texturewidthmask[i] = j - 1;
- textureheight[i] = texture->height << FRACBITS;
-
- // Clean up.
- Z_Free(s);
-}
-
-static void readpatch(MYFILE *f, const char *name, UINT16 wad)
-{
- char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
- char *word;
- char *word2;
- char *tmp;
- INT32 i = 0, j = 0, value;
- texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0, 255, AST_COPY};
-
- // Jump to the texture this patch belongs to, which,
- // coincidentally, is always the last one on the buffer cache.
- while (textures[i+1])
- i++;
-
- // Jump to the next empty patch entry.
- while (memcmp(&(textures[i]->patches[j]), &patch, sizeof(patch)))
- j++;
-
- patch.wad = wad;
- // Set the texture number, but only if the lump exists.
- if ((patch.lump = W_CheckNumForNamePwad(name, wad, 0)) == INT16_MAX)
- I_Error("readpatch: Missing patch in texture %s", textures[i]->name);
-
- // note: undoing this patch will be done by other means
- do
- {
- if (myfgets(s, MAXLINELEN, f))
- {
- if (s[0] == '\n')
- break;
-
- tmp = strchr(s, '#');
- if (tmp)
- *tmp = '\0';
-
- value = searchvalue(s);
- word = strtok(s, " ");
- if (word)
- strupr(word);
- else
- break;
-
- word2 = strtok(NULL, " ");
- if (word2)
- strupr(word2);
- else
- break;
-
- // X position of the patch in the texture.
- if (fastcmp(word, "X"))
- {
- //DEH_WriteUndoline(word, va("%d", patch->originx), UNDO_NONE);
- patch.originx = (INT16)value;
- }
- // Y position of the patch in the texture.
- else if (fastcmp(word, "Y"))
- {
- //DEH_WriteUndoline(word, va("%d", patch->originy), UNDO_NONE);
- patch.originy = (INT16)value;
- }
- else
- deh_warning("readpatch: unknown word '%s'", word);
- }
- } while (!myfeof(f));
-
- // Error checking.
- /* // Irrelevant. Origins cannot be unsigned.
- if (patch.originx == UINT16_MAX)
- I_Error("Patch %s on texture %s has no X position!\n", name, textures[i]->name);
-
- if (patch.originy == UINT16_MAX)
- I_Error("Patch %s on texture %s has no Y position!\n", name, textures[i]->name);
-*/
-
- // Set the patch as that patch number.
- textures[i]->patches[j] = patch;
-
- // Clean up.
- Z_Free(s);
-}
-
static void readmaincfg(MYFILE *f)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@@ -3405,30 +3161,17 @@ static void ignorelines(MYFILE *f)
Z_Free(s);
}
-static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
+static void DEH_LoadDehackedFile(MYFILE *f)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
char *word2;
INT32 i;
- // do a copy of this for cross references probleme
- //XBOXSTATIC actionf_t saveactions[NUMSTATES];
- //XBOXSTATIC const char *savesprnames[NUMSPRITES];
- XBOXSTATIC const char *savesfxnames[NUMSFX];
if (!deh_loaded)
initfreeslots();
deh_num_warning = 0;
- // save values for cross reference
- /*
- for (i = 0; i < NUMSTATES; i++)
- saveactions[i] = states[i].action;
- for (i = 0; i < NUMSPRITES; i++)
- savesprnames[i] = sprnames[i];
- */
- for (i = 0; i < NUMSFX; i++)
- savesfxnames[i] = S_sfx[i].name;
gamedataadded = false;
@@ -3505,19 +3248,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
if (word2[strlen(word2)-1] == '\n')
word2[strlen(word2)-1] = '\0';
i = atoi(word2);
- if (fastcmp(word, "TEXTURE"))
- {
- // Read texture from spec file.
- readtexture(f, word2);
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
- }
- else if (fastcmp(word, "PATCH"))
- {
- // Read patch from spec file.
- readpatch(f, word2, wad);
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
- }
- else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
+ if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_mobjtype(word2); // find a thing by name
@@ -3530,10 +3261,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
-/* else if (fastcmp(word, "ANIMTEX"))
- {
- readAnimTex(f, i);
- }*/
else if (fastcmp(word, "LIGHT"))
{
#ifdef HWRENDER
@@ -3605,34 +3332,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
- // Added translations to this just in case its re-enabled
-/* else if (fastcmp(word, "POINTER"))
- {
- word = strtok(NULL, " "); // get frame
- word = strtok(NULL, ")");
- if (word)
- {
- i = atoi(word);
- if (i < NUMSTATES && i >= 0)
- {
- if (myfgets(s, MAXLINELEN, f))
- states[i].action = saveactions[searchvalue(s)];
- }
- else
- {
- deh_warning("Pointer: Frame %d doesn't exist", i);
- ignorelines(f);
- }
- }
- else
- deh_warning("pointer (Frame %d) : missing ')'", i);
- }*/
else if (fastcmp(word, "SOUND"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_sfx(word2); // find a sound by name
if (i < NUMSFX && i > 0)
- readsound(f, i, savesfxnames);
+ readsound(f, i);
else
{
deh_warning("Sound %d out of range (1 - %d)", i, NUMSFX-1);
@@ -3640,26 +3345,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
-/* else if (fastcmp(word, "SPRITE"))
- {
- if (i < NUMSPRITES && i >= 0)
- {
- if (myfgets(s, MAXLINELEN, f))
- {
- INT32 k;
- k = (searchvalue(s) - 151328)/8;
- if (k >= 0 && k < NUMSPRITES)
- sprnames[i] = savesprnames[k];
- else
- {
- deh_warning("Sprite %d: offset out of bounds", i);
- ignorelines(f);
- }
- }
- }
- else
- deh_warning("Sprite %d doesn't exist",i);
- }*/
else if (fastcmp(word, "HUDITEM"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
@@ -3746,7 +3431,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// no undo support for this insanity yet
//DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
- else if (fastcmp(word, "SRB2"))
+ // Last I heard this crashes the game if you try to use it
+ // so this is disabled for now
+ // -- Monster Iestyn
+/* else if (fastcmp(word, "SRB2"))
{
INT32 ver = searchvalue(strtok(NULL, "\n"));
if (ver != PATCHVERSION)
@@ -3757,6 +3445,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// Unless you REALLY want to piss people off,
// define a custom gamedata /before/ doing this!!
// (then again, modifiedgame will prevent game data saving anyway)
+*/
else if (fastcmp(word, "CLEAR"))
{
boolean clearall = (fastcmp(word2, "ALL"));
@@ -3830,7 +3519,7 @@ void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump)
W_ReadLumpPwad(wad, lump, f.data);
f.curpos = f.data;
f.data[f.size] = 0;
- DEH_LoadDehackedFile(&f, wad);
+ DEH_LoadDehackedFile(&f);
DEH_WriteUndoline(va("# uload for wad: %u, lump: %u", wad, lump), NULL, UNDO_DONE);
Z_Free(f.data);
}
@@ -4838,12 +4527,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Individual Team Rings
"S_TEAMRING",
- // Special Stage Token
- "S_EMMY",
-
// Special Stage Token
"S_TOKEN",
- "S_MOVINGTOKEN",
// CTF Flags
"S_REDFLAG",
@@ -4994,6 +4679,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPIKED1",
"S_SPIKED2",
+ // Wall spikes
+ "S_WALLSPIKE1",
+ "S_WALLSPIKE2",
+ "S_WALLSPIKE3",
+ "S_WALLSPIKE4",
+ "S_WALLSPIKE5",
+ "S_WALLSPIKE6",
+ "S_WALLSPIKEBASE",
+ "S_WALLSPIKED1",
+ "S_WALLSPIKED2",
+
// Starpost
"S_STARPOST_IDLE",
"S_STARPOST_FLASH",
@@ -5180,6 +4876,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DEMONFIRE5",
"S_DEMONFIRE6",
+ // GFZ flowers
"S_GFZFLOWERA",
"S_GFZFLOWERB",
"S_GFZFLOWERC",
@@ -5187,6 +4884,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BERRYBUSH",
"S_BUSH",
+ // Trees (both GFZ and misc)
+ "S_GFZTREE",
+ "S_GFZBERRYTREE",
+ "S_GFZCHERRYTREE",
+ "S_CHECKERTREE",
+ "S_CHECKERSUNSETTREE",
+ "S_FHZTREE", // Frozen Hillside
+ "S_FHZPINKTREE",
+ "S_POLYGONTREE",
+ "S_BUSHTREE",
+ "S_BUSHREDTREE",
+
// THZ Plant
"S_THZFLOWERA",
"S_THZFLOWERB",
@@ -5248,18 +4957,62 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SLING1",
"S_SLING2",
- // CEZ Small Mace Chain
+ // CEZ maces and chains
"S_SMALLMACECHAIN",
-
- // CEZ Big Mace Chain
"S_BIGMACECHAIN",
-
- // CEZ Small Mace
"S_SMALLMACE",
-
- // CEZ Big Mace
"S_BIGMACE",
+ // Yellow spring on a ball
+ "S_YELLOWSPRINGBALL",
+ "S_YELLOWSPRINGBALL2",
+ "S_YELLOWSPRINGBALL3",
+ "S_YELLOWSPRINGBALL4",
+ "S_YELLOWSPRINGBALL5",
+
+ // Red spring on a ball
+ "S_REDSPRINGBALL",
+ "S_REDSPRINGBALL2",
+ "S_REDSPRINGBALL3",
+ "S_REDSPRINGBALL4",
+ "S_REDSPRINGBALL5",
+
+ // Small Firebar
+ "S_SMALLFIREBAR1",
+ "S_SMALLFIREBAR2",
+ "S_SMALLFIREBAR3",
+ "S_SMALLFIREBAR4",
+ "S_SMALLFIREBAR5",
+ "S_SMALLFIREBAR6",
+ "S_SMALLFIREBAR7",
+ "S_SMALLFIREBAR8",
+ "S_SMALLFIREBAR9",
+ "S_SMALLFIREBAR10",
+ "S_SMALLFIREBAR11",
+ "S_SMALLFIREBAR12",
+ "S_SMALLFIREBAR13",
+ "S_SMALLFIREBAR14",
+ "S_SMALLFIREBAR15",
+ "S_SMALLFIREBAR16",
+
+ // Big Firebar
+ "S_BIGFIREBAR1",
+ "S_BIGFIREBAR2",
+ "S_BIGFIREBAR3",
+ "S_BIGFIREBAR4",
+ "S_BIGFIREBAR5",
+ "S_BIGFIREBAR6",
+ "S_BIGFIREBAR7",
+ "S_BIGFIREBAR8",
+ "S_BIGFIREBAR9",
+ "S_BIGFIREBAR10",
+ "S_BIGFIREBAR11",
+ "S_BIGFIREBAR12",
+ "S_BIGFIREBAR13",
+ "S_BIGFIREBAR14",
+ "S_BIGFIREBAR15",
+ "S_BIGFIREBAR16",
+
"S_CEZFLOWER1",
// Big Tumbleweed
@@ -6233,16 +5986,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_NIGHTSWING_XMAS",
// NiGHTS Paraloop Powerups
- "S_NIGHTSPOWERUP1",
- "S_NIGHTSPOWERUP2",
- "S_NIGHTSPOWERUP3",
- "S_NIGHTSPOWERUP4",
- "S_NIGHTSPOWERUP5",
- "S_NIGHTSPOWERUP6",
- "S_NIGHTSPOWERUP7",
- "S_NIGHTSPOWERUP8",
- "S_NIGHTSPOWERUP9",
- "S_NIGHTSPOWERUP10",
+ "S_NIGHTSSUPERLOOP",
+ "S_NIGHTSDRILLREFILL",
+ "S_NIGHTSHELPER",
+ "S_NIGHTSEXTRATIME",
+ "S_NIGHTSLINKFREEZE",
"S_EGGCAPSULE",
// Orbiting Chaos Emeralds
@@ -6439,8 +6187,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BLUEBALL", // Blue sphere replacement for special stages
"MT_REDTEAMRING", //Rings collectable by red team.
"MT_BLUETEAMRING", //Rings collectable by blue team.
- "MT_EMMY", // emerald token for special stage
- "MT_TOKEN", // Special Stage Token (uncollectible part)
+ "MT_TOKEN", // Special Stage Token
"MT_REDFLAG", // Red CTF Flag
"MT_BLUEFLAG", // Blue CTF Flag
"MT_EMBLEM",
@@ -6474,6 +6221,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SPECIALSPIKEBALL",
"MT_SPINFIRE",
"MT_SPIKE",
+ "MT_WALLSPIKE",
+ "MT_WALLSPIKEBASE",
"MT_STARPOST",
"MT_BIGMINE",
"MT_BIGAIRMINE",
@@ -6564,6 +6313,17 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_GFZFLOWER3",
"MT_BERRYBUSH",
"MT_BUSH",
+ // Trees (both GFZ and misc)
+ "MT_GFZTREE",
+ "MT_GFZBERRYTREE",
+ "MT_GFZCHERRYTREE",
+ "MT_CHECKERTREE",
+ "MT_CHECKERSUNSETTREE",
+ "MT_FHZTREE", // Frozen Hillside
+ "MT_FHZPINKTREE",
+ "MT_POLYGONTREE",
+ "MT_BUSHTREE",
+ "MT_BUSHREDTREE",
// Techno Hill Scenery
"MT_THZFLOWER1",
@@ -6587,14 +6347,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEPARTICLE",
"MT_EGGSTATUE", // Eggman Statue
"MT_MACEPOINT", // Mace rotation point
- "MT_SWINGMACEPOINT", // Mace swinging point
- "MT_HANGMACEPOINT", // Hangable mace chain
- "MT_SPINMACEPOINT", // Spin/Controllable mace chain
+ "MT_CHAINMACEPOINT", // Combination of chains and maces point
+ "MT_SPRINGBALLPOINT", // Spring ball point
+ "MT_CHAINPOINT", // Mace chain
"MT_HIDDEN_SLING", // Spin mace chain (activatable)
+ "MT_FIREBARPOINT", // Firebar
+ "MT_CUSTOMMACEPOINT", // Custom mace
"MT_SMALLMACECHAIN", // Small Mace Chain
"MT_BIGMACECHAIN", // Big Mace Chain
"MT_SMALLMACE", // Small Mace
"MT_BIGMACE", // Big Mace
+ "MT_YELLOWSPRINGBALL", // Yellow spring on a ball
+ "MT_REDSPRINGBALL", // Red spring on a ball
+ "MT_SMALLFIREBAR", // Small Firebar
+ "MT_BIGFIREBAR", // Big Firebar
"MT_CEZFLOWER",
// Arid Canyon Scenery
@@ -6947,6 +6713,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
"SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
+ "MACEROTATE", // Thinker calls P_MaceRotate around tracer
NULL
};
@@ -7333,6 +7100,7 @@ struct {
{"LF_NOSSMUSIC",LF_NOSSMUSIC},
{"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE},
+ {"LF_SAVEGAME",LF_SAVEGAME},
// And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
@@ -7465,7 +7233,11 @@ struct {
{"SF_X8AWAYSOUND",SF_X8AWAYSOUND},
{"SF_NOINTERRUPT",SF_NOINTERRUPT},
{"SF_X2AWAYSOUND",SF_X2AWAYSOUND},
-
+
+ // Global emblem var flags
+ {"GE_NIGHTSPULL",GE_NIGHTSPULL},
+ {"GE_NIGHTSITEM",GE_NIGHTSITEM},
+
// Map emblem var flags
{"ME_ALLEMERALDS",ME_ALLEMERALDS},
{"ME_ULTIMATE",ME_ULTIMATE},
@@ -8147,11 +7919,14 @@ void FUNCMATH DEH_Check(void)
static inline int lib_freeslot(lua_State *L)
{
int n = lua_gettop(L);
- int r = 0; // args returned
+ int r = 0; // args returned
char *s, *type,*word;
- while (n-- > 0)
- {
+ if (!lua_lumploading)
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
+
+ while (n-- > 0)
+ {
s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_");
if (type)
diff --git a/src/doomdef.h b/src/doomdef.h
index 16d7fa218..e1e274d08 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -546,6 +546,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Hudname padding.
#define SKINNAMEPADDING
+/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
+/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
+/// on the bright side it fixes some weird issues with translucent walls
+/// \note SRB2CB port.
+/// SRB2CB itself ported this from PrBoom+
+#define NEWCLIP
+
/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
//#define SECTORSPECIALSAFTERTHINK
diff --git a/src/doomstat.h b/src/doomstat.h
index a3b07c9cb..a24bad79d 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -41,7 +41,8 @@ extern INT16 maptol;
extern UINT8 globalweather;
extern INT32 curWeather;
extern INT32 cursaveslot;
-extern INT16 lastmapsaved;
+//extern INT16 lastmapsaved;
+extern INT16 lastmaploaded;
extern boolean gamecomplete;
#define PRECIP_NONE 0
@@ -263,6 +264,7 @@ typedef struct
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
#define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title
+#define LF_SAVEGAME 32 ///< Save the game upon loading this level
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen
diff --git a/src/filesrch.c b/src/filesrch.c
index acc176d6a..a28c4d83c 100644
--- a/src/filesrch.c
+++ b/src/filesrch.c
@@ -31,6 +31,8 @@
#include "filesrch.h"
#include "d_netfil.h"
#include "m_misc.h"
+#include "z_zone.h"
+#include "m_menu.h" // Addons_option_Onchange
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)
@@ -255,6 +257,28 @@ readdir (DIR * dirp)
return (struct dirent *) 0;
}
+/*
+ * rewinddir
+ *
+ * Makes the next readdir start from the beginning.
+ */
+int
+rewinddir (DIR * dirp)
+{
+ errno = 0;
+
+ /* Check for valid DIR struct. */
+ if (!dirp)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+
+ dirp->dd_stat = 0;
+
+ return 0;
+}
+
/*
* closedir
*
@@ -285,6 +309,35 @@ closedir (DIR * dirp)
return rc;
}
#endif
+
+static CV_PossibleValue_t addons_cons_t[] = {{0, "SRB2 Folder"}, /*{1, "HOME"}, {2, "SRB2 Folder"},*/ {3, "CUSTOM"}, {0, NULL}};
+consvar_t cv_addons_option = {"addons_option", "SRB2 Folder", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_addons_folder = {"addons_folder", "./", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
+consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
+consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+char menupath[1024];
+size_t menupathindex[menudepth];
+size_t menudepthleft = menudepth;
+
+char menusearch[MAXSTRINGLENGTH+1];
+
+char **dirmenu;
+size_t sizedirmenu;
+size_t dir_on[menudepth];
+UINT8 refreshdirmenu = 0;
+
+size_t packetsizetally = 0;
+size_t mainwadstally = 0;
+
#if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
@@ -296,6 +349,13 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
completepath = false;
return FS_NOTFOUND;
}
+
+boolean preparefilemenu(boolean samedepth)
+{
+ (void)samedepth;
+ return false;
+}
+
#elif defined (_WIN32_WCE)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
@@ -346,6 +406,12 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
#endif
return FS_NOTFOUND;
}
+
+boolean preparefilemenu(boolean samedepth)
+{
+ (void)samedepth;
+ return false;
+}
#else
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
{
@@ -387,25 +453,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
{
searchpath[searchpathindex[depthleft]]=0;
dent = readdir(dirhandle[depthleft]);
- if (dent)
- strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
if (!dent)
+ {
closedir(dirhandle[depthleft++]);
- else if (dent->d_name[0]=='.' &&
+ continue;
+ }
+
+ if (dent->d_name[0]=='.' &&
(dent->d_name[1]=='\0' ||
(dent->d_name[1]=='.' &&
dent->d_name[2]=='\0')))
{
// we don't want to scan uptree
+ continue;
}
- else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
- {
- // was the file (re)moved? can't stat it
- }
+
+ // okay, now we actually want searchpath to incorporate d_name
+ strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
+
+ if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
+ ; // was the file (re)moved? can't stat it
else if (S_ISDIR(fsstat.st_mode) && depthleft)
{
- strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
searchpathindex[--depthleft] = strlen(searchpath) + 1;
dirhandle[depthleft] = opendir(searchpath);
if (!dirhandle[depthleft])
@@ -444,6 +514,255 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
free(searchname);
free(searchpathindex);
free(dirhandle);
+
return retval;
}
+
+char exttable[NUM_EXT_TABLE][5] = {
+ ".txt", ".cfg", // exec
+ ".wad", ".soc", ".lua"}; // addfile
+
+char filenamebuf[MAX_WADFILES][MAX_WADPATH];
+
+
+static boolean filemenusearch(char *haystack, char *needle)
+{
+ static char localhaystack[128];
+ strlcpy(localhaystack, haystack, 128);
+ if (!cv_addons_search_case.value)
+ strupr(localhaystack);
+ return ((cv_addons_search_type.value)
+ ? (strstr(localhaystack, needle) != 0)
+ : (!strncmp(localhaystack, needle, menusearch[0])));
+}
+
+#define searchdir if (menusearch[0] && !filemenusearch(dent->d_name, localmenusearch))\
+ {\
+ rejected++;\
+ continue;\
+ }\
+
+boolean preparefilemenu(boolean samedepth)
+{
+ DIR *dirhandle;
+ struct dirent *dent;
+ struct stat fsstat;
+ size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0;
+ char *tempname = NULL;
+ boolean noresults = false;
+ char localmenusearch[MAXSTRINGLENGTH] = "";
+
+ if (samedepth)
+ {
+ if (dirmenu && dirmenu[dir_on[menudepthleft]])
+ tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
+ }
+ else
+ menusearch[0] = menusearch[1] = 0; // clear search
+
+ for (; sizedirmenu > 0; sizedirmenu--) // clear out existing items
+ {
+ Z_Free(dirmenu[sizedirmenu-1]);
+ dirmenu[sizedirmenu-1] = NULL;
+ }
+
+ if (!(dirhandle = opendir(menupath))) // get directory
+ return false;
+
+ if (menusearch[0])
+ {
+ strcpy(localmenusearch, menusearch+1);
+ if (!cv_addons_search_case.value)
+ strupr(localmenusearch);
+ }
+
+ while (true)
+ {
+ menupath[menupathindex[menudepthleft]] = 0;
+ dent = readdir(dirhandle);
+
+ if (!dent)
+ break;
+ else if (dent->d_name[0]=='.' &&
+ (dent->d_name[1]=='\0' ||
+ (dent->d_name[1]=='.' &&
+ dent->d_name[2]=='\0')))
+ continue; // we don't want to scan uptree
+
+ strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
+
+ if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
+ ; // was the file (re)moved? can't stat it
+ else // is a file or directory
+ {
+ if (!S_ISDIR(fsstat.st_mode)) // file
+ {
+ if (!cv_addons_showall.value)
+ {
+ size_t len = strlen(dent->d_name)+1;
+ UINT8 ext;
+ for (ext = 0; ext < NUM_EXT_TABLE; ext++)
+ if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
+ if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
+ }
+ searchdir;
+ }
+ else // directory
+ {
+ searchdir;
+ numfolders++;
+ }
+ sizedirmenu++;
+ }
+ }
+
+ if (!rejected && !sizedirmenu)
+ {
+ if (tempname)
+ Z_Free(tempname);
+ closedir(dirhandle);
+ return false;
+ }
+
+ if (((noresults = (menusearch[0] && !sizedirmenu)))
+ || (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry
+ {
+ sizedirmenu++;
+ numfolders++;
+ folderpos++;
+ }
+
+ if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
+ {
+ closedir(dirhandle); // just in case
+ I_Error("Ran out of memory whilst preparing add-ons menu");
+ }
+
+ rejected = 0;
+ rewinddir(dirhandle);
+
+ while ((pos+folderpos) < sizedirmenu)
+ {
+ menupath[menupathindex[menudepthleft]] = 0;
+ dent = readdir(dirhandle);
+
+ if (!dent)
+ break;
+ else if (dent->d_name[0]=='.' &&
+ (dent->d_name[1]=='\0' ||
+ (dent->d_name[1]=='.' &&
+ dent->d_name[2]=='\0')))
+ continue; // we don't want to scan uptree
+
+ strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
+
+ if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
+ ; // was the file (re)moved? can't stat it
+ else // is a file or directory
+ {
+ char *temp;
+ size_t len = strlen(dent->d_name)+1;
+ UINT8 ext = EXT_FOLDER;
+ UINT8 folder;
+
+ if (!S_ISDIR(fsstat.st_mode)) // file
+ {
+ if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention
+ for (; ext < NUM_EXT_TABLE; ext++)
+ if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
+ if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
+ ext += EXT_START; // moving to be appropriate position
+
+ searchdir;
+
+ if (ext >= EXT_LOADSTART)
+ {
+ size_t i;
+ for (i = 0; i < numwadfiles; i++)
+ {
+ if (!filenamebuf[i][0])
+ {
+ strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
+ filenamebuf[i][MAX_WADPATH - 1] = '\0';
+ nameonly(filenamebuf[i]);
+ }
+
+ if (strcmp(dent->d_name, filenamebuf[i]))
+ continue;
+ if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
+ continue;
+
+ ext |= EXT_LOADED;
+ }
+ }
+ else if (ext == EXT_TXT)
+ {
+ if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
+ ext |= EXT_LOADED;
+ }
+
+ if (!strcmp(dent->d_name, configfile))
+ ext |= EXT_LOADED;
+
+ folder = 0;
+ }
+ else // directory
+ {
+ searchdir;
+ len += (folder = 1);
+ }
+
+ if (len > 255)
+ len = 255;
+
+ if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL)))
+ I_Error("Ran out of memory whilst preparing add-ons menu");
+ temp[DIR_TYPE] = ext;
+ temp[DIR_LEN] = (UINT8)(len);
+ strlcpy(temp+DIR_STRING, dent->d_name, len);
+ if (folder)
+ {
+ strcpy(temp+len, "/");
+ dirmenu[folderpos++] = temp;
+ }
+ else
+ dirmenu[numfolders + pos++] = temp;
+ }
+ }
+
+ closedir(dirhandle);
+
+ if (noresults) // no results
+ dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS));
+ else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry
+ dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP));
+
+ menupath[menupathindex[menudepthleft]] = 0;
+ sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind
+
+ if (tempname)
+ {
+ size_t i;
+ for (i = 0; i < sizedirmenu; i++)
+ {
+ if (!strcmp(dirmenu[i]+DIR_STRING, tempname))
+ {
+ dir_on[menudepthleft] = i;
+ break;
+ }
+ }
+ Z_Free(tempname);
+ }
+
+ if (!sizedirmenu)
+ {
+ dir_on[menudepthleft] = 0;
+ Z_Free(dirmenu);
+ return false;
+ }
+ else if (dir_on[menudepthleft] >= sizedirmenu)
+ dir_on[menudepthleft] = sizedirmenu-1;
+
+ return true;
+}
#endif
diff --git a/src/filesrch.h b/src/filesrch.h
index 33b148d4b..c2201b453 100644
--- a/src/filesrch.h
+++ b/src/filesrch.h
@@ -6,6 +6,9 @@
#include "doomdef.h"
#include "d_netfil.h"
+#include "m_menu.h" // MAXSTRINGLENGTH
+
+extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
/** \brief The filesearch function
@@ -25,4 +28,64 @@
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth);
+#define menudepth 20
+
+extern char menupath[1024];
+extern size_t menupathindex[menudepth];
+extern size_t menudepthleft;
+
+extern char menusearch[MAXSTRINGLENGTH+1];
+
+extern char **dirmenu;
+extern size_t sizedirmenu;
+extern size_t dir_on[menudepth];
+extern UINT8 refreshdirmenu;
+
+extern size_t packetsizetally;
+extern size_t mainwadstally;
+
+typedef enum
+{
+ EXT_FOLDER = 0,
+ EXT_UP,
+ EXT_NORESULTS,
+ EXT_START,
+ EXT_TXT = EXT_START,
+ EXT_CFG,
+ EXT_LOADSTART,
+ EXT_WAD = EXT_LOADSTART,
+ EXT_SOC,
+ EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt
+ NUM_EXT,
+ NUM_EXT_TABLE = NUM_EXT-EXT_START,
+ EXT_LOADED = 0x80
+ /*
+ obviously there can only be 0x7F supported extensions in
+ addons menu because we're cramming this into a char out of
+ laziness/easy memory allocation (what's the difference?)
+ and have stolen a bit to show whether it's loaded or not
+ in practice the size of the data type is probably overkill
+ toast 02/05/17
+ */
+} ext_enum;
+
+typedef enum
+{
+ DIR_TYPE = 0,
+ DIR_LEN,
+ DIR_STRING
+} dirname_enum;
+
+typedef enum
+{
+ REFRESHDIR_NORMAL = 1,
+ REFRESHDIR_ADDFILE = 2,
+ REFRESHDIR_WARNING = 4,
+ REFRESHDIR_ERROR = 8,
+ REFRESHDIR_NOTLOADED = 16,
+ REFRESHDIR_MAX = 32
+} refreshdir_enum;
+
+boolean preparefilemenu(boolean samedepth);
+
#endif // __FILESRCH_H__
diff --git a/src/g_game.c b/src/g_game.c
index 7769555ba..1a2a2aac6 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -77,7 +77,8 @@ INT16 maptol;
UINT8 globalweather = 0;
INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = -1; // Auto-save 1p savegame slot
-INT16 lastmapsaved = 0; // Last map we auto-saved at
+//INT16 lastmapsaved = 0; // Last map we auto-saved at
+INT16 lastmaploaded = 0; // Last map the game loaded
boolean gamecomplete = false;
UINT16 mainwads = 0;
diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c
index a32609fc8..fa5bce308 100644
--- a/src/hardware/hw_bsp.c
+++ b/src/hardware/hw_bsp.c
@@ -878,8 +878,8 @@ static void AdjustSegs(void)
count = subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline];
p = extrasubsectors[i].planepoly;
- if (!p)
- continue;
+ //if (!p)
+ //continue;
for (; count--; lseg++)
{
float distv1,distv2,tmp;
@@ -892,29 +892,31 @@ static void AdjustSegs(void)
continue;
#endif
- for (j = 0; j < p->numpts; j++)
- {
- distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
- tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
- distv1 = distv1*distv1+tmp*tmp;
- if (distv1 <= nearv1)
+ if (p) {
+ for (j = 0; j < p->numpts; j++)
{
- v1found = j;
- nearv1 = distv1;
- }
- // the same with v2
- distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
- tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
- distv2 = distv2*distv2+tmp*tmp;
- if (distv2 <= nearv2)
- {
- v2found = j;
- nearv2 = distv2;
+ distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
+ tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
+ distv1 = distv1*distv1+tmp*tmp;
+ if (distv1 <= nearv1)
+ {
+ v1found = j;
+ nearv1 = distv1;
+ }
+ // the same with v2
+ distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
+ tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
+ distv2 = distv2*distv2+tmp*tmp;
+ if (distv2 <= nearv2)
+ {
+ v2found = j;
+ nearv2 = distv2;
+ }
}
}
- if (nearv1 <= NEARDIST*NEARDIST)
+ if (p && nearv1 <= NEARDIST*NEARDIST)
// share vertice with segs
- lseg->v1 = (vertex_t *)&(p->pts[v1found]);
+ lseg->pv1 = &(p->pts[v1found]);
else
{
// BP: here we can do better, using PointInSeg and compute
@@ -925,24 +927,24 @@ static void AdjustSegs(void)
polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v1->x);
pv->y = FIXED_TO_FLOAT(lseg->v1->y);
- lseg->v1 = (vertex_t *)pv;
+ lseg->pv1 = pv;
}
- if (nearv2 <= NEARDIST*NEARDIST)
- lseg->v2 = (vertex_t *)&(p->pts[v2found]);
+ if (p && nearv2 <= NEARDIST*NEARDIST)
+ lseg->pv2 = &(p->pts[v2found]);
else
{
polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v2->x);
pv->y = FIXED_TO_FLOAT(lseg->v2->y);
- lseg->v2 = (vertex_t *)pv;
+ lseg->pv2 = pv;
}
// recompute length
{
float x,y;
- x = ((polyvertex_t *)lseg->v2)->x - ((polyvertex_t *)lseg->v1)->x
+ x = ((polyvertex_t *)lseg->pv2)->x - ((polyvertex_t *)lseg->pv1)->x
+ FIXED_TO_FLOAT(FRACUNIT/2);
- y = ((polyvertex_t *)lseg->v2)->y - ((polyvertex_t *)lseg->v1)->y
+ y = ((polyvertex_t *)lseg->pv2)->y - ((polyvertex_t *)lseg->pv1)->y
+ FIXED_TO_FLOAT(FRACUNIT/2);
lseg->flength = (float)hypot(x, y);
// BP: debug see this kind of segs
diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c
new file mode 100644
index 000000000..8b01cabd5
--- /dev/null
+++ b/src/hardware/hw_clip.c
@@ -0,0 +1,465 @@
+/* Emacs style mode select -*- C++ -*-
+ *-----------------------------------------------------------------------------
+ *
+ *
+ * PrBoom: a Doom port merged with LxDoom and LSDLDoom
+ * based on BOOM, a modified and improved DOOM engine
+ * Copyright (C) 1999 by
+ * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
+ * Copyright (C) 1999-2000 by
+ * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
+ * Copyright 2005, 2006 by
+ * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * DESCRIPTION:
+ *
+ *---------------------------------------------------------------------
+ */
+
+/*
+ *
+ ** gl_clipper.cpp
+ **
+ ** Handles visibility checks.
+ ** Loosely based on the JDoom clipper.
+ **
+ **---------------------------------------------------------------------------
+ ** Copyright 2003 Tim Stump
+ ** All rights reserved.
+ **
+ ** Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions
+ ** are met:
+ **
+ ** 1. Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** 2. Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in the
+ ** documentation and/or other materials provided with the distribution.
+ ** 3. The name of the author may not be used to endorse or promote products
+ ** derived from this software without specific prior written permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **---------------------------------------------------------------------------
+ **
+ */
+
+#include
+#include "../v_video.h"
+#include "hw_clip.h"
+#include "hw_glob.h"
+#include "../r_state.h"
+#include "../tables.h"
+#include "r_opengl/r_opengl.h"
+
+#ifdef HAVE_SPHEREFRUSTRUM
+static GLdouble viewMatrix[16];
+static GLdouble projMatrix[16];
+float frustum[6][4];
+#endif
+
+typedef struct clipnode_s
+ {
+ struct clipnode_s *prev, *next;
+ angle_t start, end;
+ } clipnode_t;
+
+clipnode_t *freelist;
+clipnode_t *clipnodes;
+clipnode_t *cliphead;
+
+static clipnode_t * gld_clipnode_GetNew(void);
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end);
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle);
+static void gld_clipper_AddClipRange(angle_t start, angle_t end);
+static void gld_clipper_RemoveRange(clipnode_t * range);
+static void gld_clipnode_Free(clipnode_t *node);
+
+static clipnode_t * gld_clipnode_GetNew(void)
+{
+ if (freelist)
+ {
+ clipnode_t * p = freelist;
+ freelist = p->next;
+ return p;
+ }
+ else
+ {
+ return (clipnode_t*)malloc(sizeof(clipnode_t));
+ }
+}
+
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end)
+{
+ clipnode_t * c = gld_clipnode_GetNew();
+ c->start = start;
+ c->end = end;
+ c->next = c->prev=NULL;
+ return c;
+}
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle)
+{
+ if(startAngle > endAngle)
+ {
+ return (gld_clipper_IsRangeVisible(startAngle, ANGLE_MAX) || gld_clipper_IsRangeVisible(0, endAngle));
+ }
+
+ return gld_clipper_IsRangeVisible(startAngle, endAngle);
+}
+
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle)
+{
+ clipnode_t *ci;
+ ci = cliphead;
+
+ if (endAngle == 0 && ci && ci->start == 0)
+ return false;
+
+ while (ci != NULL && ci->start < endAngle)
+ {
+ if (startAngle >= ci->start && endAngle <= ci->end)
+ {
+ return false;
+ }
+ ci = ci->next;
+ }
+
+ return true;
+}
+
+static void gld_clipnode_Free(clipnode_t *node)
+{
+ node->next = freelist;
+ freelist = node;
+}
+
+static void gld_clipper_RemoveRange(clipnode_t *range)
+{
+ if (range == cliphead)
+ {
+ cliphead = cliphead->next;
+ }
+ else
+ {
+ if (range->prev)
+ {
+ range->prev->next = range->next;
+ }
+ if (range->next)
+ {
+ range->next->prev = range->prev;
+ }
+ }
+
+ gld_clipnode_Free(range);
+}
+
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle)
+{
+ if(startangle > endangle)
+ {
+ // The range has to added in two parts.
+ gld_clipper_AddClipRange(startangle, ANGLE_MAX);
+ gld_clipper_AddClipRange(0, endangle);
+ }
+ else
+ {
+ // Add the range as usual.
+ gld_clipper_AddClipRange(startangle, endangle);
+ }
+}
+
+static void gld_clipper_AddClipRange(angle_t start, angle_t end)
+{
+ clipnode_t *node, *temp, *prevNode, *node2, *delnode;
+
+ if (cliphead)
+ {
+ //check to see if range contains any old ranges
+ node = cliphead;
+ while (node != NULL && node->start < end)
+ {
+ if (node->start >= start && node->end <= end)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipper_RemoveRange(temp);
+ }
+ else
+ {
+ if (node->start <= start && node->end >= end)
+ {
+ return;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+ }
+
+ //check to see if range overlaps a range (or possibly 2)
+ node = cliphead;
+ while (node != NULL && node->start <= end)
+ {
+ if (node->end >= start)
+ {
+ // we found the first overlapping node
+ if (node->start > start)
+ {
+ // the new range overlaps with this node's start point
+ node->start = start;
+ }
+ if (node->end < end)
+ {
+ node->end = end;
+ }
+
+ node2 = node->next;
+ while (node2 && node2->start <= node->end)
+ {
+ if (node2->end > node->end)
+ {
+ node->end = node2->end;
+ }
+
+ delnode = node2;
+ node2 = node2->next;
+ gld_clipper_RemoveRange(delnode);
+ }
+ return;
+ }
+ node = node->next;
+ }
+
+ //just add range
+ node = cliphead;
+ prevNode = NULL;
+ temp = gld_clipnode_NewRange(start, end);
+ while (node != NULL && node->start < end)
+ {
+ prevNode = node;
+ node = node->next;
+ }
+ temp->next = node;
+ if (node == NULL)
+ {
+ temp->prev = prevNode;
+ if (prevNode)
+ {
+ prevNode->next = temp;
+ }
+ if (!cliphead)
+ {
+ cliphead = temp;
+ }
+ }
+ else
+ {
+ if (node == cliphead)
+ {
+ cliphead->prev = temp;
+ cliphead = temp;
+ }
+ else
+ {
+ temp->prev = prevNode;
+ prevNode->next = temp;
+ node->prev = temp;
+ }
+ }
+ }
+ else
+ {
+ temp = gld_clipnode_NewRange(start, end);
+ cliphead = temp;
+ return;
+ }
+}
+
+void gld_clipper_Clear(void)
+{
+ clipnode_t *node = cliphead;
+ clipnode_t *temp;
+
+ while (node != NULL)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipnode_Free(temp);
+ }
+
+ cliphead = NULL;
+}
+
+#define RMUL (1.6f/1.333333f)
+
+angle_t gld_FrustumAngle(void)
+{
+ double floatangle;
+ angle_t a1;
+
+ float tilt = (float)fabs(((double)(int)aimingangle) / ANG1);
+
+ // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
+
+ float render_fov = FIXED_TO_FLOAT(cv_grfov.value);
+ float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
+ float render_multiplier = 64.0f / render_fovratio / RMUL;
+
+ if (tilt > 90.0f)
+ {
+ tilt = 90.0f;
+ }
+
+ // If the pitch is larger than this you can look all around at a FOV of 90
+ if (abs(aimingangle) > 46 * ANG1)
+ return 0xffffffff;
+
+ // ok, this is a gross hack that barely works...
+ // but at least it doesn't overestimate too much...
+ floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * (float)render_fov * 48.0f / render_multiplier / 90.0f;
+ a1 = ANG1 * (int)floatangle;
+ if (a1 >= ANGLE_180)
+ return 0xffffffff;
+ return a1;
+}
+
+// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
+// compiler complains about (p)glGetDoublev anyway, in case anyone wants this
+// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
+// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
+#ifdef HAVE_SPHEREFRUSTRUM
+//
+// gld_FrustrumSetup
+//
+
+#define CALCMATRIX(a, b, c, d, e, f, g, h)\
+(float)(viewMatrix[a] * projMatrix[b] + \
+viewMatrix[c] * projMatrix[d] + \
+viewMatrix[e] * projMatrix[f] + \
+viewMatrix[g] * projMatrix[h])
+
+#define NORMALIZE_PLANE(i)\
+t = (float)sqrt(\
+frustum[i][0] * frustum[i][0] + \
+frustum[i][1] * frustum[i][1] + \
+frustum[i][2] * frustum[i][2]); \
+frustum[i][0] /= t; \
+frustum[i][1] /= t; \
+frustum[i][2] /= t; \
+frustum[i][3] /= t
+
+void gld_FrustrumSetup(void)
+{
+ float t;
+ float clip[16];
+
+ pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+ pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
+
+ clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
+ clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);
+ clip[2] = CALCMATRIX(0, 2, 1, 6, 2, 10, 3, 14);
+ clip[3] = CALCMATRIX(0, 3, 1, 7, 2, 11, 3, 15);
+
+ clip[4] = CALCMATRIX(4, 0, 5, 4, 6, 8, 7, 12);
+ clip[5] = CALCMATRIX(4, 1, 5, 5, 6, 9, 7, 13);
+ clip[6] = CALCMATRIX(4, 2, 5, 6, 6, 10, 7, 14);
+ clip[7] = CALCMATRIX(4, 3, 5, 7, 6, 11, 7, 15);
+
+ clip[8] = CALCMATRIX(8, 0, 9, 4, 10, 8, 11, 12);
+ clip[9] = CALCMATRIX(8, 1, 9, 5, 10, 9, 11, 13);
+ clip[10] = CALCMATRIX(8, 2, 9, 6, 10, 10, 11, 14);
+ clip[11] = CALCMATRIX(8, 3, 9, 7, 10, 11, 11, 15);
+
+ clip[12] = CALCMATRIX(12, 0, 13, 4, 14, 8, 15, 12);
+ clip[13] = CALCMATRIX(12, 1, 13, 5, 14, 9, 15, 13);
+ clip[14] = CALCMATRIX(12, 2, 13, 6, 14, 10, 15, 14);
+ clip[15] = CALCMATRIX(12, 3, 13, 7, 14, 11, 15, 15);
+
+ // Right plane
+ frustum[0][0] = clip[ 3] - clip[ 0];
+ frustum[0][1] = clip[ 7] - clip[ 4];
+ frustum[0][2] = clip[11] - clip[ 8];
+ frustum[0][3] = clip[15] - clip[12];
+ NORMALIZE_PLANE(0);
+
+ // Left plane
+ frustum[1][0] = clip[ 3] + clip[ 0];
+ frustum[1][1] = clip[ 7] + clip[ 4];
+ frustum[1][2] = clip[11] + clip[ 8];
+ frustum[1][3] = clip[15] + clip[12];
+ NORMALIZE_PLANE(1);
+
+ // Bottom plane
+ frustum[2][0] = clip[ 3] + clip[ 1];
+ frustum[2][1] = clip[ 7] + clip[ 5];
+ frustum[2][2] = clip[11] + clip[ 9];
+ frustum[2][3] = clip[15] + clip[13];
+ NORMALIZE_PLANE(2);
+
+ // Top plane
+ frustum[3][0] = clip[ 3] - clip[ 1];
+ frustum[3][1] = clip[ 7] - clip[ 5];
+ frustum[3][2] = clip[11] - clip[ 9];
+ frustum[3][3] = clip[15] - clip[13];
+ NORMALIZE_PLANE(3);
+
+ // Far plane
+ frustum[4][0] = clip[ 3] - clip[ 2];
+ frustum[4][1] = clip[ 7] - clip[ 6];
+ frustum[4][2] = clip[11] - clip[10];
+ frustum[4][3] = clip[15] - clip[14];
+ NORMALIZE_PLANE(4);
+
+ // Near plane
+ frustum[5][0] = clip[ 3] + clip[ 2];
+ frustum[5][1] = clip[ 7] + clip[ 6];
+ frustum[5][2] = clip[11] + clip[10];
+ frustum[5][3] = clip[15] + clip[14];
+ NORMALIZE_PLANE(5);
+}
+
+boolean gld_SphereInFrustum(float x, float y, float z, float radius)
+{
+ int p;
+
+ for (p = 0; p < 4; p++)
+ {
+ if (frustum[p][0] * x +
+ frustum[p][1] * y +
+ frustum[p][2] * z +
+ frustum[p][3] <= -radius)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+#endif
diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h
new file mode 100644
index 000000000..3ba26e5e5
--- /dev/null
+++ b/src/hardware/hw_clip.h
@@ -0,0 +1,24 @@
+/*
+ * hw_clip.h
+ * SRB2CB
+ *
+ * PrBoom's OpenGL clipping
+ *
+ *
+ */
+
+// OpenGL BSP clipping
+#include "../doomdef.h"
+#include "../tables.h"
+#include "../doomtype.h"
+
+//#define HAVE_SPHEREFRUSTRUM // enable if you want gld_SphereInFrustum and related code
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
+void gld_clipper_Clear(void);
+angle_t gld_FrustumAngle(void);
+#ifdef HAVE_SPHEREFRUSTRUM
+void gld_FrustrumSetup(void);
+boolean gld_SphereInFrustum(float x, float y, float z, float radius);
+#endif
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index 94eef1d3e..5d1a81d4f 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -78,6 +78,7 @@ typedef struct gr_vissprite_s
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
+ float z1, z2;
} gr_vissprite_t;
// --------
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index a49a788e6..267666749 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -226,8 +226,7 @@ light_t *t_lspr[NUMSPRITES] =
// Collectible Items
&lspr[NOLIGHT], // SPR_RING
&lspr[NOLIGHT], // SPR_TRNG
- &lspr[NOLIGHT], // SPR_EMMY
- &lspr[BLUEBALL_L], // SPR_TOKE
+ &lspr[NOLIGHT], // SPR_TOKE
&lspr[REDBALL_L], // SPR_RFLG
&lspr[BLUEBALL_L], // SPR_BFLG
&lspr[NOLIGHT], // SPR_NWNG
@@ -243,6 +242,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SPIK
&lspr[NOLIGHT], // SPR_SFLM
&lspr[NOLIGHT], // SPR_USPK
+ &lspr[NOLIGHT], // SPR_WSPK
+ &lspr[NOLIGHT], // SPR_WSPB
&lspr[NOLIGHT], // SPR_STPT
&lspr[NOLIGHT], // SPR_BMNE
@@ -293,6 +294,12 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_FWR4
&lspr[NOLIGHT], // SPR_BUS1
&lspr[NOLIGHT], // SPR_BUS2
+ // Trees (both GFZ and misc)
+ &lspr[NOLIGHT], // SPR_TRE1
+ &lspr[NOLIGHT], // SPR_TRE2
+ &lspr[NOLIGHT], // SPR_TRE3
+ &lspr[NOLIGHT], // SPR_TRE4
+ &lspr[NOLIGHT], // SPR_TRE5
// Techno Hill Scenery
&lspr[NOLIGHT], // SPR_THZP
@@ -316,6 +323,10 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_BMCH
&lspr[NOLIGHT], // SPR_SMCE
&lspr[NOLIGHT], // SPR_BMCE
+ &lspr[NOLIGHT], // SPR_YSPB
+ &lspr[NOLIGHT], // SPR_RSPB
+ &lspr[REDBALL_L], // SPR_SFBR
+ &lspr[REDBALL_L], // SPR_BFBR
// Arid Canyon Scenery
&lspr[NOLIGHT], // SPR_BTBL
@@ -334,6 +345,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS1
&lspr[NOLIGHT], // SPR_XMS2
&lspr[NOLIGHT], // SPR_XMS3
+ &lspr[NOLIGHT], // SPR_XMS4
+ &lspr[NOLIGHT], // SPR_XMS5
// Botanic Serenity Scenery
&lspr[NOLIGHT], // SPR_BSZ1
@@ -345,13 +358,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_BSZ7
&lspr[NOLIGHT], // SPR_BSZ8
- // Stalagmites
+ // Misc Scenery
&lspr[NOLIGHT], // SPR_STLG
-
- // Disco Ball
&lspr[NOLIGHT], // SPR_DBAL
-
- // ATZ Red Crystal
&lspr[NOLIGHT], // SPR_RCRY
// Powerup Indicators
@@ -396,8 +405,11 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SPRB Graue
&lspr[NOLIGHT], // SPR_YSPR
&lspr[NOLIGHT], // SPR_RSPR
+ &lspr[NOLIGHT], // SPR_SSWY
+ &lspr[NOLIGHT], // SPR_SSWR
+ &lspr[NOLIGHT], // SPR_SSWB
- // Environmentals Effects
+ // Environmental Effects
&lspr[NOLIGHT], // SPR_RAIN
&lspr[NOLIGHT], // SPR_SNO1
&lspr[NOLIGHT], // SPR_SPLH
@@ -405,6 +417,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SMOK
&lspr[NOLIGHT], // SPR_BUBL
&lspr[RINGLIGHT_L], // SPR_WZAP
+ &lspr[NOLIGHT], // SPR_DUST
+ &lspr[NOLIGHT], // SPR_FPRT
&lspr[SUPERSPARK_L], // SPR_TFOG
&lspr[NIGHTSLIGHT_L], // SPR_SEED // Sonic CD flower seed
&lspr[NOLIGHT], // SPR_PRTL
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 4cfbc59e9..d74cd0587 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -44,6 +44,10 @@
#endif
#include "hw_md2.h"
+#ifdef NEWCLIP
+#include "hw_clip.h"
+#endif
+
#define R_FAKEFLOORS
#define HWPRECIP
#define SORTING
@@ -99,8 +103,9 @@ CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NU
boolean drawsky = true;
// needs fix: walls are incorrectly clipped one column less
+#ifndef NEWCLIP
static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-
+#endif
//development variables for diverse uses
static consvar_t cv_gralpha = {"gr_alpha", "160", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -323,9 +328,6 @@ static angle_t gr_xtoviewangle[MAXVIDWIDTH+1];
// test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK
-/// \note crappy
-#define drawtextured true
-
// base values set at SetViewSize
static float gr_basecentery;
@@ -641,13 +643,13 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
- angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT;
+ angle = FOFsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
- angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT;
+ angle = FOFsector->ceilingpic_angle;
}
}
else if (gr_frontsector)
@@ -656,25 +658,19 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
- angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT;
+ angle = gr_frontsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
- angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT;
+ angle = gr_frontsector->ceilingpic_angle;
}
}
if (angle) // Only needs to be done if there's an altered angle
{
-
- // This needs to be done so that it scrolls in a different direction after rotation like software
- tempxsow = FLOAT_TO_FIXED(scrollx);
- tempytow = FLOAT_TO_FIXED(scrolly);
- scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
- scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
-
+ angle = InvAngle(angle)>>ANGLETOFINESHIFT;
// This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
tempxsow = FLOAT_TO_FIXED(flatxref);
@@ -687,7 +683,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
// Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx);
- v3d->tow = (float)(flatyref - (pv->y / fflatsize) + scrolly);
+ v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly);
//v3d->sow = (float)(pv->x / fflatsize);
//v3d->tow = (float)(pv->y / fflatsize);
@@ -698,7 +694,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
- v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
+ v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
//v3d->sow = (float)(v3d->sow - flatxref + scrollx);
@@ -858,11 +854,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
M_ClearBox(segbbox);
M_AddToBox(segbbox,
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x),
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y));
M_AddToBox(segbbox,
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x),
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y));
splat = (wallsplat_t *)gr_curline->linedef->splats;
for (; splat; splat = splat->next)
@@ -1035,6 +1031,7 @@ static void HWR_ProjectWall(wallVert3D * wallVerts,
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment
//
+#ifndef NEWCLIP
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
{
float num, den;
@@ -1063,6 +1060,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
return num / den;
}
+#endif
//
// HWR_SplitWall
@@ -1437,7 +1435,11 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
// Anything between means the wall segment has been clipped with solidsegs,
// reducing wall overdraw to a minimum
//
+#ifdef NEWCLIP
+static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
+#else
static void HWR_StoreWallRange(double startfrac, double endfrac)
+#endif
{
wallVert3D wallVerts[4];
v2d_t vs, ve; // start, end vertices of 2d line (view from above)
@@ -1462,16 +1464,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
extracolormap_t *colormap;
FSurfaceInfo Surf;
+#ifndef NEWCLIP
if (startfrac > endfrac)
return;
+#endif
gr_sidedef = gr_curline->sidedef;
gr_linedef = gr_curline->linedef;
- vs.x = ((polyvertex_t *)gr_curline->v1)->x;
- vs.y = ((polyvertex_t *)gr_curline->v1)->y;
- ve.x = ((polyvertex_t *)gr_curline->v2)->x;
- ve.y = ((polyvertex_t *)gr_curline->v2)->y;
+ vs.x = ((polyvertex_t *)gr_curline->pv1)->x;
+ vs.y = ((polyvertex_t *)gr_curline->pv1)->y;
+ ve.x = ((polyvertex_t *)gr_curline->pv2)->x;
+ ve.y = ((polyvertex_t *)gr_curline->pv2)->y;
#ifdef ESLOPE
v1x = FLOAT_TO_FIXED(vs.x);
@@ -1479,44 +1483,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
v2x = FLOAT_TO_FIXED(ve.x);
v2y = FLOAT_TO_FIXED(ve.y);
#endif
-
- if (gr_frontsector->heightsec != -1)
- {
#ifdef ESLOPE
- worldtop = worldtopslope = sectors[gr_frontsector->heightsec].ceilingheight;
- worldbottom = worldbottomslope = sectors[gr_frontsector->heightsec].floorheight;
-#else
- worldtop = sectors[gr_frontsector->heightsec].ceilingheight;
- worldbottom = sectors[gr_frontsector->heightsec].floorheight;
-#endif
- }
- else
- {
-#ifdef ESLOPE
- if (gr_frontsector->c_slope)
- {
- worldtop = P_GetZAt(gr_frontsector->c_slope, v1x, v1y);
- worldtopslope = P_GetZAt(gr_frontsector->c_slope, v2x, v2y);
- }
- else
- {
- worldtop = worldtopslope = gr_frontsector->ceilingheight;
- }
- if (gr_frontsector->f_slope)
- {
- worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y);
- worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y);
- }
- else
- {
- worldbottom = worldbottomslope = gr_frontsector->floorheight;
- }
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight)
+ SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
#else
- worldtop = gr_frontsector->ceilingheight;
- worldbottom = gr_frontsector->floorheight;
+ worldtop = gr_frontsector->ceilingheight;
+ worldbottom = gr_frontsector->floorheight;
#endif
- }
// remember vertices ordering
// 3--2
@@ -1531,20 +1512,23 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[2].z = wallVerts[1].z = ve.y;
wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f;
- if (drawtextured)
{
// x offset the texture
fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset;
+#ifndef NEWCLIP
// clip texture s start/end coords with solidsegs
if (startfrac > 0.0f && startfrac < 1.0f)
cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac);
else
+#endif
cliplow = (float)texturehpeg;
+#ifndef NEWCLIP
if (endfrac > 0.0f && endfrac < 1.0f)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac);
else
+#endif
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
}
@@ -1560,43 +1544,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{
INT32 gr_toptexture, gr_bottomtexture;
// two sided line
- if (gr_backsector->heightsec != -1)
- {
-#ifdef ESLOPE
- worldhigh = worldhighslope = sectors[gr_backsector->heightsec].ceilingheight;
- worldlow = worldlowslope = sectors[gr_backsector->heightsec].floorheight;
-#else
- worldhigh = sectors[gr_backsector->heightsec].ceilingheight;
- worldlow = sectors[gr_backsector->heightsec].floorheight;
-#endif
- }
- else
- {
-#ifdef ESLOPE
- if (gr_backsector->c_slope)
- {
- worldhigh = P_GetZAt(gr_backsector->c_slope, v1x, v1y);
- worldhighslope = P_GetZAt(gr_backsector->c_slope, v2x, v2y);
- }
- else
- {
- worldhigh = worldhighslope = gr_backsector->ceilingheight;
- }
- if (gr_backsector->f_slope)
- {
- worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y);
- worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y);
- }
- else
- {
- worldlow = worldlowslope = gr_backsector->floorheight;
- }
+#ifdef ESLOPE
+ SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight)
+ SLOPEPARAMS(gr_backsector->f_slope, worldlow, worldlowslope, gr_backsector->floorheight)
+#undef SLOPEPARAMS
#else
- worldhigh = gr_backsector->ceilingheight;
- worldlow = gr_backsector->floorheight;
+ worldhigh = gr_backsector->ceilingheight;
+ worldlow = gr_backsector->floorheight;
#endif
- }
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
@@ -1620,7 +1576,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
worldhigh < worldtop
) && gr_toptexture)
{
- if (drawtextured)
{
fixed_t texturevpegtop; // top
@@ -1701,7 +1656,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
#endif
worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
{
- if (drawtextured)
{
fixed_t texturevpegbottom = 0; // bottom
@@ -1893,7 +1847,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
#ifdef ESLOPE
@@ -1949,7 +1902,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
@@ -2141,7 +2093,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
if (gr_midtexture)
{
- if (drawtextured)
{
fixed_t texturevpeg;
// PEGGING
@@ -2282,7 +2233,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
}
- else if (drawtextured)
+ else
{
#ifdef ESLOPE // P.S. this is better-organized than the old version
fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset;
@@ -2415,7 +2366,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
}
- else if (drawtextured)
+ else
{
grTex = HWR_GetTexture(texnum);
@@ -2488,6 +2439,110 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
//Hurdler: end of 3d-floors test
}
+// From PrBoom:
+//
+// e6y: Check whether the player can look beyond this line
+//
+#ifdef NEWCLIP
+boolean checkforemptylines = true;
+// Don't modify anything here, just check
+// Kalaron: Modified for sloped linedefs
+static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector)
+{
+ fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
+ fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
+
+ // GZDoom method of sloped line clipping
+
+#ifdef ESLOPE
+ if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope)
+ {
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight)
+ SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight)
+ SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight)
+ SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
+#undef SLOPEPARAMS
+ }
+ else
+#endif
+ {
+ frontf1 = frontf2 = afrontsector->floorheight;
+ frontc1 = frontc2 = afrontsector->ceilingheight;
+ backf1 = backf2 = abacksector->floorheight;
+ backc1 = backc2 = abacksector->ceilingheight;
+ }
+
+ // now check for closed sectors!
+ if (backc1 <= frontf1 && backc2 <= frontf2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->toptexture)
+ return false;
+
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backf1 >= frontc1 && backf2 >= frontc2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->bottomtexture)
+ return false;
+
+ // properly render skies (consider door "open" if both floors are sky):
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 <= backf1 && backc2 <= backf2)
+ {
+ checkforemptylines = false;
+ // preserve a kind of transparent door/lift special effect:
+ if (backc1 < frontc1 || backc2 < frontc2)
+ {
+ if (!seg->sidedef->toptexture)
+ return false;
+ }
+ if (backf1 > frontf1 || backf2 > frontf2)
+ {
+ if (!seg->sidedef->bottomtexture)
+ return false;
+ }
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 != frontc1 || backc2 != frontc2
+ || backf1 != frontf1 || backf2 != frontf2)
+ {
+ checkforemptylines = false;
+ return false;
+ }
+
+ return false;
+}
+#else
//Hurdler: just like in r_bsp.c
#if 1
#define MAXSEGS MAXVIDWIDTH/2+1
@@ -2559,7 +2614,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
// Now adjust the clip size.
@@ -2583,8 +2638,8 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
- highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
+ highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
next++;
@@ -2618,7 +2673,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
@@ -2681,8 +2736,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else
{
highfrac = HWR_ClipViewSegment(min(start->first + 1,
- start->last), (polyvertex_t *)gr_curline->v1,
- (polyvertex_t *)gr_curline->v2);
+ start->last), (polyvertex_t *)gr_curline->pv1,
+ (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
}
@@ -2701,8 +2756,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
- highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
+ highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
start++;
@@ -2732,8 +2787,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else
{
lowfrac = HWR_ClipViewSegment(max(start->last - 1,
- start->first), (polyvertex_t *)gr_curline->v1,
- (polyvertex_t *)gr_curline->v2);
+ start->first), (polyvertex_t *)gr_curline->pv1,
+ (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
@@ -2773,6 +2828,7 @@ static void HWR_ClearClipSegs(void)
gr_solidsegs[1].last = 0x7fffffff;
hw_newend = gr_solidsegs+2;
}
+#endif // NEWCLIP
// -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
@@ -2781,24 +2837,46 @@ static void HWR_ClearClipSegs(void)
// -----------------+
static void HWR_AddLine(seg_t * line)
{
- INT32 x1, x2;
angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 x1, x2;
angle_t span, tspan;
+#endif
// SoM: Backsector needs to be run through R_FakeFlat
sector_t tempsec;
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+#ifdef POLYOBJECTS
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
+#endif
gr_curline = line;
- // OPTIMIZE: quickly reject orthogonal back sides.
- angle1 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
- angle2 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+ // OPTIMIZE: quickly reject orthogonal back sides.
+ angle1 = R_PointToAngle(v1x, v1y);
+ angle2 = R_PointToAngle(v2x, v2y);
+
+#ifdef NEWCLIP
+ // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
+ if (angle2 - angle1 < ANGLE_180)
+ return;
+
+ // PrBoom: use REAL clipping math YAYYYYYYY!!!
+
+ if (!gld_clipper_SafeCheckRange(angle2, angle1))
+ {
+ return;
+ }
+
+ checkforemptylines = true;
+#else
// Clip to view edges.
span = angle1 - angle2;
@@ -2839,8 +2917,8 @@ static void HWR_AddLine(seg_t * line)
float fx1,fx2,fy1,fy2;
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
// do not enable this at release 4 mul and 2 div
- fx1 = ((polyvertex_t *)(line->v1))->x-gr_viewx;
- fy1 = ((polyvertex_t *)(line->v1))->y-gr_viewy;
+ fx1 = ((polyvertex_t *)(line->pv1))->x-gr_viewx;
+ fy1 = ((polyvertex_t *)(line->pv1))->y-gr_viewy;
fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin);
if (fy2 < 0)
// the point is back
@@ -2848,8 +2926,8 @@ static void HWR_AddLine(seg_t * line)
else
fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2;
- fx2 = ((polyvertex_t *)(line->v2))->x-gr_viewx;
- fy2 = ((polyvertex_t *)(line->v2))->y-gr_viewy;
+ fx2 = ((polyvertex_t *)(line->pv2))->x-gr_viewx;
+ fy2 = ((polyvertex_t *)(line->pv2))->y-gr_viewy;
fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin);
if (fy1 < 0)
// the point is back
@@ -2877,8 +2955,34 @@ static void HWR_AddLine(seg_t * line)
return;
}
*/
+#endif
+
gr_backsector = line->backsector;
+#ifdef NEWCLIP
+ if (!line->backsector)
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ }
+ else
+ {
+ gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true);
+ if (CheckClip(line, gr_frontsector, gr_backsector))
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ checkforemptylines = false;
+ }
+ // Reject empty lines used for triggers and special events.
+ // Identical floor and ceiling on both sides,
+ // identical light levels on both sides,
+ // and no middle texture.
+ if (checkforemptylines && R_IsEmptyLine(line, gr_frontsector, gr_backsector))
+ return;
+ }
+
+ HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
+ return;
+#else
// Single sided line?
if (!gr_backsector)
goto clipsolid;
@@ -2888,14 +2992,9 @@ static void HWR_AddLine(seg_t * line)
#ifdef ESLOPE
if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_backsector->c_slope)
{
- fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
- v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x);
- v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y);
- v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x);
- v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y);
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \
@@ -2916,6 +3015,13 @@ static void HWR_AddLine(seg_t * line)
goto clipsolid;
}
+ // Check for automap fix.
+ if (backc1 <= backf1 && backc2 <= backf2
+ && ((backc1 >= frontc1 && backc2 >= frontc2) || gr_curline->sidedef->toptexture)
+ && ((backf1 <= frontf1 && backf2 >= frontf2) || gr_curline->sidedef->bottomtexture)
+ && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
+ goto clipsolid;
+
// Window.
if (backc1 != frontc1 || backc2 != frontc2
|| backf1 != frontf1 || backf2 != frontf2)
@@ -2931,6 +3037,13 @@ static void HWR_AddLine(seg_t * line)
gr_backsector->floorheight >= gr_frontsector->ceilingheight)
goto clipsolid;
+ // Check for automap fix.
+ if (gr_backsector->ceilingheight <= gr_backsector->floorheight
+ && ((gr_backsector->ceilingheight >= gr_frontsector->ceilingheight) || gr_curline->sidedef->toptexture)
+ && ((gr_backsector->floorheight <= gr_backsector->floorheight) || gr_curline->sidedef->bottomtexture)
+ && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
+ goto clipsolid;
+
// Window.
if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight ||
gr_backsector->floorheight != gr_frontsector->floorheight)
@@ -2941,25 +3054,8 @@ static void HWR_AddLine(seg_t * line)
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
- if (
-#ifdef POLYOBJECTS
- !line->polyseg &&
-#endif
- gr_backsector->ceilingpic == gr_frontsector->ceilingpic
- && gr_backsector->floorpic == gr_frontsector->floorpic
-#ifdef ESLOPE
- && gr_backsector->f_slope == gr_frontsector->f_slope
- && gr_backsector->c_slope == gr_frontsector->c_slope
-#endif
- && gr_backsector->lightlevel == gr_frontsector->lightlevel
- && gr_curline->sidedef->midtexture == 0
- && !gr_backsector->ffloors && !gr_frontsector->ffloors)
- // SoM: For 3D sides... Boris, would you like to take a
- // crack at rendering 3D sides? You would need to add the
- // above check and add code to HWR_StoreWallRange...
- {
+ if (R_IsEmptyLine(gr_curline, gr_frontsector, gr_backsector))
return;
- }
clippass:
if (x1 == x2)
@@ -2971,6 +3067,7 @@ clipsolid:
if (x1 == x2)
goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1);
+#endif
}
// HWR_CheckBBox
@@ -2982,9 +3079,13 @@ clipsolid:
static boolean HWR_CheckBBox(fixed_t *bspcoord)
{
- INT32 boxpos, sx1, sx2;
+ INT32 boxpos;
fixed_t px1, py1, px2, py2;
- angle_t angle1, angle2, span, tspan;
+ angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 sx1, sx2;
+ angle_t span, tspan;
+#endif
// Find the corners of the box
// that define the edges from current viewpoint.
@@ -3010,6 +3111,11 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]];
+#ifdef NEWCLIP
+ angle1 = R_PointToAngle(px1, py1);
+ angle2 = R_PointToAngle(px2, py2);
+ return gld_clipper_SafeCheckRange(angle2, angle1);
+#else
// check clip list for an open space
angle1 = R_PointToAngle(px1, py1) - dup_viewangle;
angle2 = R_PointToAngle(px2, py2) - dup_viewangle;
@@ -3057,6 +3163,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
+#endif
}
#ifdef POLYOBJECTS
@@ -3090,8 +3197,8 @@ static inline void HWR_AddPolyObjectSegs(void)
pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x);
pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y);
- gr_fakeline->v1 = (vertex_t *)pv1;
- gr_fakeline->v2 = (vertex_t *)pv2;
+ gr_fakeline->pv1 = pv1;
+ gr_fakeline->pv2 = pv2;
HWR_AddLine(gr_fakeline);
}
@@ -4229,6 +4336,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
GLPatch_t *gpatch; // sprite patch converted to hardware
FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
+ //const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE));
if (spr->mobj)
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
if (hires)
@@ -4272,7 +4380,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
// make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices
- wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz;
+ wallVerts[0].z = wallVerts[3].z = spr->z1;
+ wallVerts[2].z = wallVerts[1].z = spr->z2;
// transform
wv = wallVerts;
@@ -5068,6 +5177,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
angle_t ang;
INT32 heightsec, phs;
+ const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
+ float offset;
+ float ang_scale = 1.0f, ang_scalez = 0.0f;
+ float z1, z2;
if (!thing)
return;
@@ -5082,7 +5195,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
- if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
+ if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos);
@@ -5120,6 +5233,27 @@ static void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif
+ if (papersprite)
+ {
+ // Use the actual view angle, rather than the angle formed
+ // between the view point and the thing
+ // this makes sure paper sprites always appear at the right angle!
+ // Note: DO NOT do this in software mode version, it actually
+ // makes papersprites look WORSE there (I know, I've tried)
+ // Monster Iestyn - 13/05/17
+ ang = dup_viewangle - thing->angle;
+ ang_scale = FIXED_TO_FLOAT(FINESINE(ang>>ANGLETOFINESHIFT));
+ ang_scalez = FIXED_TO_FLOAT(FINECOSINE(ang>>ANGLETOFINESHIFT));
+
+ if (ang_scale < 0)
+ {
+ ang_scale = -ang_scale;
+ ang_scalez = -ang_scalez;
+ }
+ }
+ else if (sprframe->rotate != SRF_SINGLE)
+ ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
+
if (sprframe->rotate == SRF_SINGLE)
{
// use single rotation for all views
@@ -5130,8 +5264,6 @@ static void HWR_ProjectSprite(mobj_t *thing)
else
{
// choose a different rotation based on player view
- ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
-
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
rot = 6; // F7 slot
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
@@ -5149,9 +5281,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
// calculate edges of the shape
if (flip)
- tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale;
+ offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale;
else
- tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale;
+ offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale;
+
+ z1 = tz - (offset * ang_scalez);
+ tx -= offset * ang_scale;
// project x
x1 = gr_windowcenterx + (tx * gr_centerx / tz);
@@ -5162,7 +5297,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
x1 = tx;
- tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale;
+ offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale;
+
+ z2 = z1 + (offset * ang_scalez);
+ tx += offset * ang_scale;
+
+ if (papersprite && max(z1, z2) < ZCLIP_PLANE)
+ return;
+
x2 = gr_windowcenterx + (tx * gr_centerx / tz);
if (vflip)
@@ -5211,6 +5353,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->patchlumpnum = sprframe->lumppat[rot];
vis->flip = flip;
vis->mobj = thing;
+ vis->z1 = z1;
+ vis->z2 = z2;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
@@ -5599,7 +5743,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5609,6 +5765,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5635,6 +5792,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -5829,7 +5987,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5839,6 +6009,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5865,6 +6036,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -6010,7 +6182,9 @@ static inline void HWR_AddEngineCommands(void)
{
// engine state variables
//CV_RegisterVar(&cv_grzbuffer);
+#ifndef NEWCLIP
CV_RegisterVar(&cv_grclipwalls);
+#endif
// engine development mode variables
// - usage may vary from version to version..
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 7edf02db0..18fc1bd6d 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -298,8 +298,8 @@ static md2_model_t *md2_readModel(const char *filename)
// initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1
- || model->header.magic !=
- (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I'))
+ || model->header.magic != MD2_IDENT
+ || model->header.version != MD2_VERSION)
{
fclose(file);
free(model);
@@ -313,6 +313,7 @@ static md2_model_t *md2_readModel(const char *filename)
{ \
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
md2_freeModel (model); \
+ fclose(file); \
return 0; \
}
@@ -334,6 +335,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -347,6 +349,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -360,6 +363,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -372,6 +376,7 @@ static md2_model_t *md2_readModel(const char *filename)
if (!model->frames)
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
@@ -385,6 +390,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(frame, 1, model->header.frameSize, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
@@ -410,6 +416,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -938,6 +945,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
{
UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h;
+ UINT8 c = 255;
RGBA_t *image, *blendimage, *cur, blendcolor;
if (grmip->width == 0)
@@ -961,244 +969,59 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
image = gpatch->mipmap.grInfo.data;
blendimage = blendgpatch->mipmap.grInfo.data;
+#define SUPERCOLORBLEND(name, c1, c2, c3, c4, c5) \
+ case SKINCOLOR_SUPER ## name ## 1: c = c1; break; \
+ case SKINCOLOR_SUPER ## name ## 2: c = c2; break; \
+ case SKINCOLOR_SUPER ## name ## 3: c = c3; break; \
+ case SKINCOLOR_SUPER ## name ## 4: c = c4; break; \
+ case SKINCOLOR_SUPER ## name ## 5: c = c5; break;
+
switch (color)
{
- case SKINCOLOR_WHITE:
- blendcolor = V_GetColor(3);
- break;
- case SKINCOLOR_SILVER:
- blendcolor = V_GetColor(10);
- break;
- case SKINCOLOR_GREY:
- blendcolor = V_GetColor(15);
- break;
- case SKINCOLOR_BLACK:
- blendcolor = V_GetColor(27);
- break;
- case SKINCOLOR_BEIGE:
- blendcolor = V_GetColor(247);
- break;
- case SKINCOLOR_PEACH:
- blendcolor = V_GetColor(218);
- break;
- case SKINCOLOR_BROWN:
- blendcolor = V_GetColor(234);
- break;
- case SKINCOLOR_RED:
- blendcolor = V_GetColor(38);
- break;
- case SKINCOLOR_CRIMSON:
- blendcolor = V_GetColor(45);
- break;
- case SKINCOLOR_ORANGE:
- blendcolor = V_GetColor(54);
- break;
- case SKINCOLOR_RUST:
- blendcolor = V_GetColor(60);
- break;
- case SKINCOLOR_GOLD:
- blendcolor = V_GetColor(67);
- break;
- case SKINCOLOR_YELLOW:
- blendcolor = V_GetColor(73);
- break;
- case SKINCOLOR_TAN:
- blendcolor = V_GetColor(85);
- break;
- case SKINCOLOR_MOSS:
- blendcolor = V_GetColor(92);
- break;
- case SKINCOLOR_PERIDOT:
- blendcolor = V_GetColor(188);
- break;
- case SKINCOLOR_GREEN:
- blendcolor = V_GetColor(101);
- break;
- case SKINCOLOR_EMERALD:
- blendcolor = V_GetColor(112);
- break;
- case SKINCOLOR_AQUA:
- blendcolor = V_GetColor(122);
- break;
- case SKINCOLOR_TEAL:
- blendcolor = V_GetColor(141);
- break;
- case SKINCOLOR_CYAN:
- blendcolor = V_GetColor(131);
- break;
- case SKINCOLOR_BLUE:
- blendcolor = V_GetColor(152);
- break;
- case SKINCOLOR_AZURE:
- blendcolor = V_GetColor(171);
- break;
- case SKINCOLOR_PASTEL:
- blendcolor = V_GetColor(161);
- break;
- case SKINCOLOR_PURPLE:
- blendcolor = V_GetColor(165);
- break;
- case SKINCOLOR_LAVENDER:
- blendcolor = V_GetColor(195);
- break;
- case SKINCOLOR_MAGENTA:
- blendcolor = V_GetColor(183);
- break;
- case SKINCOLOR_PINK:
- blendcolor = V_GetColor(211);
- break;
- case SKINCOLOR_ROSY:
- blendcolor = V_GetColor(202);
- break;
+ case SKINCOLOR_WHITE: c = 3; break;
+ case SKINCOLOR_SILVER: c = 10; break;
+ case SKINCOLOR_GREY: c = 15; break;
+ case SKINCOLOR_BLACK: c = 27; break;
+ case SKINCOLOR_BEIGE: c = 247; break;
+ case SKINCOLOR_PEACH: c = 218; break;
+ case SKINCOLOR_BROWN: c = 234; break;
+ case SKINCOLOR_RED: c = 38; break;
+ case SKINCOLOR_CRIMSON: c = 45; break;
+ case SKINCOLOR_ORANGE: c = 54; break;
+ case SKINCOLOR_RUST: c = 60; break;
+ case SKINCOLOR_GOLD: c = 67; break;
+ case SKINCOLOR_YELLOW: c = 73; break;
+ case SKINCOLOR_TAN: c = 85; break;
+ case SKINCOLOR_MOSS: c = 92; break;
+ case SKINCOLOR_PERIDOT: c = 188; break;
+ case SKINCOLOR_GREEN: c = 101; break;
+ case SKINCOLOR_EMERALD: c = 112; break;
+ case SKINCOLOR_AQUA: c = 122; break;
+ case SKINCOLOR_TEAL: c = 141; break;
+ case SKINCOLOR_CYAN: c = 131; break;
+ case SKINCOLOR_BLUE: c = 152; break;
+ case SKINCOLOR_AZURE: c = 171; break;
+ case SKINCOLOR_PASTEL: c = 161; break;
+ case SKINCOLOR_PURPLE: c = 165; break;
+ case SKINCOLOR_LAVENDER: c = 195; break;
+ case SKINCOLOR_MAGENTA: c = 183; break;
+ case SKINCOLOR_PINK: c = 211; break;
+ case SKINCOLOR_ROSY: c = 202; break;
- case SKINCOLOR_SUPERSILVER1: // Super silver
- blendcolor = V_GetColor(0);
- break;
- case SKINCOLOR_SUPERSILVER2:
- blendcolor = V_GetColor(2);
- break;
- case SKINCOLOR_SUPERSILVER3:
- blendcolor = V_GetColor(4);
- break;
- case SKINCOLOR_SUPERSILVER4:
- blendcolor = V_GetColor(7);
- break;
- case SKINCOLOR_SUPERSILVER5:
- blendcolor = V_GetColor(10);
- break;
-
- case SKINCOLOR_SUPERRED1: // Super red
- blendcolor = V_GetColor(208);
- break;
- case SKINCOLOR_SUPERRED2:
- blendcolor = V_GetColor(210);
- break;
- case SKINCOLOR_SUPERRED3:
- blendcolor = V_GetColor(32);
- break;
- case SKINCOLOR_SUPERRED4:
- blendcolor = V_GetColor(33);
- break;
- case SKINCOLOR_SUPERRED5:
- blendcolor = V_GetColor(35);
- break;
-
- case SKINCOLOR_SUPERORANGE1: // Super orange
- blendcolor = V_GetColor(208);
- break;
- case SKINCOLOR_SUPERORANGE2:
- blendcolor = V_GetColor(48);
- break;
- case SKINCOLOR_SUPERORANGE3:
- blendcolor = V_GetColor(50);
- break;
- case SKINCOLOR_SUPERORANGE4:
- blendcolor = V_GetColor(54);
- break;
- case SKINCOLOR_SUPERORANGE5:
- blendcolor = V_GetColor(58);
- break;
-
- case SKINCOLOR_SUPERGOLD1: // Super gold
- blendcolor = V_GetColor(80);
- break;
- case SKINCOLOR_SUPERGOLD2:
- blendcolor = V_GetColor(83);
- break;
- case SKINCOLOR_SUPERGOLD3:
- blendcolor = V_GetColor(73);
- break;
- case SKINCOLOR_SUPERGOLD4:
- blendcolor = V_GetColor(64);
- break;
- case SKINCOLOR_SUPERGOLD5:
- blendcolor = V_GetColor(67);
- break;
-
- case SKINCOLOR_SUPERPERIDOT1: // Super peridot
- blendcolor = V_GetColor(88);
- break;
- case SKINCOLOR_SUPERPERIDOT2:
- blendcolor = V_GetColor(188);
- break;
- case SKINCOLOR_SUPERPERIDOT3:
- blendcolor = V_GetColor(189);
- break;
- case SKINCOLOR_SUPERPERIDOT4:
- blendcolor = V_GetColor(190);
- break;
- case SKINCOLOR_SUPERPERIDOT5:
- blendcolor = V_GetColor(191);
- break;
-
- case SKINCOLOR_SUPERCYAN1: // Super cyan
- blendcolor = V_GetColor(128);
- break;
- case SKINCOLOR_SUPERCYAN2:
- blendcolor = V_GetColor(131);
- break;
- case SKINCOLOR_SUPERCYAN3:
- blendcolor = V_GetColor(133);
- break;
- case SKINCOLOR_SUPERCYAN4:
- blendcolor = V_GetColor(134);
- break;
- case SKINCOLOR_SUPERCYAN5:
- blendcolor = V_GetColor(136);
- break;
-
- case SKINCOLOR_SUPERPURPLE1: // Super purple
- blendcolor = V_GetColor(144);
- break;
- case SKINCOLOR_SUPERPURPLE2:
- blendcolor = V_GetColor(162);
- break;
- case SKINCOLOR_SUPERPURPLE3:
- blendcolor = V_GetColor(164);
- break;
- case SKINCOLOR_SUPERPURPLE4:
- blendcolor = V_GetColor(166);
- break;
- case SKINCOLOR_SUPERPURPLE5:
- blendcolor = V_GetColor(168);
- break;
-
- case SKINCOLOR_SUPERRUST1: // Super rust
- blendcolor = V_GetColor(51);
- break;
- case SKINCOLOR_SUPERRUST2:
- blendcolor = V_GetColor(54);
- break;
- case SKINCOLOR_SUPERRUST3:
- blendcolor = V_GetColor(68);
- break;
- case SKINCOLOR_SUPERRUST4:
- blendcolor = V_GetColor(70);
- break;
- case SKINCOLOR_SUPERRUST5:
- blendcolor = V_GetColor(234);
- break;
-
- case SKINCOLOR_SUPERTAN1: // Super tan
- blendcolor = V_GetColor(80);
- break;
- case SKINCOLOR_SUPERTAN2:
- blendcolor = V_GetColor(82);
- break;
- case SKINCOLOR_SUPERTAN3:
- blendcolor = V_GetColor(84);
- break;
- case SKINCOLOR_SUPERTAN4:
- blendcolor = V_GetColor(87);
- break;
- case SKINCOLOR_SUPERTAN5:
- blendcolor = V_GetColor(247);
- break;
-
- default:
- blendcolor = V_GetColor(255);
- break;
+ SUPERCOLORBLEND(SILVER, 0, 2, 4, 7, 10) // Super silver
+ SUPERCOLORBLEND(RED, 208, 210, 32, 33, 35) // Super red
+ SUPERCOLORBLEND(ORANGE, 208, 48, 50, 54, 58) // Super orange
+ SUPERCOLORBLEND(GOLD, 80, 83, 73, 64, 67) // Super gold
+ SUPERCOLORBLEND(PERIDOT, 88, 188, 189, 190, 191) // Super peridot
+ SUPERCOLORBLEND(CYAN, 128, 131, 133, 134, 136) // Super cyan
+ SUPERCOLORBLEND(PURPLE, 144, 162, 164, 166, 168) // Super purple
+ SUPERCOLORBLEND(RUST, 51, 54, 68, 70, 234) // Super rust
+ SUPERCOLORBLEND(TAN, 80, 82, 84, 87, 247) // Super tan
+ default: c = 255; break;
}
+ blendcolor = V_GetColor(c);
+
+#undef SUPERCOLORBLEND
while (size--)
{
diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h
index 5a7e6d2b3..299d12400 100644
--- a/src/hardware/hw_md2.h
+++ b/src/hardware/hw_md2.h
@@ -23,6 +23,11 @@
#include "hw_glob.h"
+// magic number "IDP2" or 844121161
+#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
+// model version
+#define MD2_VERSION 8
+
#define MD2_MAX_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c
index e9ba19efb..97d86b944 100644
--- a/src/hardware/hw_trick.c
+++ b/src/hardware/hw_trick.c
@@ -107,17 +107,17 @@ static void releaseLineChains(void)
for (i = 0; i < numsectors; i++)
{
- sector = §ors[i];
- nextElem = sector->sectorLines;
+ sector = §ors[i];
+ nextElem = sector->sectorLines;
- while (nextElem)
- {
- thisElem = nextElem;
- nextElem = thisElem->next;
- free(thisElem);
- }
+ while (nextElem)
+ {
+ thisElem = nextElem;
+ nextElem = thisElem->next;
+ free(thisElem);
+ }
- sector->sectorLines = NULL;
+ sector->sectorLines = NULL;
}
}
@@ -397,7 +397,7 @@ static void sortStacklist(sector_t *sector)
i = 0;
finished = true;
- while (NULL != *(list+i+1))
+ while (*(list+i+1))
{
sec1 = *(list+i);
sec2 = *(list+i+1);
@@ -438,7 +438,7 @@ static double calcLineoutLength(sector_t *sector)
double length = 0.0L;
chain = sector->sectorLines;
- while (NULL != chain) // sum up lengths of all lines
+ while (chain) // sum up lengths of all lines
{
length += lineLength(chain->line);
chain = chain->next;
@@ -454,7 +454,7 @@ static void calcLineouts(sector_t *sector)
size_t secCount = 0;
sector_t *encSector = *(sector->stackList);
- while (NULL != encSector)
+ while (encSector)
{
if (encSector->lineoutLength < 0.0L) // if length has not yet been calculated
{
@@ -552,7 +552,7 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
if (frontSector == backSector) // skip damn renderer tricks here
continue;
- if (frontSector == NULL || backSector == NULL)
+ if (!frontSector || !backSector)
continue;
sider = &sides[thisElem->line->sidenum[0]];
@@ -587,73 +587,12 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
static boolean isCeilingFloating(sector_t *thisSector)
{
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
- boolean floating = true;
linechain_t *thisElem, *nextElem;
if (!thisSector)
return false;
- nextElem = thisSector->sectorLines;
-
- while (NULL != nextElem) // walk through chain
- {
- thisElem = nextElem;
- nextElem = thisElem->next;
-
- frontSector = thisElem->line->frontsector;
- backSector = thisElem->line->backsector;
-
- if (frontSector == thisSector)
- adjSector = backSector;
- else
- adjSector = frontSector;
-
- if (!adjSector) // assume floating sectors have surrounding sectors
- {
- floating = false;
- break;
- }
-
- if (!refSector)
- {
- refSector = adjSector;
- continue;
- }
-
- // if adjacent sector has same height or more than one adjacent sector exists -> stop
- if (thisSector->ceilingheight == adjSector->ceilingheight ||
- refSector != adjSector)
- {
- floating = false;
- break;
- }
- }
-
- // now check for walltextures
- if (floating)
- {
- if (!areToptexturesMissing(thisSector))
- {
- floating = false;
- }
- }
- return floating;
-}
-
-//
-// check if no adjacent sector has same ceiling height
-// FIXME: throw that together with isCeilingFloating??
-//
-static boolean isFloorFloating(sector_t *thisSector)
-{
- sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
- boolean floating = true;
- linechain_t *thisElem, *nextElem;
-
- if (!thisSector)
- return false;
-
- nextElem = thisSector->sectorLines;
+ nextElem = thisSector->sectorLines;
while (nextElem) // walk through chain
{
@@ -668,36 +607,83 @@ static boolean isFloorFloating(sector_t *thisSector)
else
adjSector = frontSector;
- if (NULL == adjSector) // assume floating sectors have surrounding sectors
- {
- floating = false;
- break;
- }
+ if (!adjSector) // assume floating sectors have surrounding sectors
+ return false;
- if (NULL == refSector)
+#ifdef ESLOPE
+ if (adjSector->c_slope) // Don't bother with slopes
+ return false;
+#endif
+
+ if (!refSector)
{
refSector = adjSector;
continue;
}
// if adjacent sector has same height or more than one adjacent sector exists -> stop
- if (thisSector->floorheight == adjSector->floorheight ||
- refSector != adjSector)
- {
- floating = false;
- break;
- }
+ if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector)
+ return false;
}
// now check for walltextures
- if (floating)
+ if (!areToptexturesMissing(thisSector))
+ return false;
+
+ return true;
+}
+
+//
+// check if no adjacent sector has same ceiling height
+// FIXME: throw that together with isCeilingFloating??
+//
+static boolean isFloorFloating(sector_t *thisSector)
+{
+ sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
+ linechain_t *thisElem, *nextElem;
+
+ if (!thisSector)
+ return false;
+
+ nextElem = thisSector->sectorLines;
+
+ while (nextElem) // walk through chain
{
- if (!areBottomtexturesMissing(thisSector))
+ thisElem = nextElem;
+ nextElem = thisElem->next;
+
+ frontSector = thisElem->line->frontsector;
+ backSector = thisElem->line->backsector;
+
+ if (frontSector == thisSector)
+ adjSector = backSector;
+ else
+ adjSector = frontSector;
+
+ if (!adjSector) // assume floating sectors have surrounding sectors
+ return false;
+
+#ifdef ESLOPE
+ if (adjSector->f_slope) // Don't bother with slopes
+ return false;
+#endif
+
+ if (!refSector)
{
- floating = false;
+ refSector = adjSector;
+ continue;
}
+
+ // if adjacent sector has same height or more than one adjacent sector exists -> stop
+ if (thisSector->floorheight == adjSector->floorheight || refSector != adjSector)
+ return false;
}
- return floating;
+
+ // now check for walltextures
+ if (!areBottomtexturesMissing(thisSector))
+ return false;
+
+ return true;
}
//
@@ -707,14 +693,12 @@ static fixed_t estimateCeilHeight(sector_t *thisSector)
{
sector_t *adjSector;
- if (!thisSector ||
- !thisSector->sectorLines ||
- !thisSector->sectorLines->line)
+ if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
return 0;
adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector)
- adjSector = thisSector->sectorLines->line->backsector;
+ adjSector = thisSector->sectorLines->line->backsector;
if (!adjSector)
return 0;
@@ -729,17 +713,15 @@ static fixed_t estimateFloorHeight(sector_t *thisSector)
{
sector_t *adjSector;
- if (!thisSector ||
- !thisSector->sectorLines ||
- !thisSector->sectorLines->line)
- return 0;
+ if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
+ return 0;
adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector)
- adjSector = thisSector->sectorLines->line->backsector;
+ adjSector = thisSector->sectorLines->line->backsector;
- if (NULL == adjSector)
- return 0;
+ if (!adjSector)
+ return 0;
return adjSector->floorheight;
}
@@ -845,18 +827,12 @@ void HWR_CorrectSWTricks(void)
// correct height of floating sectors
if (isCeilingFloating(floatSector))
{
- fixed_t corrheight;
-
- corrheight = estimateCeilHeight(floatSector);
- floatSector->virtualCeilingheight = corrheight;
+ floatSector->virtualCeilingheight = estimateCeilHeight(floatSector);
floatSector->virtualCeiling = true;
}
if (isFloorFloating(floatSector))
{
- fixed_t corrheight;
-
- corrheight = estimateFloorHeight(floatSector);
- floatSector->virtualFloorheight = corrheight;
+ floatSector->virtualFloorheight = estimateFloorHeight(floatSector);
floatSector->virtualFloor = true;
}
}
diff --git a/src/info.c b/src/info.c
index 9e779acb0..1f5b394ab 100644
--- a/src/info.c
+++ b/src/info.c
@@ -114,7 +114,6 @@ char sprnames[NUMSPRITES + 1][5] =
// Collectible Items
"RING",
"TRNG", // Team Rings
- "EMMY", // emerald test
"TOKE", // Special Stage Token
"RFLG", // Red CTF Flag
"BFLG", // Blue CTF Flag
@@ -131,6 +130,8 @@ char sprnames[NUMSPRITES + 1][5] =
"SPIK", // Spike Ball
"SFLM", // Spin fire
"USPK", // Floor spike
+ "WSPK", // Wall spike
+ "WSPB", // Wall spike base
"STPT", // Starpost
"BMNE", // Big floating mine
@@ -181,6 +182,12 @@ char sprnames[NUMSPRITES + 1][5] =
"FWR4",
"BUS1", // GFZ Bush w/ berries
"BUS2", // GFZ Bush w/o berries
+ // Trees (both GFZ and misc)
+ "TRE1", // GFZ
+ "TRE2", // Checker
+ "TRE3", // Frozen Hillside
+ "TRE4", // Polygon
+ "TRE5", // Bush tree
// Techno Hill Scenery
"THZP", // Techno Hill Zone Plant
@@ -204,6 +211,10 @@ char sprnames[NUMSPRITES + 1][5] =
"BMCH", // Big Mace Chain
"SMCE", // Small Mace
"BMCE", // Big Mace
+ "YSPB", // Yellow spring on a ball
+ "RSPB", // Red spring on a ball
+ "SFBR", // Small Firebar
+ "BFBR", // Big Firebar
// Arid Canyon Scenery
"BTBL", // Big tumbleweed
@@ -1409,14 +1420,10 @@ state_t states[NUMSTATES] =
{SPR_GWLR, 2, 1, {NULL}, 0, 0, S_GRAVWELLRED}, // S_GRAVWELLRED3
// Individual Team Rings (now with shield attracting action! =P)
- {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING}, // S_TEAMRING1
+ {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING}, // S_TEAMRING
// Special Stage Token
- {SPR_EMMY, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 6, 2, S_EMMY}, // S_EMMY
-
- // Special Stage Token
- {SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_TOKEN
- {SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_MOVINGTOKEN}, // S_MOVINGTOKEN
+ {SPR_TOKE, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 19, 1, S_TOKEN}, // S_TOKEN
// CTF Flags
{SPR_RFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDFLAG
@@ -1560,13 +1567,24 @@ state_t states[NUMSTATES] =
// Floor Spike
{SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended
- {SPR_USPK, 5, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
- {SPR_USPK, 4, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3
+ {SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
+ {SPR_USPK, 2, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3
{SPR_USPK, 3,-1, {A_SpikeRetract}, 0, 0, S_SPIKE5}, // S_SPIKE4 -- Fully retracted
- {SPR_USPK, 4, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5
- {SPR_USPK, 5, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6
- {SPR_USPK, 1,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles
- {SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
+ {SPR_USPK, 2, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5
+ {SPR_USPK, 1, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6
+ {SPR_USPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles
+ {SPR_USPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
+
+ // Wall Spike
+ {SPR_WSPK, 0|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 1, 0, S_WALLSPIKE2}, // S_WALLSPIKE1 -- Fully extended
+ {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE3}, // S_WALLSPIKE2
+ {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE4}, // S_WALLSPIKE3
+ {SPR_WSPK, 3|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 0, 0, S_WALLSPIKE5}, // S_WALLSPIKE4 -- Fully retracted
+ {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE6}, // S_WALLSPIKE5
+ {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE1}, // S_WALLSPIKE6
+ {SPR_WSPB, 0|FF_PAPERSPRITE,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKEBASE -- Base
+ {SPR_WSPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED1 -- Busted spike particles
+ {SPR_WSPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED2
// Starpost
{SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE
@@ -1761,6 +1779,18 @@ state_t states[NUMSTATES] =
{SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH
{SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH
+ // Trees
+ {SPR_TRE1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GFZTREE
+ {SPR_TRE1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_GFZBERRYTREE
+ {SPR_TRE1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_GFZCHERRYTREE
+ {SPR_TRE2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CHECKERTREE
+ {SPR_TRE2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CHECKERSUNSETTREE
+ {SPR_TRE3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FHZTREE
+ {SPR_TRE3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_FHZPINKTREE
+ {SPR_TRE4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_POLYGONTREE
+ {SPR_TRE5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHTREE
+ {SPR_TRE5, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHREDTREE
+
{SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL}, // S_THZFLOWERA
{SPR_FWR5, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL}, // S_THZFLOWERB
@@ -1804,13 +1834,13 @@ state_t states[NUMSTATES] =
{SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN
// Flame
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, 0, S_FLAME4}, // S_FLAME3
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0, S_FLAME5}, // S_FLAME4
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, 0, S_FLAME6}, // S_FLAME5
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME6
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0, S_NULL}, // S_FLAMEPARTICLE
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME2}, // S_FLAME1
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0 , S_FLAME3}, // S_FLAME2
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME4}, // S_FLAME3
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0 , S_FLAME5}, // S_FLAME4
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME6}, // S_FLAME5
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0 , S_FLAME1}, // S_FLAME6
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0 , S_NULL}, // S_FLAMEPARTICLE
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|FF_ANIMATE, -1, {NULL}, 5, 3, S_FLAME2}, // S_FLAMEREST
@@ -1821,31 +1851,75 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_SLING2}, // S_SLING1
{SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2
- // Small Mace Chain
- {SPR_SMCH, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
+ // CEZ maces and chains
+ {SPR_SMCH, 0, -1, {NULL}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
+ {SPR_BMCH, 0, -1, {NULL}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
+ {SPR_SMCE, 0, -1, {NULL}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
+ {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_BIGMACE}, // S_BIGMACE
- // Big Mace Chain
- {SPR_BMCH, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
+ // Yellow spring on a ball
+ {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL
+ {SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2
+ {SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4}, // S_YELLOWSPRINGBALL3
+ {SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5}, // S_YELLOWSPRINGBALL4
+ {SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL}, // S_YELLOWSPRINGBALL5
- // Small Mace
- {SPR_SMCE, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
+ // Red spring on a ball
+ {SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRINGBALL
+ {SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3}, // S_REDSPRINGBALL2
+ {SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4}, // S_REDSPRINGBALL3
+ {SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5}, // S_REDSPRINGBALL4
+ {SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL}, // S_REDSPRINGBALL5
- // Big Mace
- {SPR_BMCE, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACE}, // S_BIGMACE
+ // Small Firebar
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR2}, // S_SMALLFIREBAR1
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_SMALLFIREBAR3}, // S_SMALLFIREBAR2
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR4}, // S_SMALLFIREBAR3
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_SMALLFIREBAR5}, // S_SMALLFIREBAR4
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR6}, // S_SMALLFIREBAR5
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_SMALLFIREBAR7}, // S_SMALLFIREBAR6
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR8}, // S_SMALLFIREBAR7
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_SMALLFIREBAR9}, // S_SMALLFIREBAR8
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR10}, // S_SMALLFIREBAR9
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_SMALLFIREBAR11}, // S_SMALLFIREBAR10
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR12}, // S_SMALLFIREBAR11
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_SMALLFIREBAR13}, // S_SMALLFIREBAR12
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR14}, // S_SMALLFIREBAR13
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_SMALLFIREBAR15}, // S_SMALLFIREBAR14
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR16}, // S_SMALLFIREBAR15
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_SMALLFIREBAR1}, // S_SMALLFIREBAR16
+
+ // Big Firebar
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR2}, // S_BIGFIREBAR1
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_BIGFIREBAR3}, // S_BIGFIREBAR2
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR4}, // S_BIGFIREBAR3
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_BIGFIREBAR5}, // S_BIGFIREBAR4
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR6}, // S_BIGFIREBAR5
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_BIGFIREBAR7}, // S_BIGFIREBAR6
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR8}, // S_BIGFIREBAR7
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_BIGFIREBAR9}, // S_BIGFIREBAR8
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR10}, // S_BIGFIREBAR9
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_BIGFIREBAR11}, // S_BIGFIREBAR10
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR12}, // S_BIGFIREBAR11
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_BIGFIREBAR13}, // S_BIGFIREBAR12
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR14}, // S_BIGFIREBAR13
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_BIGFIREBAR15}, // S_BIGFIREBAR14
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR16}, // S_BIGFIREBAR15
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16
// CEZ Flower
{SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER1
// Big Tumbleweed
- {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
- {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
- {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2
- {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3
- {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4
- {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5
- {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6
- {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7
- {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
+ {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
+ {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
+ {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2
+ {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3
+ {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4
+ {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5
+ {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6
+ {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7
+ {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
// Little Tumbleweed
{SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED
@@ -2870,16 +2944,11 @@ state_t states[NUMSTATES] =
{SPR_NWNG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING_XMAS
// NiGHTS Paraloop Powerups
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP1
- {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP2
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP3
- {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP4
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP5
- {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP6
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP7
- {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP8
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP9
- {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP10
+ {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSUPERLOOP
+ {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSDRILLREFILL
+ {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSHELPER
+ {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSEXTRATIME
+ {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSLINKFREEZE
{SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGCAPSULE
@@ -5162,9 +5231,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_EMMY
+ { // MT_TOKEN
312, // doomednum
- S_EMMY, // spawnstate
+ S_TOKEN, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@@ -5189,33 +5258,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_TOKEN
- -1, // doomednum
- S_TOKEN, // spawnstate
- 1000, // spawnhealth
- S_MOVINGTOKEN, // seestate
- sfx_None, // seesound
- 8, // reactiontime
- sfx_None, // attacksound
- S_NULL, // painstate
- 0, // painchance
- sfx_None, // painsound
- S_NULL, // meleestate
- S_NULL, // missilestate
- S_NULL, // deathstate
- S_NULL, // xdeathstate
- sfx_None, // deathsound
- 8, // speed
- 8*FRACUNIT, // radius
- 16*FRACUNIT, // height
- 0, // display offset
- 100, // mass
- 0, // damage
- sfx_None, // activesound
- MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP, // flags
- S_NULL // raisestate
- },
-
{ // MT_REDFLAG
310, // doomednum
S_REDFLAG, // spawnstate
@@ -5993,6 +6035,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_WALLSPIKE
+ 522, // doomednum
+ S_WALLSPIKE1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_s3k64, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_WALLSPIKED1, // deathstate
+ S_WALLSPIKED2, // xdeathstate
+ sfx_mspogo, // deathsound
+ 2*TICRATE, // speed
+ 16*FRACUNIT, // radius
+ 14*FRACUNIT, // height
+ 0, // display offset
+ 4, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_WALLSPIKEBASE
+ -1, // doomednum
+ S_WALLSPIKEBASE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 7*FRACUNIT, // radius
+ 14*FRACUNIT, // height
+ 0, // display offset
+ 4, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_STARPOST
502, // doomednum
S_STARPOST_IDLE, // spawnstate
@@ -8045,6 +8141,276 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_GFZTREE
+ 806, // doomednum
+ S_GFZTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 128*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_SOLID|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_GFZBERRYTREE
+ 807, // doomednum
+ S_GFZBERRYTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 128*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_SOLID|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_GFZCHERRYTREE
+ 808, // doomednum
+ S_GFZCHERRYTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 128*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_SOLID|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_CHECKERTREE
+ 810, // doomednum
+ S_CHECKERTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_CHECKERSUNSETTREE
+ 811, // doomednum
+ S_CHECKERSUNSETTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_FHZTREE
+ 812, // doomednum
+ S_FHZTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_FHZPINKTREE
+ 813, // doomednum
+ S_FHZPINKTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_POLYGONTREE
+ 814, // doomednum
+ S_POLYGONTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_BUSHTREE
+ 815, // doomednum
+ S_BUSHTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_BUSHREDTREE
+ 816, // doomednum
+ S_BUSHREDTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_THZFLOWER1
900, // doomednum
S_THZFLOWERA, // spawnstate
@@ -8504,7 +8870,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_SWINGMACEPOINT
+ { // MT_CHAINMACEPOINT
1105, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8531,7 +8897,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_HANGMACEPOINT
+ { // MT_SPRINGBALLPOINT
1106, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8558,7 +8924,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_SPINMACEPOINT
+ { // MT_CHAINPOINT
1107, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8578,7 +8944,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
128*FRACUNIT, // radius
1*FRACUNIT, // height
0, // display offset
- 200, // mass
+ 10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
@@ -8612,6 +8978,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_FIREBARPOINT
+ 1109, // doomednum
+ S_INVISIBLE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 0, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 10*FRACUNIT, // speed
+ 128*FRACUNIT, // radius
+ 1*FRACUNIT, // height
+ 0, // display offset
+ 200, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_CUSTOMMACEPOINT
+ 1111, // doomednum
+ S_INVISIBLE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 0, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 10*FRACUNIT, // speed
+ 128*FRACUNIT, // radius
+ 1*FRACUNIT, // height
+ 0, // display offset
+ 200, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_SMALLMACECHAIN
-1, // doomednum
S_SMALLMACECHAIN, // spawnstate
@@ -8635,7 +9055,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
- MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -8662,7 +9082,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
- MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -8685,11 +9105,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // speed
17*FRACUNIT, // radius
34*FRACUNIT, // height
- 0, // display offset
+ 1, // display offset
100, // mass
1, // damage
sfx_mswing, // activesound
- MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -8712,11 +9132,119 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
48*FRACUNIT, // speed
34*FRACUNIT, // radius
68*FRACUNIT, // height
- 0, // display offset
+ 1, // display offset
100, // mass
1, // damage
sfx_mswing, // activesound
- MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_YELLOWSPRINGBALL
+ -1, // doomednum
+ S_YELLOWSPRINGBALL, // spawnstate
+ 1000, // spawnhealth
+ S_YELLOWSPRINGBALL2, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_spring, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 24*FRACUNIT, // speed
+ 17*FRACUNIT, // radius
+ 34*FRACUNIT, // height
+ 1, // display offset
+ 20*FRACUNIT, // mass
+ 0, // damage
+ sfx_mswing, // activesound
+ MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags
+ S_YELLOWSPRINGBALL2 // raisestate
+ },
+
+ { // MT_REDSPRINGBALL
+ -1, // doomednum
+ S_REDSPRINGBALL, // spawnstate
+ 1000, // spawnhealth
+ S_REDSPRINGBALL2, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_spring, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 24*FRACUNIT, // speed
+ 17*FRACUNIT, // radius
+ 34*FRACUNIT, // height
+ 1, // display offset
+ 32*FRACUNIT, // mass
+ 0, // damage
+ sfx_mswing, // activesound
+ MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags
+ S_REDSPRINGBALL2 // raisestate
+ },
+
+ { // MT_SMALLFIREBAR
+ -1, // doomednum
+ S_SMALLFIREBAR1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ MT_FLAMEPARTICLE, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 24*FRACUNIT, // speed
+ 17*FRACUNIT, // radius
+ 34*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_BIGFIREBAR
+ -1, // doomednum
+ S_BIGFIREBAR1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ MT_FLAMEPARTICLE, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 48*FRACUNIT, // speed
+ 34*FRACUNIT, // radius
+ 68*FRACUNIT, // height
+ 1, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -13973,9 +14501,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSSUPERLOOP
1707, // doomednum
- S_NIGHTSPOWERUP1, // spawnstate
+ S_NIGHTSSUPERLOOP, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP2, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -14000,9 +14528,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSDRILLREFILL
1708, // doomednum
- S_NIGHTSPOWERUP3, // spawnstate
+ S_NIGHTSDRILLREFILL, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP4, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -14027,9 +14555,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSHELPER
1709, // doomednum
- S_NIGHTSPOWERUP5, // spawnstate
+ S_NIGHTSHELPER, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP6, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -14054,9 +14582,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSEXTRATIME
1711, // doomednum
- S_NIGHTSPOWERUP7, // spawnstate
+ S_NIGHTSEXTRATIME, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP8, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -14081,9 +14609,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSLINKFREEZE
1712, // doomednum
- S_NIGHTSPOWERUP9, // spawnstate
+ S_NIGHTSLINKFREEZE, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP10, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
diff --git a/src/info.h b/src/info.h
index 75484081e..63a4d893f 100644
--- a/src/info.h
+++ b/src/info.h
@@ -84,7 +84,6 @@ void A_DetonChase(); // Deton Chaser
void A_CapeChase(); // Fake little Super Sonic cape
void A_RotateSpikeBall(); // Spike ball rotation
void A_SlingAppear();
-void A_MaceRotate();
void A_UnidusBall();
void A_RockSpawn();
void A_SetFuse();
@@ -320,7 +319,6 @@ typedef enum sprite
// Collectible Items
SPR_RING,
SPR_TRNG, // Team Rings
- SPR_EMMY, // emerald test
SPR_TOKE, // Special Stage Token
SPR_RFLG, // Red CTF Flag
SPR_BFLG, // Blue CTF Flag
@@ -337,6 +335,8 @@ typedef enum sprite
SPR_SPIK, // Spike Ball
SPR_SFLM, // Spin fire
SPR_USPK, // Floor spike
+ SPR_WSPK, // Wall spike
+ SPR_WSPB, // Wall spike base
SPR_STPT, // Starpost
SPR_BMNE, // Big floating mine
@@ -387,6 +387,12 @@ typedef enum sprite
SPR_FWR4,
SPR_BUS1, // GFZ Bush w/ berries
SPR_BUS2, // GFZ Bush w/o berries
+ // Trees (both GFZ and misc)
+ SPR_TRE1, // GFZ
+ SPR_TRE2, // Checker
+ SPR_TRE3, // Frozen Hillside
+ SPR_TRE4, // Polygon
+ SPR_TRE5, // Bush tree
// Techno Hill Scenery
SPR_THZP, // THZ1 Flower
@@ -410,6 +416,10 @@ typedef enum sprite
SPR_BMCH, // Big Mace Chain
SPR_SMCE, // Small Mace
SPR_BMCE, // Big Mace
+ SPR_YSPB, // Yellow spring on a ball
+ SPR_RSPB, // Red spring on a ball
+ SPR_SFBR, // Small Firebar
+ SPR_BFBR, // Big Firebar
// Arid Canyon Scenery
SPR_BTBL, // Big tumbleweed
@@ -1617,12 +1627,8 @@ typedef enum state
// Individual Team Rings
S_TEAMRING,
- // Special Stage Token
- S_EMMY,
-
// Special Stage Token
S_TOKEN,
- S_MOVINGTOKEN,
// CTF Flags
S_REDFLAG,
@@ -1773,6 +1779,17 @@ typedef enum state
S_SPIKED1,
S_SPIKED2,
+ // Wall spikes
+ S_WALLSPIKE1,
+ S_WALLSPIKE2,
+ S_WALLSPIKE3,
+ S_WALLSPIKE4,
+ S_WALLSPIKE5,
+ S_WALLSPIKE6,
+ S_WALLSPIKEBASE,
+ S_WALLSPIKED1,
+ S_WALLSPIKED2,
+
// Starpost
S_STARPOST_IDLE,
S_STARPOST_FLASH,
@@ -1961,6 +1978,7 @@ typedef enum state
S_DEMONFIRE5,
S_DEMONFIRE6,
+ // GFZ flowers
S_GFZFLOWERA,
S_GFZFLOWERB,
S_GFZFLOWERC,
@@ -1968,6 +1986,18 @@ typedef enum state
S_BERRYBUSH,
S_BUSH,
+ // Trees (both GFZ and misc)
+ S_GFZTREE,
+ S_GFZBERRYTREE,
+ S_GFZCHERRYTREE,
+ S_CHECKERTREE,
+ S_CHECKERSUNSETTREE,
+ S_FHZTREE, // Frozen Hillside
+ S_FHZPINKTREE,
+ S_POLYGONTREE,
+ S_BUSHTREE,
+ S_BUSHREDTREE,
+
// THZ Plant
S_THZFLOWERA,
S_THZFLOWERB,
@@ -2029,18 +2059,62 @@ typedef enum state
S_SLING1,
S_SLING2,
- // CEZ Small Mace Chain
+ // CEZ maces and chains
S_SMALLMACECHAIN,
-
- // CEZ Big Mace Chain
S_BIGMACECHAIN,
-
- // CEZ Small Mace
S_SMALLMACE,
-
- // CEZ Big Mace
S_BIGMACE,
+ // Yellow spring on a ball
+ S_YELLOWSPRINGBALL,
+ S_YELLOWSPRINGBALL2,
+ S_YELLOWSPRINGBALL3,
+ S_YELLOWSPRINGBALL4,
+ S_YELLOWSPRINGBALL5,
+
+ // Red spring on a ball
+ S_REDSPRINGBALL,
+ S_REDSPRINGBALL2,
+ S_REDSPRINGBALL3,
+ S_REDSPRINGBALL4,
+ S_REDSPRINGBALL5,
+
+ // Small Firebar
+ S_SMALLFIREBAR1,
+ S_SMALLFIREBAR2,
+ S_SMALLFIREBAR3,
+ S_SMALLFIREBAR4,
+ S_SMALLFIREBAR5,
+ S_SMALLFIREBAR6,
+ S_SMALLFIREBAR7,
+ S_SMALLFIREBAR8,
+ S_SMALLFIREBAR9,
+ S_SMALLFIREBAR10,
+ S_SMALLFIREBAR11,
+ S_SMALLFIREBAR12,
+ S_SMALLFIREBAR13,
+ S_SMALLFIREBAR14,
+ S_SMALLFIREBAR15,
+ S_SMALLFIREBAR16,
+
+ // Big Firebar
+ S_BIGFIREBAR1,
+ S_BIGFIREBAR2,
+ S_BIGFIREBAR3,
+ S_BIGFIREBAR4,
+ S_BIGFIREBAR5,
+ S_BIGFIREBAR6,
+ S_BIGFIREBAR7,
+ S_BIGFIREBAR8,
+ S_BIGFIREBAR9,
+ S_BIGFIREBAR10,
+ S_BIGFIREBAR11,
+ S_BIGFIREBAR12,
+ S_BIGFIREBAR13,
+ S_BIGFIREBAR14,
+ S_BIGFIREBAR15,
+ S_BIGFIREBAR16,
+
S_CEZFLOWER1,
// Big Tumbleweed
@@ -3014,16 +3088,11 @@ typedef enum state
S_NIGHTSWING_XMAS,
// NiGHTS Paraloop Powerups
- S_NIGHTSPOWERUP1,
- S_NIGHTSPOWERUP2,
- S_NIGHTSPOWERUP3,
- S_NIGHTSPOWERUP4,
- S_NIGHTSPOWERUP5,
- S_NIGHTSPOWERUP6,
- S_NIGHTSPOWERUP7,
- S_NIGHTSPOWERUP8,
- S_NIGHTSPOWERUP9,
- S_NIGHTSPOWERUP10,
+ S_NIGHTSSUPERLOOP,
+ S_NIGHTSDRILLREFILL,
+ S_NIGHTSHELPER,
+ S_NIGHTSEXTRATIME,
+ S_NIGHTSLINKFREEZE,
S_EGGCAPSULE,
// Orbiting Chaos Emeralds
@@ -3239,8 +3308,7 @@ typedef enum mobj_type
MT_BLUEBALL, // Blue sphere replacement for special stages
MT_REDTEAMRING, //Rings collectable by red team.
MT_BLUETEAMRING, //Rings collectable by blue team.
- MT_EMMY, // emerald token for special stage
- MT_TOKEN, // Special Stage Token (uncollectible part)
+ MT_TOKEN, // Special Stage token for special stage
MT_REDFLAG, // Red CTF Flag
MT_BLUEFLAG, // Blue CTF Flag
MT_EMBLEM,
@@ -3274,6 +3342,8 @@ typedef enum mobj_type
MT_SPECIALSPIKEBALL,
MT_SPINFIRE,
MT_SPIKE,
+ MT_WALLSPIKE,
+ MT_WALLSPIKEBASE,
MT_STARPOST,
MT_BIGMINE,
MT_BIGAIRMINE,
@@ -3364,6 +3434,17 @@ typedef enum mobj_type
MT_GFZFLOWER3,
MT_BERRYBUSH,
MT_BUSH,
+ // Trees (both GFZ and misc)
+ MT_GFZTREE,
+ MT_GFZBERRYTREE,
+ MT_GFZCHERRYTREE,
+ MT_CHECKERTREE,
+ MT_CHECKERSUNSETTREE,
+ MT_FHZTREE, // Frozen Hillside
+ MT_FHZPINKTREE,
+ MT_POLYGONTREE,
+ MT_BUSHTREE,
+ MT_BUSHREDTREE,
// Techno Hill Scenery
MT_THZFLOWER1,
@@ -3387,14 +3468,20 @@ typedef enum mobj_type
MT_FLAMEPARTICLE,
MT_EGGSTATUE, // Eggman Statue
MT_MACEPOINT, // Mace rotation point
- MT_SWINGMACEPOINT, // Mace swinging point
- MT_HANGMACEPOINT, // Hangable mace chain
- MT_SPINMACEPOINT, // Spin/Controllable mace chain
+ MT_CHAINMACEPOINT, // Combination of chains and maces point
+ MT_SPRINGBALLPOINT, // Spring ball point
+ MT_CHAINPOINT, // Mace chain
MT_HIDDEN_SLING, // Spin mace chain (activatable)
+ MT_FIREBARPOINT, // Firebar
+ MT_CUSTOMMACEPOINT, // Custom mace
MT_SMALLMACECHAIN, // Small Mace Chain
MT_BIGMACECHAIN, // Big Mace Chain
MT_SMALLMACE, // Small Mace
MT_BIGMACE, // Big Mace
+ MT_YELLOWSPRINGBALL, // Yellow spring on a ball
+ MT_REDSPRINGBALL, // Red spring on a ball
+ MT_SMALLFIREBAR, // Small Firebar
+ MT_BIGFIREBAR, // Big Firebar
MT_CEZFLOWER,
// Arid Canyon Scenery
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index 322fecb64..b688155fb 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -22,8 +22,13 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
+// for functions not allowed in hud.add hooks
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
+// for functions not allowed in hooks or coroutines (supercedes above)
+#define NOHOOK if (!lua_lumploading)\
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
+// for functions only allowed within a level
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
@@ -184,7 +189,7 @@ static int lib_comAddCommand(lua_State *L)
strlwr(name);
luaL_checktype(L, 2, LUA_TFUNCTION);
- NOHUD
+ NOHOOK
if (lua_gettop(L) >= 3)
{ // For the third argument, only take a boolean or a number.
lua_settop(L, 3);
@@ -296,7 +301,7 @@ static int lib_cvRegisterVar(lua_State *L)
consvar_t *cvar;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
- NOHUD
+ NOHOOK
cvar = lua_newuserdata(L, sizeof(consvar_t));
luaL_getmetatable(L, META_CVAR);
lua_setmetatable(L, -2);
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 88867db2b..fe5706f56 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -46,6 +46,7 @@ enum hook {
hook_ShieldSpawn,
hook_ShieldSpecial,
hook_MobjMoveBlocked,
+ hook_MapThingSpawn,
hook_MAX // last hook
};
@@ -83,5 +84,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked)
+boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
#endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index dadc1861a..3dd3f932f 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -57,6 +57,7 @@ const char *const hookNames[hook_MAX+1] = {
"ShieldSpawn",
"ShieldSpecial",
"MobjMoveBlocked",
+ "MapThingSpawn",
NULL
};
@@ -108,8 +109,8 @@ static int lib_addHook(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION);
- if (hud_running)
- return luaL_error(L, "HUD rendering code should not call this function!");
+ if (!lua_lumploading)
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
switch(hook.type)
{
@@ -128,6 +129,7 @@ static int lib_addHook(lua_State *L)
case hook_MobjRemoved:
case hook_HurtMsg:
case hook_MobjMoveBlocked:
+ case hook_MapThingSpawn:
hook.s.mt = MT_NULL;
if (lua_isnumber(L, 2))
hook.s.mt = lua_tonumber(L, 2);
@@ -187,6 +189,7 @@ static int lib_addHook(lua_State *L)
case hook_BossDeath:
case hook_MobjRemoved:
case hook_MobjMoveBlocked:
+ case hook_MapThingSpawn:
lastp = &mobjhooks[hook.s.mt];
break;
case hook_JumpSpecial:
@@ -1073,4 +1076,66 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc)
// stack: tables
}
+boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
+{
+ hook_p hookp;
+ boolean hooked = false;
+ if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8))))
+ return false;
+
+ lua_settop(gL, 0);
+
+ // Look for all generic mobj map thing spawn hooks
+ for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+ if (hookp->type == hook_MapThingSpawn)
+ {
+ if (lua_gettop(gL) == 0)
+ {
+ LUA_PushUserdata(gL, mo, META_MOBJ);
+ LUA_PushUserdata(gL, mthing, META_MAPTHING);
+ }
+ 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_toboolean(gL, -1))
+ hooked = true;
+ lua_pop(gL, 1);
+ }
+
+ for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next)
+ if (hookp->type == hook_MapThingSpawn)
+ {
+ if (lua_gettop(gL) == 0)
+ {
+ LUA_PushUserdata(gL, mo, META_MOBJ);
+ LUA_PushUserdata(gL, mthing, META_MAPTHING);
+ }
+ 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_toboolean(gL, -1))
+ hooked = true;
+ lua_pop(gL, 1);
+ }
+
+ lua_settop(gL, 0);
+ return hooked;
+}
+
#endif
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 5b3cd46ce..29e4970c1 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -612,6 +612,9 @@ static int lib_hudadd(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION);
field = luaL_checkoption(L, 2, "game", hudhook_opt);
+ if (!lua_lumploading)
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
+
lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(L, -1));
lua_rawgeti(L, -1, field+2); // HUD[2+]
diff --git a/src/lua_script.c b/src/lua_script.c
index d30790be1..994f81a40 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -161,6 +161,11 @@ void LUA_ClearExtVars(void)
}
#endif
+// Use this variable to prevent certain functions from running
+// if they were not called on lump load
+// (i.e. they were called in hooks or coroutines etc)
+boolean lua_lumploading = false;
+
// Load a script from a MYFILE
static inline void LUA_LoadFile(MYFILE *f, char *name)
{
@@ -198,7 +203,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
name[strlen(wadfiles[wad]->filename)+9] = '\0';
}
- LUA_LoadFile(&f, name);
+ lua_lumploading = true; // turn on loading flag
+ LUA_LoadFile(&f, name); // actually load file!
+ lua_lumploading = false; // turn off again
free(name);
Z_Free(f.data);
@@ -596,14 +603,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
{
mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex));
WRITEUINT8(save_p, ARCH_MOBJINFO);
- WRITEUINT8(save_p, info - mobjinfo);
+ WRITEUINT16(save_p, info - mobjinfo);
break;
}
case ARCH_STATE:
{
state_t *state = *((state_t **)lua_touserdata(gL, myindex));
WRITEUINT8(save_p, ARCH_STATE);
- WRITEUINT8(save_p, state - states);
+ WRITEUINT16(save_p, state - states);
break;
}
case ARCH_MOBJ:
diff --git a/src/lua_script.h b/src/lua_script.h
index d143ed879..51f1eaeaa 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -38,6 +38,8 @@
void LUA_ClearExtVars(void);
#endif
+extern boolean lua_lumploading; // is LUA_LoadLump being called?
+
void LUA_LoadLump(UINT16 wad, UINT16 lump);
#ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename);
diff --git a/src/m_cond.h b/src/m_cond.h
index 94802f665..00f633a8d 100644
--- a/src/m_cond.h
+++ b/src/m_cond.h
@@ -66,14 +66,18 @@ typedef struct
} conditionset_t;
// Emblem information
-#define ET_GLOBAL 0 // Global map emblem, var == color
-#define ET_SKIN 1 // Skin specific emblem, var == skin
-#define ET_SCORE 2
-#define ET_TIME 3
-#define ET_RINGS 4
-#define ET_NGRADE 5
-#define ET_NTIME 6
-#define ET_MAP 7
+#define ET_GLOBAL 0 // Emblem with a position in space
+#define ET_SKIN 1 // Skin specific emblem with a position in space, var == skin
+#define ET_MAP 2 // Beat the map
+#define ET_SCORE 3 // Get the score
+#define ET_TIME 4 // Get the time
+#define ET_RINGS 5 // Get the rings
+#define ET_NGRADE 6 // Get the grade
+#define ET_NTIME 7 // Get the time (NiGHTS mode)
+
+// Global emblem flags
+#define GE_NIGHTSPULL 1 // sun off the nights track - loop it
+#define GE_NIGHTSITEM 2 // moon on the nights track - find it
// Map emblem flags
#define ME_ALLEMERALDS 1
diff --git a/src/m_menu.c b/src/m_menu.c
index b7f9e8802..dc74ae5d2 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -33,6 +33,9 @@
#include "s_sound.h"
#include "i_system.h"
+// Addfile
+#include "filesrch.h"
+
#include "v_video.h"
#include "i_video.h"
#include "keys.h"
@@ -74,7 +77,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#define SMALLLINEHEIGHT 8
#define SLIDER_RANGE 9
#define SLIDER_WIDTH 78
-#define MAXSTRINGLENGTH 32
#define SERVERS_PER_PAGE 11
typedef enum
@@ -211,14 +213,13 @@ menu_t SPauseDef;
// Level Select
static levelselect_t levelselect = {0, NULL};
-static UINT8 levelselectselect[4];
+static UINT8 levelselectselect[3];
static patch_t *levselp[2][3];
static INT32 lsoffs[2];
#define lsrow levelselectselect[0]
#define lscol levelselectselect[1]
-#define lstic levelselectselect[2]
-#define lshli levelselectselect[3]
+#define lshli levelselectselect[2]
#define lshseperation 101
#define lsbasevseperation 62
@@ -334,12 +335,20 @@ menu_t OP_MonitorToggleDef;
static void M_ScreenshotOptions(INT32 choice);
static void M_EraseData(INT32 choice);
-static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight);
+static void M_Addons(INT32 choice);
+static void M_AddonsOptions(INT32 choice);
+static patch_t *addonsp[NUM_EXT+6];
+static UINT8 addonsresponselimit = 0;
+
+#define numaddonsshown 4
+
+static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase);
// Drawing functions
static void M_DrawGenericMenu(void);
static void M_DrawGenericScrollMenu(void);
static void M_DrawCenteredMenu(void);
+static void M_DrawAddons(void);
static void M_DrawSkyRoom(void);
static void M_DrawChecklist(void);
static void M_DrawEmblemHints(void);
@@ -379,6 +388,7 @@ static boolean M_CancelConnect(void);
#endif
static boolean M_ExitPandorasBox(void);
static boolean M_QuitMultiPlayerMenu(void);
+static void M_HandleAddons(INT32 choice);
static void M_HandleLevelPlatter(INT32 choice);
static void M_HandleSoundTest(INT32 choice);
static void M_HandleImageDef(INT32 choice);
@@ -487,10 +497,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum
// ---------
static menuitem_t MainMenu[] =
{
- {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84},
- {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92},
- {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100},
- {IT_CALL |IT_STRING, NULL, "options", M_Options, 108},
+ {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76},
+ {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84},
+ {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92},
+ {IT_CALL |IT_STRING, NULL, "options", M_Options, 100},
+ {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108},
{IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116},
};
@@ -500,9 +511,15 @@ typedef enum
singleplr,
multiplr,
options,
+ addons,
quitdoom
} main_e;
+static menuitem_t MISC_AddonsMenu[] =
+{
+ {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func
+};
+
// ---------------------------------
// Pause Menu Mode Attacking Edition
// ---------------------------------
@@ -525,26 +542,28 @@ typedef enum
// ---------------------
static menuitem_t MPauseMenu[] =
{
- {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
- {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24},
+ {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8},
+ {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
+ {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24},
- {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40},
- {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen
- {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen
+ {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40},
+ {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen
+ {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen
{IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48},
{IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48},
{IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48},
- {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone
- {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64},
+ {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone
+ {IT_STRING | IT_CALL, NULL, "Options", M_Options, 64},
- {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80},
- {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88},
+ {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 80},
+ {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 88},
};
typedef enum
{
- mpause_scramble = 0,
+ mpause_addons = 0,
+ mpause_scramble,
mpause_switchmap,
mpause_continue,
@@ -587,6 +606,7 @@ typedef enum
spause_continue,
spause_retry,
spause_options,
+
spause_title,
spause_quit
} spause_e;
@@ -1318,9 +1338,10 @@ static menuitem_t OP_SoundOptionsMenu[] =
static menuitem_t OP_DataOptionsMenu[] =
{
- {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10},
+ {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 10},
+ {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 20},
- {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 20},
+ {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 40},
};
static menuitem_t OP_ScreenshotOptionsMenu[] =
@@ -1367,6 +1388,24 @@ static menuitem_t OP_EraseDataMenu[] =
{IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40},
};
+static menuitem_t OP_AddonsOptionsMenu[] =
+{
+ {IT_HEADER, NULL, "Menu", NULL, 0},
+ {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 12},
+ {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 22},
+ {IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 50},
+ {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 60},
+
+ {IT_HEADER, NULL, "Search", NULL, 78},
+ {IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 90},
+ {IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 100},
+};
+
+enum
+{
+ op_addons_folder = 2,
+};
+
static menuitem_t OP_ServerOptionsMenu[] =
{
{IT_HEADER, NULL, "General", NULL, 0},
@@ -1441,6 +1480,18 @@ static menuitem_t OP_MonitorToggleMenu[] =
// Main Menu and related
menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72);
+menu_t MISC_AddonsDef =
+{
+ NULL,
+ sizeof (MISC_AddonsMenu)/sizeof (menuitem_t),
+ &MainDef,
+ MISC_AddonsMenu,
+ M_DrawAddons,
+ 50, 28,
+ 0,
+ NULL
+};
+
menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72);
menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72);
menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72);
@@ -1804,17 +1855,7 @@ menu_t OP_SoundOptionsDef =
NULL
};
-menu_t OP_ServerOptionsDef =
-{
- "M_SERVER",
- sizeof (OP_ServerOptionsMenu)/sizeof (menuitem_t),
- &OP_MainDef,
- OP_ServerOptionsMenu,
- M_DrawGenericScrollMenu,
- 30, 30,
- 0,
- NULL
-};
+menu_t OP_ServerOptionsDef = DEFAULTSCROLLMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 30, 30);
menu_t OP_MonitorToggleDef =
{
@@ -1856,7 +1897,7 @@ menu_t OP_OpenGLColorDef =
NULL
};
#endif
-menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 30, 30);
+menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30);
menu_t OP_ScreenshotOptionsDef =
{
@@ -1870,6 +1911,8 @@ menu_t OP_ScreenshotOptionsDef =
NULL
};
+menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30);
+
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30);
// ==========================================================================
@@ -2088,6 +2131,12 @@ void Moviemode_mode_Onchange(void)
OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR;
}
+void Addons_option_Onchange(void)
+{
+ OP_AddonsOptionsMenu[op_addons_folder].status =
+ (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED);
+}
+
// ==========================================================================
// END ORGANIZATION STUFF.
// ==========================================================================
@@ -2150,9 +2199,12 @@ static void M_ChangeCvar(INT32 choice)
static boolean M_ChangeStringCvar(INT32 choice)
{
consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction;
- char buf[255];
+ char buf[MAXSTRINGLENGTH];
size_t len;
+ if (shiftdown && choice >= 32 && choice <= 127)
+ choice = shiftxform[choice];
+
switch (choice)
{
case KEY_BACKSPACE:
@@ -2463,8 +2515,6 @@ boolean M_Responder(event_t *ev)
{
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
{
- if (shiftdown && ch >= 32 && ch <= 127)
- ch = shiftxform[ch];
if (M_ChangeStringCvar(ch))
return true;
else
@@ -2710,6 +2760,7 @@ void M_StartControlPanel(void)
else // multiplayer
{
MPauseMenu[mpause_switchmap].status = IT_DISABLED;
+ MPauseMenu[mpause_addons].status = IT_DISABLED;
MPauseMenu[mpause_scramble].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED;
@@ -2721,6 +2772,7 @@ void M_StartControlPanel(void)
if ((server || adminplayer == consoleplayer))
{
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
+ MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL;
if (G_GametypeHasTeams())
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
}
@@ -3262,7 +3314,7 @@ static void M_DrawGenericMenu(void)
y = currentMenu->y+currentMenu->menuitems[i].alphaKey;
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
- M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true);
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false);
y += SMALLLINEHEIGHT;
break;
}
@@ -3402,7 +3454,7 @@ static void M_DrawGenericScrollMenu(void)
break;
case IT_HEADERTEXT:
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
- M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true);
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false);
break;
}
}
@@ -3912,7 +3964,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt)
I_Error("Insufficient memory to prepare level platter");
// done here so lsrow and lscol can be set if cv_nextmap is on the platter
- lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0;
+ lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0;
while (mapnum < NUMMAPS)
{
@@ -4171,10 +4223,10 @@ static void M_HandleLevelPlatter(INT32 choice)
}
}
-void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight)
+void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase)
{
y += lsheadingheight - 12;
- V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), header);
+ V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0)|(allowlowercase ? V_ALLOWLOWERCASE : 0), header);
y += 9;
if ((y >= 0) && (y < 200))
{
@@ -4183,9 +4235,7 @@ void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlig
}
y++;
if ((y >= 0) && (y < 200))
- {
V_DrawFill(19, y, 282, 1, 26);
- }
}
static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight)
@@ -4279,7 +4329,7 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y)
const boolean rowhighlight = (row == lsrow);
if (levelselect.rows[row].header[0])
{
- M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli)));
+ M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli)), false);
y += lsheadingheight;
}
@@ -4298,9 +4348,6 @@ static void M_DrawLevelPlatterMenu(void)
INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow);
const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation));
- if (++lstic == 32)
- lstic = 0;
-
if (gamestate == GS_TIMEATTACK)
V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
@@ -4320,7 +4367,7 @@ static void M_DrawLevelPlatterMenu(void)
}
// draw cursor box
- V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, ((lstic & 8) ? levselp[sizeselect][0] : levselp[sizeselect][1]));
+ V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, (levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)]));
if (levelselect.rows[lsrow].maplist[lscol])
V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE));
@@ -4620,6 +4667,511 @@ static void M_HandleImageDef(INT32 choice)
// MISC MAIN MENU OPTIONS
// ======================
+static void M_AddonsOptions(INT32 choice)
+{
+ (void)choice;
+ Addons_option_Onchange();
+
+ M_SetupNextMenu(&OP_AddonsOptionsDef);
+}
+
+#define LOCATIONSTRING "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!"
+
+static void M_Addons(INT32 choice)
+{
+ const char *pathname = ".";
+
+ (void)choice;
+
+ /*if (cv_addons_option.value == 0)
+ pathname = srb2home; usehome ? srb2home : srb2path;
+ else if (cv_addons_option.value == 1)
+ pathname = srb2home;
+ else if (cv_addons_option.value == 2)
+ pathname = srb2path;
+ else*/
+ if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
+ pathname = cv_addons_folder.string;
+
+ strlcpy(menupath, pathname, 1024);
+ menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
+
+ if (menupath[menupathindex[menudepthleft]-2] != '/')
+ {
+ menupath[menupathindex[menudepthleft]-1] = '/';
+ menupath[menupathindex[menudepthleft]] = 0;
+ }
+ else
+ --menupathindex[menudepthleft];
+
+ if (!preparefilemenu(false))
+ {
+ M_StartMessage(M_GetText("No files/folders found.\n\n"LOCATIONSTRING"\n\n(Press a key)\n"),NULL,MM_NOTHING);
+ return;
+ }
+ else
+ dir_on[menudepthleft] = 0;
+
+ if (addonsp[0]) // never going to have some provided but not all, saves individually checking
+ {
+ size_t i;
+ for (i = 0; i < NUM_EXT+6; i++)
+ W_UnlockCachedPatch(addonsp[i]);
+ }
+
+ addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC);
+ addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC);
+ addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC);
+ addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC);
+ addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC);
+ addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC);
+ addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC);
+ addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC);
+ addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC);
+ addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL1", PU_STATIC);
+ addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC);
+ addonsp[NUM_EXT+3] = W_CachePatchName("M_FLOAD", PU_STATIC);
+ addonsp[NUM_EXT+4] = W_CachePatchName("M_FSRCH", PU_STATIC);
+ addonsp[NUM_EXT+5] = W_CachePatchName("M_FSAVE", PU_STATIC);
+
+ MISC_AddonsDef.prevMenu = currentMenu;
+ M_SetupNextMenu(&MISC_AddonsDef);
+}
+
+#define width 4
+#define vpadding 27
+#define h (BASEVIDHEIGHT-(2*vpadding))
+#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker
+static void M_DrawTemperature(INT32 x, fixed_t t)
+{
+ INT32 y;
+
+ // bounds check
+ if (t > FRACUNIT)
+ t = FRACUNIT;
+ /*else if (t < 0) -- not needed
+ t = 0;*/
+
+ // scale
+ if (t > 1)
+ t = (FixedMul(h<>FRACBITS);
+
+ // border
+ V_DrawFill(x - 1, vpadding, 1, h, 3);
+ V_DrawFill(x + width, vpadding, 1, h, 3);
+ V_DrawFill(x - 1, vpadding-1, width+2, 1, 3);
+ V_DrawFill(x - 1, vpadding+h, width+2, 1, 3);
+
+ // bar itself
+ y = h;
+ if (t)
+ for (t = h - t; y > 0; y--)
+ {
+ UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98};
+ UINT8 c;
+ if (y <= t) break;
+ if (y+vpadding >= BASEVIDHEIGHT/2)
+ c = 113;
+ else
+ c = colours[(NUMCOLOURS*(y-1))/(h/2)];
+ V_DrawFill(x, y-1 + vpadding, width, 1, c);
+ }
+
+ // fill the rest of the backing
+ if (y)
+ V_DrawFill(x, vpadding, width, y, 27);
+}
+#undef width
+#undef vpadding
+#undef h
+#undef NUMCOLOURS
+
+static char *M_AddonsHeaderPath(void)
+{
+ UINT32 len;
+ static char header[1024];
+
+ if (menupath[0] == '.')
+ strlcpy(header, va("SRB2 folder%s", menupath+1), 1024);
+ else
+ strcpy(header, menupath);
+
+ len = strlen(header);
+ if (len > 34)
+ {
+ len = len-34;
+ header[len] = header[len+1] = header[len+2] = '.';
+ }
+ else
+ len = 0;
+
+ return header+len;
+}
+
+#define UNEXIST S_StartSound(NULL, sfx_lose);\
+ M_SetupNextMenu(MISC_AddonsDef.prevMenu);\
+ M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
+
+// returns whether to do message draw
+static boolean M_AddonsRefresh(void)
+{
+ if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true))
+ {
+ UNEXIST;
+ return true;
+ }
+
+ if (refreshdirmenu & REFRESHDIR_ADDFILE)
+ {
+ addonsresponselimit = 0;
+
+ if (refreshdirmenu & REFRESHDIR_NOTLOADED)
+ {
+ char *message = NULL;
+ S_StartSound(NULL, sfx_lose);
+ if (refreshdirmenu & REFRESHDIR_MAX)
+ message = va("\x82%s\x80\nMaximum number of add-ons reached.\nThis file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
+ else
+ message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
+ M_StartMessage(message,NULL,MM_NOTHING);
+ return true;
+ }
+
+ if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
+ {
+ S_StartSound(NULL, sfx_skid);
+ M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING);
+ return true;
+ }
+
+ S_StartSound(NULL, sfx_strpst);
+ }
+
+ return false;
+}
+
+#define offs 1
+
+static void M_DrawAddons(void)
+{
+ INT32 x, y;
+ ssize_t i, max;
+
+ // hack - need to refresh at end of frame to handle addfile...
+ if (refreshdirmenu & M_AddonsRefresh())
+ return M_DrawMessageMenu();
+
+ if (addonsresponselimit)
+ addonsresponselimit--;
+
+ V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, (Playing()
+ ? "\x85""Adding files mid-game may cause problems."
+ : LOCATIONSTRING));
+
+ if (numwadfiles <= mainwads+1)
+ y = 0;
+ else if (numwadfiles >= MAX_WADFILES)
+ y = FRACUNIT;
+ else
+ {
+ x = FixedDiv((numwadfiles - mainwads+1)< y)
+ y = x;
+ if (y > FRACUNIT) // happens because of how we're shrinkin' it a little
+ y = FRACUNIT;
+ }
+
+ M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y);
+
+ // DRAW MENU
+ x = currentMenu->x;
+ y = currentMenu->y + offs;
+
+ //M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width
+ V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), V_YELLOWMAP|V_ALLOWLOWERCASE, M_AddonsHeaderPath());
+ V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), (MAXSTRINGLENGTH*8+6 - 1), 1, yellowmap[3]);
+ V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 26);
+ V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 26);
+
+ V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1 + offs) - (y - 1), 159);
+
+ // get bottom...
+ max = dir_on[menudepthleft] + numaddonsshown + 1;
+ if (max > (ssize_t)sizedirmenu)
+ max = sizedirmenu;
+
+ // then top...
+ i = max - (2*numaddonsshown + 1);
+
+ // then adjust!
+ if (i < 0)
+ {
+ if ((max -= i) > (ssize_t)sizedirmenu)
+ max = sizedirmenu;
+ i = 0;
+ }
+
+ if (i != 0)
+ V_DrawString(19, y+4, V_YELLOWMAP, "\x1A");
+
+ for (; i < max; i++)
+ {
+ UINT32 flags = V_ALLOWLOWERCASE;
+ if (y > BASEVIDHEIGHT) break;
+ if (dirmenu[i])
+#define type (UINT8)(dirmenu[i][DIR_TYPE])
+ {
+ if (type & EXT_LOADED)
+ flags |= V_TRANSLUCENT;
+
+ V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]);
+
+ if (type & EXT_LOADED)
+ V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]);
+
+ if ((size_t)i == dir_on[menudepthleft])
+ {
+ V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+1+((skullAnimCounter/4) ? 1 : 0)]);
+ flags = V_ALLOWLOWERCASE|V_YELLOWMAP;
+ }
+
+#define charsonside 14
+ if (dirmenu[i][DIR_LEN] > (charsonside*2 + 3))
+ V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1)));
+#undef charsonside
+ else
+ V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING);
+ }
+#undef type
+ y += 16;
+ }
+
+ if (max != (ssize_t)sizedirmenu)
+ V_DrawString(19, y-12, V_YELLOWMAP, "\x1B");
+
+ y = BASEVIDHEIGHT - currentMenu->y + offs;
+
+ M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
+ if (menusearch[0])
+ V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1);
+ else
+ V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search...");
+ if (skullAnimCounter < 4)
+ V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8,
+ '_' | 0x80, false);
+
+ x -= (21 + 5 + 16);
+ V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
+
+#define CANSAVE (!modifiedgame || savemoddata)
+ x = BASEVIDWIDTH - x - 16;
+ V_DrawSmallScaledPatch(x, y + 4, (CANSAVE ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]);
+
+ if CANSAVE
+ V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]);
+#undef CANSAVE
+}
+
+#undef offs
+
+static void M_AddonExec(INT32 ch)
+{
+ if (ch != 'y' && ch != KEY_ENTER)
+ return;
+
+ S_StartSound(NULL, sfx_strpst);
+ COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
+}
+
+#define len menusearch[0]
+static boolean M_ChangeStringAddons(INT32 choice)
+{
+ if (shiftdown && choice >= 32 && choice <= 127)
+ choice = shiftxform[choice];
+
+ switch (choice)
+ {
+ case KEY_DEL:
+ if (len)
+ {
+ len = menusearch[1] = 0;
+ return true;
+ }
+ break;
+ case KEY_BACKSPACE:
+ if (len)
+ {
+ menusearch[1+--len] = 0;
+ return true;
+ }
+ break;
+ default:
+ if (choice >= 32 && choice <= 127)
+ {
+ if (len < MAXSTRINGLENGTH - 1)
+ {
+ menusearch[1+len++] = (char)choice;
+ menusearch[1+len] = 0;
+ return true;
+ }
+ }
+ break;
+ }
+ return false;
+}
+#undef len
+
+static void M_HandleAddons(INT32 choice)
+{
+ boolean exitmenu = false; // exit to previous menu
+
+ if (addonsresponselimit)
+ return;
+
+ if (M_ChangeStringAddons(choice))
+ {
+ if (!preparefilemenu(true))
+ {
+ UNEXIST;
+ return;
+ }
+ }
+
+ switch (choice)
+ {
+ case KEY_DOWNARROW:
+ if (dir_on[menudepthleft] < sizedirmenu-1)
+ dir_on[menudepthleft]++;
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_UPARROW:
+ if (dir_on[menudepthleft])
+ dir_on[menudepthleft]--;
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_PGDN:
+ {
+ UINT8 i;
+ for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--)
+ dir_on[menudepthleft]++;
+ }
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_PGUP:
+ {
+ UINT8 i;
+ for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--)
+ dir_on[menudepthleft]--;
+ }
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_ENTER:
+ {
+ boolean refresh = true;
+ if (!dirmenu[dir_on[menudepthleft]])
+ S_StartSound(NULL, sfx_lose);
+ else
+ {
+ switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
+ {
+ case EXT_FOLDER:
+ strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING);
+ if (menudepthleft)
+ {
+ menupathindex[--menudepthleft] = strlen(menupath);
+ menupath[menupathindex[menudepthleft]] = 0;
+
+ if (!preparefilemenu(false))
+ {
+ S_StartSound(NULL, sfx_skid);
+ M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING);
+ menupath[menupathindex[++menudepthleft]] = 0;
+
+ if (!preparefilemenu(true))
+ {
+ UNEXIST;
+ return;
+ }
+ }
+ else
+ {
+ S_StartSound(NULL, sfx_menu1);
+ dir_on[menudepthleft] = 1;
+ }
+ refresh = false;
+ }
+ else
+ {
+ S_StartSound(NULL, sfx_lose);
+ M_StartMessage(va("\x82%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING);
+ menupath[menupathindex[menudepthleft]] = 0;
+ }
+ break;
+ case EXT_UP:
+ S_StartSound(NULL, sfx_menu1);
+ menupath[menupathindex[++menudepthleft]] = 0;
+ if (!preparefilemenu(false))
+ {
+ UNEXIST;
+ return;
+ }
+ break;
+ case EXT_TXT:
+ M_StartMessage(va("\x82%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO);
+ break;
+ case EXT_CFG:
+ M_AddonExec(KEY_ENTER);
+ break;
+ case EXT_LUA:
+#ifndef HAVE_BLUA
+ S_StartSound(NULL, sfx_lose);
+ M_StartMessage(va("\x82%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
+ break;
+#endif
+ // else intentional fallthrough
+ case EXT_SOC:
+ case EXT_WAD:
+ COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
+ addonsresponselimit = 5;
+ break;
+ default:
+ S_StartSound(NULL, sfx_lose);
+ }
+ }
+ if (refresh)
+ refreshdirmenu |= REFRESHDIR_NORMAL;
+ }
+ break;
+
+ case KEY_ESCAPE:
+ exitmenu = true;
+ break;
+
+ default:
+ break;
+ }
+ if (exitmenu)
+ {
+ for (; sizedirmenu > 0; sizedirmenu--)
+ {
+ Z_Free(dirmenu[sizedirmenu-1]);
+ dirmenu[sizedirmenu-1] = NULL;
+ }
+
+ Z_Free(dirmenu);
+ dirmenu = NULL;
+
+ // secrets disabled by addfile...
+ MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
+
+ if (currentMenu->prevMenu)
+ M_SetupNextMenu(currentMenu->prevMenu);
+ else
+ M_ClearMenus(true);
+ }
+}
+
static void M_PandorasBox(INT32 choice)
{
(void)choice;
@@ -4722,7 +5274,7 @@ static void M_Options(INT32 choice)
OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL);
// if the player is playing _at all_, disable the erase data options
- OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
+ OP_DataOptionsMenu[2].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
OP_MainDef.prevMenu = currentMenu;
M_SetupNextMenu(&OP_MainDef);
@@ -5136,9 +5688,7 @@ static void M_DrawChecklist(void)
finishchecklist:
if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks.
- {
V_DrawString(10, currentMenu->y+(scrollareaheight*2), V_YELLOWMAP, "\x1B");
- }
}
#define NUMHINTS 5
@@ -6111,7 +6661,7 @@ static void M_ChoosePlayer(INT32 choice)
if (startmap != spstage_start)
cursaveslot = -1;
- lastmapsaved = 0;
+ //lastmapsaved = 0;
gamecomplete = false;
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect);
@@ -6441,7 +6991,7 @@ void M_DrawTimeAttackMenu(void)
lumpnum_t lumpnum;
char beststr[40];
- M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true);
+ M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false);
// A 160x100 image of the level as entry MAPxxP
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
@@ -6618,7 +7168,7 @@ void M_DrawNightsAttackMenu(void)
UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value);
tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value);
- M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true);
+ M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false);
// A 160x100 image of the level as entry MAPxxP
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
@@ -7374,7 +7924,7 @@ static void M_DrawServerMenu(void)
// Room name
if (currentMenu == &MP_ServerDef)
{
- M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true);
+ M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false);
if (ms_RoomId < 0)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
V_YELLOWMAP, (itemOn == mp_server_room) ? "