# Conflicts:
#	src/hardware/hw_md2.c
This commit is contained in:
toasterbabe 2017-08-07 20:33:24 +01:00
commit 780f9b1645
35 changed files with 1821 additions and 605 deletions

View file

@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
<Option target="Debug Mingw64/DirectX" /> <Option target="Debug Mingw64/DirectX" />
<Option target="Release Mingw64/DirectX" /> <Option target="Release Mingw64/DirectX" />
</Unit> </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"> <Unit filename="src/hardware/hw_data.h">
<Option target="Debug Native/SDL" /> <Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" /> <Option target="Release Native/SDL" />

View file

@ -351,6 +351,7 @@ if(${SRB2_CONFIG_HWRENDER})
set(SRB2_HWRENDER_SOURCES set(SRB2_HWRENDER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.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_draw.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
@ -359,6 +360,7 @@ if(${SRB2_CONFIG_HWRENDER})
) )
set (SRB2_HWRENDER_HEADERS 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_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h

View file

@ -259,7 +259,7 @@ ifndef DC
endif endif
OPTS+=-DHWRENDER OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ 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 endif
ifdef NOHS ifdef NOHS
@ -703,7 +703,7 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ $(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 \ 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 \ 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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(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 \ $(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 \ 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 \ 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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ $(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 \ $(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 \ 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 \ 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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(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 \ $(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 \ 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 \ 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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(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 \ $(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 \ 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 \ 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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@

View file

@ -419,10 +419,13 @@ static void D_Display(void)
} }
// Image postprocessing effect // Image postprocessing effect
if (postimgtype) if (rendermode == render_soft)
V_DoPostProcessor(0, postimgtype, postimgparam); {
if (postimgtype2) if (postimgtype)
V_DoPostProcessor(1, postimgtype2, postimgparam2); V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
} }
if (lastdraw) if (lastdraw)
@ -712,6 +715,7 @@ void D_StartTitle(void)
botskin = 0; botskin = 0;
cv_debug = 0; cv_debug = 0;
emeralds = 0; emeralds = 0;
lastmaploaded = 0;
// In case someone exits out at the same time they start a time attack run, // In case someone exits out at the same time they start a time attack run,
// reset modeattacking // reset modeattacking

View file

@ -1329,6 +1329,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
else else
mapheaderinfo[num-1]->levelflags &= ~LF_NOZONE; 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 // Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN")) else if (fastcmp(word, "HIDDEN"))
@ -1776,7 +1783,6 @@ static actionpointer_t actionpointers[] =
{{A_CapeChase}, "A_CAPECHASE"}, {{A_CapeChase}, "A_CAPECHASE"},
{{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"}, {{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"},
{{A_SlingAppear}, "A_SLINGAPPEAR"}, {{A_SlingAppear}, "A_SLINGAPPEAR"},
{{A_MaceRotate}, "A_MACEROTATE"},
{{A_UnidusBall}, "A_UNIDUSBALL"}, {{A_UnidusBall}, "A_UNIDUSBALL"},
{{A_RockSpawn}, "A_ROCKSPAWN"}, {{A_RockSpawn}, "A_ROCKSPAWN"},
{{A_SetFuse}, "A_SETFUSE"}, {{A_SetFuse}, "A_SETFUSE"},
@ -4951,18 +4957,62 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SLING1", "S_SLING1",
"S_SLING2", "S_SLING2",
// CEZ Small Mace Chain // CEZ maces and chains
"S_SMALLMACECHAIN", "S_SMALLMACECHAIN",
// CEZ Big Mace Chain
"S_BIGMACECHAIN", "S_BIGMACECHAIN",
// CEZ Small Mace
"S_SMALLMACE", "S_SMALLMACE",
// CEZ Big Mace
"S_BIGMACE", "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", "S_CEZFLOWER1",
// Big Tumbleweed // Big Tumbleweed
@ -6297,14 +6347,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEPARTICLE", "MT_FLAMEPARTICLE",
"MT_EGGSTATUE", // Eggman Statue "MT_EGGSTATUE", // Eggman Statue
"MT_MACEPOINT", // Mace rotation point "MT_MACEPOINT", // Mace rotation point
"MT_SWINGMACEPOINT", // Mace swinging point "MT_CHAINMACEPOINT", // Combination of chains and maces point
"MT_HANGMACEPOINT", // Hangable mace chain "MT_SPRINGBALLPOINT", // Spring ball point
"MT_SPINMACEPOINT", // Spin/Controllable mace chain "MT_CHAINPOINT", // Mace chain
"MT_HIDDEN_SLING", // Spin mace chain (activatable) "MT_HIDDEN_SLING", // Spin mace chain (activatable)
"MT_FIREBARPOINT", // Firebar
"MT_CUSTOMMACEPOINT", // Custom mace
"MT_SMALLMACECHAIN", // Small Mace Chain "MT_SMALLMACECHAIN", // Small Mace Chain
"MT_BIGMACECHAIN", // Big Mace Chain "MT_BIGMACECHAIN", // Big Mace Chain
"MT_SMALLMACE", // Small Mace "MT_SMALLMACE", // Small Mace
"MT_BIGMACE", // Big 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", "MT_CEZFLOWER",
// Arid Canyon Scenery // Arid Canyon Scenery
@ -6657,6 +6713,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) "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) "SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
"MACEROTATE", // Thinker calls P_MaceRotate around tracer
NULL NULL
}; };
@ -7082,6 +7139,7 @@ struct {
{"LF_NOSSMUSIC",LF_NOSSMUSIC}, {"LF_NOSSMUSIC",LF_NOSSMUSIC},
{"LF_NORELOAD",LF_NORELOAD}, {"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE}, {"LF_NOZONE",LF_NOZONE},
{"LF_SAVEGAME",LF_SAVEGAME},
// And map flags // And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
@ -7900,11 +7958,14 @@ void FUNCMATH DEH_Check(void)
static inline int lib_freeslot(lua_State *L) static inline int lib_freeslot(lua_State *L)
{ {
int n = lua_gettop(L); int n = lua_gettop(L);
int r = 0; // args returned int r = 0; // args returned
char *s, *type,*word; 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)); s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_"); type = strtok(s, "_");
if (type) if (type)

View file

@ -584,6 +584,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Hudname padding. /// Hudname padding.
#define SKINNAMEPADDING #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. /// 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. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
//#define SECTORSPECIALSAFTERTHINK //#define SECTORSPECIALSAFTERTHINK

View file

@ -41,7 +41,8 @@ extern INT16 maptol;
extern UINT8 globalweather; extern UINT8 globalweather;
extern INT32 curWeather; extern INT32 curWeather;
extern INT32 cursaveslot; extern INT32 cursaveslot;
extern INT16 lastmapsaved; //extern INT16 lastmapsaved;
extern INT16 lastmaploaded;
extern boolean gamecomplete; extern boolean gamecomplete;
#define PRECIP_NONE 0 #define PRECIP_NONE 0
@ -263,6 +264,7 @@ typedef struct
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music #define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
#define LF_NORELOAD 8 ///< Don't reload level on death #define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title #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_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen #define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen

View file

@ -77,7 +77,8 @@ INT16 maptol;
UINT8 globalweather = 0; UINT8 globalweather = 0;
INT32 curWeather = PRECIP_NONE; INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = -1; // Auto-save 1p savegame slot 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; boolean gamecomplete = false;
UINT16 mainwads = 0; UINT16 mainwads = 0;

View file

@ -878,8 +878,8 @@ static void AdjustSegs(void)
count = subsectors[i].numlines; count = subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline]; lseg = &segs[subsectors[i].firstline];
p = extrasubsectors[i].planepoly; p = extrasubsectors[i].planepoly;
if (!p) //if (!p)
continue; //continue;
for (; count--; lseg++) for (; count--; lseg++)
{ {
float distv1,distv2,tmp; float distv1,distv2,tmp;
@ -892,29 +892,31 @@ static void AdjustSegs(void)
continue; continue;
#endif #endif
for (j = 0; j < p->numpts; j++) if (p) {
{ 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; distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
nearv1 = distv1; tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
} distv1 = distv1*distv1+tmp*tmp;
// the same with v2 if (distv1 <= nearv1)
distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x); {
tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y); v1found = j;
distv2 = distv2*distv2+tmp*tmp; nearv1 = distv1;
if (distv2 <= nearv2) }
{ // the same with v2
v2found = j; distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
nearv2 = distv2; 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 // share vertice with segs
lseg->v1 = (vertex_t *)&(p->pts[v1found]); lseg->pv1 = &(p->pts[v1found]);
else else
{ {
// BP: here we can do better, using PointInSeg and compute // BP: here we can do better, using PointInSeg and compute
@ -925,24 +927,24 @@ static void AdjustSegs(void)
polyvertex_t *pv = HWR_AllocVertex(); polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v1->x); pv->x = FIXED_TO_FLOAT(lseg->v1->x);
pv->y = FIXED_TO_FLOAT(lseg->v1->y); pv->y = FIXED_TO_FLOAT(lseg->v1->y);
lseg->v1 = (vertex_t *)pv; lseg->pv1 = pv;
} }
if (nearv2 <= NEARDIST*NEARDIST) if (p && nearv2 <= NEARDIST*NEARDIST)
lseg->v2 = (vertex_t *)&(p->pts[v2found]); lseg->pv2 = &(p->pts[v2found]);
else else
{ {
polyvertex_t *pv = HWR_AllocVertex(); polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v2->x); pv->x = FIXED_TO_FLOAT(lseg->v2->x);
pv->y = FIXED_TO_FLOAT(lseg->v2->y); pv->y = FIXED_TO_FLOAT(lseg->v2->y);
lseg->v2 = (vertex_t *)pv; lseg->pv2 = pv;
} }
// recompute length // recompute length
{ {
float x,y; 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); + 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); + FIXED_TO_FLOAT(FRACUNIT/2);
lseg->flength = (float)hypot(x, y); lseg->flength = (float)hypot(x, y);
// BP: debug see this kind of segs // BP: debug see this kind of segs

465
src/hardware/hw_clip.c Normal file
View file

@ -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

24
src/hardware/hw_clip.h Normal file
View file

@ -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

View file

@ -323,6 +323,10 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_BMCH &lspr[NOLIGHT], // SPR_BMCH
&lspr[NOLIGHT], // SPR_SMCE &lspr[NOLIGHT], // SPR_SMCE
&lspr[NOLIGHT], // SPR_BMCE &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 // Arid Canyon Scenery
&lspr[NOLIGHT], // SPR_BTBL &lspr[NOLIGHT], // SPR_BTBL

View file

@ -44,6 +44,10 @@
#endif #endif
#include "hw_md2.h" #include "hw_md2.h"
#ifdef NEWCLIP
#include "hw_clip.h"
#endif
#define R_FAKEFLOORS #define R_FAKEFLOORS
#define HWPRECIP #define HWPRECIP
#define SORTING #define SORTING
@ -99,8 +103,9 @@ CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NU
boolean drawsky = true; boolean drawsky = true;
// needs fix: walls are incorrectly clipped one column less // 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}; static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
//development variables for diverse uses //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_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}; 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 :( // test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK //#define NOCRAPPYMLOOK
/// \note crappy
#define drawtextured true
// base values set at SetViewSize // base values set at SetViewSize
static float gr_basecentery; static float gr_basecentery;
@ -852,11 +854,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
M_ClearBox(segbbox); M_ClearBox(segbbox);
M_AddToBox(segbbox, M_AddToBox(segbbox,
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x), FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x),
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y)); FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y));
M_AddToBox(segbbox, M_AddToBox(segbbox,
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x), FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x),
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y)); FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y));
splat = (wallsplat_t *)gr_curline->linedef->splats; splat = (wallsplat_t *)gr_curline->linedef->splats;
for (; splat; splat = splat->next) 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) // (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment // with the wall segment
// //
#ifndef NEWCLIP
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
{ {
float num, den; float num, den;
@ -1057,6 +1060,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
return num / den; return num / den;
} }
#endif
// //
// HWR_SplitWall // 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, // Anything between means the wall segment has been clipped with solidsegs,
// reducing wall overdraw to a minimum // 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) static void HWR_StoreWallRange(double startfrac, double endfrac)
#endif
{ {
wallVert3D wallVerts[4]; wallVert3D wallVerts[4];
v2d_t vs, ve; // start, end vertices of 2d line (view from above) 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; extracolormap_t *colormap;
FSurfaceInfo Surf; FSurfaceInfo Surf;
#ifndef NEWCLIP
if (startfrac > endfrac) if (startfrac > endfrac)
return; return;
#endif
gr_sidedef = gr_curline->sidedef; gr_sidedef = gr_curline->sidedef;
gr_linedef = gr_curline->linedef; gr_linedef = gr_curline->linedef;
vs.x = ((polyvertex_t *)gr_curline->v1)->x; vs.x = ((polyvertex_t *)gr_curline->pv1)->x;
vs.y = ((polyvertex_t *)gr_curline->v1)->y; vs.y = ((polyvertex_t *)gr_curline->pv1)->y;
ve.x = ((polyvertex_t *)gr_curline->v2)->x; ve.x = ((polyvertex_t *)gr_curline->pv2)->x;
ve.y = ((polyvertex_t *)gr_curline->v2)->y; ve.y = ((polyvertex_t *)gr_curline->pv2)->y;
#ifdef ESLOPE #ifdef ESLOPE
v1x = FLOAT_TO_FIXED(vs.x); v1x = FLOAT_TO_FIXED(vs.x);
@ -1473,44 +1483,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
v2x = FLOAT_TO_FIXED(ve.x); v2x = FLOAT_TO_FIXED(ve.x);
v2y = FLOAT_TO_FIXED(ve.y); v2y = FLOAT_TO_FIXED(ve.y);
#endif #endif
if (gr_frontsector->heightsec != -1)
{
#ifdef ESLOPE #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) #define SLOPEPARAMS(slope, end1, end2, normalheight) \
{ if (slope) { \
worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y); end1 = P_GetZAt(slope, v1x, v1y); \
worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y); end2 = P_GetZAt(slope, v2x, v2y); \
} } else \
else end1 = end2 = normalheight;
{
worldbottom = worldbottomslope = gr_frontsector->floorheight; SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight)
} SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
#else #else
worldtop = gr_frontsector->ceilingheight; worldtop = gr_frontsector->ceilingheight;
worldbottom = gr_frontsector->floorheight; worldbottom = gr_frontsector->floorheight;
#endif #endif
}
// remember vertices ordering // remember vertices ordering
// 3--2 // 3--2
@ -1525,20 +1512,23 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[2].z = wallVerts[1].z = ve.y; wallVerts[2].z = wallVerts[1].z = ve.y;
wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f; wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f;
if (drawtextured)
{ {
// x offset the texture // x offset the texture
fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset; fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset;
#ifndef NEWCLIP
// clip texture s start/end coords with solidsegs // clip texture s start/end coords with solidsegs
if (startfrac > 0.0f && startfrac < 1.0f) if (startfrac > 0.0f && startfrac < 1.0f)
cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac); cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac);
else else
#endif
cliplow = (float)texturehpeg; cliplow = (float)texturehpeg;
#ifndef NEWCLIP
if (endfrac > 0.0f && endfrac < 1.0f) if (endfrac > 0.0f && endfrac < 1.0f)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac); cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac);
else else
#endif
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
} }
@ -1554,43 +1544,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{ {
INT32 gr_toptexture, gr_bottomtexture; INT32 gr_toptexture, gr_bottomtexture;
// two sided line // 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) #ifdef ESLOPE
{ SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight)
worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y); SLOPEPARAMS(gr_backsector->f_slope, worldlow, worldlowslope, gr_backsector->floorheight)
worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y); #undef SLOPEPARAMS
}
else
{
worldlow = worldlowslope = gr_backsector->floorheight;
}
#else #else
worldhigh = gr_backsector->ceilingheight; worldhigh = gr_backsector->ceilingheight;
worldlow = gr_backsector->floorheight; worldlow = gr_backsector->floorheight;
#endif #endif
}
// hack to allow height changes in outdoor areas // hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky // 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 worldhigh < worldtop
) && gr_toptexture) ) && gr_toptexture)
{ {
if (drawtextured)
{ {
fixed_t texturevpegtop; // top fixed_t texturevpegtop; // top
@ -1695,7 +1656,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
#endif #endif
worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!! worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
{ {
if (drawtextured)
{ {
fixed_t texturevpegbottom = 0; // bottom fixed_t texturevpegbottom = 0; // bottom
@ -1887,7 +1847,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop); h = min(highcut, polytop);
l = max(polybottom, lowcut); l = max(polybottom, lowcut);
if (drawtextured)
{ {
// PEGGING // PEGGING
#ifdef ESLOPE #ifdef ESLOPE
@ -1943,7 +1902,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop); h = min(highcut, polytop);
l = max(polybottom, lowcut); l = max(polybottom, lowcut);
if (drawtextured)
{ {
// PEGGING // PEGGING
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) 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); gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
if (gr_midtexture) if (gr_midtexture)
{ {
if (drawtextured)
{ {
fixed_t texturevpeg; fixed_t texturevpeg;
// PEGGING // PEGGING
@ -2276,7 +2233,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0; wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].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 #ifdef ESLOPE // P.S. this is better-organized than the old version
fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset; 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[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0; wallVerts[2].s = wallVerts[1].s = 0;
} }
else if (drawtextured) else
{ {
grTex = HWR_GetTexture(texnum); grTex = HWR_GetTexture(texnum);
@ -2482,6 +2439,110 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
//Hurdler: end of 3d-floors test //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 //Hurdler: just like in r_bsp.c
#if 1 #if 1
#define MAXSEGS MAXVIDWIDTH/2+1 #define MAXSEGS MAXVIDWIDTH/2+1
@ -2553,7 +2614,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
} }
else 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); HWR_StoreWallRange(0, highfrac);
} }
// Now adjust the clip size. // Now adjust the clip size.
@ -2577,8 +2638,8 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
} }
else 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);
highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2); highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac); HWR_StoreWallRange(lowfrac, highfrac);
} }
next++; next++;
@ -2612,7 +2673,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
} }
else 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); HWR_StoreWallRange(lowfrac, 1);
} }
} }
@ -2675,8 +2736,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else else
{ {
highfrac = HWR_ClipViewSegment(min(start->first + 1, highfrac = HWR_ClipViewSegment(min(start->first + 1,
start->last), (polyvertex_t *)gr_curline->v1, start->last), (polyvertex_t *)gr_curline->pv1,
(polyvertex_t *)gr_curline->v2); (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac); HWR_StoreWallRange(0, highfrac);
} }
} }
@ -2695,8 +2756,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
} }
else else
{ {
lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (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->v1, (polyvertex_t *)gr_curline->v2); 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); HWR_StoreWallRange(lowfrac, highfrac);
} }
start++; start++;
@ -2726,8 +2787,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else else
{ {
lowfrac = HWR_ClipViewSegment(max(start->last - 1, lowfrac = HWR_ClipViewSegment(max(start->last - 1,
start->first), (polyvertex_t *)gr_curline->v1, start->first), (polyvertex_t *)gr_curline->pv1,
(polyvertex_t *)gr_curline->v2); (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1); HWR_StoreWallRange(lowfrac, 1);
} }
} }
@ -2767,6 +2828,7 @@ static void HWR_ClearClipSegs(void)
gr_solidsegs[1].last = 0x7fffffff; gr_solidsegs[1].last = 0x7fffffff;
hw_newend = gr_solidsegs+2; hw_newend = gr_solidsegs+2;
} }
#endif // NEWCLIP
// -----------------+ // -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list. // 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) static void HWR_AddLine(seg_t * line)
{ {
INT32 x1, x2;
angle_t angle1, angle2; angle_t angle1, angle2;
#ifndef NEWCLIP
INT32 x1, x2;
angle_t span, tspan; angle_t span, tspan;
#endif
// SoM: Backsector needs to be run through R_FakeFlat // SoM: Backsector needs to be run through R_FakeFlat
sector_t tempsec; 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)) if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return; return;
#endif
gr_curline = line; gr_curline = line;
// OPTIMIZE: quickly reject orthogonal back sides. v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
angle1 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x), v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y)); v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
angle2 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x), v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
// OPTIMIZE: quickly reject orthogonal back sides.
angle1 = R_PointToAngle(v1x, v1y);
angle2 = R_PointToAngle(v2x, v2y);
#ifdef NEWCLIP
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
if (angle2 - angle1 < ANGLE_180)
return;
// PrBoom: use REAL clipping math YAYYYYYYY!!!
if (!gld_clipper_SafeCheckRange(angle2, angle1))
{
return;
}
checkforemptylines = true;
#else
// Clip to view edges. // Clip to view edges.
span = angle1 - angle2; span = angle1 - angle2;
@ -2833,8 +2917,8 @@ static void HWR_AddLine(seg_t * line)
float fx1,fx2,fy1,fy2; float fx1,fx2,fy1,fy2;
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)] //BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
// do not enable this at release 4 mul and 2 div // do not enable this at release 4 mul and 2 div
fx1 = ((polyvertex_t *)(line->v1))->x-gr_viewx; fx1 = ((polyvertex_t *)(line->pv1))->x-gr_viewx;
fy1 = ((polyvertex_t *)(line->v1))->y-gr_viewy; fy1 = ((polyvertex_t *)(line->pv1))->y-gr_viewy;
fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin); fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin);
if (fy2 < 0) if (fy2 < 0)
// the point is back // the point is back
@ -2842,8 +2926,8 @@ static void HWR_AddLine(seg_t * line)
else else
fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2; fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2;
fx2 = ((polyvertex_t *)(line->v2))->x-gr_viewx; fx2 = ((polyvertex_t *)(line->pv2))->x-gr_viewx;
fy2 = ((polyvertex_t *)(line->v2))->y-gr_viewy; fy2 = ((polyvertex_t *)(line->pv2))->y-gr_viewy;
fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin); fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin);
if (fy1 < 0) if (fy1 < 0)
// the point is back // the point is back
@ -2871,8 +2955,34 @@ static void HWR_AddLine(seg_t * line)
return; return;
} }
*/ */
#endif
gr_backsector = line->backsector; 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? // Single sided line?
if (!gr_backsector) if (!gr_backsector)
goto clipsolid; goto clipsolid;
@ -2882,14 +2992,9 @@ static void HWR_AddLine(seg_t * line)
#ifdef ESLOPE #ifdef ESLOPE
if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_backsector->c_slope) 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 frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back 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) \ #define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \ if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \ end1 = P_GetZAt(slope, v1x, v1y); \
@ -2910,6 +3015,13 @@ static void HWR_AddLine(seg_t * line)
goto clipsolid; 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. // Window.
if (backc1 != frontc1 || backc2 != frontc2 if (backc1 != frontc1 || backc2 != frontc2
|| backf1 != frontf1 || backf2 != frontf2) || backf1 != frontf1 || backf2 != frontf2)
@ -2925,6 +3037,13 @@ static void HWR_AddLine(seg_t * line)
gr_backsector->floorheight >= gr_frontsector->ceilingheight) gr_backsector->floorheight >= gr_frontsector->ceilingheight)
goto clipsolid; 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. // Window.
if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight || if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight ||
gr_backsector->floorheight != gr_frontsector->floorheight) 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 floor and ceiling on both sides,
// identical light levels on both sides, // identical light levels on both sides,
// and no middle texture. // and no middle texture.
if ( if (R_IsEmptyLine(gr_curline, gr_frontsector, gr_backsector))
#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...
{
return; return;
}
clippass: clippass:
if (x1 == x2) if (x1 == x2)
@ -2965,6 +3067,7 @@ clipsolid:
if (x1 == x2) if (x1 == x2)
goto clippass; goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1); HWR_ClipSolidWallSegment(x1, x2-1);
#endif
} }
// HWR_CheckBBox // HWR_CheckBBox
@ -2976,9 +3079,13 @@ clipsolid:
static boolean HWR_CheckBBox(fixed_t *bspcoord) static boolean HWR_CheckBBox(fixed_t *bspcoord)
{ {
INT32 boxpos, sx1, sx2; INT32 boxpos;
fixed_t px1, py1, px2, py2; 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 // Find the corners of the box
// that define the edges from current viewpoint. // that define the edges from current viewpoint.
@ -3004,6 +3111,11 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
px2 = bspcoord[checkcoord[boxpos][2]]; px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]]; 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 // check clip list for an open space
angle1 = R_PointToAngle(px1, py1) - dup_viewangle; angle1 = R_PointToAngle(px1, py1) - dup_viewangle;
angle2 = R_PointToAngle(px2, py2) - dup_viewangle; angle2 = R_PointToAngle(px2, py2) - dup_viewangle;
@ -3051,6 +3163,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return false; return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1); return HWR_ClipToSolidSegs(sx1, sx2 - 1);
#endif
} }
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
@ -3084,8 +3197,8 @@ static inline void HWR_AddPolyObjectSegs(void)
pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x); pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x);
pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y); pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y);
gr_fakeline->v1 = (vertex_t *)pv1; gr_fakeline->pv1 = pv1;
gr_fakeline->v2 = (vertex_t *)pv2; gr_fakeline->pv2 = pv2;
HWR_AddLine(gr_fakeline); HWR_AddLine(gr_fakeline);
} }
@ -5630,7 +5743,19 @@ if (0)
#ifdef SORTING #ifdef SORTING
drawcount = 0; drawcount = 0;
#endif #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(); HWR_ClearClipSegs();
#endif
//04/01/2000: Hurdler: added for T&L //04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes // Actually it only works on Walls and Planes
@ -5640,6 +5765,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1); HWR_RenderBSPNode((INT32)numnodes-1);
#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
viewangle = localaiming; viewangle = localaiming;
@ -5666,6 +5792,7 @@ if (0)
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
} }
#endif
// Check for new console commands. // Check for new console commands.
NetUpdate(); NetUpdate();
@ -5860,7 +5987,19 @@ if (0)
#ifdef SORTING #ifdef SORTING
drawcount = 0; drawcount = 0;
#endif #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(); HWR_ClearClipSegs();
#endif
//04/01/2000: Hurdler: added for T&L //04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes // Actually it only works on Walls and Planes
@ -5870,6 +6009,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1); HWR_RenderBSPNode((INT32)numnodes-1);
#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
viewangle = localaiming; viewangle = localaiming;
@ -5896,6 +6036,7 @@ if (0)
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
} }
#endif
// Check for new console commands. // Check for new console commands.
NetUpdate(); NetUpdate();
@ -6041,7 +6182,9 @@ static inline void HWR_AddEngineCommands(void)
{ {
// engine state variables // engine state variables
//CV_RegisterVar(&cv_grzbuffer); //CV_RegisterVar(&cv_grzbuffer);
#ifndef NEWCLIP
CV_RegisterVar(&cv_grclipwalls); CV_RegisterVar(&cv_grclipwalls);
#endif
// engine development mode variables // engine development mode variables
// - usage may vary from version to version.. // - usage may vary from version to version..

View file

@ -298,8 +298,8 @@ static md2_model_t *md2_readModel(const char *filename)
// initialize model and read header // initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1 if (fread(&model->header, sizeof (model->header), 1, file) != 1
|| model->header.magic != || model->header.magic != MD2_IDENT
(INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')) || model->header.version != MD2_VERSION)
{ {
fclose(file); fclose(file);
free(model); 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); \ CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
md2_freeModel (model); \ md2_freeModel (model); \
fclose(file); \
return 0; \ 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)) fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{ {
md2_freeModel (model); md2_freeModel (model);
fclose(file);
return 0; 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)) fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{ {
md2_freeModel (model); md2_freeModel (model);
fclose(file);
return 0; 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)) fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{ {
md2_freeModel (model); md2_freeModel (model);
fclose(file);
return 0; return 0;
} }
} }
@ -372,6 +376,7 @@ static md2_model_t *md2_readModel(const char *filename)
if (!model->frames) if (!model->frames)
{ {
md2_freeModel (model); md2_freeModel (model);
fclose(file);
return 0; return 0;
} }
@ -385,6 +390,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(frame, 1, model->header.frameSize, file)) fread(frame, 1, model->header.frameSize, file))
{ {
md2_freeModel (model); md2_freeModel (model);
fclose(file);
return 0; return 0;
} }
@ -410,6 +416,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file)) fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{ {
md2_freeModel (model); md2_freeModel (model);
fclose(file);
return 0; return 0;
} }
} }

View file

@ -23,6 +23,11 @@
#include "hw_glob.h" #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_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096 #define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096 #define MD2_MAX_TEXCOORDS 4096

View file

@ -107,17 +107,17 @@ static void releaseLineChains(void)
for (i = 0; i < numsectors; i++) for (i = 0; i < numsectors; i++)
{ {
sector = &sectors[i]; sector = &sectors[i];
nextElem = sector->sectorLines; nextElem = sector->sectorLines;
while (nextElem) while (nextElem)
{ {
thisElem = nextElem; thisElem = nextElem;
nextElem = thisElem->next; nextElem = thisElem->next;
free(thisElem); free(thisElem);
} }
sector->sectorLines = NULL; sector->sectorLines = NULL;
} }
} }
@ -397,7 +397,7 @@ static void sortStacklist(sector_t *sector)
i = 0; i = 0;
finished = true; finished = true;
while (NULL != *(list+i+1)) while (*(list+i+1))
{ {
sec1 = *(list+i); sec1 = *(list+i);
sec2 = *(list+i+1); sec2 = *(list+i+1);
@ -438,7 +438,7 @@ static double calcLineoutLength(sector_t *sector)
double length = 0.0L; double length = 0.0L;
chain = sector->sectorLines; chain = sector->sectorLines;
while (NULL != chain) // sum up lengths of all lines while (chain) // sum up lengths of all lines
{ {
length += lineLength(chain->line); length += lineLength(chain->line);
chain = chain->next; chain = chain->next;
@ -454,7 +454,7 @@ static void calcLineouts(sector_t *sector)
size_t secCount = 0; size_t secCount = 0;
sector_t *encSector = *(sector->stackList); sector_t *encSector = *(sector->stackList);
while (NULL != encSector) while (encSector)
{ {
if (encSector->lineoutLength < 0.0L) // if length has not yet been calculated 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 if (frontSector == backSector) // skip damn renderer tricks here
continue; continue;
if (frontSector == NULL || backSector == NULL) if (!frontSector || !backSector)
continue; continue;
sider = &sides[thisElem->line->sidenum[0]]; sider = &sides[thisElem->line->sidenum[0]];
@ -587,73 +587,12 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
static boolean isCeilingFloating(sector_t *thisSector) static boolean isCeilingFloating(sector_t *thisSector)
{ {
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector; sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
boolean floating = true;
linechain_t *thisElem, *nextElem; linechain_t *thisElem, *nextElem;
if (!thisSector) if (!thisSector)
return false; return false;
nextElem = thisSector->sectorLines; nextElem = thisSector->sectorLines;
while (NULL != nextElem) // walk through chain
{
thisElem = nextElem;
nextElem = thisElem->next;
frontSector = thisElem->line->frontsector;
backSector = thisElem->line->backsector;
if (frontSector == thisSector)
adjSector = backSector;
else
adjSector = frontSector;
if (!adjSector) // assume floating sectors have surrounding sectors
{
floating = false;
break;
}
if (!refSector)
{
refSector = adjSector;
continue;
}
// if adjacent sector has same height or more than one adjacent sector exists -> stop
if (thisSector->ceilingheight == adjSector->ceilingheight ||
refSector != adjSector)
{
floating = false;
break;
}
}
// now check for walltextures
if (floating)
{
if (!areToptexturesMissing(thisSector))
{
floating = false;
}
}
return floating;
}
//
// check if no adjacent sector has same ceiling height
// FIXME: throw that together with isCeilingFloating??
//
static boolean isFloorFloating(sector_t *thisSector)
{
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
boolean floating = true;
linechain_t *thisElem, *nextElem;
if (!thisSector)
return false;
nextElem = thisSector->sectorLines;
while (nextElem) // walk through chain while (nextElem) // walk through chain
{ {
@ -668,36 +607,83 @@ static boolean isFloorFloating(sector_t *thisSector)
else else
adjSector = frontSector; adjSector = frontSector;
if (NULL == adjSector) // assume floating sectors have surrounding sectors if (!adjSector) // assume floating sectors have surrounding sectors
{ return false;
floating = false;
break;
}
if (NULL == refSector) #ifdef ESLOPE
if (adjSector->c_slope) // Don't bother with slopes
return false;
#endif
if (!refSector)
{ {
refSector = adjSector; refSector = adjSector;
continue; continue;
} }
// if adjacent sector has same height or more than one adjacent sector exists -> stop // if adjacent sector has same height or more than one adjacent sector exists -> stop
if (thisSector->floorheight == adjSector->floorheight || if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector)
refSector != adjSector) return false;
{
floating = false;
break;
}
} }
// now check for walltextures // now check for walltextures
if (floating) if (!areToptexturesMissing(thisSector))
return false;
return true;
}
//
// check if no adjacent sector has same ceiling height
// FIXME: throw that together with isCeilingFloating??
//
static boolean isFloorFloating(sector_t *thisSector)
{
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
linechain_t *thisElem, *nextElem;
if (!thisSector)
return false;
nextElem = thisSector->sectorLines;
while (nextElem) // walk through chain
{ {
if (!areBottomtexturesMissing(thisSector)) thisElem = nextElem;
nextElem = thisElem->next;
frontSector = thisElem->line->frontsector;
backSector = thisElem->line->backsector;
if (frontSector == thisSector)
adjSector = backSector;
else
adjSector = frontSector;
if (!adjSector) // assume floating sectors have surrounding sectors
return false;
#ifdef ESLOPE
if (adjSector->f_slope) // Don't bother with slopes
return false;
#endif
if (!refSector)
{ {
floating = false; refSector = adjSector;
continue;
} }
// if adjacent sector has same height or more than one adjacent sector exists -> stop
if (thisSector->floorheight == adjSector->floorheight || refSector != adjSector)
return false;
} }
return floating;
// now check for walltextures
if (!areBottomtexturesMissing(thisSector))
return false;
return true;
} }
// //
@ -707,14 +693,12 @@ static fixed_t estimateCeilHeight(sector_t *thisSector)
{ {
sector_t *adjSector; sector_t *adjSector;
if (!thisSector || if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
!thisSector->sectorLines ||
!thisSector->sectorLines->line)
return 0; return 0;
adjSector = thisSector->sectorLines->line->frontsector; adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector) if (adjSector == thisSector)
adjSector = thisSector->sectorLines->line->backsector; adjSector = thisSector->sectorLines->line->backsector;
if (!adjSector) if (!adjSector)
return 0; return 0;
@ -729,17 +713,15 @@ static fixed_t estimateFloorHeight(sector_t *thisSector)
{ {
sector_t *adjSector; sector_t *adjSector;
if (!thisSector || if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
!thisSector->sectorLines || return 0;
!thisSector->sectorLines->line)
return 0;
adjSector = thisSector->sectorLines->line->frontsector; adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector) if (adjSector == thisSector)
adjSector = thisSector->sectorLines->line->backsector; adjSector = thisSector->sectorLines->line->backsector;
if (NULL == adjSector) if (!adjSector)
return 0; return 0;
return adjSector->floorheight; return adjSector->floorheight;
} }
@ -845,18 +827,12 @@ void HWR_CorrectSWTricks(void)
// correct height of floating sectors // correct height of floating sectors
if (isCeilingFloating(floatSector)) if (isCeilingFloating(floatSector))
{ {
fixed_t corrheight; floatSector->virtualCeilingheight = estimateCeilHeight(floatSector);
corrheight = estimateCeilHeight(floatSector);
floatSector->virtualCeilingheight = corrheight;
floatSector->virtualCeiling = true; floatSector->virtualCeiling = true;
} }
if (isFloorFloating(floatSector)) if (isFloorFloating(floatSector))
{ {
fixed_t corrheight; floatSector->virtualFloorheight = estimateFloorHeight(floatSector);
corrheight = estimateFloorHeight(floatSector);
floatSector->virtualFloorheight = corrheight;
floatSector->virtualFloor = true; floatSector->virtualFloor = true;
} }
} }

View file

@ -211,6 +211,10 @@ char sprnames[NUMSPRITES + 1][5] =
"BMCH", // Big Mace Chain "BMCH", // Big Mace Chain
"SMCE", // Small Mace "SMCE", // Small Mace
"BMCE", // Big 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 // Arid Canyon Scenery
"BTBL", // Big tumbleweed "BTBL", // Big tumbleweed
@ -1830,13 +1834,13 @@ state_t states[NUMSTATES] =
{SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN {SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN
// Flame // Flame
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1 {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|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|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|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|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_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_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 {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, {NULL}, 0, 0, S_SLING2}, // S_SLING1
{SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2 {SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2
// Small Mace Chain // CEZ maces and chains
{SPR_SMCH, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN {SPR_SMCH, 0, -1, {NULL}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
{SPR_BMCH, 0, -1, {NULL}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
{SPR_SMCE, 0, -1, {NULL}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
{SPR_BMCE, 0, -1, {NULL}, 0, 0, S_BIGMACE}, // S_BIGMACE
// Big Mace Chain // Yellow spring on a ball
{SPR_BMCH, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL
{SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2
{SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4}, // S_YELLOWSPRINGBALL3
{SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5}, // S_YELLOWSPRINGBALL4
{SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL}, // S_YELLOWSPRINGBALL5
// Small Mace // Red spring on a ball
{SPR_SMCE, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACE}, // S_SMALLMACE {SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRINGBALL
{SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3}, // S_REDSPRINGBALL2
{SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4}, // S_REDSPRINGBALL3
{SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5}, // S_REDSPRINGBALL4
{SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL}, // S_REDSPRINGBALL5
// Big Mace // Small Firebar
{SPR_BMCE, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACE}, // S_BIGMACE {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 // CEZ Flower
{SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER1 {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER1
// Big Tumbleweed // Big Tumbleweed
{SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED {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, 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, 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, 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, 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, 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, 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, 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, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
// Little Tumbleweed // Little Tumbleweed
{SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED {SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED
@ -8822,7 +8870,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_SWINGMACEPOINT { // MT_CHAINMACEPOINT
1105, // doomednum 1105, // doomednum
S_INVISIBLE, // spawnstate S_INVISIBLE, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
@ -8849,7 +8897,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_HANGMACEPOINT { // MT_SPRINGBALLPOINT
1106, // doomednum 1106, // doomednum
S_INVISIBLE, // spawnstate S_INVISIBLE, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
@ -8876,7 +8924,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_SPINMACEPOINT { // MT_CHAINPOINT
1107, // doomednum 1107, // doomednum
S_INVISIBLE, // spawnstate S_INVISIBLE, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
@ -8896,7 +8944,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
128*FRACUNIT, // radius 128*FRACUNIT, // radius
1*FRACUNIT, // height 1*FRACUNIT, // height
0, // display offset 0, // display offset
200, // mass 10000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
@ -8930,6 +8978,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate 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 { // MT_SMALLMACECHAIN
-1, // doomednum -1, // doomednum
S_SMALLMACECHAIN, // spawnstate S_SMALLMACECHAIN, // spawnstate
@ -8953,7 +9055,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
1, // damage 1, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -8980,7 +9082,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
1, // damage 1, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -9003,11 +9105,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // speed 24*FRACUNIT, // speed
17*FRACUNIT, // radius 17*FRACUNIT, // radius
34*FRACUNIT, // height 34*FRACUNIT, // height
0, // display offset 1, // display offset
100, // mass 100, // mass
1, // damage 1, // damage
sfx_mswing, // activesound sfx_mswing, // activesound
MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -9030,11 +9132,119 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
48*FRACUNIT, // speed 48*FRACUNIT, // speed
34*FRACUNIT, // radius 34*FRACUNIT, // radius
68*FRACUNIT, // height 68*FRACUNIT, // height
0, // display offset 1, // display offset
100, // mass 100, // mass
1, // damage 1, // damage
sfx_mswing, // activesound 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 S_NULL // raisestate
}, },

View file

@ -84,7 +84,6 @@ void A_DetonChase(); // Deton Chaser
void A_CapeChase(); // Fake little Super Sonic cape void A_CapeChase(); // Fake little Super Sonic cape
void A_RotateSpikeBall(); // Spike ball rotation void A_RotateSpikeBall(); // Spike ball rotation
void A_SlingAppear(); void A_SlingAppear();
void A_MaceRotate();
void A_UnidusBall(); void A_UnidusBall();
void A_RockSpawn(); void A_RockSpawn();
void A_SetFuse(); void A_SetFuse();
@ -417,6 +416,10 @@ typedef enum sprite
SPR_BMCH, // Big Mace Chain SPR_BMCH, // Big Mace Chain
SPR_SMCE, // Small Mace SPR_SMCE, // Small Mace
SPR_BMCE, // Big 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 // Arid Canyon Scenery
SPR_BTBL, // Big tumbleweed SPR_BTBL, // Big tumbleweed
@ -2056,18 +2059,62 @@ typedef enum state
S_SLING1, S_SLING1,
S_SLING2, S_SLING2,
// CEZ Small Mace Chain // CEZ maces and chains
S_SMALLMACECHAIN, S_SMALLMACECHAIN,
// CEZ Big Mace Chain
S_BIGMACECHAIN, S_BIGMACECHAIN,
// CEZ Small Mace
S_SMALLMACE, S_SMALLMACE,
// CEZ Big Mace
S_BIGMACE, 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, S_CEZFLOWER1,
// Big Tumbleweed // Big Tumbleweed
@ -3421,14 +3468,20 @@ typedef enum mobj_type
MT_FLAMEPARTICLE, MT_FLAMEPARTICLE,
MT_EGGSTATUE, // Eggman Statue MT_EGGSTATUE, // Eggman Statue
MT_MACEPOINT, // Mace rotation point MT_MACEPOINT, // Mace rotation point
MT_SWINGMACEPOINT, // Mace swinging point MT_CHAINMACEPOINT, // Combination of chains and maces point
MT_HANGMACEPOINT, // Hangable mace chain MT_SPRINGBALLPOINT, // Spring ball point
MT_SPINMACEPOINT, // Spin/Controllable mace chain MT_CHAINPOINT, // Mace chain
MT_HIDDEN_SLING, // Spin mace chain (activatable) MT_HIDDEN_SLING, // Spin mace chain (activatable)
MT_FIREBARPOINT, // Firebar
MT_CUSTOMMACEPOINT, // Custom mace
MT_SMALLMACECHAIN, // Small Mace Chain MT_SMALLMACECHAIN, // Small Mace Chain
MT_BIGMACECHAIN, // Big Mace Chain MT_BIGMACECHAIN, // Big Mace Chain
MT_SMALLMACE, // Small Mace MT_SMALLMACE, // Small Mace
MT_BIGMACE, // Big 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, MT_CEZFLOWER,
// Arid Canyon Scenery // Arid Canyon Scenery

View file

@ -22,8 +22,13 @@
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
// for functions not allowed in hud.add hooks
#define NOHUD if (hud_running)\ #define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!"); 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)\ #define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a 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); strlwr(name);
luaL_checktype(L, 2, LUA_TFUNCTION); luaL_checktype(L, 2, LUA_TFUNCTION);
NOHUD NOHOOK
if (lua_gettop(L) >= 3) if (lua_gettop(L) >= 3)
{ // For the third argument, only take a boolean or a number. { // For the third argument, only take a boolean or a number.
lua_settop(L, 3); lua_settop(L, 3);
@ -296,7 +301,7 @@ static int lib_cvRegisterVar(lua_State *L)
consvar_t *cvar; consvar_t *cvar;
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
NOHUD NOHOOK
cvar = lua_newuserdata(L, sizeof(consvar_t)); cvar = lua_newuserdata(L, sizeof(consvar_t));
luaL_getmetatable(L, META_CVAR); luaL_getmetatable(L, META_CVAR);
lua_setmetatable(L, -2); lua_setmetatable(L, -2);

View file

@ -109,8 +109,8 @@ static int lib_addHook(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION); luaL_checktype(L, 1, LUA_TFUNCTION);
if (hud_running) if (!lua_lumploading)
return luaL_error(L, "HUD rendering code should not call this function!"); return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
switch(hook.type) switch(hook.type)
{ {

View file

@ -612,6 +612,9 @@ static int lib_hudadd(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION); luaL_checktype(L, 1, LUA_TFUNCTION);
field = luaL_checkoption(L, 2, "game", hudhook_opt); 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"); lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(L, -1)); I_Assert(lua_istable(L, -1));
lua_rawgeti(L, -1, field+2); // HUD[2+] lua_rawgeti(L, -1, field+2); // HUD[2+]

View file

@ -161,6 +161,11 @@ void LUA_ClearExtVars(void)
} }
#endif #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 // Load a script from a MYFILE
static inline void LUA_LoadFile(MYFILE *f, char *name) 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'; 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); free(name);
Z_Free(f.data); Z_Free(f.data);

View file

@ -38,6 +38,8 @@
void LUA_ClearExtVars(void); void LUA_ClearExtVars(void);
#endif #endif
extern boolean lua_lumploading; // is LUA_LoadLump being called?
void LUA_LoadLump(UINT16 wad, UINT16 lump); void LUA_LoadLump(UINT16 wad, UINT16 lump);
#ifdef LUA_ALLOW_BYTECODE #ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename); void LUA_DumpFile(const char *filename);

View file

@ -6720,7 +6720,7 @@ static void M_ChoosePlayer(INT32 choice)
if (startmap != spstage_start) if (startmap != spstage_start)
cursaveslot = -1; cursaveslot = -1;
lastmapsaved = 0; //lastmapsaved = 0;
gamecomplete = false; gamecomplete = false;
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect); G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect);

View file

@ -137,7 +137,6 @@ void A_DetonChase(mobj_t *actor);
void A_CapeChase(mobj_t *actor); void A_CapeChase(mobj_t *actor);
void A_RotateSpikeBall(mobj_t *actor); void A_RotateSpikeBall(mobj_t *actor);
void A_SlingAppear(mobj_t *actor); void A_SlingAppear(mobj_t *actor);
void A_MaceRotate(mobj_t *actor);
void A_UnidusBall(mobj_t *actor); void A_UnidusBall(mobj_t *actor);
void A_RockSpawn(mobj_t *actor); void A_RockSpawn(mobj_t *actor);
void A_SetFuse(mobj_t *actor); void A_SetFuse(mobj_t *actor);
@ -5175,15 +5174,12 @@ void A_SlingAppear(mobj_t *actor)
actor->movefactor = actor->threshold; actor->movefactor = actor->threshold;
actor->friction = 128; actor->friction = 128;
actor->flags |= MF_SLIDEME;
while (mlength > 0) while (mlength > 0)
{ {
spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN); spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN);
P_SetTarget(&spawnee->target, actor); P_SetTarget(&spawnee->target, actor);
spawnee->movecount = 0;
spawnee->threshold = 0; spawnee->threshold = 0;
spawnee->reactiontime = mlength; 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 // 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) // 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. // Description: Creates the mobj's painchance at a random position around the object's radius.
// //
// var1 = momz of particle. // var1 = momz of particle.
// var2 = chance of particle spawn
// //
void A_FlameParticle(mobj_t *actor) void A_FlameParticle(mobj_t *actor)
{ {
mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
fixed_t rad, hei;
mobj_t *particle;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_FlameParticle", actor)) if (LUA_CallAction("A_FlameParticle", actor))
return; return;
#endif #endif
if (type) if (!P_RandomChance(locvar2))
{ return;
fixed_t rad = 2*actor->radius>>FRACBITS;
fixed_t hei = actor->height>>FRACBITS; if (!type)
mobj_t *particle = P_SpawnMobjFromMobj(actor, return;
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(rad, -rad)<<FRACBITS, rad = 2*actor->radius>>FRACBITS;
P_RandomRange(hei/2, hei)<<FRACBITS, hei = actor->height>>FRACBITS;
type); particle = P_SpawnMobjFromMobj(actor,
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false); P_RandomRange(rad, -rad)<<FRACBITS,
} P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(hei/2, hei)<<FRACBITS,
type);
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false);
} }

View file

@ -1496,10 +1496,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->powers[pw_flashing]) if (player->powers[pw_flashing])
return; 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_ResetPlayer(player);
P_SetTarget(&toucher->tracer, special); 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; player->powers[pw_carry] = CR_MACESPIN;
S_StartSound(toucher, sfx_spin); 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 // Can't jump first frame
player->pflags |= PF_JUMPSTASIS; player->pflags |= PF_JUMPSTASIS;
return; return;
case MT_BIGMINE: case MT_BIGMINE:
case MT_BIGAIRMINE: case MT_BIGAIRMINE:

View file

@ -6269,6 +6269,128 @@ static void P_NightsItemChase(mobj_t *thing)
P_Attract(thing, thing->tracer, true); 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) static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
{ {
if (!thing->target || thing->target->health <= 0 || !thing->target->player 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... // fade out when nearing the end of fuse...
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); 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 // Special thinker for scenery objects
if (mobj->flags & MF_SCENERY) if (mobj->flags & MF_SCENERY)
{ {
@ -7291,7 +7420,8 @@ void P_MobjThinker(mobj_t *mobj)
} }
} }
break; break;
case MT_SPINMACEPOINT: case MT_CHAINPOINT:
case MT_CHAINMACEPOINT:
if (leveltime & 1) if (leveltime & 1)
{ {
if (mobj->lastlook > mobj->movecount) if (mobj->lastlook > mobj->movecount)
@ -9635,15 +9765,20 @@ void P_SpawnMapThing(mapthing_t *mthing)
mobj->movedir = mthing->extrainfo; mobj->movedir = mthing->extrainfo;
break; break;
case MT_MACEPOINT: case MT_MACEPOINT:
case MT_SWINGMACEPOINT: case MT_CHAINMACEPOINT:
case MT_HANGMACEPOINT: case MT_SPRINGBALLPOINT:
case MT_SPINMACEPOINT: case MT_CHAINPOINT:
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
{ {
fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed; fixed_t mlength, mlengthset, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mnumspokesset, mpinch, mroll, mnumnospokes, mwidth, mmin, msound, radiusfactor;
mobjtype_t chainlink = MT_SMALLMACECHAIN; angle_t mspokeangle;
mobjtype_t macetype = MT_SMALLMACE; mobjtype_t chainlink, macetype, firsttype, linktype;
boolean firsttime; boolean mdoall = true;
mobj_t *spawnee; mobj_t *spawnee;
mobjflag_t mflagsapply;
mobjflag2_t mflags2apply;
mobjeflag_t meflagsapply;
INT32 line; INT32 line;
const size_t mthingi = (size_t)(mthing - mapthings); const size_t mthingi = (size_t)(mthing - mapthings);
@ -9657,93 +9792,240 @@ void P_SpawnMapThing(mapthing_t *mthing)
return; return;
} }
/* /*
No deaf - small mace mapthing -
Deaf - big mace MTF_AMBUSH :
MT_SPRINGBALLPOINT - upgrade from yellow to red spring
anything else - bigger mace/chain theory
MTF_OBJECTSPECIAL - force silent
MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements
Parameter value : number of "spokes"
ML_NOCLIMB : Direction not controllable linedef -
ML_NOCLIMB :
MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable
anything else - no functionality
ML_EFFECT1 : Swings instead of spins
ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT)
ML_EFFECT3 : Spawn a bonus macetype at the hinge point
ML_EFFECT4 : Don't clip inside the ground
*/ */
mlength = abs(lines[line].dx >> FRACBITS); mlength = abs(lines[line].dx >> FRACBITS);
mspeed = abs(lines[line].dy >> FRACBITS); mspeed = abs(lines[line].dy >> (FRACBITS - 4));
mxspeed = sides[lines[line].sidenum[0]].textureoffset >> FRACBITS; mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360;
mzspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS; if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> (FRACBITS - 4)) < mspeed)
mstartangle = lines[line].frontsector->floorheight >> FRACBITS; mmaxspeed = mspeed << 1;
mmaxspeed = lines[line].frontsector->ceilingheight >> FRACBITS; mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360;
myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360;
mstartangle %= 360; mnumspokes = mthing->extrainfo + 1;
mxspeed %= 360; mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT;
mzspeed %= 360;
CONS_Debug(DBG_GAMELOGIC, "Mace Chain (mapthing #%s):\n" if (lines[line].backsector)
{
mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360;
mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360;
mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS);
if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0)
mwidth = 0;
}
else
mpinch = mroll = mnumnospokes = mwidth = 0;
CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n"
"Length is %d\n" "Length is %d\n"
"Speed is %d\n" "Speed is %d\n"
"Xspeed is %d\n" "Phase is %d\n"
"Zspeed is %d\n" "Yaw is %d\n"
"startangle is %d\n" "Pitch is %d\n"
"maxspeed is %d\n", "Max. speed is %d\n"
sizeu1(mthingi), mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed); "No. of spokes is %d\n"
"Pinch is %d\n"
"Roll is %d\n"
"No. of antispokes is %d\n"
"Width is %d\n",
sizeu1(mthingi), mlength, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mpinch, mroll, mnumnospokes, mwidth);
mobj->lastlook = mspeed << 4; if (mnumnospokes > 0 && (mnumnospokes < mnumspokes))
mnumnospokes = mnumspokes/mnumnospokes;
else
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0);
mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook; mobj->movecount = mobj->lastlook;
mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); mobj->health = (FixedAngle(myaw*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->threshold = (FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->movefactor = mobj->threshold;
mobj->friction = mmaxspeed; mobj->friction = mmaxspeed;
mobj->movefactor = mpinch;
// Mobjtype selection
switch(mobj->type)
{
case MT_SPRINGBALLPOINT:
macetype = ((mthing->options & MTF_AMBUSH)
? MT_REDSPRINGBALL
: MT_YELLOWSPRINGBALL);
chainlink = MT_SMALLMACECHAIN;
break;
case MT_FIREBARPOINT:
macetype = ((mthing->options & MTF_AMBUSH)
? MT_BIGFIREBAR
: MT_SMALLFIREBAR);
chainlink = MT_NULL;
break;
case MT_CUSTOMMACEPOINT:
macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture;
if (lines[line].backsector)
chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture;
else
chainlink = MT_NULL;
break;
default:
if (mthing->options & MTF_AMBUSH)
{
macetype = MT_BIGMACE;
chainlink = MT_BIGMACECHAIN;
}
else
{
macetype = MT_SMALLMACE;
chainlink = MT_SMALLMACECHAIN;
}
break;
}
if (!macetype)
break;
if (mobj->type != MT_CHAINPOINT)
{
firsttype = macetype;
mlength++;
}
else
{
if (!mlength)
break;
firsttype = chainlink;
}
// Adjustable direction
if (lines[line].flags & ML_NOCLIMB) if (lines[line].flags & ML_NOCLIMB)
mobj->flags |= MF_SLIDEME; mobj->flags |= MF_SLIDEME;
mobj->reactiontime = 0; // Swinging
if (lines[line].flags & ML_EFFECT1)
if (mthing->options & MTF_AMBUSH)
{ {
chainlink = MT_BIGMACECHAIN; mobj->flags2 |= MF2_STRONGBOX;
macetype = MT_BIGMACE; mmin = ((mnumnospokes > 1) ? 1 : 0);
} }
if (mthing->options & MTF_OBJECTSPECIAL)
mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces.
if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SPINMACEPOINT)
firsttime = true;
else 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.
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype);
P_SetTarget(&spawnee->target, mobj);
if (mobj->type == MT_SWINGMACEPOINT)
spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
else
spawnee->movecount = 0;
spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
spawnee->reactiontime = mlength+1;
} }
else
radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
while (mlength > 0) mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT));
mflags2apply = (MF2_MACEROTATE|((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0));
meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0);
msound = ((firsttype == chainlink) ? 0 : (mwidth & 1));
// Quick and easy preparatory variable setting
mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT);
mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT);
#define makemace(mobjtype, dist, moreflags2) P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
P_SetTarget(&spawnee->tracer, mobj);\
spawnee->threshold = mphase;\
spawnee->friction = mroll;\
spawnee->movefactor = mwidth;\
spawnee->movecount = dist;\
spawnee->angle = myaw;\
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
spawnee->flags2 |= (mflags2apply|moreflags2);\
spawnee->eflags |= meflagsapply
domaceagain:
mnumspokesset = mnumspokes;
if (mdoall && lines[line].flags & ML_EFFECT3) // Innermost mace/link
{ spawnee = makemace(macetype, 0, MF2_AMBUSH); }
// The actual spawning of spokes
while (mnumspokesset-- > 0)
{ {
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); // Offsets
if (lines[line].flags & ML_EFFECT1) // Swinging
mroll = (mroll - mspokeangle) & FINEMASK;
else // Spinning
mphase = (mphase - mspokeangle) & FINEMASK;
P_SetTarget(&spawnee->target, mobj); if (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke
if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT)
spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
else
spawnee->movecount = 0;
spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
spawnee->reactiontime = mlength;
if (firsttime)
{ {
// This is the outermost link in the chain if (mobj->type != MT_CHAINMACEPOINT)
spawnee->flags2 |= MF2_AMBUSH; continue;
firsttime = false;
firsttype = linktype = chainlink;
mlengthset = 1 + (mlength - 1)*radiusfactor;
radiusfactor = 1;
}
else
{
if (mobj->type == MT_CHAINMACEPOINT)
{
// Make the links the same type as the end - repeated above
if (lines[line].flags & ML_EFFECT2)
{
linktype = macetype;
radiusfactor = 2;
}
else
{
linktype = chainlink;
radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
}
firsttype = macetype;
}
mlengthset = mlength;
} }
mlength--; // Outermost mace/link
spawnee = makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
if (mspeed && (mwidth == msound) && !(mthing->options & MTF_OBJECTSPECIAL) && mnumspokesset <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
if (!mdoall || !linktype)
continue;
// The rest of the links
while (mlengthset > 0)
{ spawnee = makemace(linktype, radiusfactor*(mlengthset--), 0); }
} }
if (mwidth > 0)
{
mwidth *= -1;
goto domaceagain;
}
else if (mwidth != 0)
{
if ((mwidth = -(mwidth + ((firsttype == chainlink) ? 1 : 2))) < 0)
break;
mdoall = false;
goto domaceagain;
}
#undef makemace
break; break;
} }
case MT_PARTICLEGEN: 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; newmobj->destscale = mobj->destscale;
P_SetScale(newmobj, mobj->scale); P_SetScale(newmobj, mobj->scale);
return newmobj; return newmobj;
} }

View file

@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH 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_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_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 // free: to and including 1<<31
} mobjflag2_t; } mobjflag2_t;

View file

@ -3159,7 +3159,8 @@ static inline void P_ArchiveMisc(void)
else else
WRITEINT16(save_p, gamemap); WRITEINT16(save_p, gamemap);
lastmapsaved = gamemap; //lastmapsaved = gamemap;
lastmaploaded = gamemap;
WRITEUINT16(save_p, (botskin ? (emeralds|(1<<10)) : emeralds)+357); WRITEUINT16(save_p, (botskin ? (emeralds|(1<<10)) : emeralds)+357);
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder)); WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
@ -3184,7 +3185,8 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
if(!mapheaderinfo[gamemap-1]) if(!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1); P_AllocMapHeader(gamemap-1);
lastmapsaved = gamemap; //lastmapsaved = gamemap;
lastmaploaded = gamemap;
tokenlist = 0; tokenlist = 0;
token = 0; token = 0;

View file

@ -489,6 +489,7 @@ static void P_LoadSegs(lumpnum_t lumpnum)
//Hurdler: 04/12/2000: for now, only used in hardware mode //Hurdler: 04/12/2000: for now, only used in hardware mode
li->lightmaps = NULL; // list of static lightmap for this seg li->lightmaps = NULL; // list of static lightmap for this seg
} }
li->pv1 = li->pv2 = NULL;
#endif #endif
li->angle = (SHORT(ml->angle))<<FRACBITS; li->angle = (SHORT(ml->angle))<<FRACBITS;
@ -1593,6 +1594,7 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
break; break;
} }
case 9: // Mace parameters
case 14: // Bustable block parameters case 14: // Bustable block parameters
case 15: // Fan particle spawner parameters case 15: // Fan particle spawner parameters
case 425: // Calls P_SetMobjState on calling mobj case 425: // Calls P_SetMobjState on calling mobj
@ -2571,6 +2573,21 @@ static void P_LoadNightsGhosts(void)
free(gpath); 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. /** Loads a level from a lump or external wad.
* *
* \param skipprecip If true, don't spawn precipitation. * \param skipprecip If true, don't spawn precipitation.
@ -3034,11 +3051,11 @@ boolean P_SetupLevel(boolean skipprecip)
P_RunCachedActions(); P_RunCachedActions();
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0) if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0)
&& (!modifiedgame || savemoddata) && cursaveslot >= 0 && !ultimatemode && (!modifiedgame || savemoddata) && cursaveslot >= 0 && CanSaveLevel(gamemap))
&& !(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
&& (!G_IsSpecialStage(gamemap)) && gamemap != lastmapsaved && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete))
G_SaveGame((UINT32)cursaveslot); G_SaveGame((UINT32)cursaveslot);
lastmaploaded = gamemap; // HAS to be set after saving!!
if (savedata.lives > 0) if (savedata.lives > 0)
{ {
players[consoleplayer].continues = savedata.continues; players[consoleplayer].continues = savedata.continues;

View file

@ -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); player->mo->height = P_GetPlayerSpinHeight(player);
// tracer is what you're hanging onto.... // tracer is what you're hanging onto....
@ -10123,14 +10123,20 @@ void P_PlayerAfterThink(player_t *player)
player->pflags &= ~PF_THOKKED; player->pflags &= ~PF_THOKKED;
if (cmd->forwardmove > 0) 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) if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction)
player->mo->tracer->target->lastlook -= 2; 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? && !(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 player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX
if (!demoplayback || P_AnalogMove(player)) if (!demoplayback || P_AnalogMove(player))

View file

@ -365,6 +365,36 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
return sec; 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 // R_AddLine
// Clips the given segment and adds any visible pieces to the line list. // 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, // Identical floor and ceiling on both sides, identical light levels on both sides,
// and no middle texture. // and no middle texture.
if ( if (R_IsEmptyLine(line, frontsector, backsector))
#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))
{
return; return;
}
clippass: clippass:
R_ClipPassWallSegment(x1, x2 - 1); R_ClipPassWallSegment(x1, x2 - 1);

View file

@ -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, sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back); 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); INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
void R_Prep3DFloors(sector_t *sector); void R_Prep3DFloors(sector_t *sector);

View file

@ -574,6 +574,9 @@ typedef struct seg_s
sector_t *backsector; sector_t *backsector;
#ifdef HWRENDER #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 float flength; // length of the seg, used by hardware renderer
lightmap_t *lightmaps; // for static lightmap lightmap_t *lightmaps; // for static lightmap

View file

@ -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) void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor)
{ {
if (skins[skinnum].flags & SF_HIRES if (skins[skinnum].flags & SF_HIRES)
#ifdef HWRENDER
// || (rendermode != render_soft && rendermode != render_none)
#endif
)
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE));
else else
{ {