mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-21 08:51:10 +00:00
Merge branch 'master' into mi-misc-whatever
This commit is contained in:
commit
030c437186
60 changed files with 4710 additions and 4008 deletions
33
SRB2.cbp
33
SRB2.cbp
|
@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
|
|||
<Option target="Debug Mingw64/DirectX" />
|
||||
<Option target="Release Mingw64/DirectX" />
|
||||
</Unit>
|
||||
<Unit filename="src/hardware/hw_clip.c">
|
||||
<Option compilerVar="CC" />
|
||||
<Option target="Debug Native/SDL" />
|
||||
<Option target="Release Native/SDL" />
|
||||
<Option target="Debug Mingw/SDL" />
|
||||
<Option target="Release Mingw/SDL" />
|
||||
<Option target="Debug Mingw/DirectX" />
|
||||
<Option target="Release Mingw/DirectX" />
|
||||
<Option target="Debug Any/Dummy" />
|
||||
<Option target="Release Any/Dummy" />
|
||||
<Option target="Debug Linux/SDL" />
|
||||
<Option target="Release Linux/SDL" />
|
||||
<Option target="Debug Mingw64/SDL" />
|
||||
<Option target="Release Mingw64/SDL" />
|
||||
<Option target="Debug Mingw64/DirectX" />
|
||||
<Option target="Release Mingw64/DirectX" />
|
||||
</Unit>
|
||||
<Unit filename="src/hardware/hw_clip.h">
|
||||
<Option target="Debug Native/SDL" />
|
||||
<Option target="Release Native/SDL" />
|
||||
<Option target="Debug Mingw/SDL" />
|
||||
<Option target="Release Mingw/SDL" />
|
||||
<Option target="Debug Mingw/DirectX" />
|
||||
<Option target="Release Mingw/DirectX" />
|
||||
<Option target="Debug Any/Dummy" />
|
||||
<Option target="Release Any/Dummy" />
|
||||
<Option target="Debug Linux/SDL" />
|
||||
<Option target="Release Linux/SDL" />
|
||||
<Option target="Debug Mingw64/SDL" />
|
||||
<Option target="Release Mingw64/SDL" />
|
||||
<Option target="Debug Mingw64/DirectX" />
|
||||
<Option target="Release Mingw64/DirectX" />
|
||||
</Unit>
|
||||
<Unit filename="src/hardware/hw_data.h">
|
||||
<Option target="Debug Native/SDL" />
|
||||
<Option target="Release Native/SDL" />
|
||||
|
|
|
@ -351,6 +351,7 @@ if(${SRB2_CONFIG_HWRENDER})
|
|||
set(SRB2_HWRENDER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
|
||||
|
@ -359,6 +360,7 @@ if(${SRB2_CONFIG_HWRENDER})
|
|||
)
|
||||
|
||||
set (SRB2_HWRENDER_HEADERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
|
||||
|
|
12
src/Makefile
12
src/Makefile
|
@ -259,7 +259,7 @@ ifndef DC
|
|||
endif
|
||||
OPTS+=-DHWRENDER
|
||||
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
|
||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
|
||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
|
||||
endif
|
||||
|
||||
ifdef NOHS
|
||||
|
@ -703,7 +703,7 @@ ifdef MINGW
|
|||
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
|
||||
|
@ -711,7 +711,7 @@ else
|
|||
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
|
||||
|
@ -864,7 +864,7 @@ ifndef NOHW
|
|||
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
|
||||
|
@ -872,7 +872,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
|
|||
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
|
||||
|
@ -880,7 +880,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
|
|||
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
|
||||
|
|
|
@ -768,8 +768,16 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
players[i].mo->scalespeed = LONG(rsp->scalespeed);
|
||||
|
||||
// And finally, SET THE MOBJ SKIN damn it.
|
||||
players[i].mo->skin = &skins[players[i].skin];
|
||||
players[i].mo->color = players[i].skincolor;
|
||||
if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NGT0].numframes == 0))
|
||||
{
|
||||
players[i].mo->skin = &skins[DEFAULTNIGHTSSKIN];
|
||||
players[i].mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; // this will be corrected by thinker to super flash
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i].mo->skin = &skins[players[i].skin];
|
||||
players[i].mo->color = players[i].skincolor; // this will be corrected by thinker to super flash/mario star
|
||||
}
|
||||
|
||||
P_SetThingPosition(players[i].mo);
|
||||
}
|
||||
|
@ -883,6 +891,7 @@ static inline void resynch_write_others(resynchend_pak *rst)
|
|||
UINT8 i;
|
||||
|
||||
rst->ingame = 0;
|
||||
rst->outofcoop = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
|
@ -899,6 +908,8 @@ static inline void resynch_write_others(resynchend_pak *rst)
|
|||
|
||||
if (!players[i].spectator)
|
||||
rst->ingame |= (1<<i);
|
||||
if (players[i].outofcoop)
|
||||
rst->outofcoop |= (1<<i);
|
||||
rst->ctfteam[i] = (INT32)LONG(players[i].ctfteam);
|
||||
rst->score[i] = (UINT32)LONG(players[i].score);
|
||||
rst->numboxes[i] = SHORT(players[i].numboxes);
|
||||
|
@ -915,11 +926,13 @@ static inline void resynch_read_others(resynchend_pak *p)
|
|||
{
|
||||
UINT8 i;
|
||||
UINT32 loc_ingame = (UINT32)LONG(p->ingame);
|
||||
UINT32 loc_outofcoop = (UINT32)LONG(p->outofcoop);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
// We don't care if they're in the game or not, just write all the data.
|
||||
players[i].spectator = !(loc_ingame & (1<<i));
|
||||
players[i].outofcoop = (loc_outofcoop & (1<<i));
|
||||
players[i].ctfteam = (INT32)LONG(p->ctfteam[i]); // no, 0 does not mean spectator, at least not in Match
|
||||
players[i].score = (UINT32)LONG(p->score[i]);
|
||||
players[i].numboxes = SHORT(p->numboxes[i]);
|
||||
|
@ -1319,7 +1332,7 @@ static void SV_SendPlayerInfo(INT32 node)
|
|||
netbuffer->u.playerinfo[i].skin = (UINT8)players[i].skin;
|
||||
|
||||
// Extra data
|
||||
netbuffer->u.playerinfo[i].data = players[i].skincolor;
|
||||
netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor;
|
||||
|
||||
if (players[i].pflags & PF_TAGIT)
|
||||
netbuffer->u.playerinfo[i].data |= 0x20;
|
||||
|
|
|
@ -136,6 +136,7 @@ typedef struct
|
|||
fixed_t flagz[2];
|
||||
|
||||
UINT32 ingame; // Spectator bit for each player
|
||||
UINT32 outofcoop; // outofcoop bit for each player
|
||||
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
|
||||
|
||||
// Resynch game scores and the like all at once
|
||||
|
|
20
src/d_main.c
20
src/d_main.c
|
@ -419,10 +419,13 @@ static void D_Display(void)
|
|||
}
|
||||
|
||||
// Image postprocessing effect
|
||||
if (postimgtype)
|
||||
V_DoPostProcessor(0, postimgtype, postimgparam);
|
||||
if (postimgtype2)
|
||||
V_DoPostProcessor(1, postimgtype2, postimgparam2);
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
if (postimgtype)
|
||||
V_DoPostProcessor(0, postimgtype, postimgparam);
|
||||
if (postimgtype2)
|
||||
V_DoPostProcessor(1, postimgtype2, postimgparam2);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastdraw)
|
||||
|
@ -712,6 +715,7 @@ void D_StartTitle(void)
|
|||
botskin = 0;
|
||||
cv_debug = 0;
|
||||
emeralds = 0;
|
||||
lastmaploaded = 0;
|
||||
|
||||
// In case someone exits out at the same time they start a time attack run,
|
||||
// reset modeattacking
|
||||
|
@ -720,6 +724,14 @@ void D_StartTitle(void)
|
|||
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
||||
maptol = 0;
|
||||
|
||||
// reset to default player stuff
|
||||
COM_BufAddText (va("%s \"%s\"\n",cv_playername.name,cv_defaultplayername.string));
|
||||
COM_BufAddText (va("%s \"%s\"\n",cv_skin.name,cv_defaultskin.string));
|
||||
COM_BufAddText (va("%s \"%s\"\n",cv_playercolor.name,cv_defaultplayercolor.string));
|
||||
COM_BufAddText (va("%s \"%s\"\n",cv_playername2.name,cv_defaultplayername2.string));
|
||||
COM_BufAddText (va("%s \"%s\"\n",cv_skin2.name,cv_defaultskin2.string));
|
||||
COM_BufAddText (va("%s \"%s\"\n",cv_playercolor2.name,cv_defaultplayercolor2.string));
|
||||
|
||||
gameaction = ga_nothing;
|
||||
displayplayer = consoleplayer = 0;
|
||||
gametype = GT_COOP;
|
||||
|
|
236
src/d_netcmd.c
236
src/d_netcmd.c
|
@ -61,9 +61,6 @@ static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
|
|||
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
|
||||
#ifdef DELFILE
|
||||
static void Got_Delfilecmd(UINT8 **cp, INT32 playernum);
|
||||
#endif
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Pause(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Suicide(UINT8 **cp, INT32 playernum);
|
||||
|
@ -85,6 +82,9 @@ static void TeamScramble_OnChange(void);
|
|||
static void NetTimeout_OnChange(void);
|
||||
static void JoinTimeout_OnChange(void);
|
||||
|
||||
static void CoopStarposts_OnChange(void);
|
||||
static void CoopLives_OnChange(void);
|
||||
|
||||
static void Ringslinger_OnChange(void);
|
||||
static void Gravity_OnChange(void);
|
||||
static void ForceSkin_OnChange(void);
|
||||
|
@ -112,9 +112,6 @@ static void Command_ResetCamera_f(void);
|
|||
|
||||
static void Command_Addfile(void);
|
||||
static void Command_ListWADS_f(void);
|
||||
#ifdef DELFILE
|
||||
static void Command_Delfile(void);
|
||||
#endif
|
||||
static void Command_RunSOC(void);
|
||||
static void Command_Pause(void);
|
||||
static void Command_Suicide(void);
|
||||
|
@ -185,15 +182,14 @@ static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"},
|
|||
#define usejoystick_cons_t NULL
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t sleeping_cons_t[] = {{-1, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, //{2, "Teleports"},
|
||||
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, //{2, "Teleport"},
|
||||
{3, "None"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"},
|
||||
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, {2, "Unchanging"},
|
||||
{3, "None"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
|
||||
|
@ -215,7 +211,7 @@ consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT, starting
|
|||
static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_respawntime = {"respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_competitionboxes = {"competitionboxes", "Random", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_competitionboxes = {"competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
#ifdef SEENAMES
|
||||
static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}};
|
||||
|
@ -223,9 +219,9 @@ consvar_t cv_seenames = {"seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0, 0,
|
|||
consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
|
||||
// these are just meant to be saved to the config
|
||||
consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
// names
|
||||
consvar_t cv_playername = {"name", "Sonic", CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_playername2 = {"name2", "Tails", CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
// player colors
|
||||
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -233,6 +229,14 @@ consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t
|
|||
consvar_t cv_skin = {"skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// saved versions of the above six
|
||||
consvar_t cv_defaultplayername = {"defaultname", "Sonic", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_defaultplayername2 = {"defaultname2", "Tails", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_defaultplayercolor = {"defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_defaultplayercolor2 = {"defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_defaultskin2 = {"defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
INT32 cv_debug;
|
||||
|
@ -303,7 +307,7 @@ consvar_t cv_countdowntime = {"countdowntime", "60", CV_NETVAR|CV_CHEAT, minitim
|
|||
consvar_t cv_touchtag = {"touchtag", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_hidetime = {"hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_autobalance = {"autobalance", "0", CV_NETVAR|CV_CALL, autobalance_cons_t, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_autobalance = {"autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_teamscramble = {"teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_scrambleonchange = {"scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
@ -348,12 +352,18 @@ consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NUL
|
|||
#endif
|
||||
// Intermission time Tails 04-19-2002
|
||||
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}};
|
||||
consvar_t cv_coopstarposts = {"coopstarposts", "Teamwork", CV_NETVAR|CV_CALL|CV_CHEAT, coopstarposts_cons_t, CoopStarposts_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}};
|
||||
consvar_t cv_cooplives = {"cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}};
|
||||
consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "All"}, {0, NULL}};
|
||||
consvar_t cv_playersforexit = {"playersforexit", "One", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}};
|
||||
consvar_t cv_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
@ -387,7 +397,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
"RANDOMSEED",
|
||||
"RUNSOC",
|
||||
"REQADDFILE",
|
||||
"DELFILE",
|
||||
"DELFILE", // replace next time we add an XD
|
||||
"SETMOTD",
|
||||
"SUICIDE",
|
||||
#ifdef HAVE_BLUA
|
||||
|
@ -413,9 +423,6 @@ void D_RegisterServerCommands(void)
|
|||
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
|
||||
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
|
||||
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
|
||||
#ifdef DELFILE
|
||||
RegisterNetXCmd(XD_DELFILE, Got_Delfilecmd);
|
||||
#endif
|
||||
RegisterNetXCmd(XD_PAUSE, Got_Pause);
|
||||
RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
|
||||
RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
|
||||
|
@ -449,9 +456,6 @@ void D_RegisterServerCommands(void)
|
|||
COM_AddCommand("addfile", Command_Addfile);
|
||||
COM_AddCommand("listwad", Command_ListWADS_f);
|
||||
|
||||
#ifdef DELFILE
|
||||
COM_AddCommand("delfile", Command_Delfile);
|
||||
#endif
|
||||
COM_AddCommand("runsoc", Command_RunSOC);
|
||||
COM_AddCommand("pause", Command_Pause);
|
||||
COM_AddCommand("suicide", Command_Suicide);
|
||||
|
@ -508,6 +512,9 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_forceskin);
|
||||
CV_RegisterVar(&cv_downloading);
|
||||
|
||||
CV_RegisterVar(&cv_coopstarposts);
|
||||
CV_RegisterVar(&cv_cooplives);
|
||||
|
||||
CV_RegisterVar(&cv_specialrings);
|
||||
CV_RegisterVar(&cv_powerstones);
|
||||
CV_RegisterVar(&cv_competitionboxes);
|
||||
|
@ -636,7 +643,7 @@ void D_RegisterClientCommands(void)
|
|||
|
||||
// register these so it is saved to config
|
||||
if ((username = I_GetUserName()))
|
||||
cv_playername.defaultvalue = username;
|
||||
cv_playername.defaultvalue = cv_defaultplayername.defaultvalue = username;
|
||||
CV_RegisterVar(&cv_playername);
|
||||
CV_RegisterVar(&cv_playercolor);
|
||||
CV_RegisterVar(&cv_skin); // r_things.c (skin NAME)
|
||||
|
@ -644,6 +651,13 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_playername2);
|
||||
CV_RegisterVar(&cv_playercolor2);
|
||||
CV_RegisterVar(&cv_skin2);
|
||||
// saved versions of the above six
|
||||
CV_RegisterVar(&cv_defaultplayername);
|
||||
CV_RegisterVar(&cv_defaultplayercolor);
|
||||
CV_RegisterVar(&cv_defaultskin);
|
||||
CV_RegisterVar(&cv_defaultplayername2);
|
||||
CV_RegisterVar(&cv_defaultplayercolor2);
|
||||
CV_RegisterVar(&cv_defaultskin2);
|
||||
|
||||
#ifdef SEENAMES
|
||||
CV_RegisterVar(&cv_seenames);
|
||||
|
@ -1173,7 +1187,7 @@ static void SendNameAndColor(void)
|
|||
{
|
||||
CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor);
|
||||
|
||||
players[consoleplayer].skincolor = (cv_playercolor.value&0x1F) % MAXSKINCOLORS;
|
||||
players[consoleplayer].skincolor = cv_playercolor.value % MAXSKINCOLORS;
|
||||
|
||||
if (players[consoleplayer].mo)
|
||||
players[consoleplayer].mo->color = (UINT8)players[consoleplayer].skincolor;
|
||||
|
@ -1300,7 +1314,7 @@ static void SendNameAndColor2(void)
|
|||
{
|
||||
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
|
||||
|
||||
players[secondplaya].skincolor = (cv_playercolor2.value&0x1F) % MAXSKINCOLORS;
|
||||
players[secondplaya].skincolor = cv_playercolor2.value % MAXSKINCOLORS;
|
||||
|
||||
if (players[secondplaya].mo)
|
||||
players[secondplaya].mo->color = players[secondplaya].skincolor;
|
||||
|
@ -3088,42 +3102,6 @@ static void Command_Addfile(void)
|
|||
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
|
||||
}
|
||||
|
||||
#ifdef DELFILE
|
||||
/** removes the last added pwad at runtime.
|
||||
* Searches for sounds, maps, music and images to remove
|
||||
*/
|
||||
static void Command_Delfile(void)
|
||||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
CONS_Printf(M_GetText("You must NOT be in a level to use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (netgame && !(server || adminplayer == consoleplayer))
|
||||
{
|
||||
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (numwadfiles <= mainwads)
|
||||
{
|
||||
CONS_Printf(M_GetText("No additional WADs are loaded.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
P_DelWadFile();
|
||||
if (mainwads == numwadfiles && modifiedgame)
|
||||
modifiedgame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
SendNetXCmd(XD_DELFILE, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3198,33 +3176,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
COM_BufAddText(va("addfile %s\n", filename));
|
||||
}
|
||||
|
||||
#ifdef DELFILE
|
||||
static void Got_Delfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
if (playernum != serverplayer && playernum != adminplayer)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal delfile command received from %s\n"), player_names[playernum]);
|
||||
if (server)
|
||||
{
|
||||
XBOXSTATIC UINT8 buf[2];
|
||||
|
||||
buf[0] = (UINT8)playernum;
|
||||
buf[1] = KICK_MSG_CON_FAIL;
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
(void)cp;
|
||||
|
||||
if (numwadfiles <= mainwads) //sanity
|
||||
return;
|
||||
|
||||
P_DelWadFile();
|
||||
if (mainwads == numwadfiles && modifiedgame)
|
||||
modifiedgame = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3430,6 +3381,102 @@ static void JoinTimeout_OnChange(void)
|
|||
jointimeout = (tic_t)cv_jointimeout.value;
|
||||
}
|
||||
|
||||
static void CoopStarposts_OnChange(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (!(netgame || multiplayer) || gametype != GT_COOP)
|
||||
return;
|
||||
|
||||
switch (cv_coopstarposts.value)
|
||||
{
|
||||
case 0:
|
||||
CONS_Printf(M_GetText("Starposts are now per-player.\n"));
|
||||
break;
|
||||
case 1:
|
||||
CONS_Printf(M_GetText("Starposts are now shared between players.\n"));
|
||||
break;
|
||||
case 2:
|
||||
CONS_Printf(M_GetText("Players now only spawn when starposts are hit.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (G_IsSpecialStage(gamemap))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (!players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (players[i].lives <= 0)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (!players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (players[i].lives <= 0 && (cv_cooplives.value == 1))
|
||||
continue;
|
||||
|
||||
P_SpectatorJoinGame(&players[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void CoopLives_OnChange(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (!(netgame || multiplayer) || gametype != GT_COOP)
|
||||
return;
|
||||
|
||||
switch (cv_cooplives.value)
|
||||
{
|
||||
case 0:
|
||||
CONS_Printf(M_GetText("Players can now respawn indefinitely.\n"));
|
||||
return;
|
||||
case 1:
|
||||
CONS_Printf(M_GetText("Lives are now per-player.\n"));
|
||||
return;
|
||||
case 2:
|
||||
CONS_Printf(M_GetText("Players can now steal lives to avoid game over.\n"));
|
||||
break;
|
||||
case 3:
|
||||
CONS_Printf(M_GetText("Lives are now shared between players.\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (cv_coopstarposts.value == 2)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (!players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 0)
|
||||
continue;
|
||||
|
||||
P_SpectatorJoinGame(&players[i]);
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 timelimitintics = 0;
|
||||
|
||||
/** Deals with a timelimit change by printing the change to the console.
|
||||
|
@ -3720,7 +3767,7 @@ retryscramble:
|
|||
{
|
||||
if (red == maxcomposition)
|
||||
newteam = 2;
|
||||
else if (blue == maxcomposition)
|
||||
else //if (blue == maxcomposition)
|
||||
newteam = 1;
|
||||
|
||||
repick = false;
|
||||
|
@ -3761,14 +3808,11 @@ retryscramble:
|
|||
newteam = (INT16)((M_RandomByte() % 2) + 1);
|
||||
repick = false;
|
||||
}
|
||||
else
|
||||
else if (i != 2) // Mystic's secret sauce - ABBA is better than ABAB, so team B doesn't get worse players all around
|
||||
{
|
||||
// We will only randomly pick the team for the first guy.
|
||||
// Otherwise, just alternate back and forth, distributing players.
|
||||
if (newteam == 1)
|
||||
newteam = 2;
|
||||
else
|
||||
newteam = 1;
|
||||
newteam = 3 - newteam;
|
||||
}
|
||||
|
||||
scrambleteams[i] = newteam;
|
||||
|
|
|
@ -25,6 +25,13 @@ extern consvar_t cv_skin;
|
|||
extern consvar_t cv_playername2;
|
||||
extern consvar_t cv_playercolor2;
|
||||
extern consvar_t cv_skin2;
|
||||
// saved versions of the above six
|
||||
extern consvar_t cv_defaultplayername;
|
||||
extern consvar_t cv_defaultplayercolor;
|
||||
extern consvar_t cv_defaultskin;
|
||||
extern consvar_t cv_defaultplayername2;
|
||||
extern consvar_t cv_defaultplayercolor2;
|
||||
extern consvar_t cv_defaultskin2;
|
||||
|
||||
#ifdef SEENAMES
|
||||
extern consvar_t cv_seenames, cv_allowseenames;
|
||||
|
@ -89,7 +96,7 @@ extern consvar_t cv_recycler;
|
|||
|
||||
extern consvar_t cv_itemfinder;
|
||||
|
||||
extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit;
|
||||
extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_playersforexit;
|
||||
extern consvar_t cv_overtime;
|
||||
extern consvar_t cv_startinglives;
|
||||
|
||||
|
@ -129,7 +136,7 @@ typedef enum
|
|||
XD_RANDOMSEED, // 15
|
||||
XD_RUNSOC, // 16
|
||||
XD_REQADDFILE, // 17
|
||||
XD_DELFILE, // 18
|
||||
XD_DELFILE, // 18 - replace next time we add an XD
|
||||
XD_SETMOTD, // 19
|
||||
XD_SUICIDE, // 20
|
||||
#ifdef HAVE_BLUA
|
||||
|
|
|
@ -181,6 +181,14 @@ typedef enum
|
|||
PA_RIDE
|
||||
} panim_t;
|
||||
|
||||
//
|
||||
// All of the base srb2 shields are either a single constant,
|
||||
// or use damagetype-protecting flags applied to a constant,
|
||||
// or are the force shield (which does everything weirdly).
|
||||
//
|
||||
// Base flags by themselves aren't used so modders can make
|
||||
// abstract, ability-less shields should they so choose.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
SH_NONE = 0,
|
||||
|
@ -189,19 +197,21 @@ typedef enum
|
|||
SH_PROTECTFIRE = 0x400,
|
||||
SH_PROTECTWATER = 0x800,
|
||||
SH_PROTECTELECTRIC = 0x1000,
|
||||
SH_PROTECTSPIKE = 0x2000, // cactus shield one day? thanks, subarashii
|
||||
//SH_PROTECTNUKE = 0x4000, // intentionally no hardcoded defense against nukes
|
||||
|
||||
// Indivisible shields
|
||||
SH_PITY = 1, // the world's most basic shield ever, given to players who suck at Match
|
||||
SH_WHIRLWIND,
|
||||
SH_ARMAGEDDON,
|
||||
|
||||
// normal shields that use flags
|
||||
SH_ATTRACT = SH_PROTECTELECTRIC,
|
||||
SH_ELEMENTAL = SH_PROTECTFIRE|SH_PROTECTWATER,
|
||||
// Normal shields that use flags
|
||||
SH_ATTRACT = SH_PITY|SH_PROTECTELECTRIC,
|
||||
SH_ELEMENTAL = SH_PITY|SH_PROTECTFIRE|SH_PROTECTWATER,
|
||||
|
||||
// Sonic 3 shields
|
||||
SH_FLAMEAURA = SH_PROTECTFIRE,
|
||||
SH_BUBBLEWRAP = SH_PROTECTWATER,
|
||||
SH_FLAMEAURA = SH_PITY|SH_PROTECTFIRE,
|
||||
SH_BUBBLEWRAP = SH_PITY|SH_PROTECTWATER,
|
||||
SH_THUNDERCOIN = SH_WHIRLWIND|SH_PROTECTELECTRIC,
|
||||
|
||||
// The force shield uses the lower 8 bits to count how many extra hits are left.
|
||||
|
@ -471,6 +481,7 @@ typedef struct player_s
|
|||
angle_t awayviewaiming; // Used for cut-away view
|
||||
|
||||
boolean spectator;
|
||||
boolean outofcoop;
|
||||
UINT8 bot;
|
||||
|
||||
tic_t jointime; // Timer when player joins game to change skin/color
|
||||
|
|
595
src/dehacked.c
595
src/dehacked.c
File diff suppressed because it is too large
Load diff
|
@ -27,13 +27,6 @@ typedef enum
|
|||
UNDO_DONE = 0,
|
||||
} undotype_f;
|
||||
|
||||
#ifdef DELFILE
|
||||
void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags);
|
||||
void DEH_UnloadDehackedWad(UINT16 wad);
|
||||
#else // null the undo lines
|
||||
#define DEH_WriteUndoline(a,b,c)
|
||||
#endif
|
||||
|
||||
void DEH_LoadDehackedLump(lumpnum_t lumpnum);
|
||||
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump);
|
||||
|
||||
|
|
|
@ -207,8 +207,9 @@ typedef struct
|
|||
|
||||
#define ZSHIFT 4
|
||||
|
||||
extern const UINT8 Color_Index[MAXTRANSLATIONS-1][16];
|
||||
extern const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS];
|
||||
extern const UINT8 Color_Opposite[MAXSKINCOLORS*2];
|
||||
extern const UINT8 Color_Opposite[(MAXSKINCOLORS - 1)*2];
|
||||
|
||||
#define NUMMAPS 1035
|
||||
|
||||
|
|
|
@ -229,39 +229,77 @@ extern FILE *logstream;
|
|||
typedef enum
|
||||
{
|
||||
SKINCOLOR_NONE = 0,
|
||||
|
||||
// Greyscale ranges
|
||||
SKINCOLOR_WHITE,
|
||||
SKINCOLOR_SILVER,
|
||||
SKINCOLOR_BONE,
|
||||
SKINCOLOR_CLOUDY,
|
||||
SKINCOLOR_GREY,
|
||||
SKINCOLOR_SILVER,
|
||||
SKINCOLOR_CARBON,
|
||||
SKINCOLOR_JET,
|
||||
SKINCOLOR_BLACK,
|
||||
SKINCOLOR_BEIGE,
|
||||
SKINCOLOR_PEACH,
|
||||
|
||||
// Desaturated
|
||||
SKINCOLOR_AETHER,
|
||||
SKINCOLOR_SLATE,
|
||||
SKINCOLOR_PINK,
|
||||
SKINCOLOR_YOGURT,
|
||||
SKINCOLOR_BROWN,
|
||||
SKINCOLOR_TAN,
|
||||
SKINCOLOR_BEIGE,
|
||||
SKINCOLOR_MOSS,
|
||||
SKINCOLOR_AZURE,
|
||||
SKINCOLOR_LAVENDER,
|
||||
|
||||
// Viv's vivid colours (toast 21/07/17)
|
||||
SKINCOLOR_RUBY,
|
||||
SKINCOLOR_SALMON,
|
||||
SKINCOLOR_RED,
|
||||
SKINCOLOR_CRIMSON,
|
||||
SKINCOLOR_FLAME,
|
||||
SKINCOLOR_PEACHY,
|
||||
SKINCOLOR_QUAIL,
|
||||
SKINCOLOR_SUNSET,
|
||||
SKINCOLOR_APRICOT,
|
||||
SKINCOLOR_ORANGE,
|
||||
SKINCOLOR_RUST,
|
||||
SKINCOLOR_GOLD,
|
||||
SKINCOLOR_SANDY,
|
||||
SKINCOLOR_YELLOW,
|
||||
SKINCOLOR_TAN,
|
||||
SKINCOLOR_MOSS,
|
||||
SKINCOLOR_OLIVE,
|
||||
SKINCOLOR_LIME,
|
||||
SKINCOLOR_PERIDOT,
|
||||
SKINCOLOR_GREEN,
|
||||
SKINCOLOR_FOREST,
|
||||
SKINCOLOR_EMERALD,
|
||||
SKINCOLOR_MINT,
|
||||
SKINCOLOR_SEAFOAM,
|
||||
SKINCOLOR_AQUA,
|
||||
SKINCOLOR_TEAL,
|
||||
SKINCOLOR_WAVE,
|
||||
SKINCOLOR_CYAN,
|
||||
SKINCOLOR_SKY,
|
||||
SKINCOLOR_CERULEAN,
|
||||
SKINCOLOR_ICY,
|
||||
SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl
|
||||
SKINCOLOR_CORNFLOWER,
|
||||
SKINCOLOR_BLUE,
|
||||
SKINCOLOR_AZURE,
|
||||
SKINCOLOR_COBALT,
|
||||
SKINCOLOR_VAPOR,
|
||||
SKINCOLOR_DUSK,
|
||||
SKINCOLOR_PASTEL,
|
||||
SKINCOLOR_PURPLE,
|
||||
SKINCOLOR_LAVENDER,
|
||||
SKINCOLOR_BUBBLEGUM,
|
||||
SKINCOLOR_MAGENTA,
|
||||
SKINCOLOR_PINK,
|
||||
SKINCOLOR_NEON,
|
||||
SKINCOLOR_VIOLET,
|
||||
SKINCOLOR_LILAC,
|
||||
SKINCOLOR_PLUM,
|
||||
SKINCOLOR_ROSY,
|
||||
//SKINCOLOR_?
|
||||
//SKINCOLOR_?
|
||||
|
||||
// Careful! MAXSKINCOLORS cannot be greater than 0x20! Two slots left...
|
||||
// SKINCOLOR_? - one left before we bump up against 0x39, which isn't a HARD limit anymore but would be excessive
|
||||
|
||||
MAXSKINCOLORS,
|
||||
|
||||
// Super special awesome Super flashing colors!
|
||||
|
@ -295,11 +333,11 @@ typedef enum
|
|||
SKINCOLOR_SUPERPERIDOT4,
|
||||
SKINCOLOR_SUPERPERIDOT5,
|
||||
|
||||
SKINCOLOR_SUPERCYAN1,
|
||||
SKINCOLOR_SUPERCYAN2,
|
||||
SKINCOLOR_SUPERCYAN3,
|
||||
SKINCOLOR_SUPERCYAN4,
|
||||
SKINCOLOR_SUPERCYAN5,
|
||||
SKINCOLOR_SUPERSKY1,
|
||||
SKINCOLOR_SUPERSKY2,
|
||||
SKINCOLOR_SUPERSKY3,
|
||||
SKINCOLOR_SUPERSKY4,
|
||||
SKINCOLOR_SUPERSKY5,
|
||||
|
||||
SKINCOLOR_SUPERPURPLE1,
|
||||
SKINCOLOR_SUPERPURPLE2,
|
||||
|
@ -483,10 +521,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
|||
#define ESLOPE_TYPESHIM
|
||||
#endif
|
||||
|
||||
/// Delete file while the game is running.
|
||||
/// \note EXTREMELY buggy, tends to crash game.
|
||||
//#define DELFILE
|
||||
|
||||
/// Allows the use of devmode in multiplayer. AKA "fishcake"
|
||||
//#define NETGAME_DEVMODE
|
||||
|
||||
|
@ -546,6 +580,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
|||
/// Hudname padding.
|
||||
#define SKINNAMEPADDING
|
||||
|
||||
/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
|
||||
/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
|
||||
/// on the bright side it fixes some weird issues with translucent walls
|
||||
/// \note SRB2CB port.
|
||||
/// SRB2CB itself ported this from PrBoom+
|
||||
#define NEWCLIP
|
||||
|
||||
/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
|
||||
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
|
||||
//#define SECTORSPECIALSAFTERTHINK
|
||||
|
|
|
@ -41,7 +41,8 @@ extern INT16 maptol;
|
|||
extern UINT8 globalweather;
|
||||
extern INT32 curWeather;
|
||||
extern INT32 cursaveslot;
|
||||
extern INT16 lastmapsaved;
|
||||
//extern INT16 lastmapsaved;
|
||||
extern INT16 lastmaploaded;
|
||||
extern boolean gamecomplete;
|
||||
|
||||
#define PRECIP_NONE 0
|
||||
|
@ -263,6 +264,7 @@ typedef struct
|
|||
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
|
||||
#define LF_NORELOAD 8 ///< Don't reload level on death
|
||||
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title
|
||||
#define LF_SAVEGAME 32 ///< Save the game upon loading this level
|
||||
|
||||
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
|
||||
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen
|
||||
|
|
187
src/g_game.c
187
src/g_game.c
|
@ -77,7 +77,8 @@ INT16 maptol;
|
|||
UINT8 globalweather = 0;
|
||||
INT32 curWeather = PRECIP_NONE;
|
||||
INT32 cursaveslot = -1; // Auto-save 1p savegame slot
|
||||
INT16 lastmapsaved = 0; // Last map we auto-saved at
|
||||
//INT16 lastmapsaved = 0; // Last map we auto-saved at
|
||||
INT16 lastmaploaded = 0; // Last map the game loaded
|
||||
boolean gamecomplete = false;
|
||||
|
||||
UINT16 mainwads = 0;
|
||||
|
@ -2090,6 +2091,7 @@ void G_PlayerReborn(INT32 player)
|
|||
UINT32 availabilities;
|
||||
tic_t jointime;
|
||||
boolean spectator;
|
||||
boolean outofcoop;
|
||||
INT16 bot;
|
||||
SINT8 pity;
|
||||
|
||||
|
@ -2100,6 +2102,7 @@ void G_PlayerReborn(INT32 player)
|
|||
exiting = players[player].exiting;
|
||||
jointime = players[player].jointime;
|
||||
spectator = players[player].spectator;
|
||||
outofcoop = players[player].outofcoop;
|
||||
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE));
|
||||
|
||||
// As long as we're not in multiplayer, carry over cheatcodes from map to map
|
||||
|
@ -2154,6 +2157,7 @@ void G_PlayerReborn(INT32 player)
|
|||
p->ctfteam = ctfteam;
|
||||
p->jointime = jointime;
|
||||
p->spectator = spectator;
|
||||
p->outofcoop = outofcoop;
|
||||
|
||||
// save player config truth reborn
|
||||
p->skincolor = skincolor;
|
||||
|
@ -2205,8 +2209,8 @@ void G_PlayerReborn(INT32 player)
|
|||
p->rings = 0; // 0 rings
|
||||
p->panim = PA_IDLE; // standing animation
|
||||
|
||||
if ((netgame || multiplayer) && !p->spectator)
|
||||
p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
|
||||
//if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there
|
||||
//p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
|
||||
|
||||
if (p-players == consoleplayer)
|
||||
{
|
||||
|
@ -2495,7 +2499,8 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
|
|||
void G_DoReborn(INT32 playernum)
|
||||
{
|
||||
player_t *player = &players[playernum];
|
||||
boolean starpost = false;
|
||||
boolean resetlevel = false;
|
||||
INT32 i;
|
||||
|
||||
if (modeattacking)
|
||||
{
|
||||
|
@ -2521,35 +2526,98 @@ void G_DoReborn(INT32 playernum)
|
|||
B_RespawnBot(playernum);
|
||||
if (oldmo)
|
||||
G_ChangePlayerReferences(oldmo, players[playernum].mo);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (countdowntimeup || (!multiplayer && gametype == GT_COOP))
|
||||
|
||||
if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP))
|
||||
resetlevel = true;
|
||||
else if (gametype == GT_COOP && (netgame || multiplayer))
|
||||
{
|
||||
boolean notgameover = true;
|
||||
|
||||
if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].exiting || players[i].lives > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
{
|
||||
notgameover = false;
|
||||
if (!countdown2)
|
||||
{
|
||||
// They're dead, Jim.
|
||||
//nextmapoverride = spstage_start;
|
||||
nextmapoverride = gamemap;
|
||||
countdown2 = TICRATE;
|
||||
skipstats = true;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
players[i].score = 0;
|
||||
}
|
||||
|
||||
//emeralds = 0;
|
||||
tokenbits = 0;
|
||||
tokenlist = 0;
|
||||
token = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (notgameover && cv_coopstarposts.value == 2)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health)
|
||||
break;
|
||||
}
|
||||
if (i == MAXPLAYERS)
|
||||
resetlevel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetlevel)
|
||||
{
|
||||
// reload the level from scratch
|
||||
if (countdowntimeup)
|
||||
{
|
||||
player->starpostangle = 0;
|
||||
player->starposttime = 0;
|
||||
player->starpostx = 0;
|
||||
player->starposty = 0;
|
||||
player->starpostz = 0;
|
||||
player->starpostnum = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
players[i].starpostangle = 0;
|
||||
players[i].starposttime = 0;
|
||||
players[i].starpostx = 0;
|
||||
players[i].starposty = 0;
|
||||
players[i].starpostz = 0;
|
||||
players[i].starpostnum = 0;
|
||||
}
|
||||
}
|
||||
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD))
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
player->playerstate = PST_REBORN;
|
||||
|
||||
P_LoadThingsOnly();
|
||||
|
||||
P_ClearStarPost(player->starpostnum);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
players[i].playerstate = PST_REBORN;
|
||||
P_ClearStarPost(players[i].starpostnum);
|
||||
}
|
||||
|
||||
// Do a wipe
|
||||
wipegamestate = -1;
|
||||
|
||||
if (player->starposttime)
|
||||
starpost = true;
|
||||
|
||||
if (camera.chase)
|
||||
P_ResetCamera(&players[displayplayer], &camera);
|
||||
if (camera2.chase && splitscreen)
|
||||
|
@ -2557,7 +2625,7 @@ void G_DoReborn(INT32 playernum)
|
|||
|
||||
// clear cmd building stuff
|
||||
memset(gamekeydown, 0, sizeof (gamekeydown));
|
||||
for (i = 0;i < JOYAXISSET; i++)
|
||||
for (i = 0; i < JOYAXISSET; i++)
|
||||
{
|
||||
joyxmove[i] = joyymove[i] = 0;
|
||||
joy2xmove[i] = joy2ymove[i] = 0;
|
||||
|
@ -2569,31 +2637,45 @@ void G_DoReborn(INT32 playernum)
|
|||
CON_ClearHUD();
|
||||
|
||||
// Starpost support
|
||||
G_SpawnPlayer(playernum, starpost);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
G_SpawnPlayer(i, (players[i].starposttime));
|
||||
}
|
||||
|
||||
if (botingame)
|
||||
{ // Bots respawn next to their master.
|
||||
players[secondarydisplayplayer].playerstate = PST_REBORN;
|
||||
G_SpawnPlayer(secondarydisplayplayer, false);
|
||||
// restore time in netgame (see also p_setup.c)
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
|
||||
{
|
||||
// is this a hack? maybe
|
||||
tic_t maxstarposttime = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && players[i].starposttime > maxstarposttime)
|
||||
maxstarposttime = players[i].starposttime;
|
||||
}
|
||||
leveltime = maxstarposttime;
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef HAVE_BLUA
|
||||
{
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_MapChange();
|
||||
#endif
|
||||
G_DoLoadLevel(true);
|
||||
#ifdef HAVE_BLUA
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// respawn at the start
|
||||
mobj_t *oldmo = NULL;
|
||||
|
||||
if (player->starposttime)
|
||||
starpost = true;
|
||||
// Not resetting map, so return to level music
|
||||
if (!countdown2
|
||||
&& player->lives <= 0
|
||||
&& cv_cooplives.value == 1) // not allowed for life steal because no way to come back from zero group lives without addons, which should call this anyways
|
||||
P_RestoreMultiMusic(player);
|
||||
|
||||
// first dissasociate the corpse
|
||||
if (player->mo)
|
||||
|
@ -2603,7 +2685,7 @@ void G_DoReborn(INT32 playernum)
|
|||
P_RemoveMobj(player->mo);
|
||||
}
|
||||
|
||||
G_SpawnPlayer(playernum, starpost);
|
||||
G_SpawnPlayer(playernum, (player->starposttime));
|
||||
if (oldmo)
|
||||
G_ChangePlayerReferences(oldmo, players[playernum].mo);
|
||||
}
|
||||
|
@ -2611,10 +2693,49 @@ void G_DoReborn(INT32 playernum)
|
|||
|
||||
void G_AddPlayer(INT32 playernum)
|
||||
{
|
||||
INT32 countplayers = 0, notexiting = 0;
|
||||
|
||||
player_t *p = &players[playernum];
|
||||
|
||||
// Go through the current players and make sure you have the latest starpost set
|
||||
if (G_PlatformGametype() && (netgame || multiplayer))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].bot) // ignore dumb, stupid tails
|
||||
continue;
|
||||
|
||||
countplayers++;
|
||||
|
||||
if (!players->exiting)
|
||||
notexiting++;
|
||||
|
||||
if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
|
||||
continue;
|
||||
|
||||
p->starposttime = players[i].starposttime;
|
||||
p->starpostx = players[i].starpostx;
|
||||
p->starposty = players[i].starposty;
|
||||
p->starpostz = players[i].starpostz;
|
||||
p->starpostangle = players[i].starpostangle;
|
||||
p->starpostnum = players[i].starpostnum;
|
||||
}
|
||||
}
|
||||
|
||||
p->jointime = 0;
|
||||
p->playerstate = PST_REBORN;
|
||||
|
||||
p->height = mobjinfo[MT_PLAYER].height;
|
||||
|
||||
if (G_GametypeUsesLives() || ((netgame || multiplayer) && gametype == GT_COOP))
|
||||
p->lives = cv_startinglives.value;
|
||||
|
||||
if (countplayers && !notexiting)
|
||||
P_DoPlayerExit(p);
|
||||
}
|
||||
|
||||
void G_ExitLevel(void)
|
||||
|
@ -3612,7 +3733,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
|
||||
if (netgame || multiplayer)
|
||||
{
|
||||
if (!FLS || (players[i].lives < cv_startinglives.value))
|
||||
if (!FLS || (players[i].lives < 1))
|
||||
players[i].lives = cv_startinglives.value;
|
||||
players[i].continues = 0;
|
||||
}
|
||||
|
@ -4414,7 +4535,7 @@ void G_GhostTicker(void)
|
|||
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
|
||||
break;
|
||||
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
|
||||
g->mo->color = (UINT8)(SKINCOLOR_RED + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RED))); // Passes through all saturated colours
|
||||
g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -878,8 +878,8 @@ static void AdjustSegs(void)
|
|||
count = subsectors[i].numlines;
|
||||
lseg = &segs[subsectors[i].firstline];
|
||||
p = extrasubsectors[i].planepoly;
|
||||
if (!p)
|
||||
continue;
|
||||
//if (!p)
|
||||
//continue;
|
||||
for (; count--; lseg++)
|
||||
{
|
||||
float distv1,distv2,tmp;
|
||||
|
@ -892,29 +892,31 @@ static void AdjustSegs(void)
|
|||
continue;
|
||||
#endif
|
||||
|
||||
for (j = 0; j < p->numpts; j++)
|
||||
{
|
||||
distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
|
||||
tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
|
||||
distv1 = distv1*distv1+tmp*tmp;
|
||||
if (distv1 <= nearv1)
|
||||
if (p) {
|
||||
for (j = 0; j < p->numpts; j++)
|
||||
{
|
||||
v1found = j;
|
||||
nearv1 = distv1;
|
||||
}
|
||||
// the same with v2
|
||||
distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
|
||||
tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
|
||||
distv2 = distv2*distv2+tmp*tmp;
|
||||
if (distv2 <= nearv2)
|
||||
{
|
||||
v2found = j;
|
||||
nearv2 = distv2;
|
||||
distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
|
||||
tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
|
||||
distv1 = distv1*distv1+tmp*tmp;
|
||||
if (distv1 <= nearv1)
|
||||
{
|
||||
v1found = j;
|
||||
nearv1 = distv1;
|
||||
}
|
||||
// the same with v2
|
||||
distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
|
||||
tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
|
||||
distv2 = distv2*distv2+tmp*tmp;
|
||||
if (distv2 <= nearv2)
|
||||
{
|
||||
v2found = j;
|
||||
nearv2 = distv2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nearv1 <= NEARDIST*NEARDIST)
|
||||
if (p && nearv1 <= NEARDIST*NEARDIST)
|
||||
// share vertice with segs
|
||||
lseg->v1 = (vertex_t *)&(p->pts[v1found]);
|
||||
lseg->pv1 = &(p->pts[v1found]);
|
||||
else
|
||||
{
|
||||
// BP: here we can do better, using PointInSeg and compute
|
||||
|
@ -925,24 +927,24 @@ static void AdjustSegs(void)
|
|||
polyvertex_t *pv = HWR_AllocVertex();
|
||||
pv->x = FIXED_TO_FLOAT(lseg->v1->x);
|
||||
pv->y = FIXED_TO_FLOAT(lseg->v1->y);
|
||||
lseg->v1 = (vertex_t *)pv;
|
||||
lseg->pv1 = pv;
|
||||
}
|
||||
if (nearv2 <= NEARDIST*NEARDIST)
|
||||
lseg->v2 = (vertex_t *)&(p->pts[v2found]);
|
||||
if (p && nearv2 <= NEARDIST*NEARDIST)
|
||||
lseg->pv2 = &(p->pts[v2found]);
|
||||
else
|
||||
{
|
||||
polyvertex_t *pv = HWR_AllocVertex();
|
||||
pv->x = FIXED_TO_FLOAT(lseg->v2->x);
|
||||
pv->y = FIXED_TO_FLOAT(lseg->v2->y);
|
||||
lseg->v2 = (vertex_t *)pv;
|
||||
lseg->pv2 = pv;
|
||||
}
|
||||
|
||||
// recompute length
|
||||
{
|
||||
float x,y;
|
||||
x = ((polyvertex_t *)lseg->v2)->x - ((polyvertex_t *)lseg->v1)->x
|
||||
x = ((polyvertex_t *)lseg->pv2)->x - ((polyvertex_t *)lseg->pv1)->x
|
||||
+ FIXED_TO_FLOAT(FRACUNIT/2);
|
||||
y = ((polyvertex_t *)lseg->v2)->y - ((polyvertex_t *)lseg->v1)->y
|
||||
y = ((polyvertex_t *)lseg->pv2)->y - ((polyvertex_t *)lseg->pv1)->y
|
||||
+ FIXED_TO_FLOAT(FRACUNIT/2);
|
||||
lseg->flength = (float)hypot(x, y);
|
||||
// BP: debug see this kind of segs
|
||||
|
|
465
src/hardware/hw_clip.c
Normal file
465
src/hardware/hw_clip.c
Normal 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
24
src/hardware/hw_clip.h
Normal 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
|
|
@ -323,6 +323,10 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_BMCH
|
||||
&lspr[NOLIGHT], // SPR_SMCE
|
||||
&lspr[NOLIGHT], // SPR_BMCE
|
||||
&lspr[NOLIGHT], // SPR_YSPB
|
||||
&lspr[NOLIGHT], // SPR_RSPB
|
||||
&lspr[REDBALL_L], // SPR_SFBR
|
||||
&lspr[REDBALL_L], // SPR_BFBR
|
||||
|
||||
// Arid Canyon Scenery
|
||||
&lspr[NOLIGHT], // SPR_BTBL
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
#endif
|
||||
#include "hw_md2.h"
|
||||
|
||||
#ifdef NEWCLIP
|
||||
#include "hw_clip.h"
|
||||
#endif
|
||||
|
||||
#define R_FAKEFLOORS
|
||||
#define HWPRECIP
|
||||
#define SORTING
|
||||
|
@ -99,8 +103,9 @@ CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NU
|
|||
boolean drawsky = true;
|
||||
|
||||
// needs fix: walls are incorrectly clipped one column less
|
||||
#ifndef NEWCLIP
|
||||
static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
#endif
|
||||
//development variables for diverse uses
|
||||
static consvar_t cv_gralpha = {"gr_alpha", "160", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -323,9 +328,6 @@ static angle_t gr_xtoviewangle[MAXVIDWIDTH+1];
|
|||
// test change fov when looking up/down but bsp projection messup :(
|
||||
//#define NOCRAPPYMLOOK
|
||||
|
||||
/// \note crappy
|
||||
#define drawtextured true
|
||||
|
||||
// base values set at SetViewSize
|
||||
static float gr_basecentery;
|
||||
|
||||
|
@ -852,11 +854,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
|
|||
|
||||
M_ClearBox(segbbox);
|
||||
M_AddToBox(segbbox,
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x),
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y));
|
||||
M_AddToBox(segbbox,
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x),
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y));
|
||||
|
||||
splat = (wallsplat_t *)gr_curline->linedef->splats;
|
||||
for (; splat; splat = splat->next)
|
||||
|
@ -1029,6 +1031,7 @@ static void HWR_ProjectWall(wallVert3D * wallVerts,
|
|||
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
|
||||
// with the wall segment
|
||||
//
|
||||
#ifndef NEWCLIP
|
||||
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
|
||||
{
|
||||
float num, den;
|
||||
|
@ -1057,6 +1060,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
|
|||
|
||||
return num / den;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// HWR_SplitWall
|
||||
|
@ -1431,7 +1435,11 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
|
|||
// Anything between means the wall segment has been clipped with solidsegs,
|
||||
// reducing wall overdraw to a minimum
|
||||
//
|
||||
#ifdef NEWCLIP
|
||||
static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
||||
#else
|
||||
static void HWR_StoreWallRange(double startfrac, double endfrac)
|
||||
#endif
|
||||
{
|
||||
wallVert3D wallVerts[4];
|
||||
v2d_t vs, ve; // start, end vertices of 2d line (view from above)
|
||||
|
@ -1456,16 +1464,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
extracolormap_t *colormap;
|
||||
FSurfaceInfo Surf;
|
||||
|
||||
#ifndef NEWCLIP
|
||||
if (startfrac > endfrac)
|
||||
return;
|
||||
#endif
|
||||
|
||||
gr_sidedef = gr_curline->sidedef;
|
||||
gr_linedef = gr_curline->linedef;
|
||||
|
||||
vs.x = ((polyvertex_t *)gr_curline->v1)->x;
|
||||
vs.y = ((polyvertex_t *)gr_curline->v1)->y;
|
||||
ve.x = ((polyvertex_t *)gr_curline->v2)->x;
|
||||
ve.y = ((polyvertex_t *)gr_curline->v2)->y;
|
||||
vs.x = ((polyvertex_t *)gr_curline->pv1)->x;
|
||||
vs.y = ((polyvertex_t *)gr_curline->pv1)->y;
|
||||
ve.x = ((polyvertex_t *)gr_curline->pv2)->x;
|
||||
ve.y = ((polyvertex_t *)gr_curline->pv2)->y;
|
||||
|
||||
#ifdef ESLOPE
|
||||
v1x = FLOAT_TO_FIXED(vs.x);
|
||||
|
@ -1473,44 +1483,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
v2x = FLOAT_TO_FIXED(ve.x);
|
||||
v2y = FLOAT_TO_FIXED(ve.y);
|
||||
#endif
|
||||
|
||||
if (gr_frontsector->heightsec != -1)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
worldtop = worldtopslope = sectors[gr_frontsector->heightsec].ceilingheight;
|
||||
worldbottom = worldbottomslope = sectors[gr_frontsector->heightsec].floorheight;
|
||||
#else
|
||||
worldtop = sectors[gr_frontsector->heightsec].ceilingheight;
|
||||
worldbottom = sectors[gr_frontsector->heightsec].floorheight;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
if (gr_frontsector->c_slope)
|
||||
{
|
||||
worldtop = P_GetZAt(gr_frontsector->c_slope, v1x, v1y);
|
||||
worldtopslope = P_GetZAt(gr_frontsector->c_slope, v2x, v2y);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldtop = worldtopslope = gr_frontsector->ceilingheight;
|
||||
}
|
||||
|
||||
if (gr_frontsector->f_slope)
|
||||
{
|
||||
worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y);
|
||||
worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldbottom = worldbottomslope = gr_frontsector->floorheight;
|
||||
}
|
||||
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
|
||||
if (slope) { \
|
||||
end1 = P_GetZAt(slope, v1x, v1y); \
|
||||
end2 = P_GetZAt(slope, v2x, v2y); \
|
||||
} else \
|
||||
end1 = end2 = normalheight;
|
||||
|
||||
SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight)
|
||||
SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
|
||||
#else
|
||||
worldtop = gr_frontsector->ceilingheight;
|
||||
worldbottom = gr_frontsector->floorheight;
|
||||
worldtop = gr_frontsector->ceilingheight;
|
||||
worldbottom = gr_frontsector->floorheight;
|
||||
#endif
|
||||
}
|
||||
|
||||
// remember vertices ordering
|
||||
// 3--2
|
||||
|
@ -1525,20 +1512,23 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
wallVerts[2].z = wallVerts[1].z = ve.y;
|
||||
wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f;
|
||||
|
||||
if (drawtextured)
|
||||
{
|
||||
// x offset the texture
|
||||
fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset;
|
||||
|
||||
#ifndef NEWCLIP
|
||||
// clip texture s start/end coords with solidsegs
|
||||
if (startfrac > 0.0f && startfrac < 1.0f)
|
||||
cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac);
|
||||
else
|
||||
#endif
|
||||
cliplow = (float)texturehpeg;
|
||||
|
||||
#ifndef NEWCLIP
|
||||
if (endfrac > 0.0f && endfrac < 1.0f)
|
||||
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac);
|
||||
else
|
||||
#endif
|
||||
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
|
||||
}
|
||||
|
||||
|
@ -1554,43 +1544,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
{
|
||||
INT32 gr_toptexture, gr_bottomtexture;
|
||||
// two sided line
|
||||
if (gr_backsector->heightsec != -1)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
worldhigh = worldhighslope = sectors[gr_backsector->heightsec].ceilingheight;
|
||||
worldlow = worldlowslope = sectors[gr_backsector->heightsec].floorheight;
|
||||
#else
|
||||
worldhigh = sectors[gr_backsector->heightsec].ceilingheight;
|
||||
worldlow = sectors[gr_backsector->heightsec].floorheight;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
if (gr_backsector->c_slope)
|
||||
{
|
||||
worldhigh = P_GetZAt(gr_backsector->c_slope, v1x, v1y);
|
||||
worldhighslope = P_GetZAt(gr_backsector->c_slope, v2x, v2y);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldhigh = worldhighslope = gr_backsector->ceilingheight;
|
||||
}
|
||||
|
||||
if (gr_backsector->f_slope)
|
||||
{
|
||||
worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y);
|
||||
worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldlow = worldlowslope = gr_backsector->floorheight;
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight)
|
||||
SLOPEPARAMS(gr_backsector->f_slope, worldlow, worldlowslope, gr_backsector->floorheight)
|
||||
#undef SLOPEPARAMS
|
||||
#else
|
||||
worldhigh = gr_backsector->ceilingheight;
|
||||
worldlow = gr_backsector->floorheight;
|
||||
worldhigh = gr_backsector->ceilingheight;
|
||||
worldlow = gr_backsector->floorheight;
|
||||
#endif
|
||||
}
|
||||
|
||||
// hack to allow height changes in outdoor areas
|
||||
// This is what gets rid of the upper textures if there should be sky
|
||||
|
@ -1614,7 +1576,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
worldhigh < worldtop
|
||||
) && gr_toptexture)
|
||||
{
|
||||
if (drawtextured)
|
||||
{
|
||||
fixed_t texturevpegtop; // top
|
||||
|
||||
|
@ -1695,7 +1656,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
#endif
|
||||
worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
|
||||
{
|
||||
if (drawtextured)
|
||||
{
|
||||
fixed_t texturevpegbottom = 0; // bottom
|
||||
|
||||
|
@ -1887,7 +1847,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
h = min(highcut, polytop);
|
||||
l = max(polybottom, lowcut);
|
||||
|
||||
if (drawtextured)
|
||||
{
|
||||
// PEGGING
|
||||
#ifdef ESLOPE
|
||||
|
@ -1943,7 +1902,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
h = min(highcut, polytop);
|
||||
l = max(polybottom, lowcut);
|
||||
|
||||
if (drawtextured)
|
||||
{
|
||||
// PEGGING
|
||||
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
|
||||
|
@ -2135,7 +2093,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
|
||||
if (gr_midtexture)
|
||||
{
|
||||
if (drawtextured)
|
||||
{
|
||||
fixed_t texturevpeg;
|
||||
// PEGGING
|
||||
|
@ -2276,7 +2233,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
wallVerts[0].s = wallVerts[3].s = 0;
|
||||
wallVerts[2].s = wallVerts[1].s = 0;
|
||||
}
|
||||
else if (drawtextured)
|
||||
else
|
||||
{
|
||||
#ifdef ESLOPE // P.S. this is better-organized than the old version
|
||||
fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset;
|
||||
|
@ -2409,7 +2366,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
wallVerts[0].s = wallVerts[3].s = 0;
|
||||
wallVerts[2].s = wallVerts[1].s = 0;
|
||||
}
|
||||
else if (drawtextured)
|
||||
else
|
||||
{
|
||||
grTex = HWR_GetTexture(texnum);
|
||||
|
||||
|
@ -2482,6 +2439,110 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
|
|||
//Hurdler: end of 3d-floors test
|
||||
}
|
||||
|
||||
// From PrBoom:
|
||||
//
|
||||
// e6y: Check whether the player can look beyond this line
|
||||
//
|
||||
#ifdef NEWCLIP
|
||||
boolean checkforemptylines = true;
|
||||
// Don't modify anything here, just check
|
||||
// Kalaron: Modified for sloped linedefs
|
||||
static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector)
|
||||
{
|
||||
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
|
||||
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
|
||||
|
||||
// GZDoom method of sloped line clipping
|
||||
|
||||
#ifdef ESLOPE
|
||||
if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope)
|
||||
{
|
||||
fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
|
||||
v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
|
||||
v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
|
||||
v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
|
||||
v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
|
||||
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
|
||||
if (slope) { \
|
||||
end1 = P_GetZAt(slope, v1x, v1y); \
|
||||
end2 = P_GetZAt(slope, v2x, v2y); \
|
||||
} else \
|
||||
end1 = end2 = normalheight;
|
||||
|
||||
SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight)
|
||||
SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight)
|
||||
SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight)
|
||||
SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
|
||||
#undef SLOPEPARAMS
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
frontf1 = frontf2 = afrontsector->floorheight;
|
||||
frontc1 = frontc2 = afrontsector->ceilingheight;
|
||||
backf1 = backf2 = abacksector->floorheight;
|
||||
backc1 = backc2 = abacksector->ceilingheight;
|
||||
}
|
||||
|
||||
// now check for closed sectors!
|
||||
if (backc1 <= frontf1 && backc2 <= frontf2)
|
||||
{
|
||||
checkforemptylines = false;
|
||||
if (!seg->sidedef->toptexture)
|
||||
return false;
|
||||
|
||||
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (backf1 >= frontc1 && backf2 >= frontc2)
|
||||
{
|
||||
checkforemptylines = false;
|
||||
if (!seg->sidedef->bottomtexture)
|
||||
return false;
|
||||
|
||||
// properly render skies (consider door "open" if both floors are sky):
|
||||
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (backc1 <= backf1 && backc2 <= backf2)
|
||||
{
|
||||
checkforemptylines = false;
|
||||
// preserve a kind of transparent door/lift special effect:
|
||||
if (backc1 < frontc1 || backc2 < frontc2)
|
||||
{
|
||||
if (!seg->sidedef->toptexture)
|
||||
return false;
|
||||
}
|
||||
if (backf1 > frontf1 || backf2 > frontf2)
|
||||
{
|
||||
if (!seg->sidedef->bottomtexture)
|
||||
return false;
|
||||
}
|
||||
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
|
||||
return false;
|
||||
|
||||
if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (backc1 != frontc1 || backc2 != frontc2
|
||||
|| backf1 != frontf1 || backf2 != frontf2)
|
||||
{
|
||||
checkforemptylines = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
//Hurdler: just like in r_bsp.c
|
||||
#if 1
|
||||
#define MAXSEGS MAXVIDWIDTH/2+1
|
||||
|
@ -2553,7 +2614,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
|
|||
}
|
||||
else
|
||||
{
|
||||
highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
|
||||
highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
|
||||
HWR_StoreWallRange(0, highfrac);
|
||||
}
|
||||
// Now adjust the clip size.
|
||||
|
@ -2577,8 +2638,8 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
|
|||
}
|
||||
else
|
||||
{
|
||||
lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
|
||||
highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
|
||||
lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
|
||||
highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
|
||||
HWR_StoreWallRange(lowfrac, highfrac);
|
||||
}
|
||||
next++;
|
||||
|
@ -2612,7 +2673,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
|
|||
}
|
||||
else
|
||||
{
|
||||
lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
|
||||
lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
|
||||
HWR_StoreWallRange(lowfrac, 1);
|
||||
}
|
||||
}
|
||||
|
@ -2675,8 +2736,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
|
|||
else
|
||||
{
|
||||
highfrac = HWR_ClipViewSegment(min(start->first + 1,
|
||||
start->last), (polyvertex_t *)gr_curline->v1,
|
||||
(polyvertex_t *)gr_curline->v2);
|
||||
start->last), (polyvertex_t *)gr_curline->pv1,
|
||||
(polyvertex_t *)gr_curline->pv2);
|
||||
HWR_StoreWallRange(0, highfrac);
|
||||
}
|
||||
}
|
||||
|
@ -2695,8 +2756,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
|
|||
}
|
||||
else
|
||||
{
|
||||
lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
|
||||
highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
|
||||
lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
|
||||
highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
|
||||
HWR_StoreWallRange(lowfrac, highfrac);
|
||||
}
|
||||
start++;
|
||||
|
@ -2726,8 +2787,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
|
|||
else
|
||||
{
|
||||
lowfrac = HWR_ClipViewSegment(max(start->last - 1,
|
||||
start->first), (polyvertex_t *)gr_curline->v1,
|
||||
(polyvertex_t *)gr_curline->v2);
|
||||
start->first), (polyvertex_t *)gr_curline->pv1,
|
||||
(polyvertex_t *)gr_curline->pv2);
|
||||
HWR_StoreWallRange(lowfrac, 1);
|
||||
}
|
||||
}
|
||||
|
@ -2767,6 +2828,7 @@ static void HWR_ClearClipSegs(void)
|
|||
gr_solidsegs[1].last = 0x7fffffff;
|
||||
hw_newend = gr_solidsegs+2;
|
||||
}
|
||||
#endif // NEWCLIP
|
||||
|
||||
// -----------------+
|
||||
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
|
||||
|
@ -2775,24 +2837,46 @@ static void HWR_ClearClipSegs(void)
|
|||
// -----------------+
|
||||
static void HWR_AddLine(seg_t * line)
|
||||
{
|
||||
INT32 x1, x2;
|
||||
angle_t angle1, angle2;
|
||||
#ifndef NEWCLIP
|
||||
INT32 x1, x2;
|
||||
angle_t span, tspan;
|
||||
#endif
|
||||
|
||||
// SoM: Backsector needs to be run through R_FakeFlat
|
||||
sector_t tempsec;
|
||||
|
||||
fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
|
||||
#ifdef POLYOBJECTS
|
||||
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
|
||||
return;
|
||||
#endif
|
||||
|
||||
gr_curline = line;
|
||||
|
||||
// OPTIMIZE: quickly reject orthogonal back sides.
|
||||
angle1 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
|
||||
angle2 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
|
||||
FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
|
||||
v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
|
||||
v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
|
||||
v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
|
||||
v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
|
||||
|
||||
// OPTIMIZE: quickly reject orthogonal back sides.
|
||||
angle1 = R_PointToAngle(v1x, v1y);
|
||||
angle2 = R_PointToAngle(v2x, v2y);
|
||||
|
||||
#ifdef NEWCLIP
|
||||
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
|
||||
if (angle2 - angle1 < ANGLE_180)
|
||||
return;
|
||||
|
||||
// PrBoom: use REAL clipping math YAYYYYYYY!!!
|
||||
|
||||
if (!gld_clipper_SafeCheckRange(angle2, angle1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
checkforemptylines = true;
|
||||
#else
|
||||
// Clip to view edges.
|
||||
span = angle1 - angle2;
|
||||
|
||||
|
@ -2833,8 +2917,8 @@ static void HWR_AddLine(seg_t * line)
|
|||
float fx1,fx2,fy1,fy2;
|
||||
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
|
||||
// do not enable this at release 4 mul and 2 div
|
||||
fx1 = ((polyvertex_t *)(line->v1))->x-gr_viewx;
|
||||
fy1 = ((polyvertex_t *)(line->v1))->y-gr_viewy;
|
||||
fx1 = ((polyvertex_t *)(line->pv1))->x-gr_viewx;
|
||||
fy1 = ((polyvertex_t *)(line->pv1))->y-gr_viewy;
|
||||
fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin);
|
||||
if (fy2 < 0)
|
||||
// the point is back
|
||||
|
@ -2842,8 +2926,8 @@ static void HWR_AddLine(seg_t * line)
|
|||
else
|
||||
fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2;
|
||||
|
||||
fx2 = ((polyvertex_t *)(line->v2))->x-gr_viewx;
|
||||
fy2 = ((polyvertex_t *)(line->v2))->y-gr_viewy;
|
||||
fx2 = ((polyvertex_t *)(line->pv2))->x-gr_viewx;
|
||||
fy2 = ((polyvertex_t *)(line->pv2))->y-gr_viewy;
|
||||
fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin);
|
||||
if (fy1 < 0)
|
||||
// the point is back
|
||||
|
@ -2871,8 +2955,34 @@ static void HWR_AddLine(seg_t * line)
|
|||
return;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
gr_backsector = line->backsector;
|
||||
|
||||
#ifdef NEWCLIP
|
||||
if (!line->backsector)
|
||||
{
|
||||
gld_clipper_SafeAddClipRange(angle2, angle1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true);
|
||||
if (CheckClip(line, gr_frontsector, gr_backsector))
|
||||
{
|
||||
gld_clipper_SafeAddClipRange(angle2, angle1);
|
||||
checkforemptylines = false;
|
||||
}
|
||||
// Reject empty lines used for triggers and special events.
|
||||
// Identical floor and ceiling on both sides,
|
||||
// identical light levels on both sides,
|
||||
// and no middle texture.
|
||||
if (checkforemptylines && R_IsEmptyLine(line, gr_frontsector, gr_backsector))
|
||||
return;
|
||||
}
|
||||
|
||||
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
|
||||
return;
|
||||
#else
|
||||
// Single sided line?
|
||||
if (!gr_backsector)
|
||||
goto clipsolid;
|
||||
|
@ -2882,14 +2992,9 @@ static void HWR_AddLine(seg_t * line)
|
|||
#ifdef ESLOPE
|
||||
if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_backsector->c_slope)
|
||||
{
|
||||
fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
|
||||
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
|
||||
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
|
||||
|
||||
v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x);
|
||||
v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y);
|
||||
v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x);
|
||||
v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y);
|
||||
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
|
||||
if (slope) { \
|
||||
end1 = P_GetZAt(slope, v1x, v1y); \
|
||||
|
@ -2910,6 +3015,13 @@ static void HWR_AddLine(seg_t * line)
|
|||
goto clipsolid;
|
||||
}
|
||||
|
||||
// Check for automap fix.
|
||||
if (backc1 <= backf1 && backc2 <= backf2
|
||||
&& ((backc1 >= frontc1 && backc2 >= frontc2) || gr_curline->sidedef->toptexture)
|
||||
&& ((backf1 <= frontf1 && backf2 >= frontf2) || gr_curline->sidedef->bottomtexture)
|
||||
&& (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
|
||||
goto clipsolid;
|
||||
|
||||
// Window.
|
||||
if (backc1 != frontc1 || backc2 != frontc2
|
||||
|| backf1 != frontf1 || backf2 != frontf2)
|
||||
|
@ -2925,6 +3037,13 @@ static void HWR_AddLine(seg_t * line)
|
|||
gr_backsector->floorheight >= gr_frontsector->ceilingheight)
|
||||
goto clipsolid;
|
||||
|
||||
// Check for automap fix.
|
||||
if (gr_backsector->ceilingheight <= gr_backsector->floorheight
|
||||
&& ((gr_backsector->ceilingheight >= gr_frontsector->ceilingheight) || gr_curline->sidedef->toptexture)
|
||||
&& ((gr_backsector->floorheight <= gr_backsector->floorheight) || gr_curline->sidedef->bottomtexture)
|
||||
&& (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
|
||||
goto clipsolid;
|
||||
|
||||
// Window.
|
||||
if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight ||
|
||||
gr_backsector->floorheight != gr_frontsector->floorheight)
|
||||
|
@ -2935,25 +3054,8 @@ static void HWR_AddLine(seg_t * line)
|
|||
// Identical floor and ceiling on both sides,
|
||||
// identical light levels on both sides,
|
||||
// and no middle texture.
|
||||
if (
|
||||
#ifdef POLYOBJECTS
|
||||
!line->polyseg &&
|
||||
#endif
|
||||
gr_backsector->ceilingpic == gr_frontsector->ceilingpic
|
||||
&& gr_backsector->floorpic == gr_frontsector->floorpic
|
||||
#ifdef ESLOPE
|
||||
&& gr_backsector->f_slope == gr_frontsector->f_slope
|
||||
&& gr_backsector->c_slope == gr_frontsector->c_slope
|
||||
#endif
|
||||
&& gr_backsector->lightlevel == gr_frontsector->lightlevel
|
||||
&& gr_curline->sidedef->midtexture == 0
|
||||
&& !gr_backsector->ffloors && !gr_frontsector->ffloors)
|
||||
// SoM: For 3D sides... Boris, would you like to take a
|
||||
// crack at rendering 3D sides? You would need to add the
|
||||
// above check and add code to HWR_StoreWallRange...
|
||||
{
|
||||
if (R_IsEmptyLine(gr_curline, gr_frontsector, gr_backsector))
|
||||
return;
|
||||
}
|
||||
|
||||
clippass:
|
||||
if (x1 == x2)
|
||||
|
@ -2965,6 +3067,7 @@ clipsolid:
|
|||
if (x1 == x2)
|
||||
goto clippass;
|
||||
HWR_ClipSolidWallSegment(x1, x2-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// HWR_CheckBBox
|
||||
|
@ -2976,9 +3079,13 @@ clipsolid:
|
|||
|
||||
static boolean HWR_CheckBBox(fixed_t *bspcoord)
|
||||
{
|
||||
INT32 boxpos, sx1, sx2;
|
||||
INT32 boxpos;
|
||||
fixed_t px1, py1, px2, py2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
angle_t angle1, angle2;
|
||||
#ifndef NEWCLIP
|
||||
INT32 sx1, sx2;
|
||||
angle_t span, tspan;
|
||||
#endif
|
||||
|
||||
// Find the corners of the box
|
||||
// that define the edges from current viewpoint.
|
||||
|
@ -3004,6 +3111,11 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
|
|||
px2 = bspcoord[checkcoord[boxpos][2]];
|
||||
py2 = bspcoord[checkcoord[boxpos][3]];
|
||||
|
||||
#ifdef NEWCLIP
|
||||
angle1 = R_PointToAngle(px1, py1);
|
||||
angle2 = R_PointToAngle(px2, py2);
|
||||
return gld_clipper_SafeCheckRange(angle2, angle1);
|
||||
#else
|
||||
// check clip list for an open space
|
||||
angle1 = R_PointToAngle(px1, py1) - dup_viewangle;
|
||||
angle2 = R_PointToAngle(px2, py2) - dup_viewangle;
|
||||
|
@ -3051,6 +3163,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
|
|||
return false;
|
||||
|
||||
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef POLYOBJECTS
|
||||
|
@ -3084,8 +3197,8 @@ static inline void HWR_AddPolyObjectSegs(void)
|
|||
pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x);
|
||||
pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y);
|
||||
|
||||
gr_fakeline->v1 = (vertex_t *)pv1;
|
||||
gr_fakeline->v2 = (vertex_t *)pv2;
|
||||
gr_fakeline->pv1 = pv1;
|
||||
gr_fakeline->pv2 = pv2;
|
||||
|
||||
HWR_AddLine(gr_fakeline);
|
||||
}
|
||||
|
@ -5630,7 +5743,19 @@ if (0)
|
|||
#ifdef SORTING
|
||||
drawcount = 0;
|
||||
#endif
|
||||
#ifdef NEWCLIP
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
angle_t a1 = gld_FrustumAngle();
|
||||
gld_clipper_Clear();
|
||||
gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
|
||||
#ifdef HAVE_SPHEREFRUSTRUM
|
||||
gld_FrustrumSetup();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
HWR_ClearClipSegs();
|
||||
#endif
|
||||
|
||||
//04/01/2000: Hurdler: added for T&L
|
||||
// Actually it only works on Walls and Planes
|
||||
|
@ -5640,6 +5765,7 @@ if (0)
|
|||
|
||||
HWR_RenderBSPNode((INT32)numnodes-1);
|
||||
|
||||
#ifndef NEWCLIP
|
||||
// Make a viewangle int so we can render things based on mouselook
|
||||
if (player == &players[consoleplayer])
|
||||
viewangle = localaiming;
|
||||
|
@ -5666,6 +5792,7 @@ if (0)
|
|||
|
||||
dup_viewangle += ANGLE_90;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for new console commands.
|
||||
NetUpdate();
|
||||
|
@ -5860,7 +5987,19 @@ if (0)
|
|||
#ifdef SORTING
|
||||
drawcount = 0;
|
||||
#endif
|
||||
#ifdef NEWCLIP
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
angle_t a1 = gld_FrustumAngle();
|
||||
gld_clipper_Clear();
|
||||
gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
|
||||
#ifdef HAVE_SPHEREFRUSTRUM
|
||||
gld_FrustrumSetup();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
HWR_ClearClipSegs();
|
||||
#endif
|
||||
|
||||
//04/01/2000: Hurdler: added for T&L
|
||||
// Actually it only works on Walls and Planes
|
||||
|
@ -5870,6 +6009,7 @@ if (0)
|
|||
|
||||
HWR_RenderBSPNode((INT32)numnodes-1);
|
||||
|
||||
#ifndef NEWCLIP
|
||||
// Make a viewangle int so we can render things based on mouselook
|
||||
if (player == &players[consoleplayer])
|
||||
viewangle = localaiming;
|
||||
|
@ -5896,6 +6036,7 @@ if (0)
|
|||
|
||||
dup_viewangle += ANGLE_90;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for new console commands.
|
||||
NetUpdate();
|
||||
|
@ -6041,7 +6182,9 @@ static inline void HWR_AddEngineCommands(void)
|
|||
{
|
||||
// engine state variables
|
||||
//CV_RegisterVar(&cv_grzbuffer);
|
||||
#ifndef NEWCLIP
|
||||
CV_RegisterVar(&cv_grclipwalls);
|
||||
#endif
|
||||
|
||||
// engine development mode variables
|
||||
// - usage may vary from version to version..
|
||||
|
|
|
@ -298,8 +298,8 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
// initialize model and read header
|
||||
|
||||
if (fread(&model->header, sizeof (model->header), 1, file) != 1
|
||||
|| model->header.magic !=
|
||||
(INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I'))
|
||||
|| model->header.magic != MD2_IDENT
|
||||
|| model->header.version != MD2_VERSION)
|
||||
{
|
||||
fclose(file);
|
||||
free(model);
|
||||
|
@ -313,6 +313,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
{ \
|
||||
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
|
||||
md2_freeModel (model); \
|
||||
fclose(file); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
@ -334,6 +335,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -347,6 +349,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +363,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -372,6 +376,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
if (!model->frames)
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -385,6 +390,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
fread(frame, 1, model->header.frameSize, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -410,6 +416,7 @@ static md2_model_t *md2_readModel(const char *filename)
|
|||
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -961,244 +968,10 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
|
|||
image = gpatch->mipmap.grInfo.data;
|
||||
blendimage = blendgpatch->mipmap.grInfo.data;
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case SKINCOLOR_WHITE:
|
||||
blendcolor = V_GetColor(3);
|
||||
break;
|
||||
case SKINCOLOR_SILVER:
|
||||
blendcolor = V_GetColor(10);
|
||||
break;
|
||||
case SKINCOLOR_GREY:
|
||||
blendcolor = V_GetColor(15);
|
||||
break;
|
||||
case SKINCOLOR_BLACK:
|
||||
blendcolor = V_GetColor(27);
|
||||
break;
|
||||
case SKINCOLOR_BEIGE:
|
||||
blendcolor = V_GetColor(247);
|
||||
break;
|
||||
case SKINCOLOR_PEACH:
|
||||
blendcolor = V_GetColor(218);
|
||||
break;
|
||||
case SKINCOLOR_BROWN:
|
||||
blendcolor = V_GetColor(234);
|
||||
break;
|
||||
case SKINCOLOR_RED:
|
||||
blendcolor = V_GetColor(38);
|
||||
break;
|
||||
case SKINCOLOR_CRIMSON:
|
||||
blendcolor = V_GetColor(45);
|
||||
break;
|
||||
case SKINCOLOR_ORANGE:
|
||||
blendcolor = V_GetColor(54);
|
||||
break;
|
||||
case SKINCOLOR_RUST:
|
||||
blendcolor = V_GetColor(60);
|
||||
break;
|
||||
case SKINCOLOR_GOLD:
|
||||
blendcolor = V_GetColor(67);
|
||||
break;
|
||||
case SKINCOLOR_YELLOW:
|
||||
blendcolor = V_GetColor(73);
|
||||
break;
|
||||
case SKINCOLOR_TAN:
|
||||
blendcolor = V_GetColor(85);
|
||||
break;
|
||||
case SKINCOLOR_MOSS:
|
||||
blendcolor = V_GetColor(92);
|
||||
break;
|
||||
case SKINCOLOR_PERIDOT:
|
||||
blendcolor = V_GetColor(188);
|
||||
break;
|
||||
case SKINCOLOR_GREEN:
|
||||
blendcolor = V_GetColor(101);
|
||||
break;
|
||||
case SKINCOLOR_EMERALD:
|
||||
blendcolor = V_GetColor(112);
|
||||
break;
|
||||
case SKINCOLOR_AQUA:
|
||||
blendcolor = V_GetColor(122);
|
||||
break;
|
||||
case SKINCOLOR_TEAL:
|
||||
blendcolor = V_GetColor(141);
|
||||
break;
|
||||
case SKINCOLOR_CYAN:
|
||||
blendcolor = V_GetColor(131);
|
||||
break;
|
||||
case SKINCOLOR_BLUE:
|
||||
blendcolor = V_GetColor(152);
|
||||
break;
|
||||
case SKINCOLOR_AZURE:
|
||||
blendcolor = V_GetColor(171);
|
||||
break;
|
||||
case SKINCOLOR_PASTEL:
|
||||
blendcolor = V_GetColor(161);
|
||||
break;
|
||||
case SKINCOLOR_PURPLE:
|
||||
blendcolor = V_GetColor(165);
|
||||
break;
|
||||
case SKINCOLOR_LAVENDER:
|
||||
blendcolor = V_GetColor(195);
|
||||
break;
|
||||
case SKINCOLOR_MAGENTA:
|
||||
blendcolor = V_GetColor(183);
|
||||
break;
|
||||
case SKINCOLOR_PINK:
|
||||
blendcolor = V_GetColor(211);
|
||||
break;
|
||||
case SKINCOLOR_ROSY:
|
||||
blendcolor = V_GetColor(202);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERSILVER1: // Super silver
|
||||
blendcolor = V_GetColor(0);
|
||||
break;
|
||||
case SKINCOLOR_SUPERSILVER2:
|
||||
blendcolor = V_GetColor(2);
|
||||
break;
|
||||
case SKINCOLOR_SUPERSILVER3:
|
||||
blendcolor = V_GetColor(4);
|
||||
break;
|
||||
case SKINCOLOR_SUPERSILVER4:
|
||||
blendcolor = V_GetColor(7);
|
||||
break;
|
||||
case SKINCOLOR_SUPERSILVER5:
|
||||
blendcolor = V_GetColor(10);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERRED1: // Super red
|
||||
blendcolor = V_GetColor(208);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRED2:
|
||||
blendcolor = V_GetColor(210);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRED3:
|
||||
blendcolor = V_GetColor(32);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRED4:
|
||||
blendcolor = V_GetColor(33);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRED5:
|
||||
blendcolor = V_GetColor(35);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERORANGE1: // Super orange
|
||||
blendcolor = V_GetColor(208);
|
||||
break;
|
||||
case SKINCOLOR_SUPERORANGE2:
|
||||
blendcolor = V_GetColor(48);
|
||||
break;
|
||||
case SKINCOLOR_SUPERORANGE3:
|
||||
blendcolor = V_GetColor(50);
|
||||
break;
|
||||
case SKINCOLOR_SUPERORANGE4:
|
||||
blendcolor = V_GetColor(54);
|
||||
break;
|
||||
case SKINCOLOR_SUPERORANGE5:
|
||||
blendcolor = V_GetColor(58);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERGOLD1: // Super gold
|
||||
blendcolor = V_GetColor(80);
|
||||
break;
|
||||
case SKINCOLOR_SUPERGOLD2:
|
||||
blendcolor = V_GetColor(83);
|
||||
break;
|
||||
case SKINCOLOR_SUPERGOLD3:
|
||||
blendcolor = V_GetColor(73);
|
||||
break;
|
||||
case SKINCOLOR_SUPERGOLD4:
|
||||
blendcolor = V_GetColor(64);
|
||||
break;
|
||||
case SKINCOLOR_SUPERGOLD5:
|
||||
blendcolor = V_GetColor(67);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERPERIDOT1: // Super peridot
|
||||
blendcolor = V_GetColor(88);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPERIDOT2:
|
||||
blendcolor = V_GetColor(188);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPERIDOT3:
|
||||
blendcolor = V_GetColor(189);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPERIDOT4:
|
||||
blendcolor = V_GetColor(190);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPERIDOT5:
|
||||
blendcolor = V_GetColor(191);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERCYAN1: // Super cyan
|
||||
blendcolor = V_GetColor(128);
|
||||
break;
|
||||
case SKINCOLOR_SUPERCYAN2:
|
||||
blendcolor = V_GetColor(131);
|
||||
break;
|
||||
case SKINCOLOR_SUPERCYAN3:
|
||||
blendcolor = V_GetColor(133);
|
||||
break;
|
||||
case SKINCOLOR_SUPERCYAN4:
|
||||
blendcolor = V_GetColor(134);
|
||||
break;
|
||||
case SKINCOLOR_SUPERCYAN5:
|
||||
blendcolor = V_GetColor(136);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERPURPLE1: // Super purple
|
||||
blendcolor = V_GetColor(144);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPURPLE2:
|
||||
blendcolor = V_GetColor(162);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPURPLE3:
|
||||
blendcolor = V_GetColor(164);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPURPLE4:
|
||||
blendcolor = V_GetColor(166);
|
||||
break;
|
||||
case SKINCOLOR_SUPERPURPLE5:
|
||||
blendcolor = V_GetColor(168);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERRUST1: // Super rust
|
||||
blendcolor = V_GetColor(51);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRUST2:
|
||||
blendcolor = V_GetColor(54);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRUST3:
|
||||
blendcolor = V_GetColor(68);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRUST4:
|
||||
blendcolor = V_GetColor(70);
|
||||
break;
|
||||
case SKINCOLOR_SUPERRUST5:
|
||||
blendcolor = V_GetColor(234);
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPERTAN1: // Super tan
|
||||
blendcolor = V_GetColor(80);
|
||||
break;
|
||||
case SKINCOLOR_SUPERTAN2:
|
||||
blendcolor = V_GetColor(82);
|
||||
break;
|
||||
case SKINCOLOR_SUPERTAN3:
|
||||
blendcolor = V_GetColor(84);
|
||||
break;
|
||||
case SKINCOLOR_SUPERTAN4:
|
||||
blendcolor = V_GetColor(87);
|
||||
break;
|
||||
case SKINCOLOR_SUPERTAN5:
|
||||
blendcolor = V_GetColor(247);
|
||||
break;
|
||||
|
||||
default:
|
||||
blendcolor = V_GetColor(255);
|
||||
break;
|
||||
}
|
||||
if (color == SKINCOLOR_NONE || color >= MAXTRANSLATIONS)
|
||||
blendcolor = V_GetColor(0xff);
|
||||
else
|
||||
blendcolor = V_GetColor(Color_Index[color-1][4]);
|
||||
|
||||
while (size--)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
|
||||
#include "hw_glob.h"
|
||||
|
||||
// magic number "IDP2" or 844121161
|
||||
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
|
||||
// model version
|
||||
#define MD2_VERSION 8
|
||||
|
||||
#define MD2_MAX_TRIANGLES 8192
|
||||
#define MD2_MAX_VERTICES 4096
|
||||
#define MD2_MAX_TEXCOORDS 4096
|
||||
|
|
|
@ -107,17 +107,17 @@ static void releaseLineChains(void)
|
|||
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
sector = §ors[i];
|
||||
nextElem = sector->sectorLines;
|
||||
sector = §ors[i];
|
||||
nextElem = sector->sectorLines;
|
||||
|
||||
while (nextElem)
|
||||
{
|
||||
thisElem = nextElem;
|
||||
nextElem = thisElem->next;
|
||||
free(thisElem);
|
||||
}
|
||||
while (nextElem)
|
||||
{
|
||||
thisElem = nextElem;
|
||||
nextElem = thisElem->next;
|
||||
free(thisElem);
|
||||
}
|
||||
|
||||
sector->sectorLines = NULL;
|
||||
sector->sectorLines = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,7 +397,7 @@ static void sortStacklist(sector_t *sector)
|
|||
i = 0;
|
||||
finished = true;
|
||||
|
||||
while (NULL != *(list+i+1))
|
||||
while (*(list+i+1))
|
||||
{
|
||||
sec1 = *(list+i);
|
||||
sec2 = *(list+i+1);
|
||||
|
@ -438,7 +438,7 @@ static double calcLineoutLength(sector_t *sector)
|
|||
double length = 0.0L;
|
||||
chain = sector->sectorLines;
|
||||
|
||||
while (NULL != chain) // sum up lengths of all lines
|
||||
while (chain) // sum up lengths of all lines
|
||||
{
|
||||
length += lineLength(chain->line);
|
||||
chain = chain->next;
|
||||
|
@ -454,7 +454,7 @@ static void calcLineouts(sector_t *sector)
|
|||
size_t secCount = 0;
|
||||
sector_t *encSector = *(sector->stackList);
|
||||
|
||||
while (NULL != encSector)
|
||||
while (encSector)
|
||||
{
|
||||
if (encSector->lineoutLength < 0.0L) // if length has not yet been calculated
|
||||
{
|
||||
|
@ -552,7 +552,7 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
|
|||
if (frontSector == backSector) // skip damn renderer tricks here
|
||||
continue;
|
||||
|
||||
if (frontSector == NULL || backSector == NULL)
|
||||
if (!frontSector || !backSector)
|
||||
continue;
|
||||
|
||||
sider = &sides[thisElem->line->sidenum[0]];
|
||||
|
@ -587,73 +587,12 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
|
|||
static boolean isCeilingFloating(sector_t *thisSector)
|
||||
{
|
||||
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
|
||||
boolean floating = true;
|
||||
linechain_t *thisElem, *nextElem;
|
||||
|
||||
if (!thisSector)
|
||||
return false;
|
||||
|
||||
nextElem = thisSector->sectorLines;
|
||||
|
||||
while (NULL != nextElem) // walk through chain
|
||||
{
|
||||
thisElem = nextElem;
|
||||
nextElem = thisElem->next;
|
||||
|
||||
frontSector = thisElem->line->frontsector;
|
||||
backSector = thisElem->line->backsector;
|
||||
|
||||
if (frontSector == thisSector)
|
||||
adjSector = backSector;
|
||||
else
|
||||
adjSector = frontSector;
|
||||
|
||||
if (!adjSector) // assume floating sectors have surrounding sectors
|
||||
{
|
||||
floating = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!refSector)
|
||||
{
|
||||
refSector = adjSector;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if adjacent sector has same height or more than one adjacent sector exists -> stop
|
||||
if (thisSector->ceilingheight == adjSector->ceilingheight ||
|
||||
refSector != adjSector)
|
||||
{
|
||||
floating = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now check for walltextures
|
||||
if (floating)
|
||||
{
|
||||
if (!areToptexturesMissing(thisSector))
|
||||
{
|
||||
floating = false;
|
||||
}
|
||||
}
|
||||
return floating;
|
||||
}
|
||||
|
||||
//
|
||||
// check if no adjacent sector has same ceiling height
|
||||
// FIXME: throw that together with isCeilingFloating??
|
||||
//
|
||||
static boolean isFloorFloating(sector_t *thisSector)
|
||||
{
|
||||
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
|
||||
boolean floating = true;
|
||||
linechain_t *thisElem, *nextElem;
|
||||
|
||||
if (!thisSector)
|
||||
return false;
|
||||
|
||||
nextElem = thisSector->sectorLines;
|
||||
nextElem = thisSector->sectorLines;
|
||||
|
||||
while (nextElem) // walk through chain
|
||||
{
|
||||
|
@ -668,36 +607,83 @@ static boolean isFloorFloating(sector_t *thisSector)
|
|||
else
|
||||
adjSector = frontSector;
|
||||
|
||||
if (NULL == adjSector) // assume floating sectors have surrounding sectors
|
||||
{
|
||||
floating = false;
|
||||
break;
|
||||
}
|
||||
if (!adjSector) // assume floating sectors have surrounding sectors
|
||||
return false;
|
||||
|
||||
if (NULL == refSector)
|
||||
#ifdef ESLOPE
|
||||
if (adjSector->c_slope) // Don't bother with slopes
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!refSector)
|
||||
{
|
||||
refSector = adjSector;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if adjacent sector has same height or more than one adjacent sector exists -> stop
|
||||
if (thisSector->floorheight == adjSector->floorheight ||
|
||||
refSector != adjSector)
|
||||
{
|
||||
floating = false;
|
||||
break;
|
||||
}
|
||||
if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector)
|
||||
return false;
|
||||
}
|
||||
|
||||
// now check for walltextures
|
||||
if (floating)
|
||||
if (!areToptexturesMissing(thisSector))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// check if no adjacent sector has same ceiling height
|
||||
// FIXME: throw that together with isCeilingFloating??
|
||||
//
|
||||
static boolean isFloorFloating(sector_t *thisSector)
|
||||
{
|
||||
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
|
||||
linechain_t *thisElem, *nextElem;
|
||||
|
||||
if (!thisSector)
|
||||
return false;
|
||||
|
||||
nextElem = thisSector->sectorLines;
|
||||
|
||||
while (nextElem) // walk through chain
|
||||
{
|
||||
if (!areBottomtexturesMissing(thisSector))
|
||||
thisElem = nextElem;
|
||||
nextElem = thisElem->next;
|
||||
|
||||
frontSector = thisElem->line->frontsector;
|
||||
backSector = thisElem->line->backsector;
|
||||
|
||||
if (frontSector == thisSector)
|
||||
adjSector = backSector;
|
||||
else
|
||||
adjSector = frontSector;
|
||||
|
||||
if (!adjSector) // assume floating sectors have surrounding sectors
|
||||
return false;
|
||||
|
||||
#ifdef ESLOPE
|
||||
if (adjSector->f_slope) // Don't bother with slopes
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!refSector)
|
||||
{
|
||||
floating = false;
|
||||
refSector = adjSector;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if adjacent sector has same height or more than one adjacent sector exists -> stop
|
||||
if (thisSector->floorheight == adjSector->floorheight || refSector != adjSector)
|
||||
return false;
|
||||
}
|
||||
return floating;
|
||||
|
||||
// now check for walltextures
|
||||
if (!areBottomtexturesMissing(thisSector))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -707,14 +693,12 @@ static fixed_t estimateCeilHeight(sector_t *thisSector)
|
|||
{
|
||||
sector_t *adjSector;
|
||||
|
||||
if (!thisSector ||
|
||||
!thisSector->sectorLines ||
|
||||
!thisSector->sectorLines->line)
|
||||
if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
|
||||
return 0;
|
||||
|
||||
adjSector = thisSector->sectorLines->line->frontsector;
|
||||
if (adjSector == thisSector)
|
||||
adjSector = thisSector->sectorLines->line->backsector;
|
||||
adjSector = thisSector->sectorLines->line->backsector;
|
||||
|
||||
if (!adjSector)
|
||||
return 0;
|
||||
|
@ -729,17 +713,15 @@ static fixed_t estimateFloorHeight(sector_t *thisSector)
|
|||
{
|
||||
sector_t *adjSector;
|
||||
|
||||
if (!thisSector ||
|
||||
!thisSector->sectorLines ||
|
||||
!thisSector->sectorLines->line)
|
||||
return 0;
|
||||
if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
|
||||
return 0;
|
||||
|
||||
adjSector = thisSector->sectorLines->line->frontsector;
|
||||
if (adjSector == thisSector)
|
||||
adjSector = thisSector->sectorLines->line->backsector;
|
||||
adjSector = thisSector->sectorLines->line->backsector;
|
||||
|
||||
if (NULL == adjSector)
|
||||
return 0;
|
||||
if (!adjSector)
|
||||
return 0;
|
||||
|
||||
return adjSector->floorheight;
|
||||
}
|
||||
|
@ -845,18 +827,12 @@ void HWR_CorrectSWTricks(void)
|
|||
// correct height of floating sectors
|
||||
if (isCeilingFloating(floatSector))
|
||||
{
|
||||
fixed_t corrheight;
|
||||
|
||||
corrheight = estimateCeilHeight(floatSector);
|
||||
floatSector->virtualCeilingheight = corrheight;
|
||||
floatSector->virtualCeilingheight = estimateCeilHeight(floatSector);
|
||||
floatSector->virtualCeiling = true;
|
||||
}
|
||||
if (isFloorFloating(floatSector))
|
||||
{
|
||||
fixed_t corrheight;
|
||||
|
||||
corrheight = estimateFloorHeight(floatSector);
|
||||
floatSector->virtualFloorheight = corrheight;
|
||||
floatSector->virtualFloorheight = estimateFloorHeight(floatSector);
|
||||
floatSector->virtualFloor = true;
|
||||
}
|
||||
}
|
||||
|
|
157
src/hu_stuff.c
157
src/hu_stuff.c
|
@ -92,6 +92,7 @@ patch_t *emeraldpics[7];
|
|||
patch_t *tinyemeraldpics[7];
|
||||
static patch_t *emblemicon;
|
||||
patch_t *tokenicon;
|
||||
static patch_t *exiticon;
|
||||
|
||||
//-------------------------------------------
|
||||
// misc vars
|
||||
|
@ -245,6 +246,7 @@ void HU_LoadGraphics(void)
|
|||
|
||||
emblemicon = W_CachePatchName("EMBLICON", PU_HUDGFX);
|
||||
tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX);
|
||||
exiticon = W_CachePatchName("EXITICON", PU_HUDGFX);
|
||||
|
||||
emeraldpics[0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
|
||||
emeraldpics[1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
|
||||
|
@ -1176,6 +1178,9 @@ void HU_Erase(void)
|
|||
// IN-LEVEL MULTIPLAYER RANKINGS
|
||||
//======================================================================
|
||||
|
||||
#define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER))
|
||||
#define greycheckdef ((players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) || players[tab[i].num].spectator)
|
||||
|
||||
//
|
||||
// HU_DrawTabRankings
|
||||
//
|
||||
|
@ -1183,6 +1188,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
{
|
||||
INT32 i;
|
||||
const UINT8 *colormap;
|
||||
boolean greycheck, supercheck;
|
||||
|
||||
//this function is designed for 9 or less score lines only
|
||||
I_Assert(scorelines <= 9);
|
||||
|
@ -1191,12 +1197,15 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
|
||||
for (i = 0; i < scorelines; i++)
|
||||
{
|
||||
if (players[tab[i].num].spectator)
|
||||
if (players[tab[i].num].spectator && gametype != GT_COOP)
|
||||
continue; //ignore them.
|
||||
|
||||
greycheck = greycheckdef;
|
||||
supercheck = supercheckdef;
|
||||
|
||||
V_DrawString(x + 20, y,
|
||||
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
|
||||
| ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS)
|
||||
| (greycheck ? V_60TRANS : 0)
|
||||
| V_ALLOWLOWERCASE, tab[i].name);
|
||||
|
||||
// Draw emeralds
|
||||
|
@ -1206,7 +1215,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
HU_DrawEmeralds(x-12,y+2,tab[i].emeralds);
|
||||
}
|
||||
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, livesback);
|
||||
else
|
||||
V_DrawSmallScaledPatch (x, y-4, 0, livesback);
|
||||
|
@ -1214,11 +1223,11 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
if (tab[i].color == 0)
|
||||
{
|
||||
colormap = colormaps;
|
||||
if (players[tab[i].num].powers[pw_super])
|
||||
if (supercheck)
|
||||
V_DrawSmallScaledPatch(x, y-4, 0, superprefix[players[tab[i].num].skin]);
|
||||
else
|
||||
{
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentPatch(x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]);
|
||||
else
|
||||
V_DrawSmallScaledPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin]);
|
||||
|
@ -1226,7 +1235,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
}
|
||||
else
|
||||
{
|
||||
if (players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9]))
|
||||
if (supercheck)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
|
||||
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
|
||||
|
@ -1234,23 +1243,26 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
else
|
||||
{
|
||||
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap);
|
||||
else
|
||||
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
|
||||
}
|
||||
}
|
||||
|
||||
if (G_GametypeUsesLives()) //show lives
|
||||
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%dx", players[tab[i].num].lives));
|
||||
if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3))) //show lives
|
||||
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives));
|
||||
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
|
||||
{
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentPatch(x-32, y-4, V_60TRANS, tagico);
|
||||
else
|
||||
V_DrawSmallScaledPatch(x-32, y-4, 0, tagico);
|
||||
}
|
||||
|
||||
if (players[tab[i].num].exiting)
|
||||
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
|
||||
|
||||
if (gametype == GT_RACE)
|
||||
{
|
||||
if (circuitmap)
|
||||
|
@ -1258,13 +1270,13 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
if (players[tab[i].num].exiting)
|
||||
V_DrawRightAlignedString(x+240, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime)));
|
||||
else
|
||||
V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count));
|
||||
V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%u", tab[i].count));
|
||||
}
|
||||
else
|
||||
V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
|
||||
V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
|
||||
}
|
||||
else
|
||||
V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count));
|
||||
V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%u", tab[i].count));
|
||||
|
||||
y += 16;
|
||||
}
|
||||
|
@ -1279,6 +1291,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
|
|||
INT32 redplayers = 0, blueplayers = 0;
|
||||
const UINT8 *colormap;
|
||||
char name[MAXPLAYERNAME+1];
|
||||
boolean greycheck, supercheck;
|
||||
|
||||
V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams.
|
||||
V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T.
|
||||
|
@ -1306,10 +1319,13 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
|
|||
else //er? not on red or blue, so ignore them
|
||||
continue;
|
||||
|
||||
greycheck = greycheckdef;
|
||||
supercheck = supercheckdef;
|
||||
|
||||
strlcpy(name, tab[i].name, 9);
|
||||
V_DrawString(x + 20, y,
|
||||
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
|
||||
| ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT)
|
||||
| (greycheck ? V_TRANSLUCENT : 0)
|
||||
| V_ALLOWLOWERCASE, name);
|
||||
|
||||
if (gametype == GT_CTF)
|
||||
|
@ -1327,7 +1343,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
|
|||
HU_DrawEmeralds(x-12,y+2,tab[i].emeralds);
|
||||
}
|
||||
|
||||
if (players[tab[i].num].powers[pw_super])
|
||||
if (supercheck)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
|
||||
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
|
||||
|
@ -1335,12 +1351,12 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
|
|||
else
|
||||
{
|
||||
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap);
|
||||
else
|
||||
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
|
||||
}
|
||||
V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
|
||||
V_DrawRightAlignedThinString(x+120, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1352,6 +1368,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
|||
INT32 i;
|
||||
const UINT8 *colormap;
|
||||
char name[MAXPLAYERNAME+1];
|
||||
boolean greycheck, supercheck;
|
||||
|
||||
V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides.
|
||||
V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T.
|
||||
|
@ -1359,20 +1376,26 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
|||
|
||||
for (i = 0; i < scorelines; i++)
|
||||
{
|
||||
if (players[tab[i].num].spectator)
|
||||
if (players[tab[i].num].spectator && gametype != GT_COOP)
|
||||
continue; //ignore them.
|
||||
|
||||
greycheck = greycheckdef;
|
||||
supercheck = supercheckdef;
|
||||
|
||||
strlcpy(name, tab[i].name, 9);
|
||||
V_DrawString(x + 20, y,
|
||||
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
|
||||
| ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT)
|
||||
| (greycheck ? V_TRANSLUCENT : 0)
|
||||
| V_ALLOWLOWERCASE, name);
|
||||
|
||||
if (G_GametypeUsesLives()) //show lives
|
||||
if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3))) //show lives
|
||||
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
|
||||
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
|
||||
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
|
||||
|
||||
if (players[tab[i].num].exiting)
|
||||
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
|
||||
|
||||
// Draw emeralds
|
||||
if (!players[tab[i].num].powers[pw_super]
|
||||
|| ((leveltime/7) & 1))
|
||||
|
@ -1384,19 +1407,19 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
|||
if (tab[i].color == 0)
|
||||
{
|
||||
colormap = colormaps;
|
||||
if (players[tab[i].num].powers[pw_super])
|
||||
if (supercheck)
|
||||
V_DrawSmallScaledPatch (x, y-4, 0, superprefix[players[tab[i].num].skin]);
|
||||
else
|
||||
{
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
V_DrawSmallTranslucentPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]);
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]);
|
||||
else
|
||||
V_DrawSmallScaledPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[tab[i].num].powers[pw_super])
|
||||
if (supercheck)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
|
||||
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
|
||||
|
@ -1404,8 +1427,8 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
|||
else
|
||||
{
|
||||
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
|
||||
if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
|
||||
V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
|
||||
if (greycheck)
|
||||
V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap);
|
||||
else
|
||||
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
|
||||
}
|
||||
|
@ -1419,13 +1442,13 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
|||
if (players[tab[i].num].exiting)
|
||||
V_DrawRightAlignedThinString(x+156, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime)));
|
||||
else
|
||||
V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
|
||||
V_DrawRightAlignedThinString(x+156, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
|
||||
}
|
||||
else
|
||||
V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
|
||||
V_DrawRightAlignedThinString(x+156, y, (greycheck ? V_TRANSLUCENT : 0), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
|
||||
}
|
||||
else
|
||||
V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
|
||||
V_DrawRightAlignedThinString(x+120, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
|
||||
|
||||
y += 16;
|
||||
if (y > 160)
|
||||
|
@ -1622,61 +1645,67 @@ static void HU_DrawRankings(void)
|
|||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (!playeringame[j] || players[j].spectator)
|
||||
if (!playeringame[j])
|
||||
continue;
|
||||
|
||||
if (gametype != GT_COOP && players[j].spectator)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (gametype != GT_COOP && players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (gametype == GT_RACE)
|
||||
{
|
||||
if (gametype == GT_RACE)
|
||||
if (circuitmap)
|
||||
{
|
||||
if (circuitmap)
|
||||
if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
tab[scorelines].count = players[i].laps+1;
|
||||
tab[scorelines].num = i;
|
||||
tab[scorelines].color = players[i].skincolor;
|
||||
tab[scorelines].name = player_names[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[i].realtime <= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
tab[scorelines].count = players[i].realtime;
|
||||
tab[scorelines].num = i;
|
||||
tab[scorelines].color = players[i].skincolor;
|
||||
tab[scorelines].name = player_names[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gametype == GT_COMPETITION)
|
||||
{
|
||||
// todo put something more fitting for the gametype here, such as current
|
||||
// number of categories led
|
||||
if (players[i].score >= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
tab[scorelines].count = players[i].score;
|
||||
tab[scorelines].count = players[i].laps+1;
|
||||
tab[scorelines].num = i;
|
||||
tab[scorelines].color = players[i].skincolor;
|
||||
tab[scorelines].name = player_names[i];
|
||||
tab[scorelines].emeralds = players[i].powers[pw_emeralds];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[i].score >= tab[scorelines].count && completed[i] == false)
|
||||
if (players[i].realtime <= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
tab[scorelines].count = players[i].score;
|
||||
tab[scorelines].count = players[i].realtime;
|
||||
tab[scorelines].num = i;
|
||||
tab[scorelines].color = players[i].skincolor;
|
||||
tab[scorelines].name = player_names[i];
|
||||
tab[scorelines].emeralds = players[i].powers[pw_emeralds];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gametype == GT_COMPETITION)
|
||||
{
|
||||
// todo put something more fitting for the gametype here, such as current
|
||||
// number of categories led
|
||||
if (players[i].score >= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
tab[scorelines].count = players[i].score;
|
||||
tab[scorelines].num = i;
|
||||
tab[scorelines].color = players[i].skincolor;
|
||||
tab[scorelines].name = player_names[i];
|
||||
tab[scorelines].emeralds = players[i].powers[pw_emeralds];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[i].score >= tab[scorelines].count && completed[i] == false)
|
||||
{
|
||||
tab[scorelines].count = players[i].score;
|
||||
tab[scorelines].num = i;
|
||||
tab[scorelines].color = players[i].skincolor;
|
||||
tab[scorelines].name = player_names[i];
|
||||
tab[scorelines].emeralds = players[i].powers[pw_emeralds];
|
||||
}
|
||||
}
|
||||
}
|
||||
completed[tab[scorelines].num] = true;
|
||||
scorelines++;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
//------------------------------------
|
||||
// heads up font
|
||||
//------------------------------------
|
||||
#define HU_FONTSTART '\x19' // the first font character
|
||||
#define HU_FONTSTART '\x16' // the first font character
|
||||
#define HU_FONTEND '~'
|
||||
|
||||
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
|
||||
|
|
298
src/info.c
298
src/info.c
|
@ -211,6 +211,10 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"BMCH", // Big Mace Chain
|
||||
"SMCE", // Small Mace
|
||||
"BMCE", // Big Mace
|
||||
"YSPB", // Yellow spring on a ball
|
||||
"RSPB", // Red spring on a ball
|
||||
"SFBR", // Small Firebar
|
||||
"BFBR", // Big Firebar
|
||||
|
||||
// Arid Canyon Scenery
|
||||
"BTBL", // Big tumbleweed
|
||||
|
@ -1675,22 +1679,22 @@ state_t states[NUMSTATES] =
|
|||
{SPR_TVRI, 2, 18, {A_RingBox}, 0, 0, S_NULL}, // S_RING_ICON2
|
||||
|
||||
{SPR_TVPI, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_PITY_ICON2}, // S_PITY_ICON1
|
||||
{SPR_TVPI, 2, 18, {A_PityShield}, 0, 0, S_NULL}, // S_PITY_ICON2
|
||||
{SPR_TVPI, 2, 18, {A_GiveShield}, SH_PITY, 0, S_NULL}, // S_PITY_ICON2
|
||||
|
||||
{SPR_TVAT, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ATTRACT_ICON2}, // S_ATTRACT_ICON1
|
||||
{SPR_TVAT, 2, 18, {A_RingShield},0, 0, S_NULL}, // S_ATTRACT_ICON2
|
||||
{SPR_TVAT, 2, 18, {A_GiveShield}, SH_ATTRACT, 0, S_NULL}, // S_ATTRACT_ICON2
|
||||
|
||||
{SPR_TVFO, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FORCE_ICON2}, // S_FORCE_ICON1
|
||||
{SPR_TVFO, 2, 18, {A_ForceShield}, 1, 0, S_NULL}, // S_FORCE_ICON2
|
||||
{SPR_TVFO, 2, 18, {A_GiveShield}, SH_FORCE|1, 0, S_NULL}, // S_FORCE_ICON2
|
||||
|
||||
{SPR_TVAR, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ARMAGEDDON_ICON2}, // S_ARMAGEDDON_ICON1
|
||||
{SPR_TVAR, 2, 18, {A_BombShield}, 0, 0, S_NULL}, // S_ARMAGEDDON_ICON2
|
||||
{SPR_TVAR, 2, 18, {A_GiveShield}, SH_ARMAGEDDON, 0, S_NULL}, // S_ARMAGEDDON_ICON2
|
||||
|
||||
{SPR_TVWW, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_WHIRLWIND_ICON2}, // S_WHIRLWIND_ICON1
|
||||
{SPR_TVWW, 2, 18, {A_JumpShield}, 0, 0, S_NULL}, // S_WHIRLWIND_ICON2
|
||||
{SPR_TVWW, 2, 18, {A_GiveShield}, SH_WHIRLWIND, 0, S_NULL}, // S_WHIRLWIND_ICON2
|
||||
|
||||
{SPR_TVEL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ELEMENTAL_ICON2}, // S_ELEMENTAL_ICON1
|
||||
{SPR_TVEL, 2, 18, {A_WaterShield}, 0, 0, S_NULL}, // S_ELEMENTAL_ICON2
|
||||
{SPR_TVEL, 2, 18, {A_GiveShield}, SH_ELEMENTAL, 0, S_NULL}, // S_ELEMENTAL_ICON2
|
||||
|
||||
{SPR_TVSS, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SNEAKERS_ICON2}, // S_SNEAKERS_ICON1
|
||||
{SPR_TVSS, 2, 18, {A_SuperSneakers}, 0, 0, S_NULL}, // S_SNEAKERS_ICON2
|
||||
|
@ -1720,13 +1724,13 @@ state_t states[NUMSTATES] =
|
|||
{SPR_TVTK, 2, 18, {A_AwardScore}, 0, 0, S_NULL}, // S_SCORE10K_ICON2
|
||||
|
||||
{SPR_TVFL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FLAMEAURA_ICON2}, // S_FLAMEAURA_ICON1
|
||||
{SPR_TVFL, 2, 18, {A_FlameShield}, 0, 0, S_NULL}, // S_FLAMEAURA_ICON2
|
||||
{SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2
|
||||
|
||||
{SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1
|
||||
{SPR_TVBB, 2, 18, {A_BubbleShield}, 0, 0, S_NULL}, // S_BUBBLERWAP_ICON2
|
||||
{SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLERWAP_ICON2
|
||||
|
||||
{SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1
|
||||
{SPR_TVZP, 2, 18, {A_ThunderShield}, 0, 0, S_NULL}, // S_THUNDERCOIN_ICON2
|
||||
{SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2
|
||||
|
||||
// ---
|
||||
|
||||
|
@ -1830,13 +1834,13 @@ state_t states[NUMSTATES] =
|
|||
{SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN
|
||||
|
||||
// Flame
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, 0, S_FLAME4}, // S_FLAME3
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0, S_FLAME5}, // S_FLAME4
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, 0, S_FLAME6}, // S_FLAME5
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME6
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0, S_NULL}, // S_FLAMEPARTICLE
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME2}, // S_FLAME1
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0 , S_FLAME3}, // S_FLAME2
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME4}, // S_FLAME3
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0 , S_FLAME5}, // S_FLAME4
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME6}, // S_FLAME5
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0 , S_FLAME1}, // S_FLAME6
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0 , S_NULL}, // S_FLAMEPARTICLE
|
||||
|
||||
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|FF_ANIMATE, -1, {NULL}, 5, 3, S_FLAME2}, // S_FLAMEREST
|
||||
|
||||
|
@ -1847,31 +1851,75 @@ state_t states[NUMSTATES] =
|
|||
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_SLING2}, // S_SLING1
|
||||
{SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2
|
||||
|
||||
// Small Mace Chain
|
||||
{SPR_SMCH, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
|
||||
// CEZ maces and chains
|
||||
{SPR_SMCH, 0, -1, {NULL}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
|
||||
{SPR_BMCH, 0, -1, {NULL}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
|
||||
{SPR_SMCE, 0, -1, {NULL}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
|
||||
{SPR_BMCE, 0, -1, {NULL}, 0, 0, S_BIGMACE}, // S_BIGMACE
|
||||
|
||||
// Big Mace Chain
|
||||
{SPR_BMCH, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
|
||||
// Yellow spring on a ball
|
||||
{SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL
|
||||
{SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2
|
||||
{SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4}, // S_YELLOWSPRINGBALL3
|
||||
{SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5}, // S_YELLOWSPRINGBALL4
|
||||
{SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL}, // S_YELLOWSPRINGBALL5
|
||||
|
||||
// Small Mace
|
||||
{SPR_SMCE, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
|
||||
// Red spring on a ball
|
||||
{SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRINGBALL
|
||||
{SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3}, // S_REDSPRINGBALL2
|
||||
{SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4}, // S_REDSPRINGBALL3
|
||||
{SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5}, // S_REDSPRINGBALL4
|
||||
{SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL}, // S_REDSPRINGBALL5
|
||||
|
||||
// Big Mace
|
||||
{SPR_BMCE, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACE}, // S_BIGMACE
|
||||
// Small Firebar
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR2}, // S_SMALLFIREBAR1
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_SMALLFIREBAR3}, // S_SMALLFIREBAR2
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR4}, // S_SMALLFIREBAR3
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_SMALLFIREBAR5}, // S_SMALLFIREBAR4
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR6}, // S_SMALLFIREBAR5
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_SMALLFIREBAR7}, // S_SMALLFIREBAR6
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR8}, // S_SMALLFIREBAR7
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_SMALLFIREBAR9}, // S_SMALLFIREBAR8
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR10}, // S_SMALLFIREBAR9
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_SMALLFIREBAR11}, // S_SMALLFIREBAR10
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR12}, // S_SMALLFIREBAR11
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_SMALLFIREBAR13}, // S_SMALLFIREBAR12
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR14}, // S_SMALLFIREBAR13
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_SMALLFIREBAR15}, // S_SMALLFIREBAR14
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR16}, // S_SMALLFIREBAR15
|
||||
{SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_SMALLFIREBAR1}, // S_SMALLFIREBAR16
|
||||
|
||||
// Big Firebar
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR2}, // S_BIGFIREBAR1
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_BIGFIREBAR3}, // S_BIGFIREBAR2
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR4}, // S_BIGFIREBAR3
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_BIGFIREBAR5}, // S_BIGFIREBAR4
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR6}, // S_BIGFIREBAR5
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_BIGFIREBAR7}, // S_BIGFIREBAR6
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR8}, // S_BIGFIREBAR7
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_BIGFIREBAR9}, // S_BIGFIREBAR8
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR10}, // S_BIGFIREBAR9
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_BIGFIREBAR11}, // S_BIGFIREBAR10
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR12}, // S_BIGFIREBAR11
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_BIGFIREBAR13}, // S_BIGFIREBAR12
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR14}, // S_BIGFIREBAR13
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_BIGFIREBAR15}, // S_BIGFIREBAR14
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR16}, // S_BIGFIREBAR15
|
||||
{SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16
|
||||
|
||||
// CEZ Flower
|
||||
{SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER1
|
||||
|
||||
// Big Tumbleweed
|
||||
{SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
|
||||
{SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
|
||||
{SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2
|
||||
{SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3
|
||||
{SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4
|
||||
{SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5
|
||||
{SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6
|
||||
{SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7
|
||||
{SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
|
||||
{SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
|
||||
{SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
|
||||
{SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2
|
||||
{SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3
|
||||
{SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4
|
||||
{SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5
|
||||
{SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6
|
||||
{SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7
|
||||
{SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
|
||||
|
||||
// Little Tumbleweed
|
||||
{SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED
|
||||
|
@ -2533,7 +2581,7 @@ state_t states[NUMSTATES] =
|
|||
|
||||
// Particle sprite
|
||||
{SPR_PRTL, FF_FULLBRIGHT|FF_TRANS70, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
|
||||
{SPR_NULL, 0, 1, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
|
||||
{SPR_NULL, 0, 3, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
|
||||
|
||||
{SPR_SCOR, 0, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRA - 100
|
||||
{SPR_SCOR, 1, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRB - 200
|
||||
|
@ -8822,7 +8870,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SWINGMACEPOINT
|
||||
{ // MT_CHAINMACEPOINT
|
||||
1105, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
|
@ -8849,7 +8897,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_HANGMACEPOINT
|
||||
{ // MT_SPRINGBALLPOINT
|
||||
1106, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
|
@ -8876,7 +8924,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SPINMACEPOINT
|
||||
{ // MT_CHAINPOINT
|
||||
1107, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
|
@ -8896,7 +8944,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
128*FRACUNIT, // radius
|
||||
1*FRACUNIT, // height
|
||||
0, // display offset
|
||||
200, // mass
|
||||
10000, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
|
@ -8930,6 +8978,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_FIREBARPOINT
|
||||
1109, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
10*FRACUNIT, // speed
|
||||
128*FRACUNIT, // radius
|
||||
1*FRACUNIT, // height
|
||||
0, // display offset
|
||||
200, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CUSTOMMACEPOINT
|
||||
1111, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
10*FRACUNIT, // speed
|
||||
128*FRACUNIT, // radius
|
||||
1*FRACUNIT, // height
|
||||
0, // display offset
|
||||
200, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SMALLMACECHAIN
|
||||
-1, // doomednum
|
||||
S_SMALLMACECHAIN, // spawnstate
|
||||
|
@ -8953,7 +9055,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags
|
||||
MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -8980,7 +9082,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags
|
||||
MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -9003,11 +9105,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
24*FRACUNIT, // speed
|
||||
17*FRACUNIT, // radius
|
||||
34*FRACUNIT, // height
|
||||
0, // display offset
|
||||
1, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_mswing, // activesound
|
||||
MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -9030,11 +9132,119 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
48*FRACUNIT, // speed
|
||||
34*FRACUNIT, // radius
|
||||
68*FRACUNIT, // height
|
||||
0, // display offset
|
||||
1, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_mswing, // activesound
|
||||
MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_YELLOWSPRINGBALL
|
||||
-1, // doomednum
|
||||
S_YELLOWSPRINGBALL, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_YELLOWSPRINGBALL2, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_spring, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
24*FRACUNIT, // speed
|
||||
17*FRACUNIT, // radius
|
||||
34*FRACUNIT, // height
|
||||
1, // display offset
|
||||
20*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_mswing, // activesound
|
||||
MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags
|
||||
S_YELLOWSPRINGBALL2 // raisestate
|
||||
},
|
||||
|
||||
{ // MT_REDSPRINGBALL
|
||||
-1, // doomednum
|
||||
S_REDSPRINGBALL, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_REDSPRINGBALL2, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_spring, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
24*FRACUNIT, // speed
|
||||
17*FRACUNIT, // radius
|
||||
34*FRACUNIT, // height
|
||||
1, // display offset
|
||||
32*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_mswing, // activesound
|
||||
MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags
|
||||
S_REDSPRINGBALL2 // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SMALLFIREBAR
|
||||
-1, // doomednum
|
||||
S_SMALLFIREBAR1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
MT_FLAMEPARTICLE, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
24*FRACUNIT, // speed
|
||||
17*FRACUNIT, // radius
|
||||
34*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BIGFIREBAR
|
||||
-1, // doomednum
|
||||
S_BIGFIREBAR1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
MT_FLAMEPARTICLE, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
48*FRACUNIT, // speed
|
||||
34*FRACUNIT, // radius
|
||||
68*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
85
src/info.h
85
src/info.h
|
@ -40,8 +40,6 @@ void A_Scream();
|
|||
void A_BossDeath();
|
||||
void A_CustomPower(); // Use this for a custom power
|
||||
void A_GiveWeapon(); // Gives the player weapon(s)
|
||||
void A_JumpShield(); // Obtained Jump Shield
|
||||
void A_RingShield(); // Obtained Ring Shield
|
||||
void A_RingBox(); // Obtained Ring Box Tails
|
||||
void A_Invincibility(); // Obtained Invincibility Box
|
||||
void A_SuperSneakers(); // Obtained Super Sneakers Box
|
||||
|
@ -52,13 +50,7 @@ void A_BubbleRise(); // Bubbles float to surface
|
|||
void A_BubbleCheck(); // Don't draw if not underwater
|
||||
void A_AwardScore();
|
||||
void A_ExtraLife(); // Extra Life
|
||||
void A_BombShield(); // Obtained Bomb Shield
|
||||
void A_WaterShield(); // Obtained Water Shield
|
||||
void A_ForceShield(); // Obtained Force Shield
|
||||
void A_PityShield(); // Obtained Pity Shield. We're... sorry.
|
||||
void A_FlameShield(); // Obtained Flame Shield
|
||||
void A_BubbleShield(); // Obtained Bubble Shield
|
||||
void A_ThunderShield(); // Obtained Thunder Shield
|
||||
void A_GiveShield(); // Obtained Shield
|
||||
void A_GravityBox();
|
||||
void A_ScoreRise(); // Rise the score logo
|
||||
void A_ParticleSpawn();
|
||||
|
@ -84,7 +76,6 @@ void A_DetonChase(); // Deton Chaser
|
|||
void A_CapeChase(); // Fake little Super Sonic cape
|
||||
void A_RotateSpikeBall(); // Spike ball rotation
|
||||
void A_SlingAppear();
|
||||
void A_MaceRotate();
|
||||
void A_UnidusBall();
|
||||
void A_RockSpawn();
|
||||
void A_SetFuse();
|
||||
|
@ -417,6 +408,10 @@ typedef enum sprite
|
|||
SPR_BMCH, // Big Mace Chain
|
||||
SPR_SMCE, // Small Mace
|
||||
SPR_BMCE, // Big Mace
|
||||
SPR_YSPB, // Yellow spring on a ball
|
||||
SPR_RSPB, // Red spring on a ball
|
||||
SPR_SFBR, // Small Firebar
|
||||
SPR_BFBR, // Big Firebar
|
||||
|
||||
// Arid Canyon Scenery
|
||||
SPR_BTBL, // Big tumbleweed
|
||||
|
@ -2056,18 +2051,62 @@ typedef enum state
|
|||
S_SLING1,
|
||||
S_SLING2,
|
||||
|
||||
// CEZ Small Mace Chain
|
||||
// CEZ maces and chains
|
||||
S_SMALLMACECHAIN,
|
||||
|
||||
// CEZ Big Mace Chain
|
||||
S_BIGMACECHAIN,
|
||||
|
||||
// CEZ Small Mace
|
||||
S_SMALLMACE,
|
||||
|
||||
// CEZ Big Mace
|
||||
S_BIGMACE,
|
||||
|
||||
// Yellow spring on a ball
|
||||
S_YELLOWSPRINGBALL,
|
||||
S_YELLOWSPRINGBALL2,
|
||||
S_YELLOWSPRINGBALL3,
|
||||
S_YELLOWSPRINGBALL4,
|
||||
S_YELLOWSPRINGBALL5,
|
||||
|
||||
// Red spring on a ball
|
||||
S_REDSPRINGBALL,
|
||||
S_REDSPRINGBALL2,
|
||||
S_REDSPRINGBALL3,
|
||||
S_REDSPRINGBALL4,
|
||||
S_REDSPRINGBALL5,
|
||||
|
||||
// Small Firebar
|
||||
S_SMALLFIREBAR1,
|
||||
S_SMALLFIREBAR2,
|
||||
S_SMALLFIREBAR3,
|
||||
S_SMALLFIREBAR4,
|
||||
S_SMALLFIREBAR5,
|
||||
S_SMALLFIREBAR6,
|
||||
S_SMALLFIREBAR7,
|
||||
S_SMALLFIREBAR8,
|
||||
S_SMALLFIREBAR9,
|
||||
S_SMALLFIREBAR10,
|
||||
S_SMALLFIREBAR11,
|
||||
S_SMALLFIREBAR12,
|
||||
S_SMALLFIREBAR13,
|
||||
S_SMALLFIREBAR14,
|
||||
S_SMALLFIREBAR15,
|
||||
S_SMALLFIREBAR16,
|
||||
|
||||
// Big Firebar
|
||||
S_BIGFIREBAR1,
|
||||
S_BIGFIREBAR2,
|
||||
S_BIGFIREBAR3,
|
||||
S_BIGFIREBAR4,
|
||||
S_BIGFIREBAR5,
|
||||
S_BIGFIREBAR6,
|
||||
S_BIGFIREBAR7,
|
||||
S_BIGFIREBAR8,
|
||||
S_BIGFIREBAR9,
|
||||
S_BIGFIREBAR10,
|
||||
S_BIGFIREBAR11,
|
||||
S_BIGFIREBAR12,
|
||||
S_BIGFIREBAR13,
|
||||
S_BIGFIREBAR14,
|
||||
S_BIGFIREBAR15,
|
||||
S_BIGFIREBAR16,
|
||||
|
||||
S_CEZFLOWER1,
|
||||
|
||||
// Big Tumbleweed
|
||||
|
@ -3421,14 +3460,20 @@ typedef enum mobj_type
|
|||
MT_FLAMEPARTICLE,
|
||||
MT_EGGSTATUE, // Eggman Statue
|
||||
MT_MACEPOINT, // Mace rotation point
|
||||
MT_SWINGMACEPOINT, // Mace swinging point
|
||||
MT_HANGMACEPOINT, // Hangable mace chain
|
||||
MT_SPINMACEPOINT, // Spin/Controllable mace chain
|
||||
MT_CHAINMACEPOINT, // Combination of chains and maces point
|
||||
MT_SPRINGBALLPOINT, // Spring ball point
|
||||
MT_CHAINPOINT, // Mace chain
|
||||
MT_HIDDEN_SLING, // Spin mace chain (activatable)
|
||||
MT_FIREBARPOINT, // Firebar
|
||||
MT_CUSTOMMACEPOINT, // Custom mace
|
||||
MT_SMALLMACECHAIN, // Small Mace Chain
|
||||
MT_BIGMACECHAIN, // Big Mace Chain
|
||||
MT_SMALLMACE, // Small Mace
|
||||
MT_BIGMACE, // Big Mace
|
||||
MT_YELLOWSPRINGBALL, // Yellow spring on a ball
|
||||
MT_REDSPRINGBALL, // Red spring on a ball
|
||||
MT_SMALLFIREBAR, // Small Firebar
|
||||
MT_BIGFIREBAR, // Big Firebar
|
||||
MT_CEZFLOWER,
|
||||
|
||||
// Arid Canyon Scenery
|
||||
|
|
|
@ -978,6 +978,19 @@ static int lib_pGivePlayerLives(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pGiveCoopLives(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
INT32 numlives = (INT32)luaL_checkinteger(L, 2);
|
||||
boolean sound = (boolean)lua_opttrueboolean(L, 3);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
P_GiveCoopLives(player, numlives, sound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pResetScore(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -1183,6 +1196,18 @@ static int lib_pTelekinesis(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pSwitchShield(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
UINT16 shield = luaL_checkinteger(L, 2);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
P_SwitchShield(player, shield);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// P_MAP
|
||||
///////////
|
||||
|
||||
|
@ -2428,6 +2453,7 @@ static luaL_Reg lib[] = {
|
|||
{"P_SpawnGhostMobj",lib_pSpawnGhostMobj},
|
||||
{"P_GivePlayerRings",lib_pGivePlayerRings},
|
||||
{"P_GivePlayerLives",lib_pGivePlayerLives},
|
||||
{"P_GiveCoopLives",lib_pGiveCoopLives},
|
||||
{"P_ResetScore",lib_pResetScore},
|
||||
{"P_DoJumpShield",lib_pDoJumpShield},
|
||||
{"P_DoBubbleBounce",lib_pDoBubbleBounce},
|
||||
|
@ -2445,6 +2471,7 @@ static luaL_Reg lib[] = {
|
|||
{"P_SpawnThokMobj",lib_pSpawnThokMobj},
|
||||
{"P_SpawnSpinMobj",lib_pSpawnSpinMobj},
|
||||
{"P_Telekinesis",lib_pTelekinesis},
|
||||
{"P_SwitchShield",lib_pSwitchShield},
|
||||
|
||||
// p_map
|
||||
{"P_CheckPosition",lib_pCheckPosition},
|
||||
|
|
|
@ -399,12 +399,21 @@ static int lib_cvRegisterVar(lua_State *L)
|
|||
// stack: cvar table, cvar userdata
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars");
|
||||
I_Assert(lua_istable(L, 3));
|
||||
|
||||
lua_getfield(L, 3, cvar->name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushvalue(L, 2);
|
||||
lua_setfield(L, 3, cvar->name);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// actually time to register it to the console now! Finally!
|
||||
cvar->flags |= CV_MODIFIED;
|
||||
CV_RegisterVar(cvar);
|
||||
if (cvar->flags & CV_MODIFIED)
|
||||
return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)");
|
||||
|
||||
// return cvar userdata
|
||||
return 1;
|
||||
|
|
155
src/lua_hudlib.c
155
src/lua_hudlib.c
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#ifdef HAVE_BLUA
|
||||
#include "fastcmp.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_local.h"
|
||||
#include "st_stuff.h" // hudinfo[]
|
||||
|
@ -343,6 +344,158 @@ static int libd_cachePatch(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// v.getSpritePatch(sprite, [frame, [angle]])
|
||||
static int libd_getSpritePatch(lua_State *L)
|
||||
{
|
||||
UINT32 i; // sprite prefix
|
||||
UINT32 frame = 0; // 'A'
|
||||
UINT8 angle = 0;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
HUDONLY
|
||||
|
||||
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR_THOK
|
||||
{
|
||||
i = lua_tonumber(L, 1);
|
||||
if (i >= NUMSPRITES)
|
||||
return 0;
|
||||
}
|
||||
else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "THOK"
|
||||
{
|
||||
const char *name = lua_tostring(L, 1);
|
||||
for (i = 0; i < NUMSPRITES; i++)
|
||||
if (fastcmp(name, sprnames[i]))
|
||||
break;
|
||||
if (i >= NUMSPRITES)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (i == SPR_PLAY) // Use getSprite2Patch instead!
|
||||
return 0;
|
||||
|
||||
sprdef = &sprites[i];
|
||||
|
||||
// set frame number
|
||||
frame = luaL_optinteger(L, 2, 0);
|
||||
frame &= FF_FRAMEMASK; // ignore any bits that are not the actual frame, just in case
|
||||
if (frame >= sprdef->numframes)
|
||||
return 0;
|
||||
// set angle number
|
||||
sprframe = &sprdef->spriteframes[frame];
|
||||
angle = luaL_optinteger(L, 3, 1);
|
||||
|
||||
// convert WAD editor angle numbers (1-8) to internal angle numbers (0-7)
|
||||
// keep 0 the same since we'll make it default to angle 1 (which is internally 0)
|
||||
// in case somebody didn't know that angle 0 really just maps all 8 angles to the same patch
|
||||
if (angle != 0)
|
||||
angle--;
|
||||
|
||||
if (angle >= 8) // out of range?
|
||||
return 0;
|
||||
|
||||
// push both the patch and it's "flip" value
|
||||
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH);
|
||||
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// v.getSprite2Patch(skin, sprite, [super?,] [frame, [angle]])
|
||||
static int libd_getSprite2Patch(lua_State *L)
|
||||
{
|
||||
INT32 i; // skin number
|
||||
UINT32 j; // sprite2 prefix
|
||||
UINT32 frame = 0; // 'A'
|
||||
UINT8 angle = 0;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
boolean super = false; // add FF_SPR2SUPER to sprite2 if true
|
||||
HUDONLY
|
||||
|
||||
// get skin first!
|
||||
if (lua_isnumber(L, 1)) // find skin by number
|
||||
{
|
||||
i = lua_tonumber(L, 1);
|
||||
if (i < 0 || i >= MAXSKINS)
|
||||
return luaL_error(L, "skin number %d out of range (0 - %d)", i, MAXSKINS-1);
|
||||
if (i >= numskins)
|
||||
return 0;
|
||||
}
|
||||
else // find skin by name
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
for (i = 0; i < numskins; i++)
|
||||
if (fastcmp(skins[i].name, name))
|
||||
break;
|
||||
if (i >= numskins)
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_remove(L, 1); // remove skin now
|
||||
|
||||
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND
|
||||
{
|
||||
j = lua_tonumber(L, 1);
|
||||
if (j & FF_SPR2SUPER) // e.g. SPR2_STND|FF_SPR2SUPER
|
||||
{
|
||||
super = true;
|
||||
j &= ~FF_SPR2SUPER; // remove flag so the next check doesn't fail
|
||||
}
|
||||
if (j >= free_spr2)
|
||||
return 0;
|
||||
}
|
||||
else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "STND"
|
||||
{
|
||||
const char *name = lua_tostring(L, 1);
|
||||
for (j = 0; j < free_spr2; j++)
|
||||
if (fastcmp(name, spr2names[j]))
|
||||
break;
|
||||
// if you want super flags you'll have to use the optional boolean following this
|
||||
if (j >= free_spr2)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (lua_isboolean(L, 2)) // optional boolean for superness
|
||||
{
|
||||
super = lua_toboolean(L, 2); // note: this can override FF_SPR2SUPER from sprite number
|
||||
lua_remove(L, 2); // remove
|
||||
}
|
||||
// if it's not boolean then just assume it's the frame number
|
||||
|
||||
if (super)
|
||||
j |= FF_SPR2SUPER;
|
||||
|
||||
j = P_GetSkinSprite2(&skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary
|
||||
|
||||
sprdef = &skins[i].sprites[j];
|
||||
|
||||
// set frame number
|
||||
frame = luaL_optinteger(L, 2, 0);
|
||||
frame &= FF_FRAMEMASK; // ignore any bits that are not the actual frame, just in case
|
||||
if (frame >= sprdef->numframes)
|
||||
return 0;
|
||||
// set angle number
|
||||
sprframe = &sprdef->spriteframes[frame];
|
||||
angle = luaL_optinteger(L, 3, 1);
|
||||
|
||||
// convert WAD editor angle numbers (1-8) to internal angle numbers (0-7)
|
||||
// keep 0 the same since we'll make it default to angle 1 (which is internally 0)
|
||||
// in case somebody didn't know that angle 0 really just maps all 8 angles to the same patch
|
||||
if (angle != 0)
|
||||
angle--;
|
||||
|
||||
if (angle >= 8) // out of range?
|
||||
return 0;
|
||||
|
||||
// push both the patch and it's "flip" value
|
||||
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH);
|
||||
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int libd_draw(lua_State *L)
|
||||
{
|
||||
INT32 x, y, flags;
|
||||
|
@ -568,6 +721,8 @@ static int libd_renderer(lua_State *L)
|
|||
static luaL_Reg lib_draw[] = {
|
||||
{"patchExists", libd_patchExists},
|
||||
{"cachePatch", libd_cachePatch},
|
||||
{"getSpritePatch", libd_getSpritePatch},
|
||||
{"getSprite2Patch", libd_getSprite2Patch},
|
||||
{"draw", libd_draw},
|
||||
{"drawScaled", libd_drawScaled},
|
||||
{"drawNum", libd_drawNum},
|
||||
|
|
|
@ -417,7 +417,7 @@ static int mobj_set(lua_State *L)
|
|||
mo->frame = (UINT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case mobj_sprite2:
|
||||
mo->sprite2 = P_GetMobjSprite2(mo, (UINT8)luaL_checkinteger(L, 3));
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player);
|
||||
break;
|
||||
case mobj_anim_duration:
|
||||
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
|
||||
|
|
|
@ -320,6 +320,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushangle(L, plr->awayviewaiming);
|
||||
else if (fastcmp(field,"spectator"))
|
||||
lua_pushboolean(L, plr->spectator);
|
||||
else if (fastcmp(field,"outofcoop"))
|
||||
lua_pushboolean(L, plr->outofcoop);
|
||||
else if (fastcmp(field,"bot"))
|
||||
lua_pushinteger(L, plr->bot);
|
||||
else if (fastcmp(field,"jointime"))
|
||||
|
@ -597,6 +599,8 @@ static int player_set(lua_State *L)
|
|||
plr->awayviewaiming = luaL_checkangle(L, 3);
|
||||
else if (fastcmp(field,"spectator"))
|
||||
plr->spectator = lua_toboolean(L, 3);
|
||||
else if (fastcmp(field,"outofcoop"))
|
||||
plr->outofcoop = lua_toboolean(L, 3);
|
||||
else if (fastcmp(field,"bot"))
|
||||
return NOSET;
|
||||
else if (fastcmp(field,"jointime"))
|
||||
|
|
20
src/m_cond.c
20
src/m_cond.c
|
@ -499,63 +499,63 @@ emblem_t emblemlocations[MAXEMBLEMS] =
|
|||
// FLORAL FIELD
|
||||
// ---
|
||||
{0, 5394, -996, 160, 50, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 50, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 50, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 50, 'T', SKINCOLOR_GREY, 40*TICRATE, "", 0},
|
||||
|
||||
|
||||
// TOXIC PLATEAU
|
||||
// ---
|
||||
{0, 780, -1664, 32, 51, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 51, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 51, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 51, 'T', SKINCOLOR_GREY, 50*TICRATE, "", 0},
|
||||
|
||||
|
||||
// FLOODED COVE
|
||||
// ---
|
||||
{0, 1824, -1888, 2448, 52, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 52, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 52, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 52, 'T', SKINCOLOR_GREY, 90*TICRATE, "", 0},
|
||||
|
||||
|
||||
// CAVERN FORTRESS
|
||||
// ---
|
||||
{0, -3089, -431, 1328, 53, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 53, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 53, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 53, 'T', SKINCOLOR_GREY, 75*TICRATE, "", 0},
|
||||
|
||||
|
||||
// DUSTY WASTELAND
|
||||
// ---
|
||||
{0, 957, 924, 2956, 54, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 54, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 54, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 54, 'T', SKINCOLOR_GREY, 65*TICRATE, "", 0},
|
||||
|
||||
|
||||
// MAGMA CAVES
|
||||
// ---
|
||||
{0, -2752, 3104, 1800, 55, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 55, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 55, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 55, 'T', SKINCOLOR_GREY, 80*TICRATE, "", 0},
|
||||
|
||||
|
||||
// EGG SATELLITE
|
||||
// ---
|
||||
{0, 5334, -609, 3426, 56, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 56, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 56, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 56, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0},
|
||||
|
||||
|
||||
// BLACK HOLE
|
||||
// ---
|
||||
{0, 2108, 3776, 32, 57, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 57, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 57, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 57, 'T', SKINCOLOR_GREY, 150*TICRATE, "", 0},
|
||||
|
||||
|
||||
// SPRING HILL
|
||||
// ---
|
||||
{0, -1840, -1024, 1644, 58, 'N', SKINCOLOR_RUST, 0, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 58, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
|
||||
{ET_NGRADE, 0,0,0, 58, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
|
||||
{ET_NTIME, 0,0,0, 58, 'T', SKINCOLOR_GREY, 60*TICRATE, "", 0},
|
||||
};
|
||||
|
||||
|
@ -566,7 +566,7 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] =
|
|||
{"All Emeralds", "Complete 1P Mode with all Emeralds", 11, 'V', SKINCOLOR_GREY, 0},
|
||||
{"Perfect Bonus", "Perfect Bonus on a non-secret stage", 30, 'P', SKINCOLOR_GOLD, 0},
|
||||
{"PLACEHOLDER", "PLACEHOLDER", 0, 'O', SKINCOLOR_RUST, 0},
|
||||
{"NiGHTS Mastery", "Show your mastery of NiGHTS!", 22, 'W', SKINCOLOR_TEAL, 0},
|
||||
{"NiGHTS Mastery", "Show your mastery of NiGHTS!", 22, 'W', SKINCOLOR_CYAN, 0},
|
||||
};
|
||||
|
||||
// Default Unlockables
|
||||
|
|
750
src/m_menu.c
750
src/m_menu.c
File diff suppressed because it is too large
Load diff
484
src/p_enemy.c
484
src/p_enemy.c
|
@ -93,20 +93,12 @@ void A_Explode(mobj_t *actor);
|
|||
void A_BossDeath(mobj_t *actor);
|
||||
void A_CustomPower(mobj_t *actor);
|
||||
void A_GiveWeapon(mobj_t *actor);
|
||||
void A_JumpShield(mobj_t *actor);
|
||||
void A_RingShield(mobj_t *actor);
|
||||
void A_RingBox(mobj_t *actor);
|
||||
void A_Invincibility(mobj_t *actor);
|
||||
void A_SuperSneakers(mobj_t *actor);
|
||||
void A_AwardScore(mobj_t *actor);
|
||||
void A_ExtraLife(mobj_t *actor);
|
||||
void A_BombShield(mobj_t *actor);
|
||||
void A_WaterShield(mobj_t *actor);
|
||||
void A_ForceShield(mobj_t *actor);
|
||||
void A_PityShield(mobj_t *actor);
|
||||
void A_FlameShield(mobj_t *actor);
|
||||
void A_BubbleShield(mobj_t *actor);
|
||||
void A_ThunderShield(mobj_t *actor);
|
||||
void A_GiveShield(mobj_t *actor);
|
||||
void A_GravityBox(mobj_t *actor);
|
||||
void A_ScoreRise(mobj_t *actor);
|
||||
void A_ParticleSpawn(mobj_t *actor);
|
||||
|
@ -137,7 +129,6 @@ void A_DetonChase(mobj_t *actor);
|
|||
void A_CapeChase(mobj_t *actor);
|
||||
void A_RotateSpikeBall(mobj_t *actor);
|
||||
void A_SlingAppear(mobj_t *actor);
|
||||
void A_MaceRotate(mobj_t *actor);
|
||||
void A_UnidusBall(mobj_t *actor);
|
||||
void A_RockSpawn(mobj_t *actor);
|
||||
void A_SetFuse(mobj_t *actor);
|
||||
|
@ -841,6 +832,34 @@ static mobjtype_t P_DoRandomBoxChances(void)
|
|||
mobjtype_t spawnchance[256];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
switch (P_RandomKey(10))
|
||||
{
|
||||
case 0:
|
||||
return MT_RING_ICON;
|
||||
case 1:
|
||||
return MT_SNEAKERS_ICON;
|
||||
case 2:
|
||||
return MT_INVULN_ICON;
|
||||
case 3:
|
||||
return MT_WHIRLWIND_ICON;
|
||||
case 4:
|
||||
return MT_ELEMENTAL_ICON;
|
||||
case 5:
|
||||
return MT_ATTRACT_ICON;
|
||||
case 6:
|
||||
return MT_FORCE_ICON;
|
||||
case 7:
|
||||
return MT_ARMAGEDDON_ICON;
|
||||
case 8:
|
||||
return MT_1UP_ICON;
|
||||
case 9:
|
||||
return MT_EGGMAN_ICON;
|
||||
}
|
||||
return MT_NULL;
|
||||
}
|
||||
|
||||
#define QUESTIONBOXCHANCES(type, cvar) \
|
||||
for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
|
||||
QUESTIONBOXCHANCES(MT_RING_ICON, cv_superring);
|
||||
|
@ -2835,8 +2854,8 @@ void A_BossDeath(mobj_t *mo)
|
|||
|
||||
// make sure there is a player alive for victory
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0)
|
||||
|| ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0))))
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health)
|
||||
|| ((netgame || multiplayer) && (players[i].lives || players[i].continues))))
|
||||
break;
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
|
@ -3057,62 +3076,6 @@ void A_GiveWeapon(mobj_t *actor)
|
|||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_JumpShield
|
||||
//
|
||||
// Description: Awards the player a jump shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_JumpShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_JumpShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_WHIRLWIND);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_RingShield
|
||||
//
|
||||
// Description: Awards the player a ring shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_RingShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_RingShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_ATTRACT);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_RingBox
|
||||
//
|
||||
// Description: Awards the player 10 rings.
|
||||
|
@ -3280,25 +3243,28 @@ void A_ExtraLife(mobj_t *actor)
|
|||
|
||||
// In shooter gametypes, give the player 100 rings instead of an extra life.
|
||||
if (gametype != GT_COOP && gametype != GT_COMPETITION)
|
||||
{
|
||||
P_GivePlayerRings(player, 100);
|
||||
P_PlayLivesJingle(player);
|
||||
}
|
||||
else
|
||||
P_GivePlayerLives(player, 1);
|
||||
P_PlayLivesJingle(player);
|
||||
P_GiveCoopLives(player, 1, true);
|
||||
}
|
||||
|
||||
// Function: A_BombShield
|
||||
// Function: A_GiveShield
|
||||
//
|
||||
// Description: Awards the player a bomb shield.
|
||||
// Description: Awards the player a specified shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var1 = Shield type (make with SH_ constants)
|
||||
// var2 = unused
|
||||
//
|
||||
void A_BombShield(mobj_t *actor)
|
||||
void A_GiveShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
UINT16 locvar1 = var1;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_BombShield", actor))
|
||||
if (LUA_CallAction("A_GiveShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
|
@ -3309,196 +3275,10 @@ void A_BombShield(mobj_t *actor)
|
|||
|
||||
player = actor->target->player;
|
||||
|
||||
// If you already have a bomb shield, use it!
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON)
|
||||
P_BlackOw(player);
|
||||
|
||||
// Now we know for certain that we don't have a bomb shield, so add one. :3
|
||||
P_SwitchShield(player, SH_ARMAGEDDON);
|
||||
|
||||
P_SwitchShield(player, locvar1);
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_WaterShield
|
||||
//
|
||||
// Description: Awards the player a water shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_WaterShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_WaterShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_ELEMENTAL);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_ForceShield
|
||||
//
|
||||
// Description: Awards the player a force shield.
|
||||
//
|
||||
// var1 = Number of additional hitpoints to give
|
||||
// var2 = unused
|
||||
//
|
||||
void A_ForceShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
INT32 locvar1 = var1;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_ForceShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (locvar1 & ~SH_FORCEHP)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Invalid number of additional hitpoints.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_FORCE|locvar1);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_PityShield
|
||||
//
|
||||
// Description: Awards the player a pity shield.
|
||||
// Because you fail it.
|
||||
// Your skill is not enough.
|
||||
// See you next time.
|
||||
// Bye-bye.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_PityShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_PityShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_PITY);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_FlameShield
|
||||
//
|
||||
// Description: Awards the player a flame shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_FlameShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlameShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_FLAMEAURA);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_BubbleShield
|
||||
//
|
||||
// Description: Awards the player a bubble shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_BubbleShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_BubbleShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_BUBBLEWRAP);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_ThunderShield
|
||||
//
|
||||
// Description: Awards the player a thunder shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_ThunderShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_ThunderShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_THUNDERCOIN);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
|
||||
// Function: A_GravityBox
|
||||
//
|
||||
// Description: Awards the player gravity boots.
|
||||
|
@ -3583,12 +3363,12 @@ void A_ParticleSpawn(mobj_t *actor)
|
|||
spawn->tics = (tic_t)actor->health;
|
||||
spawn->flags2 |= (actor->flags2 & MF2_OBJECTFLIP);
|
||||
spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
|
||||
if (spawn->frame & FF_ANIMATE)
|
||||
spawn->frame += P_RandomKey(spawn->state->var1);
|
||||
|
||||
actor->angle += actor->movedir;
|
||||
}
|
||||
|
||||
actor->angle += (angle_t)actor->movecount;
|
||||
actor->tics = (tic_t)actor->reactiontime;
|
||||
}
|
||||
|
||||
// Function: A_BunnyHop
|
||||
|
@ -4181,12 +3961,12 @@ void A_SignPlayer(mobj_t *actor)
|
|||
of in the name. If you have a better idea, feel free
|
||||
to let me know. ~toast 2016/07/20
|
||||
*/
|
||||
actor->frame += Color_Opposite[Color_Opposite[skin->prefoppositecolor*2]*2+1];
|
||||
actor->frame += (15 - Color_Opposite[(Color_Opposite[(skin->prefoppositecolor - 1)*2] - 1)*2 + 1]);
|
||||
}
|
||||
else // Set the sign to be an appropriate background color for this player's skincolor.
|
||||
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
|
||||
{
|
||||
actor->color = Color_Opposite[actor->target->player->skincolor*2];
|
||||
actor->frame += Color_Opposite[actor->target->player->skincolor*2+1];
|
||||
actor->color = Color_Opposite[(actor->target->player->skincolor - 1)*2];
|
||||
actor->frame += (15 - Color_Opposite[(actor->target->player->skincolor - 1)*2 + 1]);
|
||||
}
|
||||
|
||||
if (skin->sprites[SPR2_SIGN].numframes)
|
||||
|
@ -5145,15 +4925,12 @@ void A_SlingAppear(mobj_t *actor)
|
|||
actor->movefactor = actor->threshold;
|
||||
actor->friction = 128;
|
||||
|
||||
actor->flags |= MF_SLIDEME;
|
||||
|
||||
while (mlength > 0)
|
||||
{
|
||||
spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN);
|
||||
|
||||
P_SetTarget(&spawnee->target, actor);
|
||||
|
||||
spawnee->movecount = 0;
|
||||
spawnee->threshold = 0;
|
||||
spawnee->reactiontime = mlength;
|
||||
|
||||
|
@ -5168,129 +4945,6 @@ void A_SlingAppear(mobj_t *actor)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Function: A_MaceRotate
|
||||
//
|
||||
// Spins an object around its target, or, swings it from side to side.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
// So NOBODY forgets:
|
||||
// actor->
|
||||
// threshold - X tilt
|
||||
// movecount - Z tilt
|
||||
// reactiontime - link # in the chain (1 is closest)
|
||||
// lastlook - speed
|
||||
// friction - top speed
|
||||
// movedir - current angle holder
|
||||
// extravalue1 - smoothly move link into place
|
||||
//
|
||||
void A_MaceRotate(mobj_t *actor)
|
||||
{
|
||||
TVector v;
|
||||
TVector *res;
|
||||
fixed_t radius;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_MaceRotate", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Target was removed.
|
||||
if (!actor->target)
|
||||
{
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
P_UnsetThingPosition(actor);
|
||||
|
||||
// Radius of the link's rotation.
|
||||
radius = FixedMul(actor->info->speed * actor->reactiontime, actor->target->scale);
|
||||
|
||||
// Double the radius if the chain links are made up of maces.
|
||||
if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE))
|
||||
radius *= 2;
|
||||
|
||||
// Axis offset for the axis.
|
||||
radius += actor->target->extravalue1;
|
||||
|
||||
// Smoothly move the link into position.
|
||||
if (actor->extravalue1)
|
||||
{
|
||||
radius = FixedMul(radius, FixedDiv(actor->extravalue1, 100));
|
||||
actor->extravalue1 += 1;
|
||||
if (actor->extravalue1 >= 100)
|
||||
actor->extravalue1 = 0;
|
||||
}
|
||||
|
||||
actor->x = actor->target->x;
|
||||
actor->y = actor->target->y;
|
||||
actor->z = actor->target->z;
|
||||
|
||||
// Cut the height to align the link with the axis.
|
||||
if (actor->type == MT_SMALLMACECHAIN || actor->type == MT_BIGMACECHAIN)
|
||||
actor->z -= actor->height/4;
|
||||
else
|
||||
actor->z -= actor->height/2;
|
||||
|
||||
// Set the top speed for the link if it happens to be over that speed.
|
||||
if (actor->target->lastlook > actor->target->friction)
|
||||
actor->target->lastlook = actor->target->friction;
|
||||
|
||||
// Swinging Chain.
|
||||
if (actor->target->type == MT_HANGMACEPOINT || actor->target->type == MT_SWINGMACEPOINT)
|
||||
{
|
||||
actor->movecount += actor->target->lastlook;
|
||||
actor->movecount &= FINEMASK;
|
||||
|
||||
actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook << FRACBITS);
|
||||
|
||||
v[0] = FRACUNIT;
|
||||
v[1] = 0;
|
||||
v[2] = -radius;
|
||||
v[3] = FRACUNIT;
|
||||
|
||||
// Calculate the angle matrixes for the link.
|
||||
res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold)));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
}
|
||||
// Rotating Chain.
|
||||
else
|
||||
{
|
||||
angle_t fa;
|
||||
|
||||
actor->threshold += actor->target->lastlook;
|
||||
actor->threshold &= FINEMASK;
|
||||
actor->target->health &= FINEMASK;
|
||||
|
||||
fa = actor->threshold;
|
||||
v[0] = FixedMul(FINECOSINE(fa), radius);
|
||||
v[1] = 0;
|
||||
v[2] = FixedMul(FINESINE(fa), radius);
|
||||
v[3] = FRACUNIT;
|
||||
|
||||
// Calculate the angle matrixes for the link.
|
||||
res = VectorMatrixMultiply(v, *RotateXMatrix(actor->target->threshold << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
}
|
||||
|
||||
// Add on the appropriate distances to the actor's co-ordinates.
|
||||
actor->x += v[0];
|
||||
actor->y += v[1];
|
||||
actor->z += v[2];
|
||||
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
if (!(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes maces shut up on request
|
||||
&& !(leveltime & 63) && (actor->type == MT_BIGMACE || actor->type == MT_SMALLMACE) && actor->target->type == MT_MACEPOINT)
|
||||
S_StartSound(actor, actor->info->activesound);
|
||||
}
|
||||
|
||||
// Function: A_SetFuse
|
||||
//
|
||||
// Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall)
|
||||
|
@ -5630,7 +5284,10 @@ void A_MixUp(mobj_t *actor)
|
|||
}
|
||||
|
||||
if (numplayers <= 1) // Not enough players to mix up.
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return;
|
||||
}
|
||||
else if (numplayers == 2) // Special case -- simple swap
|
||||
{
|
||||
fixed_t x, y, z;
|
||||
|
@ -5876,7 +5533,10 @@ void A_RecyclePowers(mobj_t *actor)
|
|||
#endif
|
||||
|
||||
if (!multiplayer)
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return;
|
||||
}
|
||||
|
||||
numplayers = 0;
|
||||
|
||||
|
@ -5912,7 +5572,10 @@ void A_RecyclePowers(mobj_t *actor)
|
|||
}
|
||||
|
||||
if (numplayers <= 1)
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return; //nobody to touch!
|
||||
}
|
||||
|
||||
//shuffle the post scramble list, whee!
|
||||
// hardcoded 0-1 to 1-0 for two players
|
||||
|
@ -9392,8 +9055,8 @@ void A_ForceWin(mobj_t *actor)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0)
|
||||
|| ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0))))
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health)
|
||||
|| ((netgame || multiplayer) && (players[i].lives || players[i].continues))))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -10794,26 +10457,33 @@ void A_FlickyFlutter(mobj_t *actor)
|
|||
// Description: Creates the mobj's painchance at a random position around the object's radius.
|
||||
//
|
||||
// var1 = momz of particle.
|
||||
// var2 = chance of particle spawn
|
||||
//
|
||||
void A_FlameParticle(mobj_t *actor)
|
||||
{
|
||||
mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
|
||||
fixed_t rad, hei;
|
||||
mobj_t *particle;
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlameParticle", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (type)
|
||||
{
|
||||
fixed_t rad = 2*actor->radius>>FRACBITS;
|
||||
fixed_t hei = actor->height>>FRACBITS;
|
||||
mobj_t *particle = P_SpawnMobjFromMobj(actor,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(hei/2, hei)<<FRACBITS,
|
||||
type);
|
||||
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false);
|
||||
}
|
||||
if (!P_RandomChance(locvar2))
|
||||
return;
|
||||
|
||||
if (!type)
|
||||
return;
|
||||
|
||||
rad = 2*actor->radius>>FRACBITS;
|
||||
hei = actor->height>>FRACBITS;
|
||||
particle = P_SpawnMobjFromMobj(actor,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(hei/2, hei)<<FRACBITS,
|
||||
type);
|
||||
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false);
|
||||
}
|
||||
|
|
109
src/p_inter.c
109
src/p_inter.c
|
@ -414,13 +414,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
////////////////////////////////////////////////////////
|
||||
if (special->type == MT_GSNAPPER && !(((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|
||||
|| player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce)
|
||||
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z)
|
||||
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z
|
||||
&& !(player->powers[pw_shield] & SH_PROTECTSPIKE))
|
||||
{
|
||||
// Can only hit snapper from above
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
P_DamageMobj(toucher, special, special, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (special->type == MT_SHARP
|
||||
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2)))
|
||||
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2))
|
||||
&& !(player->powers[pw_shield] & SH_PROTECTSPIKE))
|
||||
{
|
||||
if (player->pflags & PF_BOUNCING)
|
||||
{
|
||||
|
@ -428,7 +430,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
P_DoAbilityBounce(player, false);
|
||||
}
|
||||
else // Cannot hit sharp from above or when red and angry
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
P_DamageMobj(toucher, special, special, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|
||||
|| ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
|
||||
|
@ -1291,13 +1293,40 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (player->starpostnum >= special->health)
|
||||
return; // Already hit this post
|
||||
|
||||
// Save the player's time and position.
|
||||
player->starposttime = leveltime;
|
||||
player->starpostx = toucher->x>>FRACBITS;
|
||||
player->starposty = toucher->y>>FRACBITS;
|
||||
player->starpostz = special->z>>FRACBITS;
|
||||
player->starpostangle = special->angle;
|
||||
player->starpostnum = special->health;
|
||||
if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer))
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (players[i].bot) // ignore dumb, stupid tails
|
||||
continue;
|
||||
|
||||
players[i].starposttime = leveltime;
|
||||
players[i].starpostx = player->mo->x>>FRACBITS;
|
||||
players[i].starposty = player->mo->y>>FRACBITS;
|
||||
players[i].starpostz = special->z>>FRACBITS;
|
||||
players[i].starpostangle = special->angle;
|
||||
players[i].starpostnum = special->health;
|
||||
|
||||
if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i]))
|
||||
P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
S_StartSound(NULL, special->info->painsound);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save the player's time and position.
|
||||
player->starposttime = leveltime;
|
||||
player->starpostx = toucher->x>>FRACBITS;
|
||||
player->starposty = toucher->y>>FRACBITS;
|
||||
player->starpostz = special->z>>FRACBITS;
|
||||
player->starpostangle = special->angle;
|
||||
player->starpostnum = special->health;
|
||||
S_StartSound(toucher, special->info->painsound);
|
||||
}
|
||||
|
||||
P_ClearStarPost(special->health);
|
||||
|
||||
// Find all starposts in the level with this value.
|
||||
|
@ -1469,10 +1498,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (player->powers[pw_flashing])
|
||||
return;
|
||||
|
||||
if (special->movefactor && special->tracer && (angle_t)special->tracer->health != ANGLE_90 && (angle_t)special->tracer->health != ANGLE_270)
|
||||
{ // I don't expect you to understand this, Mr Bond...
|
||||
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->threshold;
|
||||
if ((special->movefactor > 0) == ((angle_t)special->tracer->health > ANGLE_90 && (angle_t)special->tracer->health < ANGLE_270))
|
||||
ang += ANGLE_180;
|
||||
if (ang < ANGLE_180)
|
||||
return; // I expect you to die.
|
||||
}
|
||||
|
||||
P_ResetPlayer(player);
|
||||
P_SetTarget(&toucher->tracer, special);
|
||||
|
||||
if (special->target && (special->target->type == MT_SPINMACEPOINT || special->target->type == MT_HIDDEN_SLING))
|
||||
if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX))
|
||||
{
|
||||
player->powers[pw_carry] = CR_MACESPIN;
|
||||
S_StartSound(toucher, sfx_spin);
|
||||
|
@ -1483,6 +1521,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
// Can't jump first frame
|
||||
player->pflags |= PF_JUMPSTASIS;
|
||||
|
||||
return;
|
||||
case MT_BIGMINE:
|
||||
case MT_BIGAIRMINE:
|
||||
|
@ -2198,14 +2237,34 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
|
||||
P_SetThingPosition(target);
|
||||
|
||||
if (!target->player->bot && !G_IsSpecialStage(gamemap)
|
||||
if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0))
|
||||
;
|
||||
else if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap)
|
||||
&& G_GametypeUsesLives())
|
||||
{
|
||||
target->player->lives -= 1; // Lose a life Tails 03-11-2000
|
||||
|
||||
if (target->player->lives <= 0) // Tails 03-14-2000
|
||||
{
|
||||
if (P_IsLocalPlayer(target->player)/* && target->player == &players[consoleplayer] */)
|
||||
boolean gameovermus = false;
|
||||
if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAXPLAYERS)
|
||||
gameovermus = true;
|
||||
}
|
||||
else if (P_IsLocalPlayer(target->player))
|
||||
gameovermus = true;
|
||||
|
||||
if (gameovermus)
|
||||
{
|
||||
S_StopMusic(); // Stop the Music! Tails 03-14-2000
|
||||
S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
|
@ -3169,18 +3228,16 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|
||||
switch (damagetype)
|
||||
{
|
||||
case DMG_WATER:
|
||||
if (player->powers[pw_shield] & SH_PROTECTWATER)
|
||||
return false; // Invincible to water damage
|
||||
break;
|
||||
case DMG_FIRE:
|
||||
if (player->powers[pw_shield] & SH_PROTECTFIRE)
|
||||
return false; // Invincible to fire damage
|
||||
break;
|
||||
case DMG_ELECTRIC:
|
||||
if (player->powers[pw_shield] & SH_PROTECTELECTRIC)
|
||||
return false; // Invincible to electric damage
|
||||
break;
|
||||
#define DAMAGECASE(type)\
|
||||
case DMG_##type:\
|
||||
if (player->powers[pw_shield] & SH_PROTECT##type)\
|
||||
return false;\
|
||||
break
|
||||
DAMAGECASE(WATER);
|
||||
DAMAGECASE(FIRE);
|
||||
DAMAGECASE(ELECTRIC);
|
||||
DAMAGECASE(SPIKE);
|
||||
#undef DAMAGECASE
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@ void P_SwitchShield(player_t *player, UINT16 shieldtype);
|
|||
mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
|
||||
void P_GivePlayerRings(player_t *player, INT32 num_rings);
|
||||
void P_GivePlayerLives(player_t *player, INT32 numlives);
|
||||
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound);
|
||||
UINT8 P_GetNextEmerald(void);
|
||||
void P_GiveEmerald(boolean spawnObj);
|
||||
#if 0
|
||||
|
@ -198,6 +199,9 @@ void P_PlayLivesJingle(player_t *player);
|
|||
#define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4));
|
||||
#define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4));
|
||||
|
||||
boolean P_GetLives(player_t *player);
|
||||
boolean P_SpectatorJoinGame(player_t *player);
|
||||
void P_RestoreMultiMusic(player_t *player);
|
||||
|
||||
//
|
||||
// P_MOBJ
|
||||
|
@ -224,7 +228,6 @@ void P_PrecipitationEffects(void);
|
|||
void P_RemoveMobj(mobj_t *th);
|
||||
boolean P_MobjWasRemoved(mobj_t *th);
|
||||
void P_RemoveSavegameMobj(mobj_t *th);
|
||||
UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2);
|
||||
boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
|
||||
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
|
||||
void P_RunShields(void);
|
||||
|
|
736
src/p_mobj.c
736
src/p_mobj.c
|
@ -86,7 +86,7 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
|
|||
//
|
||||
FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
|
||||
{
|
||||
INT32 animlength = (mobj->skin && mobj->sprite == SPR_PLAY)
|
||||
INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin)
|
||||
? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1
|
||||
: st->var1;
|
||||
|
||||
|
@ -185,195 +185,6 @@ static void P_CyclePlayerMobjState(mobj_t *mobj)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_GetMobjSprite2
|
||||
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
|
||||
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
|
||||
//
|
||||
|
||||
UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2)
|
||||
{
|
||||
player_t *player = mobj->player;
|
||||
skin_t *skin = ((skin_t *)mobj->skin);
|
||||
UINT8 super = (spr2 & FF_SPR2SUPER);
|
||||
|
||||
if (!skin)
|
||||
return 0;
|
||||
|
||||
while (!(skin->sprites[spr2].numframes)
|
||||
&& spr2 != SPR2_STND)
|
||||
{
|
||||
if (spr2 & FF_SPR2SUPER)
|
||||
{
|
||||
spr2 &= ~FF_SPR2SUPER;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(spr2)
|
||||
{
|
||||
case SPR2_RUN:
|
||||
spr2 = SPR2_WALK;
|
||||
break;
|
||||
case SPR2_STUN:
|
||||
spr2 = SPR2_PAIN;
|
||||
break;
|
||||
case SPR2_DRWN:
|
||||
spr2 = SPR2_DEAD;
|
||||
break;
|
||||
case SPR2_SPIN:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_GASP:
|
||||
spr2 = SPR2_SPNG;
|
||||
break;
|
||||
case SPR2_JUMP:
|
||||
spr2 = ((player
|
||||
? player->charflags
|
||||
: skin->flags)
|
||||
& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_SPNG: // spring
|
||||
spr2 = SPR2_FALL;
|
||||
break;
|
||||
case SPR2_FALL:
|
||||
spr2 = SPR2_WALK;
|
||||
break;
|
||||
case SPR2_RIDE:
|
||||
spr2 = SPR2_FALL;
|
||||
break;
|
||||
|
||||
case SPR2_FLY :
|
||||
spr2 = SPR2_SPNG;
|
||||
break;
|
||||
case SPR2_SWIM:
|
||||
spr2 = SPR2_FLY ;
|
||||
break;
|
||||
case SPR2_TIRE:
|
||||
spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
|
||||
break;
|
||||
|
||||
case SPR2_GLID:
|
||||
spr2 = SPR2_FLY;
|
||||
break;
|
||||
case SPR2_CLMB:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_CLNG:
|
||||
spr2 = SPR2_CLMB;
|
||||
break;
|
||||
|
||||
case SPR2_FLT :
|
||||
spr2 = SPR2_WALK;
|
||||
break;
|
||||
case SPR2_FRUN:
|
||||
spr2 = SPR2_RUN ;
|
||||
break;
|
||||
|
||||
case SPR2_DASH:
|
||||
spr2 = SPR2_FRUN;
|
||||
break;
|
||||
|
||||
case SPR2_BNCE:
|
||||
spr2 = SPR2_FALL;
|
||||
break;
|
||||
case SPR2_BLND:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
|
||||
case SPR2_TWIN:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
|
||||
case SPR2_MLEE:
|
||||
spr2 = SPR2_TWIN;
|
||||
break;
|
||||
|
||||
// NiGHTS sprites.
|
||||
case SPR2_NSTD:
|
||||
spr2 = SPR2_STND;
|
||||
super = FF_SPR2SUPER;
|
||||
break;
|
||||
case SPR2_NFLT:
|
||||
spr2 = SPR2_FLT ;
|
||||
super = FF_SPR2SUPER;
|
||||
break;
|
||||
case SPR2_NSTN:
|
||||
spr2 = SPR2_STUN;
|
||||
break;
|
||||
case SPR2_NPUL:
|
||||
spr2 = SPR2_NSTN;
|
||||
break;
|
||||
case SPR2_NATK:
|
||||
spr2 = SPR2_ROLL;
|
||||
super = FF_SPR2SUPER;
|
||||
break;
|
||||
/*case SPR2_NGT0:
|
||||
spr2 = SPR2_NFLT;
|
||||
break;*/
|
||||
case SPR2_NGT1:
|
||||
case SPR2_NGT7:
|
||||
case SPR2_DRL0:
|
||||
spr2 = SPR2_NGT0;
|
||||
break;
|
||||
case SPR2_NGT2:
|
||||
case SPR2_DRL1:
|
||||
spr2 = SPR2_NGT1;
|
||||
break;
|
||||
case SPR2_NGT3:
|
||||
case SPR2_DRL2:
|
||||
spr2 = SPR2_NGT2;
|
||||
break;
|
||||
case SPR2_NGT4:
|
||||
case SPR2_DRL3:
|
||||
spr2 = SPR2_NGT3;
|
||||
break;
|
||||
case SPR2_NGT5:
|
||||
case SPR2_DRL4:
|
||||
spr2 = SPR2_NGT4;
|
||||
break;
|
||||
case SPR2_NGT6:
|
||||
case SPR2_DRL5:
|
||||
spr2 = SPR2_NGT5;
|
||||
break;
|
||||
case SPR2_DRL6:
|
||||
spr2 = SPR2_NGT6;
|
||||
break;
|
||||
case SPR2_NGT8:
|
||||
case SPR2_DRL7:
|
||||
spr2 = SPR2_NGT7;
|
||||
break;
|
||||
case SPR2_NGT9:
|
||||
case SPR2_DRL8:
|
||||
spr2 = SPR2_NGT8;
|
||||
break;
|
||||
case SPR2_NGTA:
|
||||
case SPR2_DRL9:
|
||||
spr2 = SPR2_NGT9;
|
||||
break;
|
||||
case SPR2_NGTB:
|
||||
case SPR2_DRLA:
|
||||
spr2 = SPR2_NGTA;
|
||||
break;
|
||||
case SPR2_NGTC:
|
||||
case SPR2_DRLB:
|
||||
spr2 = SPR2_NGTB;
|
||||
break;
|
||||
case SPR2_DRLC:
|
||||
spr2 = SPR2_NGTC;
|
||||
break;
|
||||
|
||||
// Dunno? Just go to standing then.
|
||||
default:
|
||||
spr2 = SPR2_STND;
|
||||
break;
|
||||
}
|
||||
|
||||
spr2 |= super;
|
||||
}
|
||||
|
||||
return spr2;
|
||||
}
|
||||
|
||||
//
|
||||
// P_SetPlayerMobjState
|
||||
// Returns true if the mobj is still present.
|
||||
|
@ -574,14 +385,16 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
|
|||
{
|
||||
skin_t *skin = ((skin_t *)mobj->skin);
|
||||
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
|
||||
UINT8 numframes;
|
||||
|
||||
UINT8 spr2 = P_GetMobjSprite2(mobj, (((player->powers[pw_super]) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK);
|
||||
UINT8 numframes, spr2;
|
||||
|
||||
if (skin)
|
||||
{
|
||||
spr2 = P_GetSkinSprite2(skin, (((player->powers[pw_super]) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK, mobj->player);
|
||||
numframes = skin->sprites[spr2].numframes;
|
||||
}
|
||||
else
|
||||
{
|
||||
spr2 = 0;
|
||||
frame = 0;
|
||||
numframes = 0;
|
||||
}
|
||||
|
@ -700,14 +513,16 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
|
|||
{
|
||||
skin_t *skin = ((skin_t *)mobj->skin);
|
||||
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
|
||||
UINT8 numframes;
|
||||
|
||||
UINT8 spr2 = P_GetMobjSprite2(mobj, st->frame & FF_FRAMEMASK);
|
||||
UINT8 numframes, spr2;
|
||||
|
||||
if (skin)
|
||||
{
|
||||
spr2 = P_GetSkinSprite2(skin, st->frame & FF_FRAMEMASK, mobj->player);
|
||||
numframes = skin->sprites[spr2].numframes;
|
||||
}
|
||||
else
|
||||
{
|
||||
spr2 = 0;
|
||||
frame = 0;
|
||||
numframes = 0;
|
||||
}
|
||||
|
@ -3225,8 +3040,17 @@ static void P_PlayerZMovement(mobj_t *mo)
|
|||
}
|
||||
}
|
||||
|
||||
if (mo->health && !P_CheckDeathPitCollide(mo))
|
||||
if (mo->health && !mo->player->spectator && !P_CheckDeathPitCollide(mo))
|
||||
{
|
||||
if ((mo->player->charability2 == CA2_SPINDASH) && !(mo->player->pflags & PF_THOKKED) && (mo->player->cmd.buttons & BT_USE) && (FixedHypot(mo->momx, mo->momy) > (5*mo->scale)))
|
||||
{
|
||||
mo->player->pflags |= PF_SPINNING;
|
||||
P_SetPlayerMobjState(mo, S_PLAY_ROLL);
|
||||
S_StartSound(mo, sfx_spin);
|
||||
}
|
||||
else
|
||||
mo->player->pflags &= ~PF_SPINNING;
|
||||
|
||||
if (mo->player->pflags & PF_GLIDING) // ground gliding
|
||||
{
|
||||
mo->player->skidtime = TICRATE;
|
||||
|
@ -3239,7 +3063,7 @@ static void P_PlayerZMovement(mobj_t *mo)
|
|||
S_StartSound(mo, sfx_s3k8b);
|
||||
mo->player->pflags |= PF_FULLSTASIS;
|
||||
}
|
||||
else if (mo->player->pflags & PF_JUMPED || (mo->player->pflags & (PF_SPINNING|PF_USEDOWN)) != (PF_SPINNING|PF_USEDOWN)
|
||||
else if (mo->player->pflags & PF_JUMPED || !(mo->player->pflags & PF_SPINNING)
|
||||
|| mo->player->powers[pw_tailsfly] || mo->state-states == S_PLAY_FLY_TIRED)
|
||||
{
|
||||
if (mo->player->cmomx || mo->player->cmomy)
|
||||
|
@ -3270,15 +3094,6 @@ static void P_PlayerZMovement(mobj_t *mo)
|
|||
}
|
||||
}
|
||||
|
||||
if ((mo->player->charability2 == CA2_SPINDASH) && !(mo->player->pflags & PF_THOKKED) && (mo->player->cmd.buttons & BT_USE) && (FixedHypot(mo->momx, mo->momy) > (5*mo->scale)))
|
||||
{
|
||||
mo->player->pflags |= PF_SPINNING;
|
||||
P_SetPlayerMobjState(mo, S_PLAY_ROLL);
|
||||
S_StartSound(mo, sfx_spin);
|
||||
}
|
||||
else
|
||||
mo->player->pflags &= ~PF_SPINNING;
|
||||
|
||||
if (!(mo->player->pflags & PF_GLIDING))
|
||||
mo->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
|
||||
|
||||
|
@ -6454,6 +6269,128 @@ static void P_NightsItemChase(mobj_t *thing)
|
|||
P_Attract(thing, thing->tracer, true);
|
||||
}
|
||||
|
||||
//
|
||||
// P_MaceRotate
|
||||
// Spins an object around its target, or, swings it from side to side.
|
||||
//
|
||||
static void P_MaceRotate(mobj_t *mobj)
|
||||
{
|
||||
TVector v;
|
||||
TVector *res;
|
||||
fixed_t radius, dist;
|
||||
angle_t fa;
|
||||
INT32 prevswing;
|
||||
boolean donetwice = false;
|
||||
|
||||
// Tracer was removed.
|
||||
if (!mobj->health)
|
||||
return;
|
||||
else if (!mobj->tracer)
|
||||
{
|
||||
P_KillMobj(mobj, NULL, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
mobj->momx = mobj->momy = mobj->momz = 0;
|
||||
|
||||
prevswing = mobj->threshold;
|
||||
mobj->threshold += mobj->tracer->lastlook;
|
||||
mobj->threshold &= FINEMASK;
|
||||
|
||||
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
|
||||
|
||||
// Radius of the link's rotation.
|
||||
radius = FixedMul(dist * mobj->movecount, mobj->tracer->scale) + mobj->tracer->extravalue1;
|
||||
|
||||
maceretry:
|
||||
|
||||
fa = (FixedAngle(mobj->tracer->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
|
||||
radius = FixedMul(FINECOSINE(fa), radius);
|
||||
v[1] = -FixedMul(FINESINE(fa), radius)
|
||||
+ FixedMul(dist * mobj->movefactor, mobj->tracer->scale);
|
||||
v[3] = FRACUNIT;
|
||||
|
||||
// Swinging Chain.
|
||||
if (mobj->tracer->flags2 & MF2_STRONGBOX)
|
||||
{
|
||||
fixed_t swingmagnitude = FixedMul(FINECOSINE(mobj->threshold), mobj->tracer->lastlook << FRACBITS);
|
||||
prevswing = FINECOSINE(prevswing);
|
||||
|
||||
if (!donetwice
|
||||
&& (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
|
||||
&& ((prevswing > 0) != (swingmagnitude > 0))) // just passed its lowest point
|
||||
S_StartSound(mobj, mobj->info->activesound);
|
||||
|
||||
fa = ((FixedAngle(swingmagnitude) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
|
||||
|
||||
v[0] = FixedMul(FINESINE(fa), -radius);
|
||||
v[2] = FixedMul(FINECOSINE(fa), -radius);
|
||||
}
|
||||
// Rotating Chain.
|
||||
else
|
||||
{
|
||||
prevswing = (prevswing + mobj->friction) & FINEMASK;
|
||||
fa = (mobj->threshold + mobj->friction) & FINEMASK;
|
||||
|
||||
if (!donetwice
|
||||
&& (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
|
||||
&& (!(prevswing > (FINEMASK/2)) && (fa > (FINEMASK/2)))) // completed a full swing
|
||||
S_StartSound(mobj, mobj->info->activesound);
|
||||
|
||||
v[0] = FixedMul(FINECOSINE(fa), radius);
|
||||
v[2] = FixedMul(FINESINE(fa), radius);
|
||||
}
|
||||
|
||||
// Calculate the angle matrixes for the link.
|
||||
res = VectorMatrixMultiply(v, *RotateXMatrix(mobj->tracer->threshold << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
res = VectorMatrixMultiply(v, *RotateZMatrix(mobj->tracer->health << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
|
||||
// Cut the height to align the link with the axis.
|
||||
if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
|
||||
v[2] -= P_MobjFlip(mobj)*mobj->height/4;
|
||||
else
|
||||
v[2] -= P_MobjFlip(mobj)*mobj->height/2;
|
||||
|
||||
P_UnsetThingPosition(mobj);
|
||||
|
||||
// Add on the appropriate distances to the center's co-ordinates.
|
||||
mobj->x = mobj->tracer->x + v[0];
|
||||
mobj->y = mobj->tracer->y + v[1];
|
||||
mobj->z = mobj->tracer->z + v[2];
|
||||
|
||||
P_SetThingPosition(mobj);
|
||||
|
||||
if (donetwice || P_MobjWasRemoved(mobj))
|
||||
return;
|
||||
|
||||
if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT))
|
||||
return;
|
||||
|
||||
if ((fa = ((mobj->tracer->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
|
||||
return;
|
||||
|
||||
if (mobj->subsector->sector->ffloors)
|
||||
P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
|
||||
|
||||
// Variable reuse
|
||||
if (mobj->floorz > mobj->z)
|
||||
dist = (mobj->floorz - mobj->tracer->z);
|
||||
else if (mobj->ceilingz < mobj->z)
|
||||
dist = (mobj->ceilingz - mobj->tracer->z);
|
||||
else
|
||||
return;
|
||||
|
||||
if ((dist = FixedDiv(dist, v[2])) > FRACUNIT)
|
||||
return;
|
||||
|
||||
radius = FixedMul(radius, dist);
|
||||
donetwice = true;
|
||||
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
|
||||
goto maceretry;
|
||||
}
|
||||
|
||||
static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
|
||||
{
|
||||
if (!thing->target || thing->target->health <= 0 || !thing->target->player
|
||||
|
@ -6811,6 +6748,13 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
// fade out when nearing the end of fuse...
|
||||
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT);
|
||||
|
||||
if (mobj->flags2 & MF2_MACEROTATE)
|
||||
{
|
||||
P_MaceRotate(mobj);
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
return;
|
||||
}
|
||||
|
||||
// Special thinker for scenery objects
|
||||
if (mobj->flags & MF_SCENERY)
|
||||
{
|
||||
|
@ -7476,7 +7420,8 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MT_SPINMACEPOINT:
|
||||
case MT_CHAINPOINT:
|
||||
case MT_CHAINMACEPOINT:
|
||||
if (leveltime & 1)
|
||||
{
|
||||
if (mobj->lastlook > mobj->movecount)
|
||||
|
@ -9131,40 +9076,44 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
// spawn as spectator determination
|
||||
if (!G_GametypeHasSpectators())
|
||||
{
|
||||
// Special case for (NiGHTS) special stages!
|
||||
// if stage has already started, force players to become spectators until the next stage
|
||||
if (multiplayer && netgame && G_IsSpecialStage(gamemap) && useNightsSS && leveltime > 0)
|
||||
p->spectator = true;
|
||||
else
|
||||
p->spectator = false;
|
||||
p->spectator = p->outofcoop =
|
||||
(((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop
|
||||
&& ((leveltime > 0
|
||||
&& ((G_IsSpecialStage(gamemap) && useNightsSS) // late join special stage
|
||||
|| (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop
|
||||
|| (((cv_cooplives.value == 1) || !P_GetLives(p)) && p->lives <= 0))); // game over and can't redistribute lives
|
||||
}
|
||||
else if (netgame && p->jointime < 1)
|
||||
p->spectator = true;
|
||||
else if (multiplayer && !netgame)
|
||||
else
|
||||
{
|
||||
// If you're in a team game and you don't have a team assigned yet...
|
||||
if (G_GametypeHasTeams() && p->ctfteam == 0)
|
||||
{
|
||||
changeteam_union NetPacket;
|
||||
UINT16 usvalue;
|
||||
NetPacket.value.l = NetPacket.value.b = 0;
|
||||
|
||||
// Spawn as a spectator,
|
||||
// yes even in splitscreen mode
|
||||
p->outofcoop = false;
|
||||
if (netgame && p->jointime < 1)
|
||||
p->spectator = true;
|
||||
if (playernum&1) p->skincolor = skincolor_redteam;
|
||||
else p->skincolor = skincolor_blueteam;
|
||||
else if (multiplayer && !netgame)
|
||||
{
|
||||
// If you're in a team game and you don't have a team assigned yet...
|
||||
if (G_GametypeHasTeams() && p->ctfteam == 0)
|
||||
{
|
||||
changeteam_union NetPacket;
|
||||
UINT16 usvalue;
|
||||
NetPacket.value.l = NetPacket.value.b = 0;
|
||||
|
||||
// but immediately send a team change packet.
|
||||
NetPacket.packet.playernum = playernum;
|
||||
NetPacket.packet.verification = true;
|
||||
NetPacket.packet.newteam = !(playernum&1) + 1;
|
||||
// Spawn as a spectator,
|
||||
// yes even in splitscreen mode
|
||||
p->spectator = true;
|
||||
if (playernum&1) p->skincolor = skincolor_redteam;
|
||||
else p->skincolor = skincolor_blueteam;
|
||||
|
||||
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
|
||||
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
|
||||
// but immediately send a team change packet.
|
||||
NetPacket.packet.playernum = playernum;
|
||||
NetPacket.packet.verification = true;
|
||||
NetPacket.packet.newteam = !(playernum&1) + 1;
|
||||
|
||||
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
|
||||
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
|
||||
}
|
||||
else // Otherwise, never spectator.
|
||||
p->spectator = false;
|
||||
}
|
||||
else // Otherwise, never spectator.
|
||||
p->spectator = false;
|
||||
}
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
|
@ -9181,6 +9130,9 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
p->skincolor = skincolor_blueteam;
|
||||
}
|
||||
|
||||
if ((netgame || multiplayer) && (gametype != GT_COOP || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS))
|
||||
p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
|
||||
|
||||
mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER);
|
||||
(mobj->player = p)->mo = mobj;
|
||||
|
||||
|
@ -9571,9 +9523,9 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
if (gametype == GT_COMPETITION || gametype == GT_RACE)
|
||||
{
|
||||
// Set powerup boxes to user settings for competition.
|
||||
if (cv_competitionboxes.value == 1) // Random
|
||||
if (cv_competitionboxes.value == 1) // Mystery
|
||||
i = MT_MYSTERY_BOX;
|
||||
else if (cv_competitionboxes.value == 2) // Teleports
|
||||
else if (cv_competitionboxes.value == 2) // Teleport
|
||||
i = MT_MIXUP_BOX;
|
||||
else if (cv_competitionboxes.value == 3) // None
|
||||
return; // Don't spawn!
|
||||
|
@ -9582,12 +9534,12 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
// Set powerup boxes to user settings for other netplay modes
|
||||
else if (gametype != GT_COOP)
|
||||
{
|
||||
if (cv_matchboxes.value == 1) // Random
|
||||
if (cv_matchboxes.value == 1) // Mystery
|
||||
i = MT_MYSTERY_BOX;
|
||||
else if (cv_matchboxes.value == 2) // Non-Random
|
||||
else if (cv_matchboxes.value == 2) // Unchanging
|
||||
{
|
||||
if (i == MT_MYSTERY_BOX)
|
||||
return; // don't spawn in Non-Random
|
||||
return; // don't spawn
|
||||
mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning!
|
||||
}
|
||||
else if (cv_matchboxes.value == 3) // Don't spawn
|
||||
|
@ -9813,15 +9765,20 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
mobj->movedir = mthing->extrainfo;
|
||||
break;
|
||||
case MT_MACEPOINT:
|
||||
case MT_SWINGMACEPOINT:
|
||||
case MT_HANGMACEPOINT:
|
||||
case MT_SPINMACEPOINT:
|
||||
case MT_CHAINMACEPOINT:
|
||||
case MT_SPRINGBALLPOINT:
|
||||
case MT_CHAINPOINT:
|
||||
case MT_FIREBARPOINT:
|
||||
case MT_CUSTOMMACEPOINT:
|
||||
{
|
||||
fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed;
|
||||
mobjtype_t chainlink = MT_SMALLMACECHAIN;
|
||||
mobjtype_t macetype = MT_SMALLMACE;
|
||||
boolean firsttime;
|
||||
fixed_t mlength, mlengthset, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mnumspokesset, mpinch, mroll, mnumnospokes, mwidth, mmin, msound, radiusfactor;
|
||||
angle_t mspokeangle;
|
||||
mobjtype_t chainlink, macetype, firsttype, linktype;
|
||||
boolean mdoall = true;
|
||||
mobj_t *spawnee;
|
||||
mobjflag_t mflagsapply;
|
||||
mobjflag2_t mflags2apply;
|
||||
mobjeflag_t meflagsapply;
|
||||
INT32 line;
|
||||
const size_t mthingi = (size_t)(mthing - mapthings);
|
||||
|
||||
|
@ -9835,99 +9792,246 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
return;
|
||||
}
|
||||
/*
|
||||
No deaf - small mace
|
||||
Deaf - big mace
|
||||
mapthing -
|
||||
MTF_AMBUSH :
|
||||
MT_SPRINGBALLPOINT - upgrade from yellow to red spring
|
||||
anything else - bigger mace/chain theory
|
||||
MTF_OBJECTSPECIAL - force silent
|
||||
MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements
|
||||
Parameter value : number of "spokes"
|
||||
|
||||
ML_NOCLIMB : Direction not controllable
|
||||
linedef -
|
||||
ML_NOCLIMB :
|
||||
MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable
|
||||
anything else - no functionality
|
||||
ML_EFFECT1 : Swings instead of spins
|
||||
ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT)
|
||||
ML_EFFECT3 : Spawn a bonus macetype at the hinge point
|
||||
ML_EFFECT4 : Don't clip inside the ground
|
||||
*/
|
||||
mlength = abs(lines[line].dx >> FRACBITS);
|
||||
mspeed = abs(lines[line].dy >> FRACBITS);
|
||||
mxspeed = sides[lines[line].sidenum[0]].textureoffset >> FRACBITS;
|
||||
mzspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS;
|
||||
mstartangle = lines[line].frontsector->floorheight >> FRACBITS;
|
||||
mmaxspeed = lines[line].frontsector->ceilingheight >> FRACBITS;
|
||||
mspeed = abs(lines[line].dy >> (FRACBITS - 4));
|
||||
mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360;
|
||||
if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> (FRACBITS - 4)) < mspeed)
|
||||
mmaxspeed = mspeed << 1;
|
||||
mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360;
|
||||
myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360;
|
||||
|
||||
mstartangle %= 360;
|
||||
mxspeed %= 360;
|
||||
mzspeed %= 360;
|
||||
mnumspokes = mthing->extrainfo + 1;
|
||||
mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT;
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Mace Chain (mapthing #%s):\n"
|
||||
if (lines[line].backsector)
|
||||
{
|
||||
mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360;
|
||||
mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360;
|
||||
mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS);
|
||||
if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0)
|
||||
mwidth = 0;
|
||||
}
|
||||
else
|
||||
mpinch = mroll = mnumnospokes = mwidth = 0;
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n"
|
||||
"Length is %d\n"
|
||||
"Speed is %d\n"
|
||||
"Xspeed is %d\n"
|
||||
"Zspeed is %d\n"
|
||||
"startangle is %d\n"
|
||||
"maxspeed is %d\n",
|
||||
sizeu1(mthingi), mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed);
|
||||
"Phase is %d\n"
|
||||
"Yaw is %d\n"
|
||||
"Pitch is %d\n"
|
||||
"Max. speed is %d\n"
|
||||
"No. of spokes is %d\n"
|
||||
"Pinch is %d\n"
|
||||
"Roll is %d\n"
|
||||
"No. of antispokes is %d\n"
|
||||
"Width is %d\n",
|
||||
sizeu1(mthingi), mlength, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mpinch, mroll, mnumnospokes, mwidth);
|
||||
|
||||
mobj->lastlook = mspeed << 4;
|
||||
if (mnumnospokes > 0 && (mnumnospokes < mnumspokes))
|
||||
mnumnospokes = mnumspokes/mnumnospokes;
|
||||
else
|
||||
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0);
|
||||
|
||||
mobj->lastlook = mspeed;
|
||||
mobj->movecount = mobj->lastlook;
|
||||
mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT);
|
||||
mobj->threshold = (FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT);
|
||||
mobj->movefactor = mobj->threshold;
|
||||
mobj->health = (FixedAngle(myaw*FRACUNIT)>>ANGLETOFINESHIFT);
|
||||
mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT);
|
||||
mobj->friction = mmaxspeed;
|
||||
mobj->movefactor = mpinch;
|
||||
|
||||
// Mobjtype selection
|
||||
switch(mobj->type)
|
||||
{
|
||||
case MT_SPRINGBALLPOINT:
|
||||
macetype = ((mthing->options & MTF_AMBUSH)
|
||||
? MT_REDSPRINGBALL
|
||||
: MT_YELLOWSPRINGBALL);
|
||||
chainlink = MT_SMALLMACECHAIN;
|
||||
break;
|
||||
case MT_FIREBARPOINT:
|
||||
macetype = ((mthing->options & MTF_AMBUSH)
|
||||
? MT_BIGFIREBAR
|
||||
: MT_SMALLFIREBAR);
|
||||
chainlink = MT_NULL;
|
||||
break;
|
||||
case MT_CUSTOMMACEPOINT:
|
||||
macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture;
|
||||
if (lines[line].backsector)
|
||||
chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture;
|
||||
else
|
||||
chainlink = MT_NULL;
|
||||
break;
|
||||
default:
|
||||
if (mthing->options & MTF_AMBUSH)
|
||||
{
|
||||
macetype = MT_BIGMACE;
|
||||
chainlink = MT_BIGMACECHAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
macetype = MT_SMALLMACE;
|
||||
chainlink = MT_SMALLMACECHAIN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!macetype)
|
||||
break;
|
||||
|
||||
if (mobj->type != MT_CHAINPOINT)
|
||||
{
|
||||
firsttype = macetype;
|
||||
mlength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mlength)
|
||||
break;
|
||||
firsttype = chainlink;
|
||||
}
|
||||
|
||||
// Adjustable direction
|
||||
if (lines[line].flags & ML_NOCLIMB)
|
||||
mobj->flags |= MF_SLIDEME;
|
||||
|
||||
mobj->reactiontime = 0;
|
||||
|
||||
if (mthing->options & MTF_AMBUSH)
|
||||
// Swinging
|
||||
if (lines[line].flags & ML_EFFECT1)
|
||||
{
|
||||
chainlink = MT_BIGMACECHAIN;
|
||||
macetype = MT_BIGMACE;
|
||||
mobj->flags2 |= MF2_STRONGBOX;
|
||||
mmin = ((mnumnospokes > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
if (mthing->options & MTF_OBJECTSPECIAL)
|
||||
mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces.
|
||||
|
||||
if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SPINMACEPOINT)
|
||||
firsttime = true;
|
||||
else
|
||||
mmin = mnumspokes;
|
||||
|
||||
// Make the links the same type as the end - repeated below
|
||||
if ((mobj->type != MT_CHAINPOINT) && (!(lines[line].flags & ML_EFFECT2) == (mobj->type == MT_FIREBARPOINT))) // exclusive or
|
||||
{
|
||||
firsttime = false;
|
||||
|
||||
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype);
|
||||
P_SetTarget(&spawnee->target, mobj);
|
||||
|
||||
if (mobj->type == MT_SWINGMACEPOINT)
|
||||
spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
|
||||
else
|
||||
spawnee->movecount = 0;
|
||||
|
||||
spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
|
||||
spawnee->reactiontime = mlength+1;
|
||||
linktype = macetype;
|
||||
radiusfactor = 2; // Double the radius.
|
||||
}
|
||||
else
|
||||
radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
|
||||
|
||||
while (mlength > 0)
|
||||
mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT));
|
||||
mflags2apply = (MF2_MACEROTATE|((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0));
|
||||
meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0);
|
||||
|
||||
msound = ((firsttype == chainlink) ? 0 : (mwidth & 1));
|
||||
|
||||
// Quick and easy preparatory variable setting
|
||||
mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT);
|
||||
mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT);
|
||||
|
||||
#define makemace(mobjtype, dist, moreflags2) P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
|
||||
P_SetTarget(&spawnee->tracer, mobj);\
|
||||
spawnee->threshold = mphase;\
|
||||
spawnee->friction = mroll;\
|
||||
spawnee->movefactor = mwidth;\
|
||||
spawnee->movecount = dist;\
|
||||
spawnee->angle = myaw;\
|
||||
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
|
||||
spawnee->flags2 |= (mflags2apply|moreflags2);\
|
||||
spawnee->eflags |= meflagsapply
|
||||
|
||||
domaceagain:
|
||||
mnumspokesset = mnumspokes;
|
||||
|
||||
if (mdoall && lines[line].flags & ML_EFFECT3) // Innermost mace/link
|
||||
{ spawnee = makemace(macetype, 0, MF2_AMBUSH); }
|
||||
|
||||
// The actual spawning of spokes
|
||||
while (mnumspokesset-- > 0)
|
||||
{
|
||||
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink);
|
||||
// Offsets
|
||||
if (lines[line].flags & ML_EFFECT1) // Swinging
|
||||
mroll = (mroll - mspokeangle) & FINEMASK;
|
||||
else // Spinning
|
||||
mphase = (mphase - mspokeangle) & FINEMASK;
|
||||
|
||||
P_SetTarget(&spawnee->target, mobj);
|
||||
|
||||
if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT)
|
||||
spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
|
||||
else
|
||||
spawnee->movecount = 0;
|
||||
|
||||
spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT;
|
||||
spawnee->reactiontime = mlength;
|
||||
|
||||
if (firsttime)
|
||||
if (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke
|
||||
{
|
||||
// This is the outermost link in the chain
|
||||
spawnee->flags2 |= MF2_AMBUSH;
|
||||
firsttime = false;
|
||||
if (mobj->type != MT_CHAINMACEPOINT)
|
||||
continue;
|
||||
|
||||
firsttype = linktype = chainlink;
|
||||
mlengthset = 1 + (mlength - 1)*radiusfactor;
|
||||
radiusfactor = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mobj->type == MT_CHAINMACEPOINT)
|
||||
{
|
||||
// Make the links the same type as the end - repeated above
|
||||
if (lines[line].flags & ML_EFFECT2)
|
||||
{
|
||||
linktype = macetype;
|
||||
radiusfactor = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
linktype = chainlink;
|
||||
radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
|
||||
}
|
||||
|
||||
firsttype = macetype;
|
||||
}
|
||||
|
||||
mlengthset = mlength;
|
||||
}
|
||||
|
||||
mlength--;
|
||||
// Outermost mace/link
|
||||
spawnee = makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
|
||||
|
||||
if (mspeed && (mwidth == msound) && !(mthing->options & MTF_OBJECTSPECIAL) && mnumspokesset <= mmin) // Can it make a sound?
|
||||
spawnee->flags2 |= MF2_BOSSNOTRAP;
|
||||
|
||||
if (!mdoall || !linktype)
|
||||
continue;
|
||||
|
||||
// The rest of the links
|
||||
while (mlengthset > 0)
|
||||
{ spawnee = makemace(linktype, radiusfactor*(mlengthset--), 0); }
|
||||
}
|
||||
|
||||
if (mwidth > 0)
|
||||
{
|
||||
mwidth *= -1;
|
||||
goto domaceagain;
|
||||
}
|
||||
else if (mwidth != 0)
|
||||
{
|
||||
if ((mwidth = -(mwidth + ((firsttype == chainlink) ? 1 : 2))) < 0)
|
||||
break;
|
||||
mdoall = false;
|
||||
goto domaceagain;
|
||||
}
|
||||
|
||||
#undef makemace
|
||||
|
||||
break;
|
||||
}
|
||||
case MT_PARTICLEGEN:
|
||||
{
|
||||
fixed_t radius, speed, bottomheight, topheight;
|
||||
INT32 type, numdivisions, time, anglespeed;
|
||||
INT32 type, numdivisions, time, anglespeed, ticcount;
|
||||
angle_t angledivision;
|
||||
INT32 line;
|
||||
const size_t mthingi = (size_t)(mthing - mapthings);
|
||||
|
@ -9950,6 +10054,10 @@ ML_NOCLIMB : Direction not controllable
|
|||
bottomheight = lines[line].frontsector->floorheight;
|
||||
topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height;
|
||||
|
||||
if (!lines[line].backsector
|
||||
|| (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1)
|
||||
ticcount = states[S_PARTICLEGEN].tics;
|
||||
|
||||
numdivisions = (mthing->options >> ZSHIFT);
|
||||
|
||||
if (numdivisions)
|
||||
|
@ -9986,8 +10094,9 @@ ML_NOCLIMB : Direction not controllable
|
|||
"Numdivisions is %d\n"
|
||||
"Angledivision is %d\n"
|
||||
"Time is %d\n"
|
||||
"Type is %d\n",
|
||||
sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, time, type);
|
||||
"Type is %d\n"
|
||||
"Tic seperation is %d\n",
|
||||
sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, time, type, ticcount);
|
||||
|
||||
mobj->angle = 0;
|
||||
mobj->movefactor = speed;
|
||||
|
@ -9997,6 +10106,7 @@ ML_NOCLIMB : Direction not controllable
|
|||
mobj->health = time;
|
||||
mobj->friction = radius;
|
||||
mobj->threshold = type;
|
||||
mobj->reactiontime = ticcount;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -11294,4 +11404,4 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
|
|||
newmobj->destscale = mobj->destscale;
|
||||
P_SetScale(newmobj, mobj->scale);
|
||||
return newmobj;
|
||||
}
|
||||
}
|
|
@ -194,6 +194,7 @@ typedef enum
|
|||
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
|
||||
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
|
||||
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
|
||||
MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer
|
||||
// free: to and including 1<<31
|
||||
} mobjflag2_t;
|
||||
|
||||
|
|
|
@ -3159,7 +3159,8 @@ static inline void P_ArchiveMisc(void)
|
|||
else
|
||||
WRITEINT16(save_p, gamemap);
|
||||
|
||||
lastmapsaved = gamemap;
|
||||
//lastmapsaved = gamemap;
|
||||
lastmaploaded = gamemap;
|
||||
|
||||
WRITEUINT16(save_p, (botskin ? (emeralds|(1<<10)) : emeralds)+357);
|
||||
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
|
||||
|
@ -3184,7 +3185,8 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
|
|||
if(!mapheaderinfo[gamemap-1])
|
||||
P_AllocMapHeader(gamemap-1);
|
||||
|
||||
lastmapsaved = gamemap;
|
||||
//lastmapsaved = gamemap;
|
||||
lastmaploaded = gamemap;
|
||||
|
||||
tokenlist = 0;
|
||||
token = 0;
|
||||
|
|
141
src/p_setup.c
141
src/p_setup.c
|
@ -199,74 +199,42 @@ void P_DeleteFlickies(INT16 i)
|
|||
static void P_ClearSingleMapHeaderInfo(INT16 i)
|
||||
{
|
||||
const INT16 num = (INT16)(i-1);
|
||||
DEH_WriteUndoline("LEVELNAME", mapheaderinfo[num]->lvlttl, UNDO_NONE);
|
||||
mapheaderinfo[num]->lvlttl[0] = '\0';
|
||||
DEH_WriteUndoline("SELECTHEADING", mapheaderinfo[num]->selectheading, UNDO_NONE);
|
||||
mapheaderinfo[num]->selectheading[0] = '\0';
|
||||
DEH_WriteUndoline("SUBTITLE", mapheaderinfo[num]->subttl, UNDO_NONE);
|
||||
mapheaderinfo[num]->subttl[0] = '\0';
|
||||
DEH_WriteUndoline("ACT", va("%d", mapheaderinfo[num]->actnum), UNDO_NONE);
|
||||
mapheaderinfo[num]->actnum = 0;
|
||||
DEH_WriteUndoline("TYPEOFLEVEL", va("%d", mapheaderinfo[num]->typeoflevel), UNDO_NONE);
|
||||
mapheaderinfo[num]->typeoflevel = 0;
|
||||
DEH_WriteUndoline("NEXTLEVEL", va("%d", mapheaderinfo[num]->nextlevel), UNDO_NONE);
|
||||
mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
|
||||
DEH_WriteUndoline("MUSIC", mapheaderinfo[num]->musname, UNDO_NONE);
|
||||
snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
|
||||
mapheaderinfo[num]->musname[6] = 0;
|
||||
DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
|
||||
mapheaderinfo[num]->mustrack = 0;
|
||||
DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE);
|
||||
mapheaderinfo[num]->forcecharacter[0] = '\0';
|
||||
DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE);
|
||||
mapheaderinfo[num]->weather = 0;
|
||||
DEH_WriteUndoline("SKYNUM", va("%d", mapheaderinfo[num]->skynum), UNDO_NONE);
|
||||
mapheaderinfo[num]->skynum = 1;
|
||||
DEH_WriteUndoline("SKYBOXSCALEX", va("%d", mapheaderinfo[num]->skybox_scalex), UNDO_NONE);
|
||||
mapheaderinfo[num]->skybox_scalex = 16;
|
||||
DEH_WriteUndoline("SKYBOXSCALEY", va("%d", mapheaderinfo[num]->skybox_scaley), UNDO_NONE);
|
||||
mapheaderinfo[num]->skybox_scaley = 16;
|
||||
DEH_WriteUndoline("SKYBOXSCALEZ", va("%d", mapheaderinfo[num]->skybox_scalez), UNDO_NONE);
|
||||
mapheaderinfo[num]->skybox_scalez = 16;
|
||||
DEH_WriteUndoline("INTERSCREEN", mapheaderinfo[num]->interscreen, UNDO_NONE);
|
||||
mapheaderinfo[num]->interscreen[0] = '#';
|
||||
DEH_WriteUndoline("RUNSOC", mapheaderinfo[num]->runsoc, UNDO_NONE);
|
||||
mapheaderinfo[num]->runsoc[0] = '#';
|
||||
DEH_WriteUndoline("SCRIPTNAME", mapheaderinfo[num]->scriptname, UNDO_NONE);
|
||||
mapheaderinfo[num]->scriptname[0] = '#';
|
||||
DEH_WriteUndoline("PRECUTSCENENUM", va("%d", mapheaderinfo[num]->precutscenenum), UNDO_NONE);
|
||||
mapheaderinfo[num]->precutscenenum = 0;
|
||||
DEH_WriteUndoline("CUTSCENENUM", va("%d", mapheaderinfo[num]->cutscenenum), UNDO_NONE);
|
||||
mapheaderinfo[num]->cutscenenum = 0;
|
||||
DEH_WriteUndoline("COUNTDOWN", va("%d", mapheaderinfo[num]->countdown), UNDO_NONE);
|
||||
mapheaderinfo[num]->countdown = 0;
|
||||
DEH_WriteUndoline("PALLETE", va("%u", mapheaderinfo[num]->palette), UNDO_NONE);
|
||||
mapheaderinfo[num]->palette = UINT16_MAX;
|
||||
DEH_WriteUndoline("NUMLAPS", va("%u", mapheaderinfo[num]->numlaps), UNDO_NONE);
|
||||
mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT;
|
||||
DEH_WriteUndoline("UNLOCKABLE", va("%s", mapheaderinfo[num]->unlockrequired), UNDO_NONE);
|
||||
mapheaderinfo[num]->unlockrequired = -1;
|
||||
DEH_WriteUndoline("LEVELSELECT", va("%d", mapheaderinfo[num]->levelselect), UNDO_NONE);
|
||||
mapheaderinfo[num]->levelselect = 0;
|
||||
DEH_WriteUndoline("BONUSTYPE", va("%d", mapheaderinfo[num]->bonustype), UNDO_NONE);
|
||||
mapheaderinfo[num]->bonustype = 0;
|
||||
DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE);
|
||||
mapheaderinfo[num]->levelflags = 0;
|
||||
DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE);
|
||||
mapheaderinfo[num]->menuflags = 0;
|
||||
// Flickies. Nope, no delfile support here either
|
||||
#if 1 // equivalent to "FlickyList = DEMO"
|
||||
P_SetDemoFlickies(num);
|
||||
#else // equivalent to "FlickyList = NONE"
|
||||
P_DeleteFlickies(num);
|
||||
#endif
|
||||
// TODO grades support for delfile (pfft yeah right)
|
||||
P_DeleteGrades(num);
|
||||
// an even further impossibility, delfile custom opts support
|
||||
mapheaderinfo[num]->customopts = NULL;
|
||||
mapheaderinfo[num]->numCustomOptions = 0;
|
||||
|
||||
DEH_WriteUndoline(va("# uload for map %d", i), NULL, UNDO_DONE);
|
||||
}
|
||||
|
||||
/** Allocates a new map-header structure.
|
||||
|
@ -489,6 +457,7 @@ static void P_LoadSegs(lumpnum_t lumpnum)
|
|||
//Hurdler: 04/12/2000: for now, only used in hardware mode
|
||||
li->lightmaps = NULL; // list of static lightmap for this seg
|
||||
}
|
||||
li->pv1 = li->pv2 = NULL;
|
||||
#endif
|
||||
|
||||
li->angle = (SHORT(ml->angle))<<FRACBITS;
|
||||
|
@ -1593,6 +1562,7 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
|
|||
break;
|
||||
}
|
||||
|
||||
case 9: // Mace parameters
|
||||
case 14: // Bustable block parameters
|
||||
case 15: // Fan particle spawner parameters
|
||||
case 425: // Calls P_SetMobjState on calling mobj
|
||||
|
@ -2196,6 +2166,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame
|
|||
static void P_LevelInitStuff(void)
|
||||
{
|
||||
INT32 i;
|
||||
boolean canresetlives = true;
|
||||
|
||||
leveltime = 0;
|
||||
|
||||
|
@ -2213,7 +2184,18 @@ static void P_LevelInitStuff(void)
|
|||
|
||||
// map time limit
|
||||
if (mapheaderinfo[gamemap-1]->countdown)
|
||||
{
|
||||
tic_t maxtime = 0;
|
||||
countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].starposttime > maxtime)
|
||||
maxtime = players[i].starposttime;
|
||||
}
|
||||
countdowntimer -= maxtime;
|
||||
}
|
||||
else
|
||||
countdowntimer = 0;
|
||||
countdowntimeup = false;
|
||||
|
@ -2235,9 +2217,21 @@ static void P_LevelInitStuff(void)
|
|||
// earthquake camera
|
||||
memset(&quake,0,sizeof(struct quake));
|
||||
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && players[i].lives > 0)
|
||||
{
|
||||
canresetlives = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if ((netgame || multiplayer) && (gametype == GT_COMPETITION || players[i].lives <= 0))
|
||||
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0))
|
||||
{
|
||||
// In Co-Op, replenish a user's lives if they are depleted.
|
||||
players[i].lives = cv_startinglives.value;
|
||||
|
@ -2547,6 +2541,21 @@ static void P_LoadNightsGhosts(void)
|
|||
free(gpath);
|
||||
}
|
||||
|
||||
static boolean CanSaveLevel(INT32 mapnum)
|
||||
{
|
||||
if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked)
|
||||
return false;
|
||||
|
||||
if (G_IsSpecialStage(mapnum) // don't save in special stages
|
||||
|| mapnum == lastmaploaded) // don't save if the last map loaded was this one
|
||||
return false;
|
||||
|
||||
// Any levels that have the savegame flag can save normally.
|
||||
// If the game is complete for this save slot, then any level can save!
|
||||
// On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP!
|
||||
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
|
||||
}
|
||||
|
||||
/** Loads a level from a lump or external wad.
|
||||
*
|
||||
* \param skipprecip If true, don't spawn precipitation.
|
||||
|
@ -2836,6 +2845,19 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
}
|
||||
}
|
||||
|
||||
// restore time in netgame (see also g_game.c)
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
|
||||
{
|
||||
// is this a hack? maybe
|
||||
tic_t maxstarposttime = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && players[i].starposttime > maxstarposttime)
|
||||
maxstarposttime = players[i].starposttime;
|
||||
}
|
||||
leveltime = maxstarposttime;
|
||||
}
|
||||
|
||||
if (modeattacking == ATTACKING_RECORD && !demoplayback)
|
||||
P_LoadRecordGhosts();
|
||||
else if (modeattacking == ATTACKING_NIGHTS && !demoplayback)
|
||||
|
@ -2997,11 +3019,11 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
P_RunCachedActions();
|
||||
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0)
|
||||
&& (!modifiedgame || savemoddata) && cursaveslot >= 0 && !ultimatemode
|
||||
&& !(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
|
||||
&& (!G_IsSpecialStage(gamemap)) && gamemap != lastmapsaved && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete))
|
||||
&& (!modifiedgame || savemoddata) && cursaveslot >= 0 && CanSaveLevel(gamemap))
|
||||
G_SaveGame((UINT32)cursaveslot);
|
||||
|
||||
lastmaploaded = gamemap; // HAS to be set after saving!!
|
||||
|
||||
if (savedata.lives > 0)
|
||||
{
|
||||
players[consoleplayer].continues = savedata.continues;
|
||||
|
@ -3065,7 +3087,6 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
|
|||
INT16 firstmapreplaced = 0, num;
|
||||
char *name;
|
||||
lumpinfo_t *lumpinfo;
|
||||
boolean texturechange = false;
|
||||
boolean replacedcurrentmap = false;
|
||||
|
||||
if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX)
|
||||
|
@ -3109,14 +3130,6 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
|
|||
CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name);
|
||||
digmreplaces++;
|
||||
}
|
||||
#if 0
|
||||
//
|
||||
// search for texturechange replacements
|
||||
//
|
||||
else if (!memcmp(name, "TEXTURE1", 8) || !memcmp(name, "TEXTURE2", 8)
|
||||
|| !memcmp(name, "PNAMES", 6))
|
||||
#endif
|
||||
texturechange = true;
|
||||
}
|
||||
if (!devparm && sreplaces)
|
||||
CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces));
|
||||
|
@ -3132,13 +3145,10 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
|
|||
|
||||
// Reload it all anyway, just in case they
|
||||
// added some textures but didn't insert a
|
||||
// TEXTURE1/PNAMES/etc. list.
|
||||
if (texturechange) // initialized in the sound check
|
||||
R_LoadTextures(); // numtexture changes
|
||||
else
|
||||
R_FlushTextureCache(); // just reload it from file
|
||||
// TEXTURES/etc. list.
|
||||
R_LoadTextures(); // numtexture changes
|
||||
|
||||
// Reload ANIMATED / ANIMDEFS
|
||||
// Reload ANIMDEFS
|
||||
P_InitPicAnims();
|
||||
|
||||
// Flush and reload HUD graphics
|
||||
|
@ -3151,6 +3161,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
|
|||
// look for skins
|
||||
//
|
||||
R_AddSkins(wadnum); // faB: wadfile index in wadfiles[]
|
||||
R_PatchSkins(wadnum); // toast: PATCH PATCH
|
||||
|
||||
//
|
||||
// search for maps
|
||||
|
@ -3201,31 +3212,3 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DELFILE
|
||||
boolean P_DelWadFile(void)
|
||||
{
|
||||
sfxenum_t i;
|
||||
const UINT16 wadnum = (UINT16)(numwadfiles - 1);
|
||||
const lumpnum_t lumpnum = numwadfiles<<16;
|
||||
//lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
R_DelSkins(wadnum); // only used by DELFILE
|
||||
R_DelSpriteDefs(wadnum); // only used by DELFILE
|
||||
for (i = 0; i < NUMSFX; i++)
|
||||
{
|
||||
if (S_sfx[i].lumpnum != LUMPERROR && S_sfx[i].lumpnum >= lumpnum)
|
||||
{
|
||||
S_StopSoundByNum(i);
|
||||
S_RemoveSoundFx(i);
|
||||
if (S_sfx[i].lumpnum != LUMPERROR)
|
||||
{
|
||||
I_FreeSfx(&S_sfx[i]);
|
||||
S_sfx[i].lumpnum = LUMPERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
W_UnloadWadFile(wadnum); // only used by DELFILE
|
||||
R_LoadTextures();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -60,9 +60,6 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
|
|||
void P_LoadThingsOnly(void);
|
||||
boolean P_SetupLevel(boolean skipprecip);
|
||||
boolean P_AddWadFile(const char *wadfilename, char **firstmapname);
|
||||
#ifdef DELFILE
|
||||
boolean P_DelWadFile(void);
|
||||
#endif
|
||||
boolean P_RunSOC(const char *socfilename);
|
||||
void P_WriteThings(lumpnum_t lump);
|
||||
size_t P_PrecacheLevelFlats(void);
|
||||
|
|
167
src/p_spec.c
167
src/p_spec.c
|
@ -74,7 +74,7 @@ typedef struct
|
|||
#endif
|
||||
|
||||
/** Animated texture definition.
|
||||
* Used for ::harddefs and for loading an ANIMATED lump from a wad.
|
||||
* Used for loading an ANIMDEFS lump from a wad.
|
||||
*
|
||||
* Animations are defined by the first and last frame (i.e., flat or texture).
|
||||
* The animation sequence uses all flats between the start and end entry, in
|
||||
|
@ -121,104 +121,6 @@ static anim_t *lastanim;
|
|||
static anim_t *anims = NULL; /// \todo free leak
|
||||
static size_t maxanims;
|
||||
|
||||
//
|
||||
// P_InitPicAnims
|
||||
//
|
||||
/** Hardcoded animation sequences.
|
||||
* Used if no ANIMATED lump is found in a loaded wad.
|
||||
*/
|
||||
static animdef_t harddefs[] =
|
||||
{
|
||||
// flat animations.
|
||||
{false, "LITEY3", "LITEY1", 4},
|
||||
{false, "FWATER16", "FWATER1", 4},
|
||||
{false, "BWATER16", "BWATER01", 4},
|
||||
{false, "LWATER16", "LWATER1", 4},
|
||||
{false, "WATER7", "WATER0", 4},
|
||||
{false, "LAVA4", "LAVA1", 8},
|
||||
{false, "DLAVA4", "DLAVA1", 8},
|
||||
{false, "RLAVA8", "RLAVA1", 8},
|
||||
{false, "LITER3", "LITER1", 8},
|
||||
{false, "SURF08", "SURF01", 4},
|
||||
|
||||
{false, "CHEMG16", "CHEMG01", 4}, // THZ Chemical gunk
|
||||
{false, "GOOP16", "GOOP01", 4}, // Green chemical gunk
|
||||
{false, "OIL16", "OIL01", 4}, // Oil
|
||||
{false, "THZBOXF4", "THZBOXF1", 2}, // Moved up with the flats
|
||||
{false, "ALTBOXF4", "ALTBOXF1", 2},
|
||||
|
||||
{false, "LITEB3", "LITEB1", 4},
|
||||
{false, "LITEN3", "LITEN1", 4},
|
||||
{false, "ACZRFL1H", "ACZRFL1A", 4},
|
||||
{false, "ACZRFL2H", "ACZRFL2A", 4},
|
||||
{false, "EGRIDF3", "EGRIDF1", 4},
|
||||
{false, "ERZFAN4", "ERZFAN1", 1},
|
||||
{false, "ERZFANR4", "ERZFANR1", 1},
|
||||
{false, "DISCO4", "DISCO1", 15},
|
||||
|
||||
// animated textures
|
||||
{true, "GFALL4", "GFALL1", 2}, // Short waterfall
|
||||
{true, "CFALL4", "CFALL1", 2}, // Long waterfall
|
||||
{true, "TFALL4", "TFALL1", 2}, // THZ Chemical fall
|
||||
{true, "AFALL4", "AFALL1", 2}, // Green Chemical fall
|
||||
{true, "QFALL4", "QFALL1", 2}, // Quicksand fall
|
||||
{true, "Q2FALL4", "Q2FALL1", 2},
|
||||
{true, "Q3FALL4", "Q3FALL1", 2},
|
||||
{true, "Q4FALL4", "Q4FALL1", 2},
|
||||
{true, "Q5FALL4", "Q5FALL1", 2},
|
||||
{true, "Q6FALL4", "Q6FALL1", 2},
|
||||
{true, "Q7FALL4", "Q7FALL1", 2},
|
||||
{true, "LFALL4", "LFALL1", 2},
|
||||
{true, "MFALL4", "MFALL1", 2},
|
||||
{true, "OFALL4", "OFALL1", 2},
|
||||
{true, "DLAVA4", "DLAVA1", 8},
|
||||
{true, "ERZLASA2", "ERZLASA1", 1},
|
||||
{true, "ERZLASB4", "ERZLASB1", 1},
|
||||
{true, "ERZLASC4", "ERZLASC1", 1},
|
||||
{true, "THZBOX04", "THZBOX01", 2},
|
||||
{true, "ALTBOX04", "ALTBOX01", 2},
|
||||
{true, "SFALL4", "SFALL1", 4}, // Lava fall
|
||||
{true, "RVZFALL8", "RVZFALL1", 4},
|
||||
{true, "BFALL4", "BFALL1", 2}, // HPZ waterfall
|
||||
{true, "GREYW3", "GREYW1", 4},
|
||||
{true, "BLUEW3", "BLUEW1", 4},
|
||||
{true, "COMP6", "COMP4", 4},
|
||||
{true, "RED3", "RED1", 4},
|
||||
{true, "YEL3", "YEL1", 4},
|
||||
{true, "ACWRFL1D", "ACWRFL1A", 1},
|
||||
{true, "ACWRFL2D", "ACWRFL2A", 1},
|
||||
{true, "ACWRFL3D", "ACWRFL3A", 1},
|
||||
{true, "ACWRFL4D", "ACWRFL4A", 1},
|
||||
{true, "ACWRP1D", "ACWRP1A", 1},
|
||||
{true, "ACWRP2D", "ACWRP2A", 1},
|
||||
{true, "ACZRP1D", "ACZRP1A", 1},
|
||||
{true, "ACZRP2D", "ACZRP2A", 1},
|
||||
{true, "OILFALL4", "OILFALL1", 2},
|
||||
{true, "SOLFALL4", "SOLFALL1", 2},
|
||||
{true, "DOWN1C", "DOWN1A", 4},
|
||||
{true, "DOWN2C", "DOWN2A", 4},
|
||||
{true, "DOWN3D", "DOWN3A", 4},
|
||||
{true, "DOWN4C", "DOWN4A", 4},
|
||||
{true, "DOWN5C", "DOWN5A", 4},
|
||||
{true, "UP1C", "UP1A", 4},
|
||||
{true, "UP2C", "UP2A", 4},
|
||||
{true, "UP3D", "UP3A", 4},
|
||||
{true, "UP4C", "UP4A", 4},
|
||||
{true, "UP5C", "UP5A", 4},
|
||||
{true, "EGRID3", "EGRID1", 4},
|
||||
{true, "ERFANW4", "ERFANW1", 1},
|
||||
{true, "ERFANX4", "ERFANX1", 1},
|
||||
{true, "DISCOD4", "DISCOD1", 15},
|
||||
{true, "DANCE4", "DANCE1", 8},
|
||||
{true, "SKY135", "SKY132", 2},
|
||||
{true, "APPLMS4", "APPLMS1", 2},
|
||||
{true, "APBOXW3", "APBOXW1", 2},
|
||||
{true, "ERZLAZC4", "ERZLAZC1", 4},
|
||||
|
||||
// End of line
|
||||
{ -1, "", "", 0},
|
||||
};
|
||||
|
||||
// Animating line specials
|
||||
|
||||
// Init animated textures
|
||||
|
@ -232,7 +134,7 @@ void P_ParseAnimationDefintion(SINT8 istexture);
|
|||
|
||||
/** Sets up texture and flat animations.
|
||||
*
|
||||
* Converts an ::animdef_t array loaded from ::harddefs or a lump into
|
||||
* Converts an ::animdef_t array loaded from a lump into
|
||||
* ::anim_t format.
|
||||
*
|
||||
* Issues an error if any animation cycles are invalid.
|
||||
|
@ -244,70 +146,37 @@ void P_InitPicAnims(void)
|
|||
{
|
||||
// Init animation
|
||||
INT32 w; // WAD
|
||||
UINT8 *animatedLump;
|
||||
UINT8 *currentPos;
|
||||
size_t i;
|
||||
|
||||
I_Assert(animdefs == NULL);
|
||||
|
||||
if (W_CheckNumForName("ANIMATED") != LUMPERROR || W_CheckNumForName("ANIMDEFS") != LUMPERROR)
|
||||
maxanims = 0;
|
||||
|
||||
if (W_CheckNumForName("ANIMDEFS") != LUMPERROR)
|
||||
{
|
||||
for (w = numwadfiles-1, maxanims = 0; w >= 0; w--)
|
||||
for (w = numwadfiles-1; w >= 0; w--)
|
||||
{
|
||||
UINT16 animatedLumpNum;
|
||||
UINT16 animdefsLumpNum;
|
||||
|
||||
// Find ANIMATED lump in the WAD
|
||||
animatedLumpNum = W_CheckNumForNamePwad("ANIMATED", w, 0);
|
||||
if (animatedLumpNum != INT16_MAX)
|
||||
{
|
||||
animatedLump = (UINT8 *)W_CacheLumpNumPwad(w, animatedLumpNum, PU_STATIC);
|
||||
|
||||
// Get the number of animations in the file
|
||||
i = maxanims;
|
||||
for (currentPos = animatedLump; *currentPos != UINT8_MAX; maxanims++, currentPos+=23);
|
||||
|
||||
// Resize animdefs (or if it hasn't been created, create it)
|
||||
animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL);
|
||||
// Sanity check it
|
||||
if (!animdefs)
|
||||
I_Error("Not enough free memory for ANIMATED data");
|
||||
|
||||
// Populate the new array
|
||||
for (currentPos = animatedLump; *currentPos != UINT8_MAX; i++, currentPos+=23)
|
||||
{
|
||||
M_Memcpy(&(animdefs[i].istexture), currentPos, 1); // istexture, 1 byte
|
||||
M_Memcpy(animdefs[i].endname, (currentPos + 1), 9); // endname, 9 bytes
|
||||
M_Memcpy(animdefs[i].startname, (currentPos + 10), 9); // startname, 9 bytes
|
||||
M_Memcpy(&(animdefs[i].speed), (currentPos + 19), 4); // speed, 4 bytes
|
||||
}
|
||||
|
||||
Z_Free(animatedLump);
|
||||
}
|
||||
|
||||
// Now find ANIMDEFS
|
||||
// Find ANIMDEFS lump in the WAD
|
||||
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0);
|
||||
if (animdefsLumpNum != INT16_MAX)
|
||||
P_ParseANIMDEFSLump(w, animdefsLumpNum);
|
||||
}
|
||||
// Define the last one
|
||||
animdefs[maxanims].istexture = -1;
|
||||
strncpy(animdefs[maxanims].endname, "", 9);
|
||||
strncpy(animdefs[maxanims].startname, "", 9);
|
||||
animdefs[maxanims].speed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
animdefs = harddefs;
|
||||
for (maxanims = 0; animdefs[maxanims].istexture != -1; maxanims++);
|
||||
}
|
||||
|
||||
// Define the last one
|
||||
animdefs[maxanims].istexture = -1;
|
||||
strncpy(animdefs[maxanims].endname, "", 9);
|
||||
strncpy(animdefs[maxanims].startname, "", 9);
|
||||
animdefs[maxanims].speed = 0;
|
||||
|
||||
if (anims)
|
||||
free(anims);
|
||||
|
||||
anims = (anim_t *)malloc(sizeof (*anims)*(maxanims + 1));
|
||||
if (!anims)
|
||||
I_Error("Not enough free memory for ANIMATED data");
|
||||
I_Error("Not enough free memory for ANIMDEFS data");
|
||||
|
||||
lastanim = anims;
|
||||
for (i = 0; animdefs[i].istexture != -1; i++)
|
||||
|
@ -339,10 +208,7 @@ void P_InitPicAnims(void)
|
|||
animdefs[i].startname, animdefs[i].endname);
|
||||
}
|
||||
|
||||
if (animdefs == harddefs)
|
||||
lastanim->speed = animdefs[i].speed;
|
||||
else
|
||||
lastanim->speed = LONG(animdefs[i].speed);
|
||||
lastanim->speed = LONG(animdefs[i].speed);
|
||||
lastanim++;
|
||||
}
|
||||
lastanim->istexture = -1;
|
||||
|
@ -350,8 +216,7 @@ void P_InitPicAnims(void)
|
|||
|
||||
// Clear animdefs now that we're done with it.
|
||||
// We'll only be using anims from now on.
|
||||
if (animdefs != harddefs)
|
||||
Z_Free(animdefs);
|
||||
Z_Free(animdefs);
|
||||
animdefs = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -359,7 +359,7 @@ static void P_DoAutobalanceTeams(void)
|
|||
totalred = red + redflagcarrier;
|
||||
totalblue = blue + blueflagcarrier;
|
||||
|
||||
if ((abs(totalred - totalblue) > cv_autobalance.value))
|
||||
if ((abs(totalred - totalblue) > max(1, (totalred + totalblue) / 8)))
|
||||
{
|
||||
if (totalred > totalblue)
|
||||
{
|
||||
|
@ -372,8 +372,7 @@ static void P_DoAutobalanceTeams(void)
|
|||
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
|
||||
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
|
||||
}
|
||||
|
||||
if (totalblue > totalred)
|
||||
else //if (totalblue > totalred)
|
||||
{
|
||||
i = M_RandomKey(blue);
|
||||
NetPacket.packet.newteam = 1;
|
||||
|
@ -651,7 +650,7 @@ void P_Ticker(boolean run)
|
|||
|
||||
if (run)
|
||||
{
|
||||
if (countdowntimer && --countdowntimer <= 0)
|
||||
if (countdowntimer && G_PlatformGametype() && (gametype == GT_COOP || leveltime >= 4*TICRATE) && --countdowntimer <= 0)
|
||||
{
|
||||
countdowntimer = 0;
|
||||
countdowntimeup = true;
|
||||
|
@ -663,6 +662,8 @@ void P_Ticker(boolean run)
|
|||
if (!players[i].mo)
|
||||
continue;
|
||||
|
||||
if (multiplayer || netgame)
|
||||
players[i].exiting = 0;
|
||||
P_DamageMobj(players[i].mo, NULL, NULL, 1, DMG_INSTAKILL);
|
||||
}
|
||||
}
|
||||
|
|
431
src/p_user.c
431
src/p_user.c
|
@ -666,7 +666,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
if (skins[player->skin].sprites[SPR2_NGT0].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin.
|
||||
{
|
||||
player->mo->skin = &skins[DEFAULTNIGHTSSKIN];
|
||||
player->mo->color = ((skin_t *)(player->mo->skin))->prefcolor;
|
||||
player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor;
|
||||
}
|
||||
|
||||
player->nightstime = player->startedtime = nighttime*TICRATE;
|
||||
|
@ -958,6 +958,29 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
|
|||
player->lives = 1;
|
||||
}
|
||||
|
||||
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound)
|
||||
{
|
||||
if (!((netgame || multiplayer) && gametype == GT_COOP))
|
||||
{
|
||||
P_GivePlayerLives(player, numlives);
|
||||
if (sound)
|
||||
P_PlayLivesJingle(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
P_GivePlayerLives(&players[i], numlives);
|
||||
if (sound)
|
||||
P_PlayLivesJingle(&players[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_DoSuperTransformation
|
||||
//
|
||||
|
@ -1130,7 +1153,9 @@ void P_PlayLivesJingle(player_t *player)
|
|||
if (player && !P_IsLocalPlayer(player))
|
||||
return;
|
||||
|
||||
if (use1upSound)
|
||||
if (gametype == GT_COOP && (netgame || multiplayer) && cv_cooplives.value == 0)
|
||||
S_StartSound(NULL, sfx_lose);
|
||||
else if (use1upSound)
|
||||
S_StartSound(NULL, sfx_oneup);
|
||||
else if (mariomode)
|
||||
S_StartSound(NULL, sfx_marioa);
|
||||
|
@ -1473,9 +1498,15 @@ void P_SpawnShieldOrb(player_t *player)
|
|||
//
|
||||
void P_SwitchShield(player_t *player, UINT16 shieldtype)
|
||||
{
|
||||
boolean donthavealready = (shieldtype & SH_FORCE)
|
||||
? (!(player->powers[pw_shield] & SH_FORCE) || (player->powers[pw_shield] & SH_FORCEHP) < (shieldtype & ~SH_FORCE))
|
||||
: ((player->powers[pw_shield] & SH_NOSTACK) != shieldtype);
|
||||
boolean donthavealready;
|
||||
|
||||
// If you already have a bomb shield, use it!
|
||||
if ((shieldtype == SH_ARMAGEDDON) && (player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON)
|
||||
P_BlackOw(player);
|
||||
|
||||
donthavealready = (shieldtype & SH_FORCE)
|
||||
? (!(player->powers[pw_shield] & SH_FORCE) || (player->powers[pw_shield] & SH_FORCEHP) < (shieldtype & ~SH_FORCE))
|
||||
: ((player->powers[pw_shield] & SH_NOSTACK) != shieldtype);
|
||||
|
||||
if (donthavealready)
|
||||
{
|
||||
|
@ -2260,7 +2291,7 @@ static void P_CheckInvincibilityTimer(player_t *player)
|
|||
return;
|
||||
|
||||
if (mariomode && !player->powers[pw_super])
|
||||
player->mo->color = (UINT8)(SKINCOLOR_RED + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RED))); // Passes through all saturated colours
|
||||
player->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
|
||||
else if (leveltime % (TICRATE/7) == 0)
|
||||
{
|
||||
mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP);
|
||||
|
@ -2317,7 +2348,7 @@ static void P_DoBubbleBreath(player_t *player)
|
|||
|
||||
if (player->charflags & SF_MACHINE)
|
||||
{
|
||||
if (P_RandomChance((128-(player->powers[pw_underwater]/4))*FRACUNIT/256))
|
||||
if (player->powers[pw_underwater] && P_RandomChance((128-(player->powers[pw_underwater]/4))*FRACUNIT/256))
|
||||
{
|
||||
fixed_t r = player->mo->radius>>FRACBITS;
|
||||
x += (P_RandomRange(r, -r)<<FRACBITS);
|
||||
|
@ -4334,11 +4365,6 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
|
|||
player->mo->momy /= 3;
|
||||
}
|
||||
|
||||
if (player->mo->info->attacksound && !player->spectator)
|
||||
S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound
|
||||
|
||||
P_SpawnThokMobj(player);
|
||||
|
||||
if (player->charability == CA_HOMINGTHOK)
|
||||
{
|
||||
P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon));
|
||||
|
@ -4351,10 +4377,16 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
|
||||
player->pflags &= ~PF_JUMPED;
|
||||
player->mo->height = P_GetPlayerHeight(player);
|
||||
}
|
||||
player->pflags &= ~PF_NOJUMPDAMAGE;
|
||||
}
|
||||
|
||||
if (player->mo->info->attacksound && !player->spectator)
|
||||
S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound
|
||||
|
||||
P_SpawnThokMobj(player);
|
||||
|
||||
player->pflags &= ~(PF_SPINNING|PF_STARTDASH);
|
||||
player->pflags |= PF_THOKKED;
|
||||
}
|
||||
|
@ -4816,7 +4848,7 @@ static void P_3dMovement(player_t *player)
|
|||
angle_t dangle; // replaces old quadrants bits
|
||||
fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale);
|
||||
boolean analogmove = false;
|
||||
boolean spin = (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH));
|
||||
boolean spin = ((onground = P_IsObjectOnGround(player->mo)) && player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH));
|
||||
fixed_t oldMagnitude, newMagnitude;
|
||||
#ifdef ESLOPE
|
||||
vector3_t totalthrust;
|
||||
|
@ -4906,9 +4938,6 @@ static void P_3dMovement(player_t *player)
|
|||
if (player->pflags & PF_SLIDING)
|
||||
cmd->forwardmove = 0;
|
||||
|
||||
// Do not let the player control movement if not onground.
|
||||
onground = P_IsObjectOnGround(player->mo);
|
||||
|
||||
player->aiming = cmd->aiming<<FRACBITS;
|
||||
|
||||
// Set the player speeds.
|
||||
|
@ -4969,10 +4998,7 @@ static void P_3dMovement(player_t *player)
|
|||
if (spin) // Prevent gaining speed whilst rolling!
|
||||
{
|
||||
const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); // P_XYFriction
|
||||
if (onground)
|
||||
topspeed = FixedMul(oldMagnitude, ns);
|
||||
else
|
||||
topspeed = oldMagnitude;
|
||||
topspeed = FixedMul(oldMagnitude, ns);
|
||||
}
|
||||
|
||||
// Better maneuverability while flying
|
||||
|
@ -5013,19 +5039,20 @@ static void P_3dMovement(player_t *player)
|
|||
{
|
||||
movepushforward = cmd->forwardmove * (thrustfactor * acceleration);
|
||||
|
||||
// allow very small movement while in air for gameplay
|
||||
if (!onground)
|
||||
movepushforward >>= 2; // proper air movement
|
||||
|
||||
// Allow a bit of movement while spinning
|
||||
if (player->pflags & PF_SPINNING)
|
||||
{
|
||||
if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)
|
||||
|| (player->pflags & PF_STARTDASH))
|
||||
movepushforward = 0;
|
||||
else if (onground)
|
||||
movepushforward >>= 4;
|
||||
else
|
||||
movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
|
||||
movepushforward >>= 3;
|
||||
}
|
||||
// allow very small movement while in air for gameplay
|
||||
else if (!onground)
|
||||
movepushforward >>= 2; // proper air movement
|
||||
|
||||
movepushforward = FixedMul(movepushforward, player->mo->scale);
|
||||
|
||||
|
@ -5053,21 +5080,20 @@ static void P_3dMovement(player_t *player)
|
|||
|
||||
movepushforward = max(abs(cmd->sidemove), abs(cmd->forwardmove)) * (thrustfactor * acceleration);
|
||||
|
||||
// allow very small movement while in air for gameplay
|
||||
if (!onground)
|
||||
movepushforward >>= 2; // proper air movement
|
||||
|
||||
// Allow a bit of movement while spinning
|
||||
if (player->pflags & PF_SPINNING)
|
||||
{
|
||||
// Stupid little movement prohibitor hack
|
||||
// that REALLY shouldn't belong in analog code.
|
||||
if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)
|
||||
|| (player->pflags & PF_STARTDASH))
|
||||
movepushforward = 0;
|
||||
else if (onground)
|
||||
movepushforward >>= 4;
|
||||
else
|
||||
movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
|
||||
movepushforward >>= 3;
|
||||
}
|
||||
// allow very small movement while in air for gameplay
|
||||
else if (!onground)
|
||||
movepushforward >>= 2; // proper air movement
|
||||
|
||||
movepushsideangle = controldirection;
|
||||
|
||||
|
@ -5085,25 +5111,26 @@ static void P_3dMovement(player_t *player)
|
|||
{
|
||||
movepushside = cmd->sidemove * (thrustfactor * acceleration);
|
||||
|
||||
// allow very small movement while in air for gameplay
|
||||
if (!onground)
|
||||
{
|
||||
movepushside >>= 2;
|
||||
|
||||
movepushside >>= 2; // proper air movement
|
||||
// Reduce movepushslide even more if over "max" flight speed
|
||||
if (player->powers[pw_tailsfly] && player->speed > topspeed)
|
||||
if ((player->pflags & PF_SPINNING) || (player->powers[pw_tailsfly] && player->speed > topspeed))
|
||||
movepushside >>= 2;
|
||||
}
|
||||
|
||||
// Allow a bit of movement while spinning
|
||||
if (player->pflags & PF_SPINNING)
|
||||
else if (player->pflags & PF_SPINNING)
|
||||
{
|
||||
if ((player->pflags & PF_STARTDASH))
|
||||
if (player->pflags & PF_STARTDASH)
|
||||
movepushside = 0;
|
||||
else if (onground)
|
||||
movepushside >>= 4;
|
||||
else
|
||||
movepushside = FixedDiv(movepushside,16*FRACUNIT);
|
||||
movepushside >>= 3;
|
||||
}
|
||||
|
||||
// Finally move the player now that his speed/direction has been decided.
|
||||
// Finally move the player now that their speed/direction has been decided.
|
||||
movepushside = FixedMul(movepushside, player->mo->scale);
|
||||
|
||||
#ifdef ESLOPE
|
||||
|
@ -5186,16 +5213,16 @@ static void P_SpectatorMovement(player_t *player)
|
|||
if (!(cmd->angleturn & TICCMD_RECEIVED))
|
||||
ticmiss++;
|
||||
|
||||
if (player->mo->z > player->mo->ceilingz - player->mo->height)
|
||||
player->mo->z = player->mo->ceilingz - player->mo->height;
|
||||
if (player->mo->z < player->mo->floorz)
|
||||
player->mo->z = player->mo->floorz;
|
||||
|
||||
if (cmd->buttons & BT_JUMP)
|
||||
player->mo->z += FRACUNIT*16;
|
||||
else if (cmd->buttons & BT_USE)
|
||||
player->mo->z -= FRACUNIT*16;
|
||||
|
||||
if (player->mo->z > player->mo->ceilingz - player->mo->height)
|
||||
player->mo->z = player->mo->ceilingz - player->mo->height;
|
||||
if (player->mo->z < player->mo->floorz)
|
||||
player->mo->z = player->mo->floorz;
|
||||
|
||||
// Aiming needed for SEENAMES, etc.
|
||||
// We may not need to fire as a spectator, but this is still handy!
|
||||
player->aiming = cmd->aiming<<FRACBITS;
|
||||
|
@ -6671,9 +6698,6 @@ static void P_MovePlayer(player_t *player)
|
|||
|
||||
fixed_t runspd;
|
||||
|
||||
if (countdowntimeup)
|
||||
return;
|
||||
|
||||
if (player->mo->state >= &states[S_PLAY_SUPER_TRANS] && player->mo->state <= &states[S_PLAY_SUPER_TRANS9])
|
||||
{
|
||||
player->mo->momx = player->mo->momy = player->mo->momz = 0;
|
||||
|
@ -6734,6 +6758,7 @@ static void P_MovePlayer(player_t *player)
|
|||
|
||||
if (player->spectator)
|
||||
{
|
||||
player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip...
|
||||
P_SpectatorMovement(player);
|
||||
return;
|
||||
}
|
||||
|
@ -8125,6 +8150,111 @@ void P_FindEmerald(void)
|
|||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// P_GetLives
|
||||
// Get extra lives in new co-op if you're allowed to.
|
||||
//
|
||||
|
||||
boolean P_GetLives(player_t *player)
|
||||
{
|
||||
INT32 i, maxlivesplayer = -1, livescheck = 1;
|
||||
if (!(netgame || multiplayer)
|
||||
|| (gametype != GT_COOP)
|
||||
|| (cv_cooplives.value == 1))
|
||||
return true;
|
||||
|
||||
if ((cv_cooplives.value == 2 || cv_cooplives.value == 0) && player->lives > 0)
|
||||
return true;
|
||||
|
||||
if (cv_cooplives.value == 0) // infinite lives
|
||||
{
|
||||
player->lives++;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives > livescheck)
|
||||
{
|
||||
maxlivesplayer = i;
|
||||
livescheck = players[i].lives;
|
||||
}
|
||||
}
|
||||
if (maxlivesplayer != -1 && &players[maxlivesplayer] != player)
|
||||
{
|
||||
if (cv_cooplives.value == 2 && (P_IsLocalPlayer(player) || P_IsLocalPlayer(&players[maxlivesplayer])))
|
||||
S_StartSound(NULL, sfx_jshard); // placeholder
|
||||
players[maxlivesplayer].lives--;
|
||||
player->lives++;
|
||||
if (player->lives < 1)
|
||||
player->lives = 1;
|
||||
return true;
|
||||
}
|
||||
return (player->lives > 0);
|
||||
}
|
||||
|
||||
//
|
||||
// P_ConsiderAllGone
|
||||
// Shamelessly lifted from TD. Thanks, Sryder!
|
||||
//
|
||||
|
||||
static void P_ConsiderAllGone(void)
|
||||
{
|
||||
INT32 i, lastdeadplayer = -1, deadtimercheck = INT32_MAX;
|
||||
|
||||
if (countdown2)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health)
|
||||
break;
|
||||
|
||||
if (players[i].spectator)
|
||||
{
|
||||
if (lastdeadplayer == -1)
|
||||
lastdeadplayer = i;
|
||||
}
|
||||
else if (players[i].lives > 0)
|
||||
{
|
||||
lastdeadplayer = i;
|
||||
if (players[i].deadtimer < deadtimercheck)
|
||||
deadtimercheck = players[i].deadtimer;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS && lastdeadplayer != -1 && deadtimercheck > 2*TICRATE) // the last killed player will reset the level in G_DoReborn
|
||||
{
|
||||
//players[lastdeadplayer].spectator = true;
|
||||
players[lastdeadplayer].outofcoop = true;
|
||||
players[lastdeadplayer].playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
|
||||
void P_RestoreMultiMusic(player_t *player)
|
||||
{
|
||||
if (netgame)
|
||||
{
|
||||
if (P_IsLocalPlayer(player))
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
}
|
||||
else if (multiplayer) // local multiplayer only
|
||||
{
|
||||
// Restore the other player's music once we're dead for long enough
|
||||
// -- that is, as long as they aren't dead too
|
||||
if (player == &players[displayplayer] && players[secondarydisplayplayer].lives > 0)
|
||||
P_RestoreMusic(&players[secondarydisplayplayer]);
|
||||
else if (player == &players[secondarydisplayplayer] && players[displayplayer].lives > 0)
|
||||
P_RestoreMusic(&players[displayplayer]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_DeathThink
|
||||
// Fall on your face when dying.
|
||||
|
@ -8133,6 +8263,8 @@ void P_FindEmerald(void)
|
|||
|
||||
static void P_DeathThink(player_t *player)
|
||||
{
|
||||
INT32 j = MAXPLAYERS;
|
||||
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
player->deltaviewheight = 0;
|
||||
|
||||
|
@ -8148,76 +8280,100 @@ static void P_DeathThink(player_t *player)
|
|||
G_UseContinue(); // Even if we don't have one this handles ending the game
|
||||
}
|
||||
|
||||
if ((cv_cooplives.value != 1)
|
||||
&& (gametype == GT_COOP)
|
||||
&& (netgame || multiplayer)
|
||||
&& (player->lives <= 0))
|
||||
{
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (!playeringame[j])
|
||||
continue;
|
||||
|
||||
if (players[j].lives > 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Force respawn if idle for more than 30 seconds in shooter modes.
|
||||
if (player->deadtimer > 30*TICRATE && !G_PlatformGametype())
|
||||
player->playerstate = PST_REBORN;
|
||||
else if (player->lives > 0 && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages!
|
||||
else if ((player->lives > 0 || j != MAXPLAYERS) && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages!
|
||||
{
|
||||
// Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes.
|
||||
if ((cmd->buttons & BT_JUMP) && player->deadtimer > cv_respawntime.value*TICRATE
|
||||
&& gametype != GT_RACE && gametype != GT_COOP)
|
||||
player->playerstate = PST_REBORN;
|
||||
if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2)
|
||||
{
|
||||
P_ConsiderAllGone();
|
||||
if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))
|
||||
{
|
||||
//player->spectator = true;
|
||||
player->outofcoop = true;
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes.
|
||||
if (cmd->buttons & BT_JUMP)
|
||||
{
|
||||
if (gametype != GT_COOP && player->spectator)
|
||||
player->playerstate = PST_REBORN;
|
||||
else switch(gametype) {
|
||||
case GT_COOP:
|
||||
if (player->deadtimer > TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
break;
|
||||
case GT_COMPETITION:
|
||||
if (player->deadtimer > TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
break;
|
||||
case GT_RACE:
|
||||
player->playerstate = PST_REBORN;
|
||||
break;
|
||||
default:
|
||||
if (player->deadtimer > cv_respawntime.value*TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Instant respawn in race or if you're spectating.
|
||||
if ((cmd->buttons & BT_JUMP) && (gametype == GT_RACE || player->spectator))
|
||||
player->playerstate = PST_REBORN;
|
||||
|
||||
// One second respawn in coop.
|
||||
if ((cmd->buttons & BT_JUMP) && player->deadtimer > TICRATE && (gametype == GT_COOP || gametype == GT_COMPETITION))
|
||||
player->playerstate = PST_REBORN;
|
||||
|
||||
// Single player auto respawn
|
||||
if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
// Single player auto respawn
|
||||
if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE)
|
||||
else if ((netgame || multiplayer) && player->deadtimer >= 8*TICRATE)
|
||||
{
|
||||
|
||||
INT32 i, deadtimercheck = INT32_MAX;
|
||||
|
||||
// In a net/multiplayer game, and out of lives
|
||||
if (gametype == GT_COMPETITION)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && !players[i].exiting && players[i].lives > 0)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (!players[i].exiting && players[i].lives)
|
||||
break;
|
||||
if (players[i].deadtimer < deadtimercheck)
|
||||
deadtimercheck = players[i].deadtimer;
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
if (i == MAXPLAYERS && deadtimercheck == 8*TICRATE)
|
||||
{
|
||||
// Everyone's either done with the race, or dead.
|
||||
if (!countdown2 || countdown2 > 1*TICRATE)
|
||||
countdown2 = 1*TICRATE;
|
||||
}
|
||||
}
|
||||
//else if (gametype == GT_COOP) -- moved to G_DoReborn
|
||||
}
|
||||
|
||||
// In a coop game, and out of lives
|
||||
if (gametype == GT_COOP)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && (players[i].exiting || players[i].lives > 0))
|
||||
break;
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
{
|
||||
// They're dead, Jim.
|
||||
//nextmapoverride = spstage_start;
|
||||
nextmapoverride = gamemap;
|
||||
countdown2 = 1*TICRATE;
|
||||
skipstats = true;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
players[i].score = 0;
|
||||
}
|
||||
|
||||
//emeralds = 0;
|
||||
tokenbits = 0;
|
||||
tokenlist = 0;
|
||||
token = 0;
|
||||
}
|
||||
}
|
||||
if (gametype == GT_COOP && (multiplayer || netgame) && (player->lives <= 0) && (player->deadtimer >= 8*TICRATE || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))))
|
||||
{
|
||||
//player->spectator = true;
|
||||
player->outofcoop = true;
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
|
||||
if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame)))
|
||||
|
@ -8237,25 +8393,8 @@ static void P_DeathThink(player_t *player)
|
|||
}
|
||||
|
||||
// Return to level music
|
||||
if (player->lives <= 0)
|
||||
{
|
||||
if (netgame)
|
||||
{
|
||||
if (player->deadtimer == gameovertics && P_IsLocalPlayer(player))
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
}
|
||||
else if (multiplayer) // local multiplayer only
|
||||
{
|
||||
if (player->deadtimer != gameovertics)
|
||||
;
|
||||
// Restore the other player's music once we're dead for long enough
|
||||
// -- that is, as long as they aren't dead too
|
||||
else if (player == &players[displayplayer] && players[secondarydisplayplayer].lives > 0)
|
||||
P_RestoreMusic(&players[secondarydisplayplayer]);
|
||||
else if (player == &players[secondarydisplayplayer] && players[displayplayer].lives > 0)
|
||||
P_RestoreMusic(&players[displayplayer]);
|
||||
}
|
||||
}
|
||||
if (gametype != GT_COOP && player->lives <= 0 && player->deadtimer == gameovertics)
|
||||
P_RestoreMultiMusic(player);
|
||||
}
|
||||
|
||||
if (!player->mo)
|
||||
|
@ -8909,16 +9048,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming);
|
||||
}
|
||||
|
||||
static boolean P_SpectatorJoinGame(player_t *player)
|
||||
boolean P_SpectatorJoinGame(player_t *player)
|
||||
{
|
||||
if (!G_GametypeHasSpectators() && G_IsSpecialStage(gamemap) && useNightsSS) // Special Stage spectators should NEVER be allowed to rejoin the game
|
||||
{
|
||||
if (P_IsLocalPlayer(player))
|
||||
CONS_Printf(M_GetText("You cannot enter the game while a special stage is in progress.\n"));
|
||||
player->powers[pw_flashing] += 2*TICRATE; //to prevent message spam.
|
||||
}
|
||||
|
||||
else if (!cv_allowteamchange.value)
|
||||
if (gametype != GT_COOP && !cv_allowteamchange.value)
|
||||
{
|
||||
if (P_IsLocalPlayer(player))
|
||||
CONS_Printf(M_GetText("Server does not allow team change.\n"));
|
||||
|
@ -8987,7 +9119,7 @@ static boolean P_SpectatorJoinGame(player_t *player)
|
|||
P_RemoveMobj(player->mo);
|
||||
player->mo = NULL;
|
||||
}
|
||||
player->spectator = false;
|
||||
player->spectator = player->outofcoop = false;
|
||||
player->playerstate = PST_REBORN;
|
||||
|
||||
if (gametype == GT_TAG)
|
||||
|
@ -9006,7 +9138,8 @@ static boolean P_SpectatorJoinGame(player_t *player)
|
|||
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
|
||||
displayplayer = consoleplayer;
|
||||
|
||||
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]);
|
||||
if (gametype != GT_COOP)
|
||||
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]);
|
||||
return true; // no more player->mo, cannot continue.
|
||||
}
|
||||
else
|
||||
|
@ -9300,7 +9433,7 @@ void P_PlayerThink(player_t *player)
|
|||
{
|
||||
if (cv_playersforexit.value) // Count to be sure everyone's exited
|
||||
{
|
||||
INT32 i;
|
||||
INT32 i, total = 0, exiting = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -9309,11 +9442,12 @@ void P_PlayerThink(player_t *player)
|
|||
if (players[i].lives <= 0)
|
||||
continue;
|
||||
|
||||
if (!players[i].exiting || players[i].exiting > 3)
|
||||
break;
|
||||
total++;
|
||||
if (players[i].exiting && players[i].exiting < 4)
|
||||
exiting++;
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
if (!total || ((4*exiting)/total) >= cv_playersforexit.value)
|
||||
{
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
|
@ -9340,7 +9474,12 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
if (!player->spectator)
|
||||
P_PlayerInSpecialSector(player);
|
||||
else if (
|
||||
#else
|
||||
if (player->spectator &&
|
||||
#endif
|
||||
gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2)
|
||||
P_ConsiderAllGone();
|
||||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
|
@ -9353,14 +9492,14 @@ void P_PlayerThink(player_t *player)
|
|||
// Make sure spectators always have a score and ring count of 0.
|
||||
if (player->spectator)
|
||||
{
|
||||
player->score = 0;
|
||||
if (gametype != GT_COOP)
|
||||
player->score = 0;
|
||||
player->mo->health = 1;
|
||||
player->rings = 0;
|
||||
}
|
||||
|
||||
if ((netgame || multiplayer) && player->lives <= 0)
|
||||
else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP)
|
||||
{
|
||||
// In Co-Op, replenish a user's lives if they are depleted.
|
||||
// Outside of Co-Op, replenish a user's lives if they are depleted.
|
||||
// of course, this is just a cheap hack, meh...
|
||||
player->lives = cv_startinglives.value;
|
||||
}
|
||||
|
@ -9386,7 +9525,7 @@ void P_PlayerThink(player_t *player)
|
|||
player->realtime = leveltime;
|
||||
}
|
||||
|
||||
if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing])
|
||||
if (player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing] && G_GametypeHasSpectators())
|
||||
{
|
||||
if (P_SpectatorJoinGame(player))
|
||||
return; // player->mo was removed.
|
||||
|
@ -9974,7 +10113,7 @@ void P_PlayerAfterThink(player_t *player)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->target)
|
||||
else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->tracer)
|
||||
{
|
||||
player->mo->height = P_GetPlayerSpinHeight(player);
|
||||
// tracer is what you're hanging onto....
|
||||
|
@ -9990,14 +10129,20 @@ void P_PlayerAfterThink(player_t *player)
|
|||
player->pflags &= ~PF_THOKKED;
|
||||
|
||||
if (cmd->forwardmove > 0)
|
||||
player->mo->tracer->target->lastlook += 2;
|
||||
else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount)
|
||||
player->mo->tracer->target->lastlook -= 2;
|
||||
{
|
||||
if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction)
|
||||
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->friction;
|
||||
}
|
||||
else if (cmd->forwardmove < 0)
|
||||
{
|
||||
if ((player->mo->tracer->tracer->lastlook -= 2) < player->mo->tracer->tracer->movecount)
|
||||
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->movecount;
|
||||
}
|
||||
|
||||
if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
|
||||
if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
|
||||
&& !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode?
|
||||
{
|
||||
player->mo->tracer->target->health += cmd->sidemove;
|
||||
player->mo->tracer->tracer->health += cmd->sidemove;
|
||||
player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX
|
||||
|
||||
if (!demoplayback || P_AnalogMove(player))
|
||||
|
|
105
src/r_bsp.c
105
src/r_bsp.c
|
@ -365,6 +365,36 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
|
|||
return sec;
|
||||
}
|
||||
|
||||
boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
|
||||
{
|
||||
return (
|
||||
#ifdef POLYOBJECTS
|
||||
!line->polyseg &&
|
||||
#endif
|
||||
back->ceilingpic == front->ceilingpic
|
||||
&& back->floorpic == front->floorpic
|
||||
#ifdef ESLOPE
|
||||
&& back->f_slope == front->f_slope
|
||||
&& back->c_slope == front->c_slope
|
||||
#endif
|
||||
&& back->lightlevel == front->lightlevel
|
||||
&& !line->sidedef->midtexture
|
||||
// Check offsets too!
|
||||
&& back->floor_xoffs == front->floor_xoffs
|
||||
&& back->floor_yoffs == front->floor_yoffs
|
||||
&& back->floorpic_angle == front->floorpic_angle
|
||||
&& back->ceiling_xoffs == front->ceiling_xoffs
|
||||
&& back->ceiling_yoffs == front->ceiling_yoffs
|
||||
&& back->ceilingpic_angle == front->ceilingpic_angle
|
||||
// Consider altered lighting.
|
||||
&& back->floorlightsec == front->floorlightsec
|
||||
&& back->ceilinglightsec == front->ceilinglightsec
|
||||
// Consider colormaps
|
||||
&& back->extra_colormap == front->extra_colormap
|
||||
&& ((!front->ffloors && !back->ffloors)
|
||||
|| front->tag == back->tag));
|
||||
}
|
||||
|
||||
//
|
||||
// R_AddLine
|
||||
// Clips the given segment and adds any visible pieces to the line list.
|
||||
|
@ -526,36 +556,8 @@ static void R_AddLine(seg_t *line)
|
|||
// Identical floor and ceiling on both sides, identical light levels on both sides,
|
||||
// and no middle texture.
|
||||
|
||||
if (
|
||||
#ifdef POLYOBJECTS
|
||||
!line->polyseg &&
|
||||
#endif
|
||||
backsector->ceilingpic == frontsector->ceilingpic
|
||||
&& backsector->floorpic == frontsector->floorpic
|
||||
#ifdef ESLOPE
|
||||
&& backsector->f_slope == frontsector->f_slope
|
||||
&& backsector->c_slope == frontsector->c_slope
|
||||
#endif
|
||||
&& backsector->lightlevel == frontsector->lightlevel
|
||||
&& !curline->sidedef->midtexture
|
||||
// Check offsets too!
|
||||
&& backsector->floor_xoffs == frontsector->floor_xoffs
|
||||
&& backsector->floor_yoffs == frontsector->floor_yoffs
|
||||
&& backsector->floorpic_angle == frontsector->floorpic_angle
|
||||
&& backsector->ceiling_xoffs == frontsector->ceiling_xoffs
|
||||
&& backsector->ceiling_yoffs == frontsector->ceiling_yoffs
|
||||
&& backsector->ceilingpic_angle == frontsector->ceilingpic_angle
|
||||
// Consider altered lighting.
|
||||
&& backsector->floorlightsec == frontsector->floorlightsec
|
||||
&& backsector->ceilinglightsec == frontsector->ceilinglightsec
|
||||
// Consider colormaps
|
||||
&& backsector->extra_colormap == frontsector->extra_colormap
|
||||
&& ((!frontsector->ffloors && !backsector->ffloors)
|
||||
|| frontsector->tag == backsector->tag))
|
||||
{
|
||||
if (R_IsEmptyLine(line, frontsector, backsector))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
clippass:
|
||||
R_ClipPassWallSegment(x1, x2 - 1);
|
||||
|
@ -1102,30 +1104,12 @@ static void R_Subsector(size_t num)
|
|||
&& polysec->floorheight >= floorcenterz
|
||||
&& (viewz < polysec->floorheight))
|
||||
{
|
||||
fixed_t xoff, yoff;
|
||||
xoff = polysec->floor_xoffs;
|
||||
yoff = polysec->floor_yoffs;
|
||||
|
||||
if (po->angle != 0) {
|
||||
angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
|
||||
|
||||
xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
|
||||
yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
|
||||
} else {
|
||||
xoff -= po->centerPt.x;
|
||||
yoff += po->centerPt.y;
|
||||
}
|
||||
|
||||
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
|
||||
light = 0;
|
||||
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
|
||||
polysec->lightlevel, xoff, yoff,
|
||||
polysec->floorpic_angle-po->angle,
|
||||
NULL,
|
||||
NULL
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
, po
|
||||
#endif
|
||||
polysec->lightlevel, polysec->floor_xoffs, polysec->floor_yoffs,
|
||||
polysec->floorpic_angle-po->angle,
|
||||
NULL, NULL, po
|
||||
#ifdef ESLOPE
|
||||
, NULL // will ffloors be slopable eventually?
|
||||
#endif
|
||||
|
@ -1150,28 +1134,11 @@ static void R_Subsector(size_t num)
|
|||
&& polysec->ceilingheight <= ceilingcenterz
|
||||
&& (viewz > polysec->ceilingheight))
|
||||
{
|
||||
fixed_t xoff, yoff;
|
||||
xoff = polysec->ceiling_xoffs;
|
||||
yoff = polysec->ceiling_yoffs;
|
||||
|
||||
if (po->angle != 0) {
|
||||
angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
|
||||
|
||||
xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
|
||||
yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
|
||||
} else {
|
||||
xoff -= po->centerPt.x;
|
||||
yoff += po->centerPt.y;
|
||||
}
|
||||
|
||||
light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight);
|
||||
light = 0;
|
||||
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
|
||||
polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
|
||||
NULL, NULL
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
, po
|
||||
#endif
|
||||
polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
|
||||
NULL, NULL, po
|
||||
#ifdef ESLOPE
|
||||
, NULL // will ffloors be slopable eventually?
|
||||
#endif
|
||||
|
|
|
@ -50,6 +50,7 @@ extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
|
|||
|
||||
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
|
||||
INT32 *ceilinglightlevel, boolean back);
|
||||
boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
|
||||
|
||||
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
|
||||
void R_Prep3DFloors(sector_t *sector);
|
||||
|
|
53
src/r_data.c
53
src/r_data.c
|
@ -625,44 +625,33 @@ void R_LoadTextures(void)
|
|||
{
|
||||
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
|
||||
|
||||
// Then, check the lump directly to see if it's a texture SOC,
|
||||
// and if it is, load it using dehacked instead.
|
||||
if (strstr((const char *)patchlump, "TEXTURE"))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "%s is a Texture SOC.\n", W_CheckNameForNumPwad((UINT16)w,texstart+j));
|
||||
Z_Unlock(patchlump);
|
||||
DEH_LoadDehackedLumpPwad((UINT16)w, texstart + j);
|
||||
}
|
||||
else
|
||||
{
|
||||
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
|
||||
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
|
||||
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
|
||||
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
|
||||
|
||||
// Set texture properties.
|
||||
M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
|
||||
texture->width = SHORT(patchlump->width);
|
||||
texture->height = SHORT(patchlump->height);
|
||||
texture->patchcount = 1;
|
||||
texture->holes = false;
|
||||
texture->flip = 0;
|
||||
// Set texture properties.
|
||||
M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
|
||||
texture->width = SHORT(patchlump->width);
|
||||
texture->height = SHORT(patchlump->height);
|
||||
texture->patchcount = 1;
|
||||
texture->holes = false;
|
||||
texture->flip = 0;
|
||||
|
||||
// Allocate information for the texture's patches.
|
||||
patch = &texture->patches[0];
|
||||
// Allocate information for the texture's patches.
|
||||
patch = &texture->patches[0];
|
||||
|
||||
patch->originx = patch->originy = 0;
|
||||
patch->wad = (UINT16)w;
|
||||
patch->lump = texstart + j;
|
||||
patch->flip = 0;
|
||||
patch->originx = patch->originy = 0;
|
||||
patch->wad = (UINT16)w;
|
||||
patch->lump = texstart + j;
|
||||
patch->flip = 0;
|
||||
|
||||
Z_Unlock(patchlump);
|
||||
Z_Unlock(patchlump);
|
||||
|
||||
k = 1;
|
||||
while (k << 1 <= texture->width)
|
||||
k <<= 1;
|
||||
k = 1;
|
||||
while (k << 1 <= texture->width)
|
||||
k <<= 1;
|
||||
|
||||
texturewidthmask[i] = k - 1;
|
||||
textureheight[i] = texture->height << FRACBITS;
|
||||
}
|
||||
texturewidthmask[i] = k - 1;
|
||||
textureheight[i] = texture->height << FRACBITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ extern INT16 *hicolormaps; // remap high colors to high colors..
|
|||
|
||||
extern CV_PossibleValue_t Color_cons_t[];
|
||||
|
||||
// Load TEXTURE1/TEXTURE2/PNAMES definitions, create lookup tables
|
||||
// Load TEXTURES definitions, create lookup tables
|
||||
void R_LoadTextures(void);
|
||||
void R_FlushTextureCache(void);
|
||||
|
||||
|
|
|
@ -574,6 +574,9 @@ typedef struct seg_s
|
|||
sector_t *backsector;
|
||||
|
||||
#ifdef HWRENDER
|
||||
// new pointers so that AdjustSegs doesn't mess with v1/v2
|
||||
void *pv1; // polyvertex_t
|
||||
void *pv2; // polyvertex_t
|
||||
float flength; // length of the seg, used by hardware renderer
|
||||
|
||||
lightmap_t *lightmaps; // for static lightmap
|
||||
|
@ -685,7 +688,7 @@ typedef enum
|
|||
// Patches.
|
||||
// A patch holds one or more columns.
|
||||
// Patches are used for sprites and all masked pictures, and we compose
|
||||
// textures from the TEXTURE1 list of patches.
|
||||
// textures from the TEXTURES list of patches.
|
||||
//
|
||||
// WARNING: this structure is cloned in GLPatch_t
|
||||
typedef struct
|
||||
|
|
1163
src/r_draw.c
1163
src/r_draw.c
File diff suppressed because it is too large
Load diff
|
@ -459,6 +459,23 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
if (polyobj)
|
||||
{
|
||||
if (polyobj->angle != 0)
|
||||
{
|
||||
angle_t fineshift = polyobj->angle >> ANGLETOFINESHIFT;
|
||||
xoff -= FixedMul(FINECOSINE(fineshift), polyobj->centerPt.x)+FixedMul(FINESINE(fineshift), polyobj->centerPt.y);
|
||||
yoff -= FixedMul(FINESINE(fineshift), polyobj->centerPt.x)-FixedMul(FINECOSINE(fineshift), polyobj->centerPt.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
xoff -= polyobj->centerPt.x;
|
||||
yoff += polyobj->centerPt.y;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// This appears to fix the Nimbus Ruins sky bug.
|
||||
if (picnum == skyflatnum && pfloor)
|
||||
{
|
||||
|
|
805
src/r_things.c
805
src/r_things.c
|
@ -20,6 +20,7 @@
|
|||
#include "z_zone.h"
|
||||
#include "m_menu.h" // character select
|
||||
#include "m_misc.h"
|
||||
#include "info.h" // spr2names
|
||||
#include "i_video.h" // rendermode
|
||||
#include "r_things.h"
|
||||
#include "r_plane.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "d_netfil.h" // blargh. for nameonly().
|
||||
#include "m_cheat.h" // objectplace
|
||||
#include "m_cond.h"
|
||||
#include "fastcmp.h"
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_md2.h"
|
||||
#endif
|
||||
|
@ -429,117 +431,6 @@ void R_AddSpriteDefs(UINT16 wadnum)
|
|||
CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites));
|
||||
}
|
||||
|
||||
#ifdef DELFILE
|
||||
static void R_RemoveSpriteLump(UINT16 wad, // graphics patch
|
||||
UINT16 lump,
|
||||
size_t lumpid, // identifier
|
||||
UINT8 frame,
|
||||
UINT8 rotation,
|
||||
UINT8 flipped)
|
||||
{
|
||||
(void)wad; /// \todo: how do I remove sprites?
|
||||
(void)lump;
|
||||
(void)lumpid;
|
||||
(void)frame;
|
||||
(void)rotation;
|
||||
(void)flipped;
|
||||
}
|
||||
|
||||
static boolean R_DelSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump)
|
||||
{
|
||||
UINT16 l;
|
||||
UINT8 frame;
|
||||
UINT8 rotation;
|
||||
lumpinfo_t *lumpinfo;
|
||||
|
||||
maxframe = (size_t)-1;
|
||||
|
||||
// scan the lumps,
|
||||
// filling in the frames for whatever is found
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
if (endlump > wadfiles[wadnum]->numlumps)
|
||||
endlump = wadfiles[wadnum]->numlumps;
|
||||
|
||||
for (l = startlump; l < endlump; l++)
|
||||
{
|
||||
if (memcmp(lumpinfo[l].name,sprname,4)==0)
|
||||
{
|
||||
frame = (UINT8)(lumpinfo[l].name[4] - 'A');
|
||||
rotation = (UINT8)(lumpinfo[l].name[5] - '0');
|
||||
|
||||
// skip NULL sprites from very old dmadds pwads
|
||||
if (W_LumpLengthPwad(wadnum,l)<=8)
|
||||
continue;
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
R_RemoveSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0);
|
||||
|
||||
if (lumpinfo[l].name[6])
|
||||
{
|
||||
frame = (UINT8)(lumpinfo[l].name[6] - 'A');
|
||||
rotation = (UINT8)(lumpinfo[l].name[7] - '0');
|
||||
R_RemoveSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maxframe == (size_t)-1)
|
||||
return false;
|
||||
|
||||
spritedef->numframes = 0;
|
||||
Z_Free(spritedef->spriteframes);
|
||||
spritedef->spriteframes = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_DelSpriteDefs(UINT16 wadnum)
|
||||
{
|
||||
size_t i, delsprites = 0;
|
||||
UINT16 start, end;
|
||||
|
||||
// find the sprites section in this pwad
|
||||
// we need at least the S_END
|
||||
// (not really, but for speedup)
|
||||
|
||||
start = W_CheckNumForNamePwad("S_START", wadnum, 0);
|
||||
if (start == INT16_MAX)
|
||||
start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib.
|
||||
if (start == INT16_MAX)
|
||||
start = 0; //let say S_START is lump 0
|
||||
else
|
||||
start++; // just after S_START
|
||||
|
||||
end = W_CheckNumForNamePwad("S_END",wadnum,start);
|
||||
if (end == INT16_MAX)
|
||||
end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib.
|
||||
if (end == INT16_MAX)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum);
|
||||
return;
|
||||
//I_Error("R_DelSpriteDefs: S_END, or SS_END missing for sprites "
|
||||
// "in pwad %d\n",wadnum);
|
||||
}
|
||||
|
||||
//
|
||||
// scan through lumps, for each sprite, find all the sprite frames
|
||||
//
|
||||
for (i = 0; i < numsprites; i++)
|
||||
{
|
||||
spritename = sprnames[i];
|
||||
|
||||
if (R_DelSingleSpriteDef(spritename, &sprites[i], wadnum, start, end))
|
||||
{
|
||||
// if a new sprite was removed (not just replaced)
|
||||
delsprites++;
|
||||
CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", spritename, wadnum);
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Printf(M_GetText("%s sprites removed from file %s\n"), sizeu1(delsprites), wadfiles[wadnum]->filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// GAME FUNCTIONS
|
||||
//
|
||||
|
@ -924,7 +815,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
texturecolumn = frac>>FRACBITS;
|
||||
|
||||
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
|
||||
I_Error("R_DrawSpriteRange: bad texturecolumn");
|
||||
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
|
||||
#else
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
|
||||
|
@ -1262,7 +1153,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
offset2 = FixedMul(spritecachedinfo[lump].width, this_scale);
|
||||
tx += FixedMul(offset2, ang_scale);
|
||||
x2 = ((centerxfrac + FixedMul (tx,xscale)) >>FRACBITS) - 1;
|
||||
x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - (papersprite ? 2 : 1);
|
||||
|
||||
// off the left side
|
||||
if (x2 < 0)
|
||||
|
@ -2532,6 +2423,193 @@ skin_t skins[MAXSKINS+1];
|
|||
CV_PossibleValue_t skin_cons_t[MAXSKINS+1];
|
||||
#endif
|
||||
|
||||
//
|
||||
// P_GetSkinSprite2
|
||||
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
|
||||
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
|
||||
//
|
||||
|
||||
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
|
||||
{
|
||||
UINT8 super = (spr2 & FF_SPR2SUPER);
|
||||
|
||||
if (!skin)
|
||||
return 0;
|
||||
|
||||
while (!(skin->sprites[spr2].numframes)
|
||||
&& spr2 != SPR2_STND)
|
||||
{
|
||||
if (spr2 & FF_SPR2SUPER)
|
||||
{
|
||||
spr2 &= ~FF_SPR2SUPER;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(spr2)
|
||||
{
|
||||
case SPR2_RUN:
|
||||
spr2 = SPR2_WALK;
|
||||
break;
|
||||
case SPR2_STUN:
|
||||
spr2 = SPR2_PAIN;
|
||||
break;
|
||||
case SPR2_DRWN:
|
||||
spr2 = SPR2_DEAD;
|
||||
break;
|
||||
case SPR2_SPIN:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_GASP:
|
||||
spr2 = SPR2_SPNG;
|
||||
break;
|
||||
case SPR2_JUMP:
|
||||
spr2 = ((player
|
||||
? player->charflags
|
||||
: skin->flags)
|
||||
& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_SPNG: // spring
|
||||
spr2 = SPR2_FALL;
|
||||
break;
|
||||
case SPR2_FALL:
|
||||
spr2 = SPR2_WALK;
|
||||
break;
|
||||
case SPR2_RIDE:
|
||||
spr2 = SPR2_FALL;
|
||||
break;
|
||||
|
||||
case SPR2_FLY :
|
||||
spr2 = SPR2_SPNG;
|
||||
break;
|
||||
case SPR2_SWIM:
|
||||
spr2 = SPR2_FLY ;
|
||||
break;
|
||||
case SPR2_TIRE:
|
||||
spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
|
||||
break;
|
||||
|
||||
case SPR2_GLID:
|
||||
spr2 = SPR2_FLY;
|
||||
break;
|
||||
case SPR2_CLMB:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_CLNG:
|
||||
spr2 = SPR2_CLMB;
|
||||
break;
|
||||
|
||||
case SPR2_FLT :
|
||||
spr2 = SPR2_WALK;
|
||||
break;
|
||||
case SPR2_FRUN:
|
||||
spr2 = SPR2_RUN ;
|
||||
break;
|
||||
|
||||
case SPR2_DASH:
|
||||
spr2 = SPR2_FRUN;
|
||||
break;
|
||||
|
||||
case SPR2_BNCE:
|
||||
spr2 = SPR2_FALL;
|
||||
break;
|
||||
case SPR2_BLND:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
|
||||
case SPR2_TWIN:
|
||||
spr2 = SPR2_ROLL;
|
||||
break;
|
||||
|
||||
case SPR2_MLEE:
|
||||
spr2 = SPR2_TWIN;
|
||||
break;
|
||||
|
||||
// NiGHTS sprites.
|
||||
case SPR2_NSTD:
|
||||
spr2 = SPR2_STND;
|
||||
super = FF_SPR2SUPER;
|
||||
break;
|
||||
case SPR2_NFLT:
|
||||
spr2 = SPR2_FLT ;
|
||||
super = FF_SPR2SUPER;
|
||||
break;
|
||||
case SPR2_NSTN:
|
||||
spr2 = SPR2_STUN;
|
||||
break;
|
||||
case SPR2_NPUL:
|
||||
spr2 = SPR2_NSTN;
|
||||
break;
|
||||
case SPR2_NATK:
|
||||
spr2 = SPR2_ROLL;
|
||||
super = FF_SPR2SUPER;
|
||||
break;
|
||||
/*case SPR2_NGT0:
|
||||
spr2 = SPR2_NFLT;
|
||||
break;*/
|
||||
case SPR2_NGT1:
|
||||
case SPR2_NGT7:
|
||||
case SPR2_DRL0:
|
||||
spr2 = SPR2_NGT0;
|
||||
break;
|
||||
case SPR2_NGT2:
|
||||
case SPR2_DRL1:
|
||||
spr2 = SPR2_NGT1;
|
||||
break;
|
||||
case SPR2_NGT3:
|
||||
case SPR2_DRL2:
|
||||
spr2 = SPR2_NGT2;
|
||||
break;
|
||||
case SPR2_NGT4:
|
||||
case SPR2_DRL3:
|
||||
spr2 = SPR2_NGT3;
|
||||
break;
|
||||
case SPR2_NGT5:
|
||||
case SPR2_DRL4:
|
||||
spr2 = SPR2_NGT4;
|
||||
break;
|
||||
case SPR2_NGT6:
|
||||
case SPR2_DRL5:
|
||||
spr2 = SPR2_NGT5;
|
||||
break;
|
||||
case SPR2_DRL6:
|
||||
spr2 = SPR2_NGT6;
|
||||
break;
|
||||
case SPR2_NGT8:
|
||||
case SPR2_DRL7:
|
||||
spr2 = SPR2_NGT7;
|
||||
break;
|
||||
case SPR2_NGT9:
|
||||
case SPR2_DRL8:
|
||||
spr2 = SPR2_NGT8;
|
||||
break;
|
||||
case SPR2_NGTA:
|
||||
case SPR2_DRL9:
|
||||
spr2 = SPR2_NGT9;
|
||||
break;
|
||||
case SPR2_NGTB:
|
||||
case SPR2_DRLA:
|
||||
spr2 = SPR2_NGTA;
|
||||
break;
|
||||
case SPR2_NGTC:
|
||||
case SPR2_DRLB:
|
||||
spr2 = SPR2_NGTB;
|
||||
break;
|
||||
case SPR2_DRLC:
|
||||
spr2 = SPR2_NGTC;
|
||||
break;
|
||||
|
||||
// Dunno? Just go to standing then.
|
||||
default:
|
||||
spr2 = SPR2_STND;
|
||||
break;
|
||||
}
|
||||
|
||||
spr2 |= super;
|
||||
}
|
||||
|
||||
return spr2;
|
||||
}
|
||||
|
||||
static void Sk_SetDefaultValue(skin_t *skin)
|
||||
{
|
||||
INT32 i;
|
||||
|
@ -2585,7 +2663,7 @@ static void Sk_SetDefaultValue(skin_t *skin)
|
|||
skin->spinitem = -1;
|
||||
skin->revitem = -1;
|
||||
|
||||
skin->highresscale = FRACUNIT>>1;
|
||||
skin->highresscale = FRACUNIT;
|
||||
|
||||
skin->availability = 0;
|
||||
|
||||
|
@ -2724,16 +2802,17 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
|
||||
if (player->mo)
|
||||
{
|
||||
fixed_t radius = FixedMul(skin->radius, player->mo->scale);
|
||||
if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NGT0].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin.
|
||||
{
|
||||
skin = &skins[DEFAULTNIGHTSSKIN];
|
||||
newcolor = ((skin->flags & SF_SUPER) ? skin->supercolor : skin->prefcolor);
|
||||
newcolor = skin->prefcolor; // will be updated in thinker to flashing
|
||||
}
|
||||
player->mo->skin = skin;
|
||||
if (newcolor)
|
||||
player->mo->color = newcolor;
|
||||
P_SetScale(player->mo, player->mo->scale);
|
||||
player->mo->radius = FixedMul(skin->radius, player->mo->scale);
|
||||
player->mo->radius = radius;
|
||||
|
||||
P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames
|
||||
}
|
||||
|
@ -2778,6 +2857,189 @@ static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
|
|||
#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value)
|
||||
#endif
|
||||
|
||||
// turn _ into spaces and . into katana dot
|
||||
#define SYMBOLCONVERT(name) for (value = name; *value; value++)\
|
||||
{\
|
||||
if (*value == '_') *value = ' ';\
|
||||
else if (*value == '.') *value = '\x1E';\
|
||||
}
|
||||
|
||||
//
|
||||
// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker
|
||||
//
|
||||
|
||||
// Does the same is in w_wad, but check only for
|
||||
// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2..
|
||||
// for wad editors that don't like multiple resources of the same name)
|
||||
//
|
||||
static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
|
||||
{
|
||||
UINT16 i;
|
||||
const char *P_SKIN = "P_SKIN";
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
// scan forward, start at <startlump>
|
||||
if (startlump < wadfiles[wadid]->numlumps)
|
||||
{
|
||||
lump_p = wadfiles[wadid]->lumpinfo + startlump;
|
||||
for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++)
|
||||
if (memcmp(lump_p->name,P_SKIN,6)==0)
|
||||
return i;
|
||||
}
|
||||
return INT16_MAX; // not found
|
||||
}
|
||||
|
||||
static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin)
|
||||
{
|
||||
UINT16 newlastlump;
|
||||
UINT8 sprite2;
|
||||
|
||||
*lump += 1; // start after S_SKIN
|
||||
*lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END
|
||||
|
||||
// old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END.
|
||||
newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump);
|
||||
if (newlastlump < *lastlump) *lastlump = newlastlump;
|
||||
newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump);
|
||||
if (newlastlump < *lastlump) *lastlump = newlastlump;
|
||||
newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump);
|
||||
if (newlastlump < *lastlump) *lastlump = newlastlump;
|
||||
|
||||
// ...and let's handle super, too
|
||||
newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump);
|
||||
if (newlastlump < *lastlump)
|
||||
{
|
||||
newlastlump++;
|
||||
// load all sprite sets we are aware of... for super!
|
||||
for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
|
||||
R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump);
|
||||
|
||||
newlastlump--;
|
||||
*lastlump = newlastlump; // okay, make the normal sprite set loading end there
|
||||
}
|
||||
|
||||
// load all sprite sets we are aware of... for normal stuff.
|
||||
for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
|
||||
R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump);
|
||||
|
||||
}
|
||||
|
||||
// returns whether found appropriate property
|
||||
static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
|
||||
{
|
||||
// custom translation table
|
||||
if (!stricmp(stoken, "startcolor"))
|
||||
skin->starttranscolor = atoi(value);
|
||||
|
||||
#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
|
||||
// character type identification
|
||||
FULLPROCESS(flags)
|
||||
FULLPROCESS(ability)
|
||||
FULLPROCESS(ability2)
|
||||
|
||||
FULLPROCESS(thokitem)
|
||||
FULLPROCESS(spinitem)
|
||||
FULLPROCESS(revitem)
|
||||
#undef FULLPROCESS
|
||||
|
||||
#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<<FRACBITS;
|
||||
GETFRACBITS(normalspeed)
|
||||
GETFRACBITS(runspeed)
|
||||
|
||||
GETFRACBITS(mindash)
|
||||
GETFRACBITS(maxdash)
|
||||
GETFRACBITS(actionspd)
|
||||
|
||||
GETFRACBITS(radius)
|
||||
GETFRACBITS(height)
|
||||
GETFRACBITS(spinheight)
|
||||
#undef GETFRACBITS
|
||||
|
||||
#define GETINT(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value);
|
||||
GETINT(thrustfactor)
|
||||
GETINT(accelstart)
|
||||
GETINT(acceleration)
|
||||
#undef GETINT
|
||||
|
||||
#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value);
|
||||
GETSKINCOLOR(prefcolor)
|
||||
GETSKINCOLOR(prefoppositecolor)
|
||||
#undef GETSKINCOLOR
|
||||
else if (!stricmp(stoken, "supercolor"))
|
||||
skin->supercolor = R_GetSuperColorByName(value);
|
||||
|
||||
#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value));
|
||||
GETFLOAT(jumpfactor)
|
||||
GETFLOAT(highresscale)
|
||||
GETFLOAT(shieldscale)
|
||||
GETFLOAT(camerascale)
|
||||
#undef GETFLOAT
|
||||
|
||||
#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \
|
||||
strupr(value); \
|
||||
if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \
|
||||
skin->flags |= (SF_##field); \
|
||||
else \
|
||||
skin->flags &= ~(SF_##field); \
|
||||
}
|
||||
// parameters for individual character flags
|
||||
// these are uppercase so they can be concatenated with SF_
|
||||
// 1, true, yes are all valid values
|
||||
GETFLAG(SUPER)
|
||||
GETFLAG(NOSUPERSPIN)
|
||||
GETFLAG(NOSPINDASHDUST)
|
||||
GETFLAG(HIRES)
|
||||
GETFLAG(NOSKID)
|
||||
GETFLAG(NOSPEEDADJUST)
|
||||
GETFLAG(RUNONWATER)
|
||||
GETFLAG(NOJUMPSPIN)
|
||||
GETFLAG(NOJUMPDAMAGE)
|
||||
GETFLAG(STOMPDAMAGE)
|
||||
GETFLAG(MARIODAMAGE)
|
||||
GETFLAG(MACHINE)
|
||||
GETFLAG(DASHMODE)
|
||||
GETFLAG(FASTEDGE)
|
||||
GETFLAG(MULTIABILITY)
|
||||
#undef GETFLAG
|
||||
|
||||
else // let's check if it's a sound, otherwise error out
|
||||
{
|
||||
boolean found = false;
|
||||
sfxenum_t i;
|
||||
size_t stokenadjust;
|
||||
|
||||
// Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.)
|
||||
if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS*
|
||||
stokenadjust = 2;
|
||||
else // sfx_*
|
||||
stokenadjust = 4;
|
||||
|
||||
// Remove the prefix. (We can affect this directly since we're not going to use it again.)
|
||||
if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS*
|
||||
value += 2;
|
||||
else // sfx_*
|
||||
value += 4;
|
||||
|
||||
// copy name of sounds that are remapped
|
||||
// for this skin
|
||||
for (i = 0; i < sfx_skinsoundslot0; i++)
|
||||
{
|
||||
if (!S_sfx[i].name)
|
||||
continue;
|
||||
if (S_sfx[i].skinsound != -1
|
||||
&& !stricmp(S_sfx[i].name,
|
||||
stoken + stokenadjust))
|
||||
{
|
||||
skin->soundsid[S_sfx[i].skinsound] =
|
||||
S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Find skin sprites, sounds & optional status bar face, & add them
|
||||
//
|
||||
|
@ -2837,6 +3099,8 @@ void R_AddSkins(UINT16 wadnum)
|
|||
if (!value)
|
||||
I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
|
||||
|
||||
// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines.
|
||||
// Others can't go in there because we don't want them to be patchable.
|
||||
if (!stricmp(stoken, "name"))
|
||||
{
|
||||
INT32 skinnum = R_SkinAvailable(value);
|
||||
|
@ -2875,22 +3139,14 @@ void R_AddSkins(UINT16 wadnum)
|
|||
{
|
||||
HUDNAMEWRITE(skin->name);
|
||||
strupr(skin->hudname);
|
||||
for (value = skin->hudname; *value; value++)
|
||||
{
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
else if (*value == '.') *value = '\x1E'; // turn . into katana dot.
|
||||
}
|
||||
SYMBOLCONVERT(skin->hudname)
|
||||
}
|
||||
}
|
||||
else if (!stricmp(stoken, "realname"))
|
||||
{ // Display name (eg. "Knuckles")
|
||||
realname = true;
|
||||
STRBUFCPY(skin->realname, value);
|
||||
for (value = skin->realname; *value; value++)
|
||||
{
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
else if (*value == '.') *value = '\x1E'; // turn . into katana dot.
|
||||
}
|
||||
SYMBOLCONVERT(skin->realname)
|
||||
if (!hudname)
|
||||
HUDNAMEWRITE(skin->realname);
|
||||
}
|
||||
|
@ -2898,15 +3154,10 @@ void R_AddSkins(UINT16 wadnum)
|
|||
{ // Life icon name (eg. "K.T.E")
|
||||
hudname = true;
|
||||
HUDNAMEWRITE(value);
|
||||
for (value = skin->hudname; *value; value++)
|
||||
{
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
else if (*value == '.') *value = '\x1E'; // turn . into katana dot.
|
||||
}
|
||||
SYMBOLCONVERT(skin->hudname)
|
||||
if (!realname)
|
||||
STRBUFCPY(skin->realname, skin->hudname);
|
||||
}
|
||||
|
||||
else if (!stricmp(stoken, "charsel"))
|
||||
{
|
||||
strupr(value);
|
||||
|
@ -2925,37 +3176,6 @@ void R_AddSkins(UINT16 wadnum)
|
|||
strupr(value);
|
||||
strncpy(skin->superface, value, sizeof skin->superface);
|
||||
}
|
||||
|
||||
#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
|
||||
// character type identification
|
||||
FULLPROCESS(flags)
|
||||
FULLPROCESS(ability)
|
||||
FULLPROCESS(ability2)
|
||||
|
||||
FULLPROCESS(thokitem)
|
||||
FULLPROCESS(spinitem)
|
||||
FULLPROCESS(revitem)
|
||||
#undef FULLPROCESS
|
||||
|
||||
#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<<FRACBITS;
|
||||
GETFRACBITS(normalspeed)
|
||||
GETFRACBITS(runspeed)
|
||||
|
||||
GETFRACBITS(mindash)
|
||||
GETFRACBITS(maxdash)
|
||||
GETFRACBITS(actionspd)
|
||||
|
||||
GETFRACBITS(radius)
|
||||
GETFRACBITS(height)
|
||||
GETFRACBITS(spinheight)
|
||||
#undef GETFRACBITS
|
||||
|
||||
#define GETINT(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value);
|
||||
GETINT(thrustfactor)
|
||||
GETINT(accelstart)
|
||||
GETINT(acceleration)
|
||||
#undef GETINT
|
||||
|
||||
else if (!stricmp(stoken, "availability"))
|
||||
{
|
||||
skin->availability = atoi(value);
|
||||
|
@ -2964,125 +3184,16 @@ void R_AddSkins(UINT16 wadnum)
|
|||
if (skin->availability)
|
||||
STRBUFCPY(unlockables[skin->availability - 1].name, skin->realname);
|
||||
}
|
||||
else if (!R_ProcessPatchableFields(skin, stoken, value))
|
||||
CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
|
||||
|
||||
// custom translation table
|
||||
else if (!stricmp(stoken, "startcolor"))
|
||||
skin->starttranscolor = atoi(value);
|
||||
|
||||
#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value);
|
||||
GETSKINCOLOR(prefcolor)
|
||||
GETSKINCOLOR(prefoppositecolor)
|
||||
#undef GETSKINCOLOR
|
||||
else if (!stricmp(stoken, "supercolor"))
|
||||
skin->supercolor = R_GetSuperColorByName(value);
|
||||
|
||||
#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value));
|
||||
GETFLOAT(jumpfactor)
|
||||
GETFLOAT(highresscale)
|
||||
GETFLOAT(shieldscale)
|
||||
GETFLOAT(camerascale)
|
||||
#undef GETFLOAT
|
||||
|
||||
#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \
|
||||
strupr(value); \
|
||||
if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \
|
||||
skin->flags |= (SF_##field); \
|
||||
else \
|
||||
skin->flags &= ~(SF_##field); \
|
||||
}
|
||||
// parameters for individual character flags
|
||||
// these are uppercase so they can be concatenated with SF_
|
||||
// 1, true, yes are all valid values
|
||||
GETFLAG(SUPER)
|
||||
GETFLAG(NOSUPERSPIN)
|
||||
GETFLAG(NOSPINDASHDUST)
|
||||
GETFLAG(HIRES)
|
||||
GETFLAG(NOSKID)
|
||||
GETFLAG(NOSPEEDADJUST)
|
||||
GETFLAG(RUNONWATER)
|
||||
GETFLAG(NOJUMPSPIN)
|
||||
GETFLAG(NOJUMPDAMAGE)
|
||||
GETFLAG(STOMPDAMAGE)
|
||||
GETFLAG(MARIODAMAGE)
|
||||
GETFLAG(MACHINE)
|
||||
GETFLAG(DASHMODE)
|
||||
GETFLAG(FASTEDGE)
|
||||
GETFLAG(MULTIABILITY)
|
||||
#undef GETFLAG
|
||||
|
||||
else // let's check if it's a sound, otherwise error out
|
||||
{
|
||||
boolean found = false;
|
||||
sfxenum_t i;
|
||||
size_t stokenadjust;
|
||||
|
||||
// Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.)
|
||||
if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS*
|
||||
stokenadjust = 2;
|
||||
else // sfx_*
|
||||
stokenadjust = 4;
|
||||
|
||||
// Remove the prefix. (We can affect this directly since we're not going to use it again.)
|
||||
if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS*
|
||||
value += 2;
|
||||
else // sfx_*
|
||||
value += 4;
|
||||
|
||||
// copy name of sounds that are remapped
|
||||
// for this skin
|
||||
for (i = 0; i < sfx_skinsoundslot0; i++)
|
||||
{
|
||||
if (!S_sfx[i].name)
|
||||
continue;
|
||||
if (S_sfx[i].skinsound != -1
|
||||
&& !stricmp(S_sfx[i].name,
|
||||
stoken + stokenadjust))
|
||||
{
|
||||
skin->soundsid[S_sfx[i].skinsound] =
|
||||
S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
|
||||
}
|
||||
next_token:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
}
|
||||
free(buf2);
|
||||
|
||||
// Add sprites
|
||||
{
|
||||
UINT16 newlastlump;
|
||||
UINT8 sprite2;
|
||||
|
||||
lump++; // start after S_SKIN
|
||||
lastlump = W_CheckNumForNamePwad("S_END",wadnum,lump); // stop at S_END
|
||||
|
||||
// old wadding practices die hard -- stop at S_SKIN or S_START if they come before S_END.
|
||||
newlastlump = W_CheckNumForNamePwad("S_SKIN",wadnum,lump);
|
||||
if (newlastlump < lastlump) lastlump = newlastlump;
|
||||
newlastlump = W_CheckNumForNamePwad("S_START",wadnum,lump);
|
||||
if (newlastlump < lastlump) lastlump = newlastlump;
|
||||
|
||||
// ...and let's handle super, too
|
||||
newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,lump);
|
||||
if (newlastlump < lastlump)
|
||||
{
|
||||
newlastlump++;
|
||||
// load all sprite sets we are aware of... for super!
|
||||
for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
|
||||
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, lastlump);
|
||||
|
||||
newlastlump--;
|
||||
lastlump = newlastlump; // okay, make the normal sprite set loading end there
|
||||
}
|
||||
|
||||
// load all sprite sets we are aware of... for normal stuff.
|
||||
for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
|
||||
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, lump, lastlump);
|
||||
|
||||
}
|
||||
R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
|
||||
|
||||
R_FlushTranslationColormapCache();
|
||||
|
||||
|
@ -3106,50 +3217,124 @@ next_token:
|
|||
return;
|
||||
}
|
||||
|
||||
#undef HUDNAMEWRITE
|
||||
|
||||
#ifdef DELFILE
|
||||
void R_DelSkins(UINT16 wadnum)
|
||||
//
|
||||
// Patch skin sprites
|
||||
//
|
||||
void R_PatchSkins(UINT16 wadnum)
|
||||
{
|
||||
UINT16 lump, lastlump = 0;
|
||||
while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
|
||||
char *buf;
|
||||
char *buf2;
|
||||
char *stoken;
|
||||
char *value;
|
||||
size_t size;
|
||||
skin_t *skin;
|
||||
boolean noskincomplain, realname, hudname;
|
||||
|
||||
//
|
||||
// search for all skin patch markers in pwad
|
||||
//
|
||||
|
||||
while ((lump = W_CheckForPatchSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
|
||||
{
|
||||
if (skins[numskins].wadnum != wadnum)
|
||||
break;
|
||||
numskins--;
|
||||
ST_UnLoadFaceGraphics(numskins); // only used by DELFILE
|
||||
if (skins[numskins].sprite[0] != '\0')
|
||||
{
|
||||
const char *csprname = W_CheckNameForNumPwad(wadnum, lump);
|
||||
INT32 skinnum = 0;
|
||||
|
||||
// skip to end of this skin's frames
|
||||
lastlump = lump;
|
||||
while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0)
|
||||
lastlump++;
|
||||
// allocate (or replace) sprite frames, and set spritedef
|
||||
R_DelSingleSpriteDef(csprname, &skins[numskins].spritedef, wadnum, lump, lastlump);
|
||||
}
|
||||
else
|
||||
// advance by default
|
||||
lastlump = lump + 1;
|
||||
|
||||
buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
||||
size = W_LumpLengthPwad(wadnum, lump);
|
||||
|
||||
// for strtok
|
||||
buf2 = malloc(size+1);
|
||||
if (!buf2)
|
||||
I_Error("R_PatchSkins: No more free memory\n");
|
||||
M_Memcpy(buf2,buf,size);
|
||||
buf2[size] = '\0';
|
||||
|
||||
skin = NULL;
|
||||
noskincomplain = realname = hudname = false;
|
||||
|
||||
/*
|
||||
Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation)
|
||||
*/
|
||||
|
||||
stoken = strtok(buf2, "\r\n= ");
|
||||
while (stoken)
|
||||
{
|
||||
// search in the normal sprite tables
|
||||
size_t name;
|
||||
boolean found = false;
|
||||
const char *sprname = skins[numskins].sprite;
|
||||
for (name = 0;sprnames[name][0] != '\0';name++)
|
||||
if (strcmp(sprnames[name], sprname) == 0)
|
||||
if ((stoken[0] == '/' && stoken[1] == '/')
|
||||
|| (stoken[0] == '#'))// skip comments
|
||||
{
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto next_token; // find the real next token
|
||||
}
|
||||
|
||||
value = strtok(NULL, "\r\n= ");
|
||||
|
||||
if (!value)
|
||||
I_Error("R_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
|
||||
|
||||
if (!skin) // Get the name!
|
||||
{
|
||||
if (!stricmp(stoken, "name"))
|
||||
{
|
||||
found = true;
|
||||
skins[numskins].spritedef = sprites[name];
|
||||
strlwr(value);
|
||||
skinnum = R_SkinAvailable(value);
|
||||
if (skinnum != -1)
|
||||
skin = &skins[skinnum];
|
||||
else
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
|
||||
noskincomplain = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Get the properties!
|
||||
{
|
||||
// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines.
|
||||
if (!stricmp(stoken, "realname"))
|
||||
{ // Display name (eg. "Knuckles")
|
||||
realname = true;
|
||||
STRBUFCPY(skin->realname, value);
|
||||
SYMBOLCONVERT(skin->realname)
|
||||
if (!hudname)
|
||||
HUDNAMEWRITE(skin->realname);
|
||||
}
|
||||
else if (!stricmp(stoken, "hudname"))
|
||||
{ // Life icon name (eg. "K.T.E")
|
||||
hudname = true;
|
||||
HUDNAMEWRITE(value);
|
||||
SYMBOLCONVERT(skin->hudname)
|
||||
if (!realname)
|
||||
STRBUFCPY(skin->realname, skin->hudname);
|
||||
}
|
||||
else if (!R_ProcessPatchableFields(skin, stoken, value))
|
||||
CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
|
||||
}
|
||||
|
||||
// not found so make a new one
|
||||
if (!found)
|
||||
R_DelSingleSpriteDef(sprname, &skins[numskins].spritedef, wadnum, 0, INT16_MAX);
|
||||
if (!skin)
|
||||
break;
|
||||
|
||||
while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),sprname,4)==0)
|
||||
lastlump++;
|
||||
next_token:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
}
|
||||
CONS_Printf(M_GetText("Removed skin '%s'\n"), skins[numskins].name);
|
||||
free(buf2);
|
||||
|
||||
if (!skin) // Didn't include a name parameter? What a waste.
|
||||
{
|
||||
if (!noskincomplain)
|
||||
CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Patch sprites
|
||||
R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
|
||||
|
||||
if (!skin->availability) // Safe to print...
|
||||
CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef HUDNAMEWRITE
|
||||
#undef SYMBOLCONVERT
|
||||
|
|
|
@ -51,10 +51,6 @@ void R_SortVisSprites(void);
|
|||
// (only sprites from namelist are added or replaced)
|
||||
void R_AddSpriteDefs(UINT16 wadnum);
|
||||
|
||||
#ifdef DELFILE
|
||||
void R_DelSpriteDefs(UINT16 wadnum);
|
||||
#endif
|
||||
|
||||
//SoM: 6/5/2000: Light sprites correctly!
|
||||
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
||||
void R_InitSprites(void);
|
||||
|
@ -216,11 +212,10 @@ void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
|
|||
boolean R_SkinUsable(INT32 playernum, INT32 skinnum);
|
||||
UINT32 R_GetSkinAvailabilities(void);
|
||||
INT32 R_SkinAvailable(const char *name);
|
||||
void R_PatchSkins(UINT16 wadnum);
|
||||
void R_AddSkins(UINT16 wadnum);
|
||||
|
||||
#ifdef DELFILE
|
||||
void R_DelSkins(UINT16 wadnum);
|
||||
#endif
|
||||
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);
|
||||
|
||||
void R_InitDrawNodes(void);
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"gravch", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Recycler"},
|
||||
{"itemup", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"},
|
||||
{"jet", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jet engine"},
|
||||
{"jshard", true, 167, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got shard"},
|
||||
{"jshard", true, 167, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Life transfer"}, // placeholder repurpose; original string was "Got Shard"
|
||||
{"lose" , false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Failure"},
|
||||
{"lvpass", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning signpost"},
|
||||
{"mindig", false, 8, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Tunnelling"},
|
||||
|
@ -346,7 +346,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3k78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"},
|
||||
{"s3k79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric charge"},
|
||||
{"s3k7a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising from lava"},
|
||||
{"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Organic bounce"},
|
||||
{"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Soft bounce"},
|
||||
{"s3k7c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"},
|
||||
{"s3k7d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Eating dirt"},
|
||||
|
|
261
src/st_stuff.c
261
src/st_stuff.c
|
@ -68,6 +68,7 @@ static patch_t *sboover;
|
|||
static patch_t *timeover;
|
||||
static patch_t *stlivex;
|
||||
static patch_t *sboredrings;
|
||||
static patch_t *sboredtime;
|
||||
static patch_t *getall; // Special Stage HUD
|
||||
static patch_t *timeup; // Special Stage HUD
|
||||
static patch_t *hunthoming[6];
|
||||
|
@ -251,6 +252,7 @@ void ST_LoadGraphics(void)
|
|||
sboredrings = W_CachePatchName("STTRRING", PU_HUDGFX);
|
||||
sboscore = W_CachePatchName("STTSCORE", PU_HUDGFX);
|
||||
sbotime = W_CachePatchName("STTTIME", PU_HUDGFX); // Time logo
|
||||
sboredtime = W_CachePatchName("STTRTIME", PU_HUDGFX);
|
||||
sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time
|
||||
sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds
|
||||
|
||||
|
@ -344,15 +346,6 @@ void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 skinnum)
|
|||
facefreed[skinnum] = false;
|
||||
}
|
||||
|
||||
#ifdef DELFILE
|
||||
void ST_UnLoadFaceGraphics(INT32 skinnum)
|
||||
{
|
||||
Z_Free(faceprefix[skinnum]);
|
||||
Z_Free(superprefix[skinnum]);
|
||||
facefreed[skinnum] = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ST_ReloadSkinFaceGraphics(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
@ -501,12 +494,12 @@ static INT32 SCR(INT32 r)
|
|||
#define ST_DrawPaddedOverlayNum(x,y,n,d) V_DrawPaddedTallNum(x, y, V_NOSCALESTART|V_HUDTRANS, n, d)
|
||||
#define ST_DrawOverlayPatch(x,y,p) V_DrawScaledPatch(x, y, V_NOSCALESTART|V_HUDTRANS, p)
|
||||
#define ST_DrawMappedOverlayPatch(x,y,p,c) V_DrawMappedScaledPatch(x, y, V_NOSCALESTART|V_HUDTRANS, p, c)
|
||||
#define ST_DrawNumFromHud(h,n) V_DrawTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|V_HUDTRANS, n)
|
||||
#define ST_DrawPadNumFromHud(h,n,q) V_DrawPaddedTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|V_HUDTRANS, n, q)
|
||||
#define ST_DrawPatchFromHud(h,p) V_DrawScaledPatch(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|V_HUDTRANS, p)
|
||||
#define ST_DrawNumFromHudWS(h,n) V_DrawTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|V_HUDTRANS, n)
|
||||
#define ST_DrawPadNumFromHudWS(h,n,q) V_DrawPaddedTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|V_HUDTRANS, n, q)
|
||||
#define ST_DrawPatchFromHudWS(h,p) V_DrawScaledPatch(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|V_HUDTRANS, p)
|
||||
#define ST_DrawNumFromHud(h,n,f) V_DrawTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|f, n)
|
||||
#define ST_DrawPadNumFromHud(h,n,q,f) V_DrawPaddedTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|f, n, q)
|
||||
#define ST_DrawPatchFromHud(h,p,f) V_DrawScaledPatch(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|f, p)
|
||||
#define ST_DrawNumFromHudWS(h,n,f) V_DrawTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|f, n)
|
||||
#define ST_DrawPadNumFromHudWS(h,n,q,f) V_DrawPaddedTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|f, n, q)
|
||||
#define ST_DrawPatchFromHudWS(h,p,f) V_DrawScaledPatch(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|f, p)
|
||||
|
||||
// Draw a number, scaled, over the view, maybe with set translucency
|
||||
// Always draw the number completely since it's overlay
|
||||
|
@ -618,16 +611,16 @@ static void ST_drawDebugInfo(void)
|
|||
static void ST_drawScore(void)
|
||||
{
|
||||
// SCORE:
|
||||
ST_DrawPatchFromHud(HUD_SCORE, sboscore);
|
||||
ST_DrawPatchFromHud(HUD_SCORE, sboscore, V_HUDTRANS);
|
||||
if (objectplacing)
|
||||
{
|
||||
if (op_displayflags > UINT16_MAX)
|
||||
ST_DrawOverlayPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), tallminus);
|
||||
else
|
||||
ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags);
|
||||
ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags, V_HUDTRANS);
|
||||
}
|
||||
else
|
||||
ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score);
|
||||
ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score,V_HUDTRANS);
|
||||
}
|
||||
|
||||
static void ST_drawTime(void)
|
||||
|
@ -635,7 +628,7 @@ static void ST_drawTime(void)
|
|||
INT32 seconds, minutes, tictrn, tics;
|
||||
|
||||
// TIME:
|
||||
ST_DrawPatchFromHudWS(HUD_TIME, sbotime);
|
||||
ST_DrawPatchFromHudWS(HUD_TIME, ((mapheaderinfo[gamemap-1]->countdown && countdowntimer < 11*TICRATE && leveltime/5 & 1) ? sboredtime : sbotime), V_HUDTRANS);
|
||||
|
||||
if (objectplacing)
|
||||
{
|
||||
|
@ -646,24 +639,24 @@ static void ST_drawTime(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
tics = stplyr->realtime;
|
||||
tics = (mapheaderinfo[gamemap-1]->countdown ? countdowntimer : stplyr->realtime);
|
||||
seconds = G_TicsToSeconds(tics);
|
||||
minutes = G_TicsToMinutes(tics, true);
|
||||
tictrn = G_TicsToCentiseconds(tics);
|
||||
}
|
||||
|
||||
if (cv_timetic.value == 1) // Tics only -- how simple is this?
|
||||
ST_DrawNumFromHudWS(HUD_SECONDS, tics);
|
||||
ST_DrawNumFromHudWS(HUD_SECONDS, tics, V_HUDTRANS);
|
||||
else
|
||||
{
|
||||
ST_DrawNumFromHudWS(HUD_MINUTES, minutes); // Minutes
|
||||
ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon); // Colon
|
||||
ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2); // Seconds
|
||||
ST_DrawNumFromHudWS(HUD_MINUTES, minutes, V_HUDTRANS); // Minutes
|
||||
ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon, V_HUDTRANS); // Colon
|
||||
ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2, V_HUDTRANS); // Seconds
|
||||
|
||||
if (!splitscreen && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying!
|
||||
{
|
||||
ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period
|
||||
ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics
|
||||
ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod, V_HUDTRANS); // Period
|
||||
ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2, V_HUDTRANS); // Tics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -672,7 +665,7 @@ static inline void ST_drawRings(void)
|
|||
{
|
||||
INT32 ringnum = max(stplyr->rings, 0);
|
||||
|
||||
ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings));
|
||||
ST_DrawPatchFromHudWS(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
|
||||
|
||||
if (objectplacing)
|
||||
ringnum = op_currentdoomednum;
|
||||
|
@ -685,7 +678,7 @@ static inline void ST_drawRings(void)
|
|||
ringnum += players[i].rings;
|
||||
}
|
||||
|
||||
ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum);
|
||||
ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum, ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
|
||||
}
|
||||
|
||||
static void ST_drawLives(void)
|
||||
|
@ -728,9 +721,68 @@ static void ST_drawLives(void)
|
|||
// x
|
||||
V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0),
|
||||
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, stlivex);
|
||||
// lives
|
||||
|
||||
// lives number
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP)
|
||||
{
|
||||
switch (cv_cooplives.value)
|
||||
{
|
||||
case 0:
|
||||
V_DrawCharacter(hudinfo[HUD_LIVESNUM].x - 8, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), '\x16' | 0x80 | V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, false);
|
||||
return;
|
||||
case 3:
|
||||
{
|
||||
INT32 i, sum = 0;
|
||||
boolean canrespawn = (stplyr->lives > 0);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives < 1)
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 1)
|
||||
canrespawn = true;
|
||||
|
||||
sum += (players[i].lives);
|
||||
}
|
||||
V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0),
|
||||
V_SNAPTOLEFT|V_SNAPTOBOTTOM|(canrespawn ? V_HUDTRANS : V_HUDTRANSHALF)|v_splitflag,
|
||||
va("%d",sum));
|
||||
return;
|
||||
}
|
||||
#if 0 // render the number of lives you COULD steal
|
||||
case 2:
|
||||
{
|
||||
INT32 i, sum = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (&players[i] == stplyr)
|
||||
continue;
|
||||
|
||||
if (players[i].lives < 2)
|
||||
continue;
|
||||
|
||||
sum += (players[i].lives - 1);
|
||||
}
|
||||
V_DrawString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0),
|
||||
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANSHALF|v_splitflag, va("/%d",sum));
|
||||
}
|
||||
// intentional fallthrough
|
||||
#endif
|
||||
default:
|
||||
// don't return so the SP one can be drawn below
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0),
|
||||
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, va("%d",stplyr->lives));
|
||||
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,
|
||||
va("%d",stplyr->lives));
|
||||
}
|
||||
|
||||
static void ST_drawLevelTitle(void)
|
||||
|
@ -908,15 +960,25 @@ static void ST_drawFirstPersonHUD(void)
|
|||
/*#define NUMLINKCOLORS 14
|
||||
static skincolors_t linkColor[NUMLINKCOLORS] =
|
||||
{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_AZURE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE,
|
||||
SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED,
|
||||
SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/
|
||||
SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED,
|
||||
SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/
|
||||
|
||||
// 2.2+: (unix time 1470866042) <Rob> Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot
|
||||
#define NUMLINKCOLORS 13
|
||||
// 2.2 indev list: (unix time 1470866042) <Rob> Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot
|
||||
/*#define NUMLINKCOLORS 13
|
||||
static skincolors_t linkColor[NUMLINKCOLORS] =
|
||||
{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL,
|
||||
SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE,
|
||||
SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT};
|
||||
{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL,
|
||||
SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE,
|
||||
SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT};*/
|
||||
|
||||
// 2.2+ list: [19:59:52] <baldobo> Ruby > Red > Flame > Sunset > Orange > Gold > Yellow > Lime > Green > Aqua > cyan > Sky > Blue > Pastel > Purple > Bubblegum > Magenta > Rosy > repeat
|
||||
// [20:00:25] <baldobo> Also Icy for the link freeze text color
|
||||
// [20:04:03] <baldobo> I would start it on lime
|
||||
#define NUMLINKCOLORS 18
|
||||
static skincolors_t linkColor[NUMLINKCOLORS] =
|
||||
{SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_SKY,
|
||||
SKINCOLOR_SAPPHIRE, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA,
|
||||
SKINCOLOR_ROSY, SKINCOLOR_RUBY, SKINCOLOR_RED, SKINCOLOR_FLAME, SKINCOLOR_SUNSET,
|
||||
SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW};
|
||||
|
||||
static void ST_drawNightsRecords(void)
|
||||
{
|
||||
|
@ -1017,8 +1079,8 @@ static void ST_drawNiGHTSHUD(void)
|
|||
stplyr->linkcount > minlink)
|
||||
{
|
||||
skincolors_t colornum = linkColor[((stplyr->linkcount-1) / 5) % NUMLINKCOLORS];
|
||||
if (stplyr->powers[pw_nights_linkfreeze])
|
||||
colornum = SKINCOLOR_WHITE;
|
||||
if (stplyr->powers[pw_nights_linkfreeze] && (!(stplyr->powers[pw_nights_linkfreeze] & 2) || (stplyr->powers[pw_nights_linkfreeze] > flashingtics)))
|
||||
colornum = SKINCOLOR_ICY;
|
||||
|
||||
if (stplyr->linktimer < 2*TICRATE/3)
|
||||
{
|
||||
|
@ -1297,7 +1359,7 @@ static void ST_drawNiGHTSHUD(void)
|
|||
realnightstime = lowest_time/TICRATE;
|
||||
}
|
||||
|
||||
if (stplyr->powers[pw_flashing] > TICRATE ) // was hit
|
||||
if (stplyr->powers[pw_flashing] > TICRATE) // was hit
|
||||
{
|
||||
UINT16 flashingLeft = stplyr->powers[pw_flashing]-(TICRATE);
|
||||
if (flashingLeft < TICRATE/2) // Start fading out
|
||||
|
@ -1639,21 +1701,21 @@ static inline void ST_drawTeamName(void)
|
|||
static void ST_drawSpecialStageHUD(void)
|
||||
{
|
||||
if (totalrings > 0)
|
||||
ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings);
|
||||
ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings, V_HUDTRANS);
|
||||
|
||||
if (leveltime < 5*TICRATE && totalrings > 0)
|
||||
{
|
||||
ST_DrawPatchFromHud(HUD_GETRINGS, getall);
|
||||
ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings);
|
||||
ST_DrawPatchFromHud(HUD_GETRINGS, getall, V_HUDTRANS);
|
||||
ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings, V_HUDTRANS);
|
||||
}
|
||||
|
||||
if (sstimer)
|
||||
{
|
||||
V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), V_HUDTRANS, M_GetText("TIME LEFT"));
|
||||
ST_DrawNumFromHud(HUD_TIMELEFTNUM, sstimer/TICRATE);
|
||||
ST_DrawNumFromHud(HUD_TIMELEFTNUM, sstimer/TICRATE, V_HUDTRANS);
|
||||
}
|
||||
else
|
||||
ST_DrawPatchFromHud(HUD_TIMEUP, timeup);
|
||||
ST_DrawPatchFromHud(HUD_TIMEUP, timeup, V_HUDTRANS);
|
||||
}
|
||||
|
||||
static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset)
|
||||
|
@ -1816,7 +1878,11 @@ static void ST_overlayDrawer(void)
|
|||
}
|
||||
|
||||
// GAME OVER pic
|
||||
if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer)))
|
||||
if ((gametype == GT_COOP)
|
||||
&& (netgame || multiplayer)
|
||||
&& (cv_cooplives.value == 0))
|
||||
;
|
||||
else if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer)))
|
||||
{
|
||||
patch_t *p;
|
||||
|
||||
|
@ -1825,7 +1891,29 @@ static void ST_overlayDrawer(void)
|
|||
else
|
||||
p = sboover;
|
||||
|
||||
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, STRINGY(BASEVIDHEIGHT/2 - (SHORT(p->height)/2)), 0, p);
|
||||
if ((gametype == GT_COOP)
|
||||
&& (netgame || multiplayer)
|
||||
&& (cv_cooplives.value != 1))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (&players[i] == stplyr)
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 0)
|
||||
{
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p)
|
||||
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, STRINGY(BASEVIDHEIGHT/2 - (SHORT(p->height)/2)) - (splitscreen ? 4 : 0), (stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS), p);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1910,15 +1998,49 @@ static void ST_overlayDrawer(void)
|
|||
)
|
||||
ST_drawLevelTitle();
|
||||
|
||||
if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer)
|
||||
if (!hu_showscores && (netgame || multiplayer) && displayplayer == consoleplayer)
|
||||
{
|
||||
if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player."));
|
||||
if (!stplyr->spectator && stplyr->exiting && cv_playersforexit.value && gametype == GT_COOP)
|
||||
{
|
||||
INT32 i, total = 0, exiting = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
if (players[i].lives <= 0)
|
||||
continue;
|
||||
|
||||
total++;
|
||||
if (players[i].exiting)
|
||||
exiting++;
|
||||
}
|
||||
|
||||
if (cv_playersforexit.value != 4)
|
||||
{
|
||||
total *= cv_playersforexit.value;
|
||||
if (total % 4) total += 4; // round up
|
||||
total /= 4;
|
||||
}
|
||||
|
||||
if (exiting >= total)
|
||||
;
|
||||
else
|
||||
{
|
||||
total -= exiting;
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(124), 0, va(M_GetText("%d more player%s required to exit."), total, ((total == 1) ? "" : "s")));
|
||||
if (!splitscreen)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 132, 0, M_GetText("Press F12 to watch another player."));
|
||||
}
|
||||
}
|
||||
else if (!splitscreen && gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1)))
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 132, 0, M_GetText("Press F12 to watch another player."));
|
||||
else if (gametype == GT_HIDEANDSEEK &&
|
||||
(!stplyr->spectator && !(stplyr->pflags & PF_TAGIT)) && (leveltime > hidetime * TICRATE))
|
||||
{
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(116), 0, M_GetText("You cannot move while hiding."));
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player."));
|
||||
if (!splitscreen)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 132, 0, M_GetText("Press F12 to watch another player."));
|
||||
}
|
||||
else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text.
|
||||
{
|
||||
|
@ -1928,7 +2050,7 @@ static void ST_overlayDrawer(void)
|
|||
else
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn."));
|
||||
}
|
||||
else if (stplyr->spectator
|
||||
else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)
|
||||
#ifdef HAVE_BLUA
|
||||
&& LUA_HudEnabled(hud_textspectator)
|
||||
#endif
|
||||
|
@ -1938,11 +2060,38 @@ static void ST_overlayDrawer(void)
|
|||
if (G_GametypeHasTeams())
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to be assigned to a team."));
|
||||
else if (G_IsSpecialStage(gamemap) && useNightsSS)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("You cannot join the game until the stage has ended."));
|
||||
else
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("You cannot play until the stage has ended."));
|
||||
else if (gametype == GT_COOP && stplyr->lives <= 0)
|
||||
{
|
||||
if (cv_cooplives.value == 1
|
||||
&& (netgame || multiplayer))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (&players[i] == stplyr)
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != MAXPLAYERS)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132)-(splitscreen ? 12 : 0), V_HUDTRANSHALF, M_GetText("You'll steal a life on respawn."));
|
||||
}
|
||||
}
|
||||
else if (!gametype == GT_COOP)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to enter the game."));
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_HUDTRANSHALF, M_GetText("Press F12 to watch another player."));
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink."));
|
||||
if (!splitscreen)
|
||||
{
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 148, V_HUDTRANSHALF, M_GetText("Press F12 to watch another player."));
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 164, V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink."));
|
||||
}
|
||||
else
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(136), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,6 @@ void ST_LoadGraphics(void);
|
|||
// face load graphics, called when skin changes
|
||||
void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 playernum);
|
||||
void ST_ReloadSkinFaceGraphics(void);
|
||||
#ifdef DELFILE
|
||||
void ST_UnLoadFaceGraphics(INT32 skinnum);
|
||||
#endif
|
||||
|
||||
void ST_doPaletteStuff(void);
|
||||
|
||||
|
|
|
@ -865,11 +865,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
//
|
||||
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor)
|
||||
{
|
||||
if (skins[skinnum].flags & SF_HIRES
|
||||
#ifdef HWRENDER
|
||||
// || (rendermode != render_soft && rendermode != render_none)
|
||||
#endif
|
||||
)
|
||||
if (skins[skinnum].flags & SF_HIRES)
|
||||
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE));
|
||||
else
|
||||
{
|
||||
|
|
32
src/w_wad.c
32
src/w_wad.c
|
@ -505,38 +505,6 @@ UINT16 W_LoadWadFile(const char *filename)
|
|||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
#ifdef DELFILE
|
||||
void W_UnloadWadFile(UINT16 num)
|
||||
{
|
||||
INT32 i;
|
||||
wadfile_t *delwad = wadfiles[num];
|
||||
lumpcache_t *lumpcache;
|
||||
if (num == 0)
|
||||
return;
|
||||
CONS_Printf(M_GetText("Removing WAD %s...\n"), wadfiles[num]->filename);
|
||||
|
||||
DEH_UnloadDehackedWad(num);
|
||||
wadfiles[num] = NULL;
|
||||
lumpcache = delwad->lumpcache;
|
||||
numwadfiles--;
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
HWR_FreeTextureCache();
|
||||
M_AATreeFree(delwad->hwrcache);
|
||||
#endif
|
||||
if (*lumpcache)
|
||||
{
|
||||
for (i = 0;i < delwad->numlumps;i++)
|
||||
Z_ChangeTag(lumpcache[i], PU_PURGELEVEL);
|
||||
}
|
||||
Z_Free(lumpcache);
|
||||
fclose(delwad->handle);
|
||||
Z_Free(delwad->filename);
|
||||
Z_Free(delwad);
|
||||
CONS_Printf(M_GetText("Done unloading WAD.\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Tries to load a series of files.
|
||||
* All files are wads unless they have an extension of ".soc" or ".lua".
|
||||
*
|
||||
|
|
|
@ -87,9 +87,6 @@ void W_Shutdown(void);
|
|||
FILE *W_OpenWadFile(const char **filename, boolean useerrors);
|
||||
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
|
||||
UINT16 W_LoadWadFile(const char *filename);
|
||||
#ifdef DELFILE
|
||||
void W_UnloadWadFile(UINT16 num);
|
||||
#endif
|
||||
|
||||
// W_InitMultipleFiles returns 1 if all is okay, 0 otherwise,
|
||||
// so that it stops with a message if a file was not found, but not if all is okay.
|
||||
|
|
Loading…
Reference in a new issue