diff --git a/SRB2.cbp b/SRB2.cbp index 88dc400fee58d949fe3f59eb968662e45702ffd1..2a1eb87b8565b3d2d9c13216c23d39dceecd6f92 100644 --- a/SRB2.cbp +++ b/SRB2.cbp @@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw64/DirectX" /> <Option target="Release Mingw64/DirectX" /> </Unit> + <Unit filename="src/hardware/hw_clip.c"> + <Option compilerVar="CC" /> + <Option target="Debug Native/SDL" /> + <Option target="Release Native/SDL" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> + <Option target="Debug Mingw/DirectX" /> + <Option target="Release Mingw/DirectX" /> + <Option target="Debug Any/Dummy" /> + <Option target="Release Any/Dummy" /> + <Option target="Debug Linux/SDL" /> + <Option target="Release Linux/SDL" /> + <Option target="Debug Mingw64/SDL" /> + <Option target="Release Mingw64/SDL" /> + <Option target="Debug Mingw64/DirectX" /> + <Option target="Release Mingw64/DirectX" /> + </Unit> + <Unit filename="src/hardware/hw_clip.h"> + <Option target="Debug Native/SDL" /> + <Option target="Release Native/SDL" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> + <Option target="Debug Mingw/DirectX" /> + <Option target="Release Mingw/DirectX" /> + <Option target="Debug Any/Dummy" /> + <Option target="Release Any/Dummy" /> + <Option target="Debug Linux/SDL" /> + <Option target="Release Linux/SDL" /> + <Option target="Debug Mingw64/SDL" /> + <Option target="Release Mingw64/SDL" /> + <Option target="Debug Mingw64/DirectX" /> + <Option target="Release Mingw64/DirectX" /> + </Unit> <Unit filename="src/hardware/hw_data.h"> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da8438a59ef123836a88593f30c1438f2b69e4da..6a8b7e3f1228f2e7028a9f9cd324768c85182025 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 426dc22898716a92ce7e6bc4330616939ad479a6..27569b36ca772f45fffc26b09625498e16a058d2 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 02362f3458aa9bd202f706e901a950d4597f8ffd..7a8a85f255e96db1f7e4f5ad3c86963131df7325 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 5019ad58d4a5f2a218bee8dd3e896d305ad188de..f85df62ac2b4d318e82a39d1ea159edab49ce2b2 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 ec01d50c902a103674996abf2b0711fcdd87be38..ce503455f003a468fa6144657a34fa8574f706ef 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 a3b07c9cbf153d3d7e081a60a0afda2b91054592..a24bad79d73dc21dbd1b7b5b63728e4efb4862f0 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 600c8c8964be2b1a7781818095cd26c39f2feea0..e996938ab30ac44cc2d655406e8008e46aaca748 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 a32609fc80ebb1e0316f1c1f6d2dd5897a00c707..fa5bce308eff82bf52021c98bc19e1797ceb87ee 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) - { - 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) + if (p) { + for (j = 0; j < p->numpts; j++) { - 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 0000000000000000000000000000000000000000..8b01cabd5ed37696652b931548eed18de3aea344 --- /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 <math.h> +#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 0000000000000000000000000000000000000000..3ba26e5e56f3dc053adc068078dc11859e8a86df --- /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 cf9b1c5368d44dc07ec55df33e77345aafe36729..267666749baf363ec02652fdb65f342a96f0d8f0 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 3bc071f5c02f514b694e4e001434d5f874da3c80..d74cd0587778e9181e63d75d6de7ce01ce0eafb9 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; + 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(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)); + 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 c7d35e9134be1a4c09809669778db14cdf670118..df2c9f59a60b675f5aacfdce1be23a30064af3bd 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 5a7e6d2b3cdaf0c3ae7d5813e835d5cf8711403e..299d1240005daba28769c1e8b5e12adfd1b67401 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 e9ba19efb60a8fb8a6fe26c657866bcd2d764927..97d86b944890de2fae05d11bfd05ed607722b3d3 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,15 +587,14 @@ 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; + nextElem = thisSector->sectorLines; - while (NULL != nextElem) // walk through chain + while (nextElem) // walk through chain { thisElem = nextElem; nextElem = thisElem->next; @@ -609,10 +608,12 @@ static boolean isCeilingFloating(sector_t *thisSector) adjSector = frontSector; if (!adjSector) // assume floating sectors have surrounding sectors - { - floating = false; - break; - } + return false; + +#ifdef ESLOPE + if (adjSector->c_slope) // Don't bother with slopes + return false; +#endif if (!refSector) { @@ -621,23 +622,15 @@ static boolean isCeilingFloating(sector_t *thisSector) } // if adjacent sector has same height or more than one adjacent sector exists -> stop - if (thisSector->ceilingheight == adjSector->ceilingheight || - refSector != adjSector) - { - floating = false; - break; - } + if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector) + return false; } // now check for walltextures - if (floating) - { - if (!areToptexturesMissing(thisSector)) - { - floating = false; - } - } - return floating; + if (!areToptexturesMissing(thisSector)) + return false; + + return true; } // @@ -647,13 +640,12 @@ static boolean isCeilingFloating(sector_t *thisSector) 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 +660,30 @@ 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; + +#ifdef ESLOPE + if (adjSector->f_slope) // Don't bother with slopes + return false; +#endif - if (NULL == refSector) + 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->floorheight == adjSector->floorheight || refSector != adjSector) + return false; } // now check for walltextures - if (floating) - { - if (!areBottomtexturesMissing(thisSector)) - { - floating = false; - } - } - return floating; + 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 90bd817f435c241771d9100227ec104f45c98c90..1f5b394abc1a7e6a5056515b20603dddead39580 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 - - // Big Mace Chain - {SPR_BMCH, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN - - // Small Mace - {SPR_SMCE, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACE}, // S_SMALLMACE - - // Big Mace - {SPR_BMCE, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACE}, // S_BIGMACE + // 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 + + // 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 + + // 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 + + // 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 540c2853becbf4810b9cfd6780a9bd153388884d..63a4d893f5f926c91d3c30236b64ea5fba5f35d3 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 322fecb64f1739b3d9749e731f1eef59b9f8570c..b688155fbfd31a9bb5cbee5a5bbaecfff89a7606 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 04efac070f52f722334df2e363038dc6673f39c7..3dd3f932f81a41bb82c046a7eb4fe8a564de796f 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 5b3cd46ce8f86cf3f987dc716d2b4f0e0c86d7f3..29e4970c1d3153536315e2d7151d0bf885854ad6 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 7bc9b88ec2a2c7a8525aab75a1d18637d3e135ad..994f81a40bb54880fffcefd061bb909a43e6fead 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 d143ed879a25944778f6105c6b123b0190184ab0..51f1eaeaaeb4d00b4c55721aa4ae8fad165cd185 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 7a606f450608fa441d476bebd50e0e96dbb7067e..64255e71a82d6630a962878cde7c634a8262af9c 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 b0b03b487363a84badee7d71b65af3e2847d0e4e..e4e386d8d02a7fbbb9e6629e7ec133ebea18f2a8 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)<<FRACBITS, - P_RandomRange(rad, -rad)<<FRACBITS, - P_RandomRange(hei/2, hei)<<FRACBITS, - type); - P_SetObjectMomZ(particle, locvar1<<FRACBITS, false); - } + if (!P_RandomChance(locvar2)) + return; + + if (!type) + return; + + rad = 2*actor->radius>>FRACBITS; + hei = actor->height>>FRACBITS; + particle = P_SpawnMobjFromMobj(actor, + P_RandomRange(rad, -rad)<<FRACBITS, + P_RandomRange(rad, -rad)<<FRACBITS, + P_RandomRange(hei/2, hei)<<FRACBITS, + type); + P_SetObjectMomZ(particle, locvar1<<FRACBITS, false); } diff --git a/src/p_inter.c b/src/p_inter.c index 523d9720a89631bb9ca7dba26719b4e9e8cd6cd9..9b00d1bf07536457ea1e5386416ab21ec792da42 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1496,10 +1496,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->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 06afce7dd92f987a9e2591ecd5308d72850e1184..f71666f93ac164ed7c91c38a5b6837db4365e2e7 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: - { - fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed; - mobjtype_t chainlink = MT_SMALLMACECHAIN; - mobjtype_t macetype = MT_SMALLMACE; - boolean firsttime; + case MT_CHAINMACEPOINT: + case MT_SPRINGBALLPOINT: + case MT_CHAINPOINT: + case MT_FIREBARPOINT: + case MT_CUSTOMMACEPOINT: + { + 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 - -ML_NOCLIMB : Direction not controllable +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" + +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; + + mnumspokes = mthing->extrainfo + 1; + mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT; - mstartangle %= 360; - mxspeed %= 360; - mzspeed %= 360; + 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" + 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); + + if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) + mnumnospokes = mnumspokes/mnumnospokes; + else + mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0); - mobj->lastlook = mspeed << 4; + 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; - if (lines[line].flags & ML_NOCLIMB) - mobj->flags |= MF_SLIDEME; + // 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; + } - mobj->reactiontime = 0; + if (!macetype) + break; - if (mthing->options & MTF_AMBUSH) + if (mobj->type != MT_CHAINPOINT) + { + firsttype = macetype; + mlength++; + } + else { - chainlink = MT_BIGMACECHAIN; - macetype = MT_BIGMACE; + if (!mlength) + break; + firsttype = chainlink; } - if (mthing->options & MTF_OBJECTSPECIAL) - mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces. + // Adjustable direction + if (lines[line].flags & ML_NOCLIMB) + mobj->flags |= MF_SLIDEME; - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SPINMACEPOINT) - firsttime = true; + // Swinging + if (lines[line].flags & ML_EFFECT1) + { + mobj->flags2 |= MF2_STRONGBOX; + mmin = ((mnumnospokes > 1) ? 1 : 0); + } 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; + linktype = macetype; + radiusfactor = 2; // Double the radius. + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype); - P_SetTarget(&spawnee->target, mobj); + 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); - if (mobj->type == MT_SWINGMACEPOINT) - spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - else - spawnee->movecount = 0; + msound = ((firsttype == chainlink) ? 0 : (mwidth & 1)); - spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - spawnee->reactiontime = mlength+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; - while (mlength > 0) + 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 (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke + { + if (mobj->type != MT_CHAINMACEPOINT) + continue; - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT) - spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; + firsttype = linktype = chainlink; + mlengthset = 1 + (mlength - 1)*radiusfactor; + radiusfactor = 1; + } else - spawnee->movecount = 0; + { + 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); + } - spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - spawnee->reactiontime = mlength; + firsttype = macetype; + } - if (firsttime) - { - // This is the outermost link in the chain - spawnee->flags2 |= MF2_AMBUSH; - firsttime = false; + 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 f6ebd3cadc497465312a139860ee2975b74619cc..c6e1bfbf2317b3f6a4f2f83f42fe04f9e63102fb 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 3853dc7e63826c08a337de65aeea322a9aba6b94..2d3412e65736115c07122edb3b0dddb80328ed8f 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 8a91de76bb57e4b3a2654901682263eb41ed432a..529589bec6c6c0546b79c99078b927a18a597db9 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))<<FRACBITS; @@ -1593,6 +1594,7 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) break; } + case 9: // Mace parameters case 14: // Bustable block parameters case 15: // Fan particle spawner parameters case 425: // Calls P_SetMobjState on calling mobj @@ -2571,6 +2573,21 @@ static void P_LoadNightsGhosts(void) free(gpath); } +static boolean CanSaveLevel(INT32 mapnum) +{ + if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked) + return false; + + if (G_IsSpecialStage(mapnum) // don't save in special stages + || mapnum == lastmaploaded) // don't save if the last map loaded was this one + return false; + + // Any levels that have the savegame flag can save normally. + // If the game is complete for this save slot, then any level can save! + // On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP! + return (mapheaderinfo[mapnum-1]->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 afa0ee960c940fb7108620121b5f59f3a2f24e65..a2c8c9279a14f19af242170f18b1aeab6a5651d9 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<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX if (!demoplayback || P_AnalogMove(player)) diff --git a/src/r_bsp.c b/src/r_bsp.c index abb11204a60233a8e59faf5f6618fc4fe09938b0..4ce89f009154b3145a96fd1f8ef63b87b6bab4fd 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 e871b5dde5c6ae704b5d772d06371f94e62ad361..80824831b8511fe1f6b02b22b66213bb82e26b31 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 32be7c4c8d360a6de6bbef0dbbff78fdf9175861..7744a12d8e93c81279842c9fc4ee5e514215b750 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 f7a5c2841a11f52c45447d3d4bb8a58f3b6301bb..6ac101f2d6474f6464c787bbafe0b00caa546292 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 {