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/d_main.c b/src/d_main.c
index 02362f345..7a8a85f25 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -419,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)
@@ -712,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
diff --git a/src/dehacked.c b/src/dehacked.c
index 5019ad58d..f85df62ac 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1329,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"))
@@ -1776,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"},
@@ -4951,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
@@ -6297,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
@@ -6657,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
};
@@ -7082,6 +7139,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},
@@ -7900,11 +7958,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 ec01d50c9..ce503455f 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -584,6 +584,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/g_game.c b/src/g_game.c
index 600c8c896..e996938ab 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_light.c b/src/hardware/hw_light.c
index cf9b1c536..267666749 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -323,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
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 3bc071f5c..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;
@@ -852,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)
@@ -1029,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;
@@ -1057,6 +1060,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
return num / den;
}
+#endif
//
// HWR_SplitWall
@@ -1431,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)
@@ -1456,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);
@@ -1473,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
@@ -1525,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));
}
@@ -1554,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
@@ -1614,7 +1576,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
worldhigh < worldtop
) && gr_toptexture)
{
- if (drawtextured)
{
fixed_t texturevpegtop; // top
@@ -1695,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
@@ -1887,7 +1847,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
#ifdef ESLOPE
@@ -1943,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))
@@ -2135,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
@@ -2276,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;
@@ -2409,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);
@@ -2482,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
@@ -2553,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.
@@ -2577,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++;
@@ -2612,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);
}
}
@@ -2675,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);
}
}
@@ -2695,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++;
@@ -2726,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);
}
}
@@ -2767,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.
@@ -2775,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;
@@ -2833,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
@@ -2842,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
@@ -2871,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;
@@ -2882,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); \
@@ -2910,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)
@@ -2925,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)
@@ -2935,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)
@@ -2965,6 +3067,7 @@ clipsolid:
if (x1 == x2)
goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1);
+#endif
}
// HWR_CheckBBox
@@ -2976,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.
@@ -3004,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;
@@ -3051,6 +3163,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
+#endif
}
#ifdef POLYOBJECTS
@@ -3084,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);
}
@@ -5630,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
@@ -5640,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;
@@ -5666,6 +5792,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -5860,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
@@ -5870,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;
@@ -5896,6 +6036,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -6041,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 c7d35e913..df2c9f59a 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;
}
}
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 90bd817f4..1f5b394ab 100644
--- a/src/info.c
+++ b/src/info.c
@@ -211,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
@@ -1830,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
@@ -1847,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
@@ -8822,7 +8870,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_SWINGMACEPOINT
+ { // MT_CHAINMACEPOINT
1105, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8849,7 +8897,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_HANGMACEPOINT
+ { // MT_SPRINGBALLPOINT
1106, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8876,7 +8924,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_SPINMACEPOINT
+ { // MT_CHAINPOINT
1107, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8896,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
@@ -8930,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
@@ -8953,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
},
@@ -8980,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
},
@@ -9003,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
},
@@ -9030,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
},
diff --git a/src/info.h b/src/info.h
index 540c2853b..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();
@@ -417,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
@@ -2056,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
@@ -3421,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_hooklib.c b/src/lua_hooklib.c
index 04efac070..3dd3f932f 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -109,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)
{
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 7bc9b88ec..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);
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_menu.c b/src/m_menu.c
index 7a606f450..64255e71a 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -6720,7 +6720,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);
diff --git a/src/p_enemy.c b/src/p_enemy.c
index b0b03b487..e4e386d8d 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -137,7 +137,6 @@ void A_DetonChase(mobj_t *actor);
void A_CapeChase(mobj_t *actor);
void A_RotateSpikeBall(mobj_t *actor);
void A_SlingAppear(mobj_t *actor);
-void A_MaceRotate(mobj_t *actor);
void A_UnidusBall(mobj_t *actor);
void A_RockSpawn(mobj_t *actor);
void A_SetFuse(mobj_t *actor);
@@ -5175,15 +5174,12 @@ void A_SlingAppear(mobj_t *actor)
actor->movefactor = actor->threshold;
actor->friction = 128;
- actor->flags |= MF_SLIDEME;
-
while (mlength > 0)
{
spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN);
P_SetTarget(&spawnee->target, actor);
- spawnee->movecount = 0;
spawnee->threshold = 0;
spawnee->reactiontime = mlength;
@@ -5198,129 +5194,6 @@ void A_SlingAppear(mobj_t *actor)
}
}
-//
-// Function: A_MaceRotate
-//
-// Spins an object around its target, or, swings it from side to side.
-//
-// var1 = unused
-// var2 = unused
-//
-// So NOBODY forgets:
-// actor->
-// threshold - X tilt
-// movecount - Z tilt
-// reactiontime - link # in the chain (1 is closest)
-// lastlook - speed
-// friction - top speed
-// movedir - current angle holder
-// extravalue1 - smoothly move link into place
-//
-void A_MaceRotate(mobj_t *actor)
-{
- TVector v;
- TVector *res;
- fixed_t radius;
-#ifdef HAVE_BLUA
- if (LUA_CallAction("A_MaceRotate", actor))
- return;
-#endif
-
- // Target was removed.
- if (!actor->target)
- {
- P_RemoveMobj(actor);
- return;
- }
-
- P_UnsetThingPosition(actor);
-
- // Radius of the link's rotation.
- radius = FixedMul(actor->info->speed * actor->reactiontime, actor->target->scale);
-
- // Double the radius if the chain links are made up of maces.
- if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE))
- radius *= 2;
-
- // Axis offset for the axis.
- radius += actor->target->extravalue1;
-
- // Smoothly move the link into position.
- if (actor->extravalue1)
- {
- radius = FixedMul(radius, FixedDiv(actor->extravalue1, 100));
- actor->extravalue1 += 1;
- if (actor->extravalue1 >= 100)
- actor->extravalue1 = 0;
- }
-
- actor->x = actor->target->x;
- actor->y = actor->target->y;
- actor->z = actor->target->z;
-
- // Cut the height to align the link with the axis.
- if (actor->type == MT_SMALLMACECHAIN || actor->type == MT_BIGMACECHAIN)
- actor->z -= actor->height/4;
- else
- actor->z -= actor->height/2;
-
- // Set the top speed for the link if it happens to be over that speed.
- if (actor->target->lastlook > actor->target->friction)
- actor->target->lastlook = actor->target->friction;
-
- // Swinging Chain.
- if (actor->target->type == MT_HANGMACEPOINT || actor->target->type == MT_SWINGMACEPOINT)
- {
- actor->movecount += actor->target->lastlook;
- actor->movecount &= FINEMASK;
-
- actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook << FRACBITS);
-
- v[0] = FRACUNIT;
- v[1] = 0;
- v[2] = -radius;
- v[3] = FRACUNIT;
-
- // Calculate the angle matrixes for the link.
- res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold)));
- M_Memcpy(&v, res, sizeof(v));
- res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
- M_Memcpy(&v, res, sizeof(v));
- }
- // Rotating Chain.
- else
- {
- angle_t fa;
-
- actor->threshold += actor->target->lastlook;
- actor->threshold &= FINEMASK;
- actor->target->health &= FINEMASK;
-
- fa = actor->threshold;
- v[0] = FixedMul(FINECOSINE(fa), radius);
- v[1] = 0;
- v[2] = FixedMul(FINESINE(fa), radius);
- v[3] = FRACUNIT;
-
- // Calculate the angle matrixes for the link.
- res = VectorMatrixMultiply(v, *RotateXMatrix(actor->target->threshold << ANGLETOFINESHIFT));
- M_Memcpy(&v, res, sizeof(v));
- res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
- M_Memcpy(&v, res, sizeof(v));
- }
-
- // Add on the appropriate distances to the actor's co-ordinates.
- actor->x += v[0];
- actor->y += v[1];
- actor->z += v[2];
-
- P_SetThingPosition(actor);
-
- if (!(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes maces shut up on request
- && !(leveltime & 63) && (actor->type == MT_BIGMACE || actor->type == MT_SMALLMACE) && actor->target->type == MT_MACEPOINT)
- S_StartSound(actor, actor->info->activesound);
-}
-
// Function: A_SetFuse
//
// Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall)
@@ -10833,26 +10706,33 @@ void A_FlickyFlutter(mobj_t *actor)
// Description: Creates the mobj's painchance at a random position around the object's radius.
//
// var1 = momz of particle.
+// var2 = chance of particle spawn
//
void A_FlameParticle(mobj_t *actor)
{
mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
+ fixed_t rad, hei;
+ mobj_t *particle;
INT32 locvar1 = var1;
+ INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlameParticle", actor))
return;
#endif
- if (type)
- {
- fixed_t rad = 2*actor->radius>>FRACBITS;
- fixed_t hei = actor->height>>FRACBITS;
- mobj_t *particle = P_SpawnMobjFromMobj(actor,
- P_RandomRange(rad, -rad)<radius>>FRACBITS;
+ hei = actor->height>>FRACBITS;
+ particle = P_SpawnMobjFromMobj(actor,
+ P_RandomRange(rad, -rad)<powers[pw_flashing])
return;
+ if (special->movefactor && special->tracer && (angle_t)special->tracer->health != ANGLE_90 && (angle_t)special->tracer->health != ANGLE_270)
+ { // I don't expect you to understand this, Mr Bond...
+ angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->threshold;
+ if ((special->movefactor > 0) == ((angle_t)special->tracer->health > ANGLE_90 && (angle_t)special->tracer->health < ANGLE_270))
+ ang += ANGLE_180;
+ if (ang < ANGLE_180)
+ return; // I expect you to die.
+ }
+
P_ResetPlayer(player);
P_SetTarget(&toucher->tracer, special);
- if (special->target && (special->target->type == MT_SPINMACEPOINT || special->target->type == MT_HIDDEN_SLING))
+ if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX))
{
player->powers[pw_carry] = CR_MACESPIN;
S_StartSound(toucher, sfx_spin);
@@ -1510,6 +1519,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Can't jump first frame
player->pflags |= PF_JUMPSTASIS;
+
return;
case MT_BIGMINE:
case MT_BIGAIRMINE:
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 06afce7dd..f71666f93 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -6269,6 +6269,128 @@ static void P_NightsItemChase(mobj_t *thing)
P_Attract(thing, thing->tracer, true);
}
+//
+// P_MaceRotate
+// Spins an object around its target, or, swings it from side to side.
+//
+static void P_MaceRotate(mobj_t *mobj)
+{
+ TVector v;
+ TVector *res;
+ fixed_t radius, dist;
+ angle_t fa;
+ INT32 prevswing;
+ boolean donetwice = false;
+
+ // Tracer was removed.
+ if (!mobj->health)
+ return;
+ else if (!mobj->tracer)
+ {
+ P_KillMobj(mobj, NULL, NULL, 0);
+ return;
+ }
+
+ mobj->momx = mobj->momy = mobj->momz = 0;
+
+ prevswing = mobj->threshold;
+ mobj->threshold += mobj->tracer->lastlook;
+ mobj->threshold &= FINEMASK;
+
+ dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
+
+ // Radius of the link's rotation.
+ radius = FixedMul(dist * mobj->movecount, mobj->tracer->scale) + mobj->tracer->extravalue1;
+
+maceretry:
+
+ fa = (FixedAngle(mobj->tracer->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
+ radius = FixedMul(FINECOSINE(fa), radius);
+ v[1] = -FixedMul(FINESINE(fa), radius)
+ + FixedMul(dist * mobj->movefactor, mobj->tracer->scale);
+ v[3] = FRACUNIT;
+
+ // Swinging Chain.
+ if (mobj->tracer->flags2 & MF2_STRONGBOX)
+ {
+ fixed_t swingmagnitude = FixedMul(FINECOSINE(mobj->threshold), mobj->tracer->lastlook << FRACBITS);
+ prevswing = FINECOSINE(prevswing);
+
+ if (!donetwice
+ && (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
+ && ((prevswing > 0) != (swingmagnitude > 0))) // just passed its lowest point
+ S_StartSound(mobj, mobj->info->activesound);
+
+ fa = ((FixedAngle(swingmagnitude) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
+
+ v[0] = FixedMul(FINESINE(fa), -radius);
+ v[2] = FixedMul(FINECOSINE(fa), -radius);
+ }
+ // Rotating Chain.
+ else
+ {
+ prevswing = (prevswing + mobj->friction) & FINEMASK;
+ fa = (mobj->threshold + mobj->friction) & FINEMASK;
+
+ if (!donetwice
+ && (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
+ && (!(prevswing > (FINEMASK/2)) && (fa > (FINEMASK/2)))) // completed a full swing
+ S_StartSound(mobj, mobj->info->activesound);
+
+ v[0] = FixedMul(FINECOSINE(fa), radius);
+ v[2] = FixedMul(FINESINE(fa), radius);
+ }
+
+ // Calculate the angle matrixes for the link.
+ res = VectorMatrixMultiply(v, *RotateXMatrix(mobj->tracer->threshold << ANGLETOFINESHIFT));
+ M_Memcpy(&v, res, sizeof(v));
+ res = VectorMatrixMultiply(v, *RotateZMatrix(mobj->tracer->health << ANGLETOFINESHIFT));
+ M_Memcpy(&v, res, sizeof(v));
+
+ // Cut the height to align the link with the axis.
+ if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
+ v[2] -= P_MobjFlip(mobj)*mobj->height/4;
+ else
+ v[2] -= P_MobjFlip(mobj)*mobj->height/2;
+
+ P_UnsetThingPosition(mobj);
+
+ // Add on the appropriate distances to the center's co-ordinates.
+ mobj->x = mobj->tracer->x + v[0];
+ mobj->y = mobj->tracer->y + v[1];
+ mobj->z = mobj->tracer->z + v[2];
+
+ P_SetThingPosition(mobj);
+
+ if (donetwice || P_MobjWasRemoved(mobj))
+ return;
+
+ if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT))
+ return;
+
+ if ((fa = ((mobj->tracer->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
+ return;
+
+ if (mobj->subsector->sector->ffloors)
+ P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
+
+ // Variable reuse
+ if (mobj->floorz > mobj->z)
+ dist = (mobj->floorz - mobj->tracer->z);
+ else if (mobj->ceilingz < mobj->z)
+ dist = (mobj->ceilingz - mobj->tracer->z);
+ else
+ return;
+
+ if ((dist = FixedDiv(dist, v[2])) > FRACUNIT)
+ return;
+
+ radius = FixedMul(radius, dist);
+ donetwice = true;
+ dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
+ goto maceretry;
+}
+
static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
{
if (!thing->target || thing->target->health <= 0 || !thing->target->player
@@ -6626,6 +6748,13 @@ void P_MobjThinker(mobj_t *mobj)
// fade out when nearing the end of fuse...
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT);
+ if (mobj->flags2 & MF2_MACEROTATE)
+ {
+ P_MaceRotate(mobj);
+ if (P_MobjWasRemoved(mobj))
+ return;
+ }
+
// Special thinker for scenery objects
if (mobj->flags & MF_SCENERY)
{
@@ -7291,7 +7420,8 @@ void P_MobjThinker(mobj_t *mobj)
}
}
break;
- case MT_SPINMACEPOINT:
+ case MT_CHAINPOINT:
+ case MT_CHAINMACEPOINT:
if (leveltime & 1)
{
if (mobj->lastlook > mobj->movecount)
@@ -9635,15 +9765,20 @@ void P_SpawnMapThing(mapthing_t *mthing)
mobj->movedir = mthing->extrainfo;
break;
case MT_MACEPOINT:
- case MT_SWINGMACEPOINT:
- case MT_HANGMACEPOINT:
- case MT_SPINMACEPOINT:
+ case MT_CHAINMACEPOINT:
+ case MT_SPRINGBALLPOINT:
+ case MT_CHAINPOINT:
+ case MT_FIREBARPOINT:
+ case MT_CUSTOMMACEPOINT:
{
- fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed;
- mobjtype_t chainlink = MT_SMALLMACECHAIN;
- mobjtype_t macetype = MT_SMALLMACE;
- boolean firsttime;
+ fixed_t mlength, mlengthset, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mnumspokesset, mpinch, mroll, mnumnospokes, mwidth, mmin, msound, radiusfactor;
+ angle_t mspokeangle;
+ mobjtype_t chainlink, macetype, firsttype, linktype;
+ boolean mdoall = true;
mobj_t *spawnee;
+ mobjflag_t mflagsapply;
+ mobjflag2_t mflags2apply;
+ mobjeflag_t meflagsapply;
INT32 line;
const size_t mthingi = (size_t)(mthing - mapthings);
@@ -9657,93 +9792,240 @@ void P_SpawnMapThing(mapthing_t *mthing)
return;
}
/*
-No deaf - small mace
-Deaf - big mace
+mapthing -
+MTF_AMBUSH :
+ MT_SPRINGBALLPOINT - upgrade from yellow to red spring
+ anything else - bigger mace/chain theory
+MTF_OBJECTSPECIAL - force silent
+MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements
+Parameter value : number of "spokes"
-ML_NOCLIMB : Direction not controllable
+linedef -
+ML_NOCLIMB :
+ MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable
+ anything else - no functionality
+ML_EFFECT1 : Swings instead of spins
+ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT)
+ML_EFFECT3 : Spawn a bonus macetype at the hinge point
+ML_EFFECT4 : Don't clip inside the ground
*/
mlength = abs(lines[line].dx >> FRACBITS);
- mspeed = abs(lines[line].dy >> FRACBITS);
- mxspeed = sides[lines[line].sidenum[0]].textureoffset >> FRACBITS;
- mzspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS;
- mstartangle = lines[line].frontsector->floorheight >> FRACBITS;
- mmaxspeed = lines[line].frontsector->ceilingheight >> FRACBITS;
+ mspeed = abs(lines[line].dy >> (FRACBITS - 4));
+ mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360;
+ if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> (FRACBITS - 4)) < mspeed)
+ mmaxspeed = mspeed << 1;
+ mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360;
+ myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360;
- mstartangle %= 360;
- mxspeed %= 360;
- mzspeed %= 360;
+ mnumspokes = mthing->extrainfo + 1;
+ mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT;
- CONS_Debug(DBG_GAMELOGIC, "Mace Chain (mapthing #%s):\n"
+ if (lines[line].backsector)
+ {
+ mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360;
+ mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360;
+ mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS);
+ if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0)
+ mwidth = 0;
+ }
+ else
+ mpinch = mroll = mnumnospokes = mwidth = 0;
+
+ CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n"
"Length is %d\n"
"Speed is %d\n"
- "Xspeed is %d\n"
- "Zspeed is %d\n"
- "startangle is %d\n"
- "maxspeed is %d\n",
- sizeu1(mthingi), mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed);
+ "Phase is %d\n"
+ "Yaw is %d\n"
+ "Pitch is %d\n"
+ "Max. speed is %d\n"
+ "No. of spokes is %d\n"
+ "Pinch is %d\n"
+ "Roll is %d\n"
+ "No. of antispokes is %d\n"
+ "Width is %d\n",
+ sizeu1(mthingi), mlength, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mpinch, mroll, mnumnospokes, mwidth);
- mobj->lastlook = mspeed << 4;
+ if (mnumnospokes > 0 && (mnumnospokes < mnumspokes))
+ mnumnospokes = mnumspokes/mnumnospokes;
+ else
+ mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0);
+
+ mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook;
- mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT);
- mobj->threshold = (FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT);
- mobj->movefactor = mobj->threshold;
+ mobj->health = (FixedAngle(myaw*FRACUNIT)>>ANGLETOFINESHIFT);
+ mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->friction = mmaxspeed;
+ mobj->movefactor = mpinch;
+ // Mobjtype selection
+ switch(mobj->type)
+ {
+ case MT_SPRINGBALLPOINT:
+ macetype = ((mthing->options & MTF_AMBUSH)
+ ? MT_REDSPRINGBALL
+ : MT_YELLOWSPRINGBALL);
+ chainlink = MT_SMALLMACECHAIN;
+ break;
+ case MT_FIREBARPOINT:
+ macetype = ((mthing->options & MTF_AMBUSH)
+ ? MT_BIGFIREBAR
+ : MT_SMALLFIREBAR);
+ chainlink = MT_NULL;
+ break;
+ case MT_CUSTOMMACEPOINT:
+ macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture;
+ if (lines[line].backsector)
+ chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture;
+ else
+ chainlink = MT_NULL;
+ break;
+ default:
+ if (mthing->options & MTF_AMBUSH)
+ {
+ macetype = MT_BIGMACE;
+ chainlink = MT_BIGMACECHAIN;
+ }
+ else
+ {
+ macetype = MT_SMALLMACE;
+ chainlink = MT_SMALLMACECHAIN;
+ }
+ break;
+ }
+
+ if (!macetype)
+ break;
+
+ if (mobj->type != MT_CHAINPOINT)
+ {
+ firsttype = macetype;
+ mlength++;
+ }
+ else
+ {
+ if (!mlength)
+ break;
+ firsttype = chainlink;
+ }
+
+ // Adjustable direction
if (lines[line].flags & ML_NOCLIMB)
mobj->flags |= MF_SLIDEME;
- mobj->reactiontime = 0;
-
- if (mthing->options & MTF_AMBUSH)
+ // Swinging
+ if (lines[line].flags & ML_EFFECT1)
{
- chainlink = MT_BIGMACECHAIN;
- macetype = MT_BIGMACE;
+ mobj->flags2 |= MF2_STRONGBOX;
+ mmin = ((mnumnospokes > 1) ? 1 : 0);
}
-
- if (mthing->options & MTF_OBJECTSPECIAL)
- mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces.
-
- if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SPINMACEPOINT)
- firsttime = true;
else
+ mmin = mnumspokes;
+
+ // Make the links the same type as the end - repeated below
+ if ((mobj->type != MT_CHAINPOINT) && (!(lines[line].flags & ML_EFFECT2) == (mobj->type == MT_FIREBARPOINT))) // exclusive or
{
- firsttime = false;
-
- spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype);
- P_SetTarget(&spawnee->target, mobj);
-
- if (mobj->type == MT_SWINGMACEPOINT)
- spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
- else
- spawnee->movecount = 0;
-
- spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
- spawnee->reactiontime = mlength+1;
+ linktype = macetype;
+ radiusfactor = 2; // Double the radius.
}
+ else
+ radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
- while (mlength > 0)
+ mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT));
+ mflags2apply = (MF2_MACEROTATE|((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0));
+ meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0);
+
+ msound = ((firsttype == chainlink) ? 0 : (mwidth & 1));
+
+ // Quick and easy preparatory variable setting
+ mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT);
+ mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT);
+
+#define makemace(mobjtype, dist, moreflags2) P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
+ P_SetTarget(&spawnee->tracer, mobj);\
+ spawnee->threshold = mphase;\
+ spawnee->friction = mroll;\
+ spawnee->movefactor = mwidth;\
+ spawnee->movecount = dist;\
+ spawnee->angle = myaw;\
+ spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
+ spawnee->flags2 |= (mflags2apply|moreflags2);\
+ spawnee->eflags |= meflagsapply
+
+domaceagain:
+ mnumspokesset = mnumspokes;
+
+ if (mdoall && lines[line].flags & ML_EFFECT3) // Innermost mace/link
+ { spawnee = makemace(macetype, 0, MF2_AMBUSH); }
+
+ // The actual spawning of spokes
+ while (mnumspokesset-- > 0)
{
- spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink);
+ // Offsets
+ if (lines[line].flags & ML_EFFECT1) // Swinging
+ mroll = (mroll - mspokeangle) & FINEMASK;
+ else // Spinning
+ mphase = (mphase - mspokeangle) & FINEMASK;
- P_SetTarget(&spawnee->target, mobj);
-
- if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT)
- spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
- else
- spawnee->movecount = 0;
-
- spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
- spawnee->reactiontime = mlength;
-
- if (firsttime)
+ if (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke
{
- // This is the outermost link in the chain
- spawnee->flags2 |= MF2_AMBUSH;
- firsttime = false;
+ if (mobj->type != MT_CHAINMACEPOINT)
+ continue;
+
+ firsttype = linktype = chainlink;
+ mlengthset = 1 + (mlength - 1)*radiusfactor;
+ radiusfactor = 1;
+ }
+ else
+ {
+ if (mobj->type == MT_CHAINMACEPOINT)
+ {
+ // Make the links the same type as the end - repeated above
+ if (lines[line].flags & ML_EFFECT2)
+ {
+ linktype = macetype;
+ radiusfactor = 2;
+ }
+ else
+ {
+ linktype = chainlink;
+ radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
+ }
+
+ firsttype = macetype;
+ }
+
+ mlengthset = mlength;
}
- mlength--;
+ // Outermost mace/link
+ spawnee = makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
+
+ if (mspeed && (mwidth == msound) && !(mthing->options & MTF_OBJECTSPECIAL) && mnumspokesset <= mmin) // Can it make a sound?
+ spawnee->flags2 |= MF2_BOSSNOTRAP;
+
+ if (!mdoall || !linktype)
+ continue;
+
+ // The rest of the links
+ while (mlengthset > 0)
+ { spawnee = makemace(linktype, radiusfactor*(mlengthset--), 0); }
}
+
+ if (mwidth > 0)
+ {
+ mwidth *= -1;
+ goto domaceagain;
+ }
+ else if (mwidth != 0)
+ {
+ if ((mwidth = -(mwidth + ((firsttype == chainlink) ? 1 : 2))) < 0)
+ break;
+ mdoall = false;
+ goto domaceagain;
+ }
+
+#undef makemace
+
break;
}
case MT_PARTICLEGEN:
@@ -11116,4 +11398,4 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
newmobj->destscale = mobj->destscale;
P_SetScale(newmobj, mobj->scale);
return newmobj;
-}
+}
\ No newline at end of file
diff --git a/src/p_mobj.h b/src/p_mobj.h
index f6ebd3cad..c6e1bfbf2 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
+ MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer
// free: to and including 1<<31
} mobjflag2_t;
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 3853dc7e6..2d3412e65 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -3159,7 +3159,8 @@ static inline void P_ArchiveMisc(void)
else
WRITEINT16(save_p, gamemap);
- lastmapsaved = gamemap;
+ //lastmapsaved = gamemap;
+ lastmaploaded = gamemap;
WRITEUINT16(save_p, (botskin ? (emeralds|(1<<10)) : emeralds)+357);
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
@@ -3184,7 +3185,8 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
if(!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1);
- lastmapsaved = gamemap;
+ //lastmapsaved = gamemap;
+ lastmaploaded = gamemap;
tokenlist = 0;
token = 0;
diff --git a/src/p_setup.c b/src/p_setup.c
index 8a91de76b..529589bec 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -489,6 +489,7 @@ static void P_LoadSegs(lumpnum_t lumpnum)
//Hurdler: 04/12/2000: for now, only used in hardware mode
li->lightmaps = NULL; // list of static lightmap for this seg
}
+ li->pv1 = li->pv2 = NULL;
#endif
li->angle = (SHORT(ml->angle))<levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
+}
+
/** Loads a level from a lump or external wad.
*
* \param skipprecip If true, don't spawn precipitation.
@@ -3034,11 +3051,11 @@ boolean P_SetupLevel(boolean skipprecip)
P_RunCachedActions();
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0)
- && (!modifiedgame || savemoddata) && cursaveslot >= 0 && !ultimatemode
- && !(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
- && (!G_IsSpecialStage(gamemap)) && gamemap != lastmapsaved && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete))
+ && (!modifiedgame || savemoddata) && cursaveslot >= 0 && CanSaveLevel(gamemap))
G_SaveGame((UINT32)cursaveslot);
+ lastmaploaded = gamemap; // HAS to be set after saving!!
+
if (savedata.lives > 0)
{
players[consoleplayer].continues = savedata.continues;
diff --git a/src/p_user.c b/src/p_user.c
index afa0ee960..a2c8c9279 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -10107,7 +10107,7 @@ void P_PlayerAfterThink(player_t *player)
}
}
}
- else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->target)
+ else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->tracer)
{
player->mo->height = P_GetPlayerSpinHeight(player);
// tracer is what you're hanging onto....
@@ -10123,14 +10123,20 @@ void P_PlayerAfterThink(player_t *player)
player->pflags &= ~PF_THOKKED;
if (cmd->forwardmove > 0)
- player->mo->tracer->target->lastlook += 2;
- else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount)
- player->mo->tracer->target->lastlook -= 2;
+ {
+ if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction)
+ player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->friction;
+ }
+ else if (cmd->forwardmove < 0)
+ {
+ if ((player->mo->tracer->tracer->lastlook -= 2) < player->mo->tracer->tracer->movecount)
+ player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->movecount;
+ }
- if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
+ if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
&& !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode?
{
- player->mo->tracer->target->health += cmd->sidemove;
+ player->mo->tracer->tracer->health += cmd->sidemove;
player->mo->angle += cmd->sidemove< ANGLE_MAX
if (!demoplayback || P_AnalogMove(player))
diff --git a/src/r_bsp.c b/src/r_bsp.c
index abb11204a..4ce89f009 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -365,6 +365,36 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
return sec;
}
+boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
+{
+ return (
+#ifdef POLYOBJECTS
+ !line->polyseg &&
+#endif
+ back->ceilingpic == front->ceilingpic
+ && back->floorpic == front->floorpic
+#ifdef ESLOPE
+ && back->f_slope == front->f_slope
+ && back->c_slope == front->c_slope
+#endif
+ && back->lightlevel == front->lightlevel
+ && !line->sidedef->midtexture
+ // Check offsets too!
+ && back->floor_xoffs == front->floor_xoffs
+ && back->floor_yoffs == front->floor_yoffs
+ && back->floorpic_angle == front->floorpic_angle
+ && back->ceiling_xoffs == front->ceiling_xoffs
+ && back->ceiling_yoffs == front->ceiling_yoffs
+ && back->ceilingpic_angle == front->ceilingpic_angle
+ // Consider altered lighting.
+ && back->floorlightsec == front->floorlightsec
+ && back->ceilinglightsec == front->ceilinglightsec
+ // Consider colormaps
+ && back->extra_colormap == front->extra_colormap
+ && ((!front->ffloors && !back->ffloors)
+ || front->tag == back->tag));
+}
+
//
// R_AddLine
// Clips the given segment and adds any visible pieces to the line list.
@@ -526,36 +556,8 @@ static void R_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
- backsector->ceilingpic == frontsector->ceilingpic
- && backsector->floorpic == frontsector->floorpic
-#ifdef ESLOPE
- && backsector->f_slope == frontsector->f_slope
- && backsector->c_slope == frontsector->c_slope
-#endif
- && backsector->lightlevel == frontsector->lightlevel
- && !curline->sidedef->midtexture
- // Check offsets too!
- && backsector->floor_xoffs == frontsector->floor_xoffs
- && backsector->floor_yoffs == frontsector->floor_yoffs
- && backsector->floorpic_angle == frontsector->floorpic_angle
- && backsector->ceiling_xoffs == frontsector->ceiling_xoffs
- && backsector->ceiling_yoffs == frontsector->ceiling_yoffs
- && backsector->ceilingpic_angle == frontsector->ceilingpic_angle
- // Consider altered lighting.
- && backsector->floorlightsec == frontsector->floorlightsec
- && backsector->ceilinglightsec == frontsector->ceilinglightsec
- // Consider colormaps
- && backsector->extra_colormap == frontsector->extra_colormap
- && ((!frontsector->ffloors && !backsector->ffloors)
- || frontsector->tag == backsector->tag))
- {
+ if (R_IsEmptyLine(line, frontsector, backsector))
return;
- }
-
clippass:
R_ClipPassWallSegment(x1, x2 - 1);
diff --git a/src/r_bsp.h b/src/r_bsp.h
index e871b5dde..80824831b 100644
--- a/src/r_bsp.h
+++ b/src/r_bsp.h
@@ -50,6 +50,7 @@ extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back);
+boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
void R_Prep3DFloors(sector_t *sector);
diff --git a/src/r_defs.h b/src/r_defs.h
index 32be7c4c8..7744a12d8 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -574,6 +574,9 @@ typedef struct seg_s
sector_t *backsector;
#ifdef HWRENDER
+ // new pointers so that AdjustSegs doesn't mess with v1/v2
+ void *pv1; // polyvertex_t
+ void *pv2; // polyvertex_t
float flength; // length of the seg, used by hardware renderer
lightmap_t *lightmaps; // for static lightmap
diff --git a/src/v_video.c b/src/v_video.c
index f7a5c2841..6ac101f2d 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -865,11 +865,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
//
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor)
{
- if (skins[skinnum].flags & SF_HIRES
-#ifdef HWRENDER
-// || (rendermode != render_soft && rendermode != render_none)
-#endif
- )
+ if (skins[skinnum].flags & SF_HIRES)
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE));
else
{