diff --git a/SRB2.cbp b/SRB2.cbp
index 88dc400fe..2a1eb87b8 100644
--- a/SRB2.cbp
+++ b/SRB2.cbp
@@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index da8438a59..6a8b7e3f1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -351,6 +351,7 @@ if(${SRB2_CONFIG_HWRENDER})
set(SRB2_HWRENDER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
@@ -359,6 +360,7 @@ if(${SRB2_CONFIG_HWRENDER})
)
set (SRB2_HWRENDER_HEADERS
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
diff --git a/src/Makefile b/src/Makefile
index 426dc2289..27569b36c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -259,7 +259,7 @@ ifndef DC
endif
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
- $(OBJDIR)/hw_main.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
+ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
endif
ifdef NOHS
@@ -703,7 +703,7 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
@@ -711,7 +711,7 @@ else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
@@ -864,7 +864,7 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -872,7 +872,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -880,7 +880,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index decc2e74b..3878d8795 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -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<outofcoop |= (1<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<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;
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index da077c682..b9a4eec3e 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -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
diff --git a/src/d_main.c b/src/d_main.c
index 0fbb7dd31..7a8a85f25 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -419,10 +419,13 @@ static void D_Display(void)
}
// Image postprocessing effect
- if (postimgtype)
- V_DoPostProcessor(0, postimgtype, postimgparam);
- if (postimgtype2)
- V_DoPostProcessor(1, postimgtype2, postimgparam2);
+ if (rendermode == render_soft)
+ {
+ if (postimgtype)
+ V_DoPostProcessor(0, postimgtype, postimgparam);
+ if (postimgtype2)
+ V_DoPostProcessor(1, postimgtype2, postimgparam2);
+ }
}
if (lastdraw)
@@ -712,6 +715,7 @@ void D_StartTitle(void)
botskin = 0;
cv_debug = 0;
emeralds = 0;
+ lastmaploaded = 0;
// In case someone exits out at the same time they start a time attack run,
// reset modeattacking
@@ -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;
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 1d0f2d478..7f408a2b5 100644
--- a/src/d_netcmd.c
+++ b/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;
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 80481c6a5..57e23b0f1 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -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
diff --git a/src/d_player.h b/src/d_player.h
index 4e4a53a08..d578d15ef 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -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
diff --git a/src/dehacked.c b/src/dehacked.c
index 9465d154c..719476543 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -78,97 +78,6 @@ static int dbg_line;
static boolean gamedataadded = false;
-#ifdef DELFILE
-typedef struct undehacked_s
-{
- char *undata;
- struct undehacked_s *next;
-} undehacked_t;
-
-static UINT16 unsocwad;
-static undehacked_t *unsocdata[MAX_WADFILES];
-static boolean disableundo = false;
-
-void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags)
-{
- const char *eqstr = " = ";
- const char *space = " ";
- const char *pader = eqstr;
- undehacked_t *newdata;
-
- if (disableundo || !unsocwad)
- return;
-
- if ((newdata = malloc(sizeof(*newdata))) == NULL)
- I_Error("Out of memory for unsoc line");
-
- if (flags & UNDO_SPACE)
- pader = space;
-
- if (flags & UNDO_ENDTEXT && !data)
- data = space;
-
- if (value)
- {
- const size_t plen = strlen(pader);
- const char *pound = "#";
- char *undata = NULL;
- const size_t elen = strlen(pound);
- size_t vlen = strlen(value), dlen = 0, len = 1;
-
- if (*(value+vlen-1) == '\n')
- vlen--; // lnet not copy the ending \n
-
- if (flags & UNDO_ENDTEXT)
- len += elen; // let malloc more space
-
- if (flags & UNDO_NEWLINE)
- len++; // more space for the beginning \n
-
- if (data)
- {
- dlen = strlen(data);
- if (flags & UNDO_CUTLINE && *(data+dlen-1) == '\n')
- dlen--; // let not copy the ending \n
- newdata->undata = malloc(vlen+plen+dlen+len);
- newdata->undata[vlen+plen+dlen+len-1] = '\0';
- }
- else
- {
- newdata->undata = malloc(vlen+len);
- newdata->undata[vlen+len-1] = '\0';
- }
-
- if (newdata->undata)
- {
- undata = newdata->undata;
- *undata = '\0';
- }
- else
- {
- free(newdata);
- I_Error("Out of memory for unsoc data");
- }
-
- if (flags & UNDO_NEWLINE) // let start with \n
- strcat(undata, "\n");
-
- strncat(undata, value, vlen);
-
- if (data) // value+pader+data
- strncat(strncat(undata, pader, plen), data, dlen);
-
- if (flags & UNDO_ENDTEXT) // let end the text
- strncat(undata, pound, elen);
- }
- else
- newdata->undata = NULL;
-
- newdata->next = unsocdata[unsocwad];
- unsocdata[unsocwad] = newdata;
-}
-#endif
-
ATTRINLINE static FUNCINLINE char myfget_color(MYFILE *f)
{
char c = *f->curpos++;
@@ -408,8 +317,6 @@ static void readPlayer(MYFILE *f, INT32 num)
INT32 i;
boolean slotfound = false;
- DEH_WriteUndoline("PLAYERTEXT", description[num].notes, UNDO_ENDTEXT);
-
do
{
if (myfgets(s, MAXLINELEN, f))
@@ -478,7 +385,6 @@ static void readPlayer(MYFILE *f, INT32 num)
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
- DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE);
strncpy(description[num].picname, word2, 8);
}
@@ -493,7 +399,7 @@ static void readPlayer(MYFILE *f, INT32 num)
*/
if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
- DEH_WriteUndoline(word, va("%d", description[num].used), UNDO_NONE);
+
description[num].used = (!!i);
}
else if (fastcmp(word, "SKINNAME"))
@@ -501,7 +407,6 @@ static void readPlayer(MYFILE *f, INT32 num)
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
- DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE);
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
strlwr(description[num].skinname);
@@ -511,11 +416,6 @@ static void readPlayer(MYFILE *f, INT32 num)
}
} while (!myfeof(f)); // finish when the line is empty
-#ifdef DELFILE
- if (slotfound)
- DEH_WriteUndoline("MENUPOSITION", va("%d", num), UNDO_NONE);
-#endif
-
done:
Z_Free(s);
}
@@ -653,122 +553,98 @@ static void readthing(MYFILE *f, INT32 num)
if (fastcmp(word, "MAPTHINGNUM") || fastcmp(word, "DOOMEDNUM"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].doomednum), UNDO_NONE);
mobjinfo[num].doomednum = (INT32)atoi(word2);
}
else if (fastcmp(word, "SPAWNSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnstate), UNDO_NONE);
mobjinfo[num].spawnstate = get_number(word2);
}
else if (fastcmp(word, "SPAWNHEALTH"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnhealth), UNDO_NONE);
mobjinfo[num].spawnhealth = (INT32)get_number(word2);
}
else if (fastcmp(word, "SEESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].seestate), UNDO_NONE);
mobjinfo[num].seestate = get_number(word2);
}
else if (fastcmp(word, "SEESOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].seesound), UNDO_NONE);
mobjinfo[num].seesound = get_number(word2);
}
else if (fastcmp(word, "REACTIONTIME"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].reactiontime), UNDO_NONE);
mobjinfo[num].reactiontime = (INT32)get_number(word2);
}
else if (fastcmp(word, "ATTACKSOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].attacksound), UNDO_NONE);
mobjinfo[num].attacksound = get_number(word2);
}
else if (fastcmp(word, "PAINSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].painstate), UNDO_NONE);
mobjinfo[num].painstate = get_number(word2);
}
else if (fastcmp(word, "PAINCHANCE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].painchance), UNDO_NONE);
mobjinfo[num].painchance = (INT32)get_number(word2);
}
else if (fastcmp(word, "PAINSOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].painsound), UNDO_NONE);
mobjinfo[num].painsound = get_number(word2);
}
else if (fastcmp(word, "MELEESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].meleestate), UNDO_NONE);
mobjinfo[num].meleestate = get_number(word2);
}
else if (fastcmp(word, "MISSILESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].missilestate), UNDO_NONE);
mobjinfo[num].missilestate = get_number(word2);
}
else if (fastcmp(word, "DEATHSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathstate), UNDO_NONE);
mobjinfo[num].deathstate = get_number(word2);
}
else if (fastcmp(word, "DEATHSOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathsound), UNDO_NONE);
mobjinfo[num].deathsound = get_number(word2);
}
else if (fastcmp(word, "XDEATHSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].xdeathstate), UNDO_NONE);
mobjinfo[num].xdeathstate = get_number(word2);
}
else if (fastcmp(word, "SPEED"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].speed), UNDO_NONE);
mobjinfo[num].speed = get_number(word2);
}
else if (fastcmp(word, "RADIUS"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].radius), UNDO_NONE);
mobjinfo[num].radius = get_number(word2);
}
else if (fastcmp(word, "HEIGHT"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].height), UNDO_NONE);
mobjinfo[num].height = get_number(word2);
}
else if (fastcmp(word, "DISPOFFSET"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].dispoffset), UNDO_NONE);
mobjinfo[num].dispoffset = get_number(word2);
}
else if (fastcmp(word, "MASS"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].mass), UNDO_NONE);
mobjinfo[num].mass = (INT32)get_number(word2);
}
else if (fastcmp(word, "DAMAGE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].damage), UNDO_NONE);
mobjinfo[num].damage = (INT32)get_number(word2);
}
else if (fastcmp(word, "ACTIVESOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].activesound), UNDO_NONE);
mobjinfo[num].activesound = get_number(word2);
}
else if (fastcmp(word, "FLAGS"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].flags), UNDO_NONE);
mobjinfo[num].flags = (INT32)get_number(word2);
}
else if (fastcmp(word, "RAISESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].raisestate), UNDO_NONE);
mobjinfo[num].raisestate = get_number(word2);
}
else
@@ -812,37 +688,30 @@ static void readlight(MYFILE *f, INT32 num)
if (fastcmp(word, "TYPE"))
{
- DEH_WriteUndoline(word, va("%d", lspr[num].type), UNDO_NONE);
lspr[num].type = (UINT16)value;
}
else if (fastcmp(word, "OFFSETX"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].light_xoffset), UNDO_NONE);
lspr[num].light_xoffset = fvalue;
}
else if (fastcmp(word, "OFFSETY"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].light_yoffset), UNDO_NONE);
lspr[num].light_yoffset = fvalue;
}
else if (fastcmp(word, "CORONACOLOR"))
{
- DEH_WriteUndoline(word, va("%u", lspr[num].corona_color), UNDO_NONE);
lspr[num].corona_color = value;
}
else if (fastcmp(word, "CORONARADIUS"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].corona_radius), UNDO_NONE);
lspr[num].corona_radius = fvalue;
}
else if (fastcmp(word, "DYNAMICCOLOR"))
{
- DEH_WriteUndoline(word, va("%u", lspr[num].dynamic_color), UNDO_NONE);
lspr[num].dynamic_color = value;
}
else if (fastcmp(word, "DYNAMICRADIUS"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].dynamic_radius), UNDO_NONE);
lspr[num].dynamic_radius = fvalue;
/// \note Update the sqrradius! unnecessary?
@@ -889,7 +758,6 @@ static void readspritelight(MYFILE *f, INT32 num)
INT32 oldvar;
for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++)
;
- DEH_WriteUndoline(word, va("%d", oldvar), UNDO_NONE);
t_lspr[num] = &lspr[value];
}
else
@@ -972,8 +840,6 @@ static void readlevelheader(MYFILE *f, INT32 num)
INT32 i;
// Reset all previous map header information
- // This call automatically saves all previous information when DELFILE is defined.
- // We don't need to do it ourselves.
P_AllocMapHeader((INT16)(num-1));
do
@@ -1329,6 +1195,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
else
mapheaderinfo[num-1]->levelflags &= ~LF_NOZONE;
}
+ else if (fastcmp(word, "SAVEGAME"))
+ {
+ if (i || word2[0] == 'T' || word2[0] == 'Y')
+ mapheaderinfo[num-1]->levelflags |= LF_SAVEGAME;
+ else
+ mapheaderinfo[num-1]->levelflags &= ~LF_SAVEGAME;
+ }
// Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN"))
@@ -1392,8 +1265,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
UINT16 usi;
UINT8 picid;
- DEH_WriteUndoline("SCENETEXT", cutscenes[num]->scene[scenenum].text, UNDO_ENDTEXT);
-
do
{
if (myfgets(s, MAXLINELEN, f))
@@ -1470,7 +1341,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
if (fastcmp(word, "NUMBEROFPICS"))
{
- DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].numpics), UNDO_NONE);
cutscenes[num]->scene[scenenum].numpics = (UINT8)i;
}
else if (fastncmp(word, "PIC", 3))
@@ -1485,27 +1355,22 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
if (fastcmp(word+4, "NAME"))
{
- DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].picname[picid], UNDO_NONE);
strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8);
}
else if (fastcmp(word+4, "HIRES"))
{
- DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].pichires[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word+4, "DURATION"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].picduration[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].picduration[picid] = usi;
}
else if (fastcmp(word+4, "XCOORD"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].xcoord[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].xcoord[picid] = usi;
}
else if (fastcmp(word+4, "YCOORD"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].ycoord[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].ycoord[picid] = usi;
}
else
@@ -1513,14 +1378,12 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
}
else if (fastcmp(word, "MUSIC"))
{
- DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7);
cutscenes[num]->scene[scenenum].musswitch[6] = 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (fastcmp(word, "MUSICSLOT"))
{
- DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
i = get_mus(word2, true);
if (i && i <= 1035)
snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i));
@@ -1533,37 +1396,30 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
#endif
else if (fastcmp(word, "MUSICTRACK"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
}
else if (fastcmp(word, "MUSICLOOP"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
cutscenes[num]->scene[scenenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TEXTXPOS"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textxpos), UNDO_NONE);
cutscenes[num]->scene[scenenum].textxpos = usi;
}
else if (fastcmp(word, "TEXTYPOS"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textypos), UNDO_NONE);
cutscenes[num]->scene[scenenum].textypos = usi;
}
else if (fastcmp(word, "FADEINID"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadeinid = (UINT8)i;
}
else if (fastcmp(word, "FADEOUTID"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadeoutid = (UINT8)i;
}
else if (fastcmp(word, "FADECOLOR"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i;
}
else
@@ -1581,9 +1437,6 @@ static void readcutscene(MYFILE *f, INT32 num)
char *word2;
char *tmp;
INT32 value;
-#ifdef DELFILE
- const INT32 oldnumscenes = cutscenes[num]->numscenes;
-#endif
// Allocate memory for this cutscene if we don't yet have any
if (!cutscenes[num])
@@ -1626,8 +1479,6 @@ static void readcutscene(MYFILE *f, INT32 num)
if (1 <= value && value <= 128)
{
readcutscenescene(f, num, value - 1);
- DEH_WriteUndoline(word, word2, UNDO_SPACE|UNDO_CUTLINE);
- DEH_WriteUndoline("NUMSCENES", va("%d", oldnumscenes), UNDO_SPACE);
}
else
deh_warning("Scene number %d out of range (1 - 128)", value);
@@ -1680,12 +1531,10 @@ static void readhuditem(MYFILE *f, INT32 num)
if (fastcmp(word, "X"))
{
- DEH_WriteUndoline(word, va("%d", hudinfo[num].x), UNDO_NONE);
hudinfo[num].x = i;
}
else if (fastcmp(word, "Y"))
{
- DEH_WriteUndoline(word, va("%d", hudinfo[num].y), UNDO_NONE);
hudinfo[num].y = i;
}
else
@@ -1732,7 +1581,6 @@ static actionpointer_t actionpointers[] =
{{A_BossDeath}, "A_BOSSDEATH"},
{{A_CustomPower}, "A_CUSTOMPOWER"},
{{A_GiveWeapon}, "A_GIVEWEAPON"},
- {{A_RingShield}, "A_RINGSHIELD"},
{{A_RingBox}, "A_RINGBOX"},
{{A_Invincibility}, "A_INVINCIBILITY"},
{{A_SuperSneakers}, "A_SUPERSNEAKERS"},
@@ -1743,14 +1591,7 @@ static actionpointer_t actionpointers[] =
{{A_BubbleCheck}, "A_BUBBLECHECK"},
{{A_AwardScore}, "A_AWARDSCORE"},
{{A_ExtraLife}, "A_EXTRALIFE"},
- {{A_BombShield}, "A_BOMBSHIELD"},
- {{A_JumpShield}, "A_JUMPSHIELD"},
- {{A_WaterShield}, "A_WATERSHIELD"},
- {{A_ForceShield}, "A_FORCESHIELD"},
- {{A_PityShield}, "A_PITYSHIELD"},
- {{A_FlameShield}, "A_FLAMESHIELD"},
- {{A_BubbleShield}, "A_BUBBLESHIELD"},
- {{A_ThunderShield}, "A_THUNDERSHIELD"},
+ {{A_GiveShield}, "A_GIVESHIELD"},
{{A_GravityBox}, "A_GRAVITYBOX"},
{{A_ScoreRise}, "A_SCORERISE"},
{{A_ParticleSpawn}, "A_PARTICLESPAWN"},
@@ -1776,7 +1617,6 @@ static actionpointer_t actionpointers[] =
{{A_CapeChase}, "A_CAPECHASE"},
{{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"},
{{A_SlingAppear}, "A_SLINGAPPEAR"},
- {{A_MaceRotate}, "A_MACEROTATE"},
{{A_UnidusBall}, "A_UNIDUSBALL"},
{{A_RockSpawn}, "A_ROCKSPAWN"},
{{A_SetFuse}, "A_SETFUSE"},
@@ -1971,32 +1811,26 @@ static void readframe(MYFILE *f, INT32 num)
if (fastcmp(word1, "SPRITENUMBER") || fastcmp(word1, "SPRITENAME"))
{
- DEH_WriteUndoline(word1, va("%u", states[num].sprite), UNDO_NONE);
states[num].sprite = get_sprite(word2);
}
else if (fastcmp(word1, "SPRITESUBNUMBER") || fastcmp(word1, "SPRITEFRAME"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].frame), UNDO_NONE);
states[num].frame = (INT32)get_number(word2); // So the FF_ flags get calculated
}
else if (fastcmp(word1, "DURATION"))
{
- DEH_WriteUndoline(word1, va("%u", states[num].tics), UNDO_NONE);
states[num].tics = (INT32)get_number(word2); // So TICRATE can be used
}
else if (fastcmp(word1, "NEXT"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].nextstate), UNDO_NONE);
states[num].nextstate = get_state(word2);
}
else if (fastcmp(word1, "VAR1"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].var1), UNDO_NONE);
states[num].var1 = (INT32)get_number(word2);
}
else if (fastcmp(word1, "VAR2"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].var2), UNDO_NONE);
states[num].var2 = (INT32)get_number(word2);
}
else if (fastcmp(word1, "ACTION"))
@@ -2021,10 +1855,7 @@ static void readframe(MYFILE *f, INT32 num)
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action.acv == states[num].action.acv)
- {
- DEH_WriteUndoline(word1, actionpointers[z].name, UNDO_NONE);
break;
- }
}
z = 0;
@@ -2094,17 +1925,14 @@ static void readsound(MYFILE *f, INT32 num)
if (fastcmp(word, "SINGULAR"))
{
- DEH_WriteUndoline(word, va("%d", S_sfx[num].singularity), UNDO_NONE);
S_sfx[num].singularity = value;
}
else if (fastcmp(word, "PRIORITY"))
{
- DEH_WriteUndoline(word, va("%d", S_sfx[num].priority), UNDO_NONE);
S_sfx[num].priority = value;
}
else if (fastcmp(word, "FLAGS"))
{
- DEH_WriteUndoline(word, va("%d", S_sfx[num].pitch), UNDO_NONE);
S_sfx[num].pitch = value;
}
else if (fastcmp(word, "CAPTION") || fastcmp(word, "DESCRIPTION"))
@@ -2148,11 +1976,7 @@ static boolean GoodDataFileName(const char *s)
p = s + strlen(s) - strlen(tail);
if (p <= s) return false; // too short
if (!fasticmp(p, tail)) return false; // doesn't end in .dat
-#ifdef DELFILE
- if (fasticmp(s, "gamedata.dat") && !disableundo) return false;
-#else
if (fasticmp(s, "gamedata.dat")) return false;
-#endif
return true;
}
@@ -2165,17 +1989,6 @@ static void reademblemdata(MYFILE *f, INT32 num)
char *tmp;
INT32 value;
- // Reset all data initially
- DEH_WriteUndoline("TYPE", va("%d", emblemlocations[num-1].type), UNDO_NONE);
- DEH_WriteUndoline("X", va("%d", emblemlocations[num-1].x), UNDO_NONE);
- DEH_WriteUndoline("Y", va("%d", emblemlocations[num-1].y), UNDO_NONE);
- DEH_WriteUndoline("Z", va("%d", emblemlocations[num-1].z), UNDO_NONE);
- DEH_WriteUndoline("MAPNUM", va("%d", emblemlocations[num-1].level), UNDO_NONE);
- DEH_WriteUndoline("VAR", va("%d", emblemlocations[num-1].var), UNDO_NONE);
- DEH_WriteUndoline("SPRITE", va("%d", emblemlocations[num-1].sprite), UNDO_NONE);
- DEH_WriteUndoline("COLOR", va("%d", emblemlocations[num-1].color), UNDO_NONE);
- DEH_WriteUndoline("HINT", extraemblems[num-1].hint, UNDO_NONE);
-
memset(&emblemlocations[num-1], 0, sizeof(emblem_t));
do
@@ -2311,13 +2124,6 @@ static void readextraemblemdata(MYFILE *f, INT32 num)
char *tmp;
INT32 value;
- // Reset all data initially
- DEH_WriteUndoline("NAME", extraemblems[num-1].name, UNDO_NONE);
- DEH_WriteUndoline("OBJECTIVE", extraemblems[num-1].description, UNDO_NONE);
- DEH_WriteUndoline("CONDITIONSET", va("%d", extraemblems[num-1].conditionset), UNDO_NONE);
- DEH_WriteUndoline("SPRITE", va("%d", extraemblems[num-1].sprite), UNDO_NONE);
- DEH_WriteUndoline("COLOR", va("%d", extraemblems[num-1].color), UNDO_NONE);
-
memset(&extraemblems[num-1], 0, sizeof(extraemblem_t));
do
@@ -2392,16 +2198,6 @@ static void readunlockable(MYFILE *f, INT32 num)
char *tmp;
INT32 i;
- // Same deal with unlockables, clear all first
- DEH_WriteUndoline("NAME", unlockables[num].name, UNDO_NONE);
- DEH_WriteUndoline("OBJECTIVE", unlockables[num].objective, UNDO_NONE);
- DEH_WriteUndoline("HEIGHT", va("%d", unlockables[num].height), UNDO_NONE);
- DEH_WriteUndoline("CONDITIONSET", va("%d", unlockables[num].conditionset), UNDO_NONE);
- DEH_WriteUndoline("TYPE", va("%d", unlockables[num].type), UNDO_NONE);
- DEH_WriteUndoline("NOCECHO", va("%d", unlockables[num].nocecho), UNDO_NONE);
- DEH_WriteUndoline("NOCHECKLIST", va("%d", unlockables[num].nochecklist), UNDO_NONE);
- DEH_WriteUndoline("VAR", va("%d", unlockables[num].variable), UNDO_NONE);
-
memset(&unlockables[num], 0, sizeof(unlockable_t));
unlockables[num].objective[0] = '/';
@@ -2796,7 +2592,6 @@ static void readmaincfg(MYFILE *f)
else
value = get_number(word2);
- DEH_WriteUndoline(word, va("%d", spstage_start), UNDO_NONE);
spstage_start = (INT16)value;
}
else if (fastcmp(word, "SSTAGE_START"))
@@ -2810,79 +2605,64 @@ static void readmaincfg(MYFILE *f)
else
value = get_number(word2);
- DEH_WriteUndoline(word, va("%d", sstage_start), UNDO_NONE);
sstage_start = (INT16)value;
sstage_end = (INT16)(sstage_start+6); // 7 special stages total
}
else if (fastcmp(word, "USENIGHTSSS"))
{
- DEH_WriteUndoline(word, va("%d", useNightsSS), UNDO_NONE);
useNightsSS = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "REDTEAM"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_redteam), UNDO_NONE);
skincolor_redteam = (UINT8)get_number(word2);
}
else if (fastcmp(word, "BLUETEAM"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_blueteam), UNDO_NONE);
skincolor_blueteam = (UINT8)get_number(word2);
}
else if (fastcmp(word, "REDRING"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_redring), UNDO_NONE);
skincolor_redring = (UINT8)get_number(word2);
}
else if (fastcmp(word, "BLUERING"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_bluering), UNDO_NONE);
skincolor_bluering = (UINT8)get_number(word2);
}
else if (fastcmp(word, "INVULNTICS"))
{
- DEH_WriteUndoline(word, va("%u", invulntics), UNDO_NONE);
invulntics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SNEAKERTICS"))
{
- DEH_WriteUndoline(word, va("%u", sneakertics), UNDO_NONE);
sneakertics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "FLASHINGTICS"))
{
- DEH_WriteUndoline(word, va("%u", flashingtics), UNDO_NONE);
flashingtics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "TAILSFLYTICS"))
{
- DEH_WriteUndoline(word, va("%u", tailsflytics), UNDO_NONE);
tailsflytics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "UNDERWATERTICS"))
{
- DEH_WriteUndoline(word, va("%u", underwatertics), UNDO_NONE);
underwatertics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SPACETIMETICS"))
{
- DEH_WriteUndoline(word, va("%u", spacetimetics), UNDO_NONE);
spacetimetics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "EXTRALIFETICS"))
{
- DEH_WriteUndoline(word, va("%u", extralifetics), UNDO_NONE);
extralifetics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "GAMEOVERTICS"))
{
- DEH_WriteUndoline(word, va("%u", gameovertics), UNDO_NONE);
gameovertics = get_number(word2);
}
else if (fastcmp(word, "INTROTOPLAY"))
{
- DEH_WriteUndoline(word, va("%d", introtoplay), UNDO_NONE);
introtoplay = (UINT8)get_number(word2);
// range check, you morons.
if (introtoplay > 128)
@@ -2890,17 +2670,14 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "LOOPTITLE"))
{
- DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE);
looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TITLESCROLLSPEED"))
{
- DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE);
titlescrollspeed = get_number(word2);
}
else if (fastcmp(word, "CREDITSCUTSCENE"))
{
- DEH_WriteUndoline(word, va("%d", creditscutscene), UNDO_NONE);
creditscutscene = (UINT8)get_number(word2);
// range check, you morons.
if (creditscutscene > 128)
@@ -2908,32 +2685,26 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "DISABLESPEEDADJUST"))
{
- DEH_WriteUndoline(word, va("%d", disableSpeedAdjust), UNDO_NONE);
disableSpeedAdjust = (UINT8)get_number(word2);
}
else if (fastcmp(word, "NUMDEMOS"))
{
- DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE);
numDemos = (UINT8)get_number(word2);
}
else if (fastcmp(word, "DEMODELAYTIME"))
{
- DEH_WriteUndoline(word, va("%d", demoDelayTime), UNDO_NONE);
demoDelayTime = get_number(word2);
}
else if (fastcmp(word, "DEMOIDLETIME"))
{
- DEH_WriteUndoline(word, va("%d", demoIdleTime), UNDO_NONE);
demoIdleTime = get_number(word2);
}
else if (fastcmp(word, "USE1UPSOUND"))
{
- DEH_WriteUndoline(word, va("%u", use1upSound), UNDO_NONE);
use1upSound = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "MAXXTRALIFE"))
{
- DEH_WriteUndoline(word, va("%u", maxXtraLife), UNDO_NONE);
maxXtraLife = (UINT8)get_number(word2);
}
@@ -2947,7 +2718,6 @@ static void readmaincfg(MYFILE *f)
I_Error("Maincfg: bad data file name '%s'\n", word2);
G_SaveGameData();
- DEH_WriteUndoline(word, gamedatafilename, UNDO_NONE);
strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
strlwr(gamedatafilename);
savemoddata = true;
@@ -2964,12 +2734,10 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "RESETDATA"))
{
- DEH_WriteUndoline(word, "0", UNDO_TODO); /// \todo
P_ResetData(value);
}
else if (fastcmp(word, "CUSTOMVERSION"))
{
- DEH_WriteUndoline(word, customversionstring, UNDO_NONE);
strlcpy(customversionstring, word2, sizeof (customversionstring));
}
else
@@ -3207,13 +2975,11 @@ static void DEH_LoadDehackedFile(MYFILE *f)
else if (fastcmp(word, "MAINCFG"))
{
readmaincfg(f);
- DEH_WriteUndoline(word, "", UNDO_HEADER);
continue;
}
else if (fastcmp(word, "WIPES"))
{
readwipes(f);
- DEH_WriteUndoline(word, "", UNDO_HEADER);
continue;
}
word2 = strtok(NULL, " ");
@@ -3233,7 +2999,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Character %d out of range (0 - 31)", i);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
continue;
}
if (word2)
@@ -3242,6 +3007,7 @@ static void DEH_LoadDehackedFile(MYFILE *f)
if (word2[strlen(word2)-1] == '\n')
word2[strlen(word2)-1] = '\0';
i = atoi(word2);
+
if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
@@ -3253,7 +3019,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Thing %d out of range (1 - %d)", i, NUMMOBJTYPES-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "LIGHT"))
{
@@ -3266,7 +3031,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Light number %d out of range (1 - %d)", i, NUMLIGHTS-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
#endif
}
else if (fastcmp(word, "SPRITE"))
@@ -3281,7 +3045,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
#endif
}
else if (fastcmp(word, "LEVEL"))
@@ -3300,7 +3063,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CUTSCENE"))
{
@@ -3311,7 +3073,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Cutscene number %d out of range (1 - 128)", i);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE"))
{
@@ -3324,7 +3085,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Frame %d out of range (0 - %d)", i, NUMSTATES-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "SOUND"))
{
@@ -3337,7 +3097,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Sound %d out of range (1 - %d)", i, NUMSFX-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "HUDITEM"))
{
@@ -3350,7 +3109,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("HUD item number %d out of range (0 - %d)", i, NUMHUDITEMS-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "EMBLEM"))
{
@@ -3370,7 +3128,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Emblem number %d out of range (1 - %d)", i, MAXEMBLEMS);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "EXTRAEMBLEM"))
{
@@ -3390,7 +3147,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Extra emblem number %d out of range (1 - %d)", i, MAXEXTRAEMBLEMS);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "UNLOCKABLE"))
{
@@ -3406,7 +3162,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Unlockable number %d out of range (1 - %d)", i, MAXUNLOCKABLES);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CONDITIONSET"))
{
@@ -3422,8 +3177,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
deh_warning("Condition set number %d out of range (1 - %d)", i, MAXCONDITIONSETS);
ignorelines(f);
}
- // no undo support for this insanity yet
- //DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
// Last I heard this crashes the game if you try to use it
// so this is disabled for now
@@ -3433,7 +3186,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
INT32 ver = searchvalue(strtok(NULL, "\n"));
if (ver != PATCHVERSION)
deh_warning("Patch is for SRB2 version %d,\nonly version %d is supported", ver, PATCHVERSION);
- //DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE);
}
// Clear all data in certain locations (mostly for unlocks)
// Unless you REALLY want to piss people off,
@@ -3504,9 +3256,6 @@ static void DEH_LoadDehackedFile(MYFILE *f)
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump)
{
MYFILE f;
-#ifdef DELFILE
- unsocwad = wad;
-#endif
f.wad = wad;
f.size = W_LumpLengthPwad(wad, lump);
f.data = Z_Malloc(f.size + 1, PU_STATIC, NULL);
@@ -3514,7 +3263,6 @@ void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump)
f.curpos = f.data;
f.data[f.size] = 0;
DEH_LoadDehackedFile(&f);
- DEH_WriteUndoline(va("# uload for wad: %u, lump: %u", wad, lump), NULL, UNDO_DONE);
Z_Free(f.data);
}
@@ -3523,67 +3271,6 @@ void DEH_LoadDehackedLump(lumpnum_t lumpnum)
DEH_LoadDehackedLumpPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
}
-#ifdef DELFILE
-#define DUMPUNDONE
-
-// read (un)dehacked lump in wad's memory
-void DEH_UnloadDehackedWad(UINT16 wad)
-{
- undehacked_t *tmp, *curundo = unsocdata[wad];
- MYFILE f;
- size_t len = 0;
- char *data;
-#ifdef DUMPUNDONE
- FILE *UNDO = fopen("undo.soc", "wt");
-#endif
- CONS_Printf(M_GetText("Unloading WAD SOC edits\n"));
- while (curundo)
- {
- data = curundo->undata;
- curundo = curundo->next;
- if (data)
- len += strlen(data);
- len += 1;
-#ifdef DUMPUNDONE
- if (UNDO)
- {
- if (data)
- fprintf(UNDO, "%s\n", data);
- else
- fprintf(UNDO, "\n");
- }
-#endif
- }
-#ifndef DUMPUNDONE
- if (UNDO) fclose(UNDO);
-#endif
- if (!len) return;
- f.size = len;
- data = f.data = Z_Malloc(f.size + 1, PU_STATIC, NULL);
- curundo = unsocdata[wad];
- unsocdata[wad] = NULL;
- while (curundo)
- {
- tmp = curundo;
- curundo = curundo->next;
- if (tmp->undata)
- data += sprintf(data, "%s\n", tmp->undata);
- else
- data += sprintf(data, "\n");
- if (tmp->undata) free(tmp->undata);
- free(tmp);
- }
- f.wad = wad;
- f.curpos = f.data;
- f.data[f.size] = 0;
- disableundo = true;
- DEH_LoadDehackedFile(&f);
- disableundo = false;
- Z_Free(f.data);
-}
-#endif //DELFILE
-
-
////////////////////////////////////////////////////////////////////////////////
// CRAZY LIST OF STATE NAMES AND ALL FROM HERE DOWN
// TODO: Make this all a seperate file or something, like part of info.c??
@@ -4951,18 +4638,62 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SLING1",
"S_SLING2",
- // CEZ Small Mace Chain
+ // CEZ maces and chains
"S_SMALLMACECHAIN",
-
- // CEZ Big Mace Chain
"S_BIGMACECHAIN",
-
- // CEZ Small Mace
"S_SMALLMACE",
-
- // CEZ Big Mace
"S_BIGMACE",
+ // Yellow spring on a ball
+ "S_YELLOWSPRINGBALL",
+ "S_YELLOWSPRINGBALL2",
+ "S_YELLOWSPRINGBALL3",
+ "S_YELLOWSPRINGBALL4",
+ "S_YELLOWSPRINGBALL5",
+
+ // Red spring on a ball
+ "S_REDSPRINGBALL",
+ "S_REDSPRINGBALL2",
+ "S_REDSPRINGBALL3",
+ "S_REDSPRINGBALL4",
+ "S_REDSPRINGBALL5",
+
+ // Small Firebar
+ "S_SMALLFIREBAR1",
+ "S_SMALLFIREBAR2",
+ "S_SMALLFIREBAR3",
+ "S_SMALLFIREBAR4",
+ "S_SMALLFIREBAR5",
+ "S_SMALLFIREBAR6",
+ "S_SMALLFIREBAR7",
+ "S_SMALLFIREBAR8",
+ "S_SMALLFIREBAR9",
+ "S_SMALLFIREBAR10",
+ "S_SMALLFIREBAR11",
+ "S_SMALLFIREBAR12",
+ "S_SMALLFIREBAR13",
+ "S_SMALLFIREBAR14",
+ "S_SMALLFIREBAR15",
+ "S_SMALLFIREBAR16",
+
+ // Big Firebar
+ "S_BIGFIREBAR1",
+ "S_BIGFIREBAR2",
+ "S_BIGFIREBAR3",
+ "S_BIGFIREBAR4",
+ "S_BIGFIREBAR5",
+ "S_BIGFIREBAR6",
+ "S_BIGFIREBAR7",
+ "S_BIGFIREBAR8",
+ "S_BIGFIREBAR9",
+ "S_BIGFIREBAR10",
+ "S_BIGFIREBAR11",
+ "S_BIGFIREBAR12",
+ "S_BIGFIREBAR13",
+ "S_BIGFIREBAR14",
+ "S_BIGFIREBAR15",
+ "S_BIGFIREBAR16",
+
"S_CEZFLOWER1",
// Big Tumbleweed
@@ -6297,14 +6028,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEPARTICLE",
"MT_EGGSTATUE", // Eggman Statue
"MT_MACEPOINT", // Mace rotation point
- "MT_SWINGMACEPOINT", // Mace swinging point
- "MT_HANGMACEPOINT", // Hangable mace chain
- "MT_SPINMACEPOINT", // Spin/Controllable mace chain
+ "MT_CHAINMACEPOINT", // Combination of chains and maces point
+ "MT_SPRINGBALLPOINT", // Spring ball point
+ "MT_CHAINPOINT", // Mace chain
"MT_HIDDEN_SLING", // Spin mace chain (activatable)
+ "MT_FIREBARPOINT", // Firebar
+ "MT_CUSTOMMACEPOINT", // Custom mace
"MT_SMALLMACECHAIN", // Small Mace Chain
"MT_BIGMACECHAIN", // Big Mace Chain
"MT_SMALLMACE", // Small Mace
"MT_BIGMACE", // Big Mace
+ "MT_YELLOWSPRINGBALL", // Yellow spring on a ball
+ "MT_REDSPRINGBALL", // Red spring on a ball
+ "MT_SMALLFIREBAR", // Small Firebar
+ "MT_BIGFIREBAR", // Big Firebar
"MT_CEZFLOWER",
// Arid Canyon Scenery
@@ -6657,6 +6394,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
"SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
+ "MACEROTATE", // Thinker calls P_MaceRotate around tracer
NULL
};
@@ -6767,91 +6505,130 @@ static const char *const ML_LIST[16] = {
// This DOES differ from r_draw's Color_Names, unfortunately.
// Also includes Super colors
static const char *COLOR_ENUMS[] = {
- "NONE", // SKINCOLOR_NONE
- "WHITE", // SKINCOLOR_WHITE
- "SILVER", // SKINCOLOR_SILVER
- "GREY", // SKINCOLOR_GREY
- "BLACK", // SKINCOLOR_BLACK
- "BEIGE", // SKINCOLOR_BEIGE
- "PEACH", // SKINCOLOR_PEACH
- "BROWN", // SKINCOLOR_BROWN
- "RED", // SKINCOLOR_RED
- "CRIMSON", // SKINCOLOR_CRIMSON
- "ORANGE", // SKINCOLOR_ORANGE
- "RUST", // SKINCOLOR_RUST
- "GOLD", // SKINCOLOR_GOLD
- "YELLOW", // SKINCOLOR_YELLOW
- "TAN", // SKINCOLOR_TAN
- "MOSS", // SKINCOLOR_MOSS
- "PERIDOT", // SKINCOLOR_PERIDOT
- "GREEN", // SKINCOLOR_GREEN
- "EMERALD", // SKINCOLOR_EMERALD
- "AQUA", // SKINCOLOR_AQUA
- "TEAL", // SKINCOLOR_TEAL
- "CYAN", // SKINCOLOR_CYAN
- "BLUE", // SKINCOLOR_BLUE
- "AZURE", // SKINCOLOR_AZURE
- "PASTEL", // SKINCOLOR_PASTEL
- "PURPLE", // SKINCOLOR_PURPLE
- "LAVENDER", // SKINCOLOR_LAVENDER
- "MAGENTA", // SKINCOLOR_MAGENTA
- "PINK", // SKINCOLOR_PINK
- "ROSY", // SKINCOLOR_ROSY
+ "NONE", // SKINCOLOR_NONE,
+
+ // Greyscale ranges
+ "WHITE", // SKINCOLOR_WHITE,
+ "BONE", // SKINCOLOR_BONE,
+ "CLOUDY", // SKINCOLOR_CLOUDY,
+ "GREY", // SKINCOLOR_GREY,
+ "SILVER", // SKINCOLOR_SILVER,
+ "CARBON", // SKINCOLOR_CARBON,
+ "JET", // SKINCOLOR_JET,
+ "BLACK", // SKINCOLOR_BLACK,
+
+ // Desaturated
+ "AETHER", // SKINCOLOR_AETHER,
+ "SLATE", // SKINCOLOR_SLATE,
+ "PINK", // SKINCOLOR_PINK,
+ "YOGURT", // SKINCOLOR_YOGURT,
+ "BROWN", // SKINCOLOR_BROWN,
+ "TAN", // SKINCOLOR_TAN,
+ "BEIGE", // SKINCOLOR_BEIGE,
+ "MOSS", // SKINCOLOR_MOSS,
+ "AZURE", // SKINCOLOR_AZURE,
+ "LAVENDER", // SKINCOLOR_LAVENDER,
+
+ // Viv's vivid colours (toast 21/07/17)
+ "RUBY", // SKINCOLOR_RUBY,
+ "SALMON", // SKINCOLOR_SALMON,
+ "RED", // SKINCOLOR_RED,
+ "CRIMSON", // SKINCOLOR_CRIMSON,
+ "FLAME", // SKINCOLOR_FLAME,
+ "PEACHY", // SKINCOLOR_PEACHY,
+ "QUAIL", // SKINCOLOR_QUAIL,
+ "SUNSET", // SKINCOLOR_SUNSET,
+ "APRICOT", // SKINCOLOR_APRICOT,
+ "ORANGE", // SKINCOLOR_ORANGE,
+ "RUST", // SKINCOLOR_RUST,
+ "GOLD", // SKINCOLOR_GOLD,
+ "SANDY", // SKINCOLOR_SANDY,
+ "YELLOW", // SKINCOLOR_YELLOW,
+ "OLIVE", // SKINCOLOR_OLIVE,
+ "LIME", // SKINCOLOR_LIME,
+ "PERIDOT", // SKINCOLOR_PERIDOT,
+ "GREEN", // SKINCOLOR_GREEN,
+ "FOREST", // SKINCOLOR_FOREST,
+ "EMERALD", // SKINCOLOR_EMERALD,
+ "MINT", // SKINCOLOR_MINT,
+ "SEAFOAM", // SKINCOLOR_SEAFOAM,
+ "AQUA", // SKINCOLOR_AQUA,
+ "TEAL", // SKINCOLOR_TEAL,
+ "WAVE", // SKINCOLOR_WAVE,
+ "CYAN", // SKINCOLOR_CYAN,
+ "SKY", // SKINCOLOR_SKY,
+ "CERULEAN", // SKINCOLOR_CERULEAN,
+ "ICY", // SKINCOLOR_ICY,
+ "SAPPHIRE", // SKINCOLOR_SAPPHIRE,
+ "CORNFLOWER", // SKINCOLOR_CORNFLOWER,
+ "BLUE", // SKINCOLOR_BLUE,
+ "COBALT", // SKINCOLOR_COBALT,
+ "VAPOR", // SKINCOLOR_VAPOR,
+ "DUSK", // SKINCOLOR_DUSK,
+ "PASTEL", // SKINCOLOR_PASTEL,
+ "PURPLE", // SKINCOLOR_PURPLE,
+ "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM,
+ "MAGENTA", // SKINCOLOR_MAGENTA,
+ "NEON", // SKINCOLOR_NEON,
+ "VIOLET", // SKINCOLOR_VIOLET,
+ "LILAC", // SKINCOLOR_LILAC,
+ "PLUM", // SKINCOLOR_PLUM,
+ "ROSY", // SKINCOLOR_ROSY,
// Super special awesome Super flashing colors!
- "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1
- "SUPERSILVER2", // SKINCOLOR_SUPERSILVER2,
- "SUPERSILVER3", // SKINCOLOR_SUPERSILVER3,
- "SUPERSILVER4", // SKINCOLOR_SUPERSILVER4,
- "SUPERSILVER5", // SKINCOLOR_SUPERSILVER5,
+ "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1
+ "SUPERSILVER2", // SKINCOLOR_SUPERSILVER2,
+ "SUPERSILVER3", // SKINCOLOR_SUPERSILVER3,
+ "SUPERSILVER4", // SKINCOLOR_SUPERSILVER4,
+ "SUPERSILVER5", // SKINCOLOR_SUPERSILVER5,
- "SUPERRED1", // SKINCOLOR_SUPERRED1
- "SUPERRED2", // SKINCOLOR_SUPERRED2,
- "SUPERRED3", // SKINCOLOR_SUPERRED3,
- "SUPERRED4", // SKINCOLOR_SUPERRED4,
- "SUPERRED5", // SKINCOLOR_SUPERRED5,
+ "SUPERRED1", // SKINCOLOR_SUPERRED1
+ "SUPERRED2", // SKINCOLOR_SUPERRED2,
+ "SUPERRED3", // SKINCOLOR_SUPERRED3,
+ "SUPERRED4", // SKINCOLOR_SUPERRED4,
+ "SUPERRED5", // SKINCOLOR_SUPERRED5,
- "SUPERORANGE1", // SKINCOLOR_SUPERORANGE1
- "SUPERORANGE2", // SKINCOLOR_SUPERORANGE2,
- "SUPERORANGE3", // SKINCOLOR_SUPERORANGE3,
- "SUPERORANGE4", // SKINCOLOR_SUPERORANGE4,
- "SUPERORANGE5", // SKINCOLOR_SUPERORANGE5,
+ "SUPERORANGE1", // SKINCOLOR_SUPERORANGE1
+ "SUPERORANGE2", // SKINCOLOR_SUPERORANGE2,
+ "SUPERORANGE3", // SKINCOLOR_SUPERORANGE3,
+ "SUPERORANGE4", // SKINCOLOR_SUPERORANGE4,
+ "SUPERORANGE5", // SKINCOLOR_SUPERORANGE5,
- "SUPERGOLD1", // SKINCOLOR_SUPERGOLD1
- "SUPERGOLD2", // SKINCOLOR_SUPERGOLD2,
- "SUPERGOLD3", // SKINCOLOR_SUPERGOLD3,
- "SUPERGOLD4", // SKINCOLOR_SUPERGOLD4,
- "SUPERGOLD5", // SKINCOLOR_SUPERGOLD5,
+ "SUPERGOLD1", // SKINCOLOR_SUPERGOLD1
+ "SUPERGOLD2", // SKINCOLOR_SUPERGOLD2,
+ "SUPERGOLD3", // SKINCOLOR_SUPERGOLD3,
+ "SUPERGOLD4", // SKINCOLOR_SUPERGOLD4,
+ "SUPERGOLD5", // SKINCOLOR_SUPERGOLD5,
- "SUPERPERIDOT1", // SKINCOLOR_SUPERPERIDOT1
- "SUPERPERIDOT2", // SKINCOLOR_SUPERPERIDOT2,
- "SUPERPERIDOT3", // SKINCOLOR_SUPERPERIDOT3,
- "SUPERPERIDOT4", // SKINCOLOR_SUPERPERIDOT4,
- "SUPERPERIDOT5", // SKINCOLOR_SUPERPERIDOT5,
+ "SUPERPERIDOT1", // SKINCOLOR_SUPERPERIDOT1
+ "SUPERPERIDOT2", // SKINCOLOR_SUPERPERIDOT2,
+ "SUPERPERIDOT3", // SKINCOLOR_SUPERPERIDOT3,
+ "SUPERPERIDOT4", // SKINCOLOR_SUPERPERIDOT4,
+ "SUPERPERIDOT5", // SKINCOLOR_SUPERPERIDOT5,
- "SUPERCYAN1", // SKINCOLOR_SUPERCYAN1
- "SUPERCYAN2", // SKINCOLOR_SUPERCYAN2,
- "SUPERCYAN3", // SKINCOLOR_SUPERCYAN3,
- "SUPERCYAN4", // SKINCOLOR_SUPERCYAN4,
- "SUPERCYAN5", // SKINCOLOR_SUPERCYAN5,
+ "SUPERSKY1", // SKINCOLOR_SUPERSKY1
+ "SUPERSKY2", // SKINCOLOR_SUPERSKY2,
+ "SUPERSKY3", // SKINCOLOR_SUPERSKY3,
+ "SUPERSKY4", // SKINCOLOR_SUPERSKY4,
+ "SUPERSKY5", // SKINCOLOR_SUPERSKY5,
- "SUPERPURPLE1", // SKINCOLOR_SUPERPURPLE1,
- "SUPERPURPLE2", // SKINCOLOR_SUPERPURPLE2,
- "SUPERPURPLE3", // SKINCOLOR_SUPERPURPLE3,
- "SUPERPURPLE4", // SKINCOLOR_SUPERPURPLE4,
- "SUPERPURPLE5", // SKINCOLOR_SUPERPURPLE5,
+ "SUPERPURPLE1", // SKINCOLOR_SUPERPURPLE1,
+ "SUPERPURPLE2", // SKINCOLOR_SUPERPURPLE2,
+ "SUPERPURPLE3", // SKINCOLOR_SUPERPURPLE3,
+ "SUPERPURPLE4", // SKINCOLOR_SUPERPURPLE4,
+ "SUPERPURPLE5", // SKINCOLOR_SUPERPURPLE5,
- "SUPERRUST1", // SKINCOLOR_SUPERRUST1
- "SUPERRUST2", // SKINCOLOR_SUPERRUST2,
- "SUPERRUST3", // SKINCOLOR_SUPERRUST3,
- "SUPERRUST4", // SKINCOLOR_SUPERRUST4,
- "SUPERRUST5", // SKINCOLOR_SUPERRUST5,
+ "SUPERRUST1", // SKINCOLOR_SUPERRUST1
+ "SUPERRUST2", // SKINCOLOR_SUPERRUST2,
+ "SUPERRUST3", // SKINCOLOR_SUPERRUST3,
+ "SUPERRUST4", // SKINCOLOR_SUPERRUST4,
+ "SUPERRUST5", // SKINCOLOR_SUPERRUST5,
- "SUPERTAN1", // SKINCOLOR_SUPERTAN1
- "SUPERTAN2", // SKINCOLOR_SUPERTAN2,
- "SUPERTAN3", // SKINCOLOR_SUPERTAN3,
- "SUPERTAN4", // SKINCOLOR_SUPERTAN4,
- "SUPERTAN5" // SKINCOLOR_SUPERTAN5,
+ "SUPERTAN1", // SKINCOLOR_SUPERTAN1
+ "SUPERTAN2", // SKINCOLOR_SUPERTAN2,
+ "SUPERTAN3", // SKINCOLOR_SUPERTAN3,
+ "SUPERTAN4", // SKINCOLOR_SUPERTAN4,
+ "SUPERTAN5" // SKINCOLOR_SUPERTAN5,
};
static const char *const POWERS_LIST[] = {
@@ -7043,6 +6820,7 @@ struct {
{"LF_NOSSMUSIC",LF_NOSSMUSIC},
{"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE},
+ {"LF_SAVEGAME",LF_SAVEGAME},
// And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
@@ -7088,6 +6866,7 @@ struct {
{"SH_PROTECTFIRE",SH_PROTECTFIRE},
{"SH_PROTECTWATER",SH_PROTECTWATER},
{"SH_PROTECTELECTRIC",SH_PROTECTELECTRIC},
+ {"SH_PROTECTSPIKE",SH_PROTECTSPIKE},
// Indivisible shields
{"SH_PITY",SH_PITY},
{"SH_WHIRLWIND",SH_WHIRLWIND},
diff --git a/src/dehacked.h b/src/dehacked.h
index 8832216b8..dfce996a2 100644
--- a/src/dehacked.h
+++ b/src/dehacked.h
@@ -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);
diff --git a/src/doomdata.h b/src/doomdata.h
index 033cc71b3..c0586fd65 100644
--- a/src/doomdata.h
+++ b/src/doomdata.h
@@ -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
diff --git a/src/doomdef.h b/src/doomdef.h
index 16d7fa218..4d6bf75bb 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -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
diff --git a/src/doomstat.h b/src/doomstat.h
index a3b07c9cb..a24bad79d 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -41,7 +41,8 @@ extern INT16 maptol;
extern UINT8 globalweather;
extern INT32 curWeather;
extern INT32 cursaveslot;
-extern INT16 lastmapsaved;
+//extern INT16 lastmapsaved;
+extern INT16 lastmaploaded;
extern boolean gamecomplete;
#define PRECIP_NONE 0
@@ -263,6 +264,7 @@ typedef struct
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
#define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title
+#define LF_SAVEGAME 32 ///< Save the game upon loading this level
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen
diff --git a/src/g_game.c b/src/g_game.c
index 7769555ba..e996938ab 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -77,7 +77,8 @@ INT16 maptol;
UINT8 globalweather = 0;
INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = -1; // Auto-save 1p savegame slot
-INT16 lastmapsaved = 0; // Last map we auto-saved at
+//INT16 lastmapsaved = 0; // Last map we auto-saved at
+INT16 lastmaploaded = 0; // Last map the game loaded
boolean gamecomplete = false;
UINT16 mainwads = 0;
@@ -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;
diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c
index a32609fc8..fa5bce308 100644
--- a/src/hardware/hw_bsp.c
+++ b/src/hardware/hw_bsp.c
@@ -878,8 +878,8 @@ static void AdjustSegs(void)
count = subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline];
p = extrasubsectors[i].planepoly;
- if (!p)
- continue;
+ //if (!p)
+ //continue;
for (; count--; lseg++)
{
float distv1,distv2,tmp;
@@ -892,29 +892,31 @@ static void AdjustSegs(void)
continue;
#endif
- for (j = 0; j < p->numpts; j++)
- {
- distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
- tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
- distv1 = distv1*distv1+tmp*tmp;
- if (distv1 <= nearv1)
+ if (p) {
+ for (j = 0; j < p->numpts; j++)
{
- v1found = j;
- nearv1 = distv1;
- }
- // the same with v2
- distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
- tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
- distv2 = distv2*distv2+tmp*tmp;
- if (distv2 <= nearv2)
- {
- v2found = j;
- nearv2 = distv2;
+ distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
+ tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
+ distv1 = distv1*distv1+tmp*tmp;
+ if (distv1 <= nearv1)
+ {
+ v1found = j;
+ nearv1 = distv1;
+ }
+ // the same with v2
+ distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
+ tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
+ distv2 = distv2*distv2+tmp*tmp;
+ if (distv2 <= nearv2)
+ {
+ v2found = j;
+ nearv2 = distv2;
+ }
}
}
- if (nearv1 <= NEARDIST*NEARDIST)
+ if (p && nearv1 <= NEARDIST*NEARDIST)
// share vertice with segs
- lseg->v1 = (vertex_t *)&(p->pts[v1found]);
+ lseg->pv1 = &(p->pts[v1found]);
else
{
// BP: here we can do better, using PointInSeg and compute
@@ -925,24 +927,24 @@ static void AdjustSegs(void)
polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v1->x);
pv->y = FIXED_TO_FLOAT(lseg->v1->y);
- lseg->v1 = (vertex_t *)pv;
+ lseg->pv1 = pv;
}
- if (nearv2 <= NEARDIST*NEARDIST)
- lseg->v2 = (vertex_t *)&(p->pts[v2found]);
+ if (p && nearv2 <= NEARDIST*NEARDIST)
+ lseg->pv2 = &(p->pts[v2found]);
else
{
polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v2->x);
pv->y = FIXED_TO_FLOAT(lseg->v2->y);
- lseg->v2 = (vertex_t *)pv;
+ lseg->pv2 = pv;
}
// recompute length
{
float x,y;
- x = ((polyvertex_t *)lseg->v2)->x - ((polyvertex_t *)lseg->v1)->x
+ x = ((polyvertex_t *)lseg->pv2)->x - ((polyvertex_t *)lseg->pv1)->x
+ FIXED_TO_FLOAT(FRACUNIT/2);
- y = ((polyvertex_t *)lseg->v2)->y - ((polyvertex_t *)lseg->v1)->y
+ y = ((polyvertex_t *)lseg->pv2)->y - ((polyvertex_t *)lseg->pv1)->y
+ FIXED_TO_FLOAT(FRACUNIT/2);
lseg->flength = (float)hypot(x, y);
// BP: debug see this kind of segs
diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c
new file mode 100644
index 000000000..8b01cabd5
--- /dev/null
+++ b/src/hardware/hw_clip.c
@@ -0,0 +1,465 @@
+/* Emacs style mode select -*- C++ -*-
+ *-----------------------------------------------------------------------------
+ *
+ *
+ * PrBoom: a Doom port merged with LxDoom and LSDLDoom
+ * based on BOOM, a modified and improved DOOM engine
+ * Copyright (C) 1999 by
+ * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
+ * Copyright (C) 1999-2000 by
+ * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
+ * Copyright 2005, 2006 by
+ * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * DESCRIPTION:
+ *
+ *---------------------------------------------------------------------
+ */
+
+/*
+ *
+ ** gl_clipper.cpp
+ **
+ ** Handles visibility checks.
+ ** Loosely based on the JDoom clipper.
+ **
+ **---------------------------------------------------------------------------
+ ** Copyright 2003 Tim Stump
+ ** All rights reserved.
+ **
+ ** Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions
+ ** are met:
+ **
+ ** 1. Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** 2. Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in the
+ ** documentation and/or other materials provided with the distribution.
+ ** 3. The name of the author may not be used to endorse or promote products
+ ** derived from this software without specific prior written permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **---------------------------------------------------------------------------
+ **
+ */
+
+#include
+#include "../v_video.h"
+#include "hw_clip.h"
+#include "hw_glob.h"
+#include "../r_state.h"
+#include "../tables.h"
+#include "r_opengl/r_opengl.h"
+
+#ifdef HAVE_SPHEREFRUSTRUM
+static GLdouble viewMatrix[16];
+static GLdouble projMatrix[16];
+float frustum[6][4];
+#endif
+
+typedef struct clipnode_s
+ {
+ struct clipnode_s *prev, *next;
+ angle_t start, end;
+ } clipnode_t;
+
+clipnode_t *freelist;
+clipnode_t *clipnodes;
+clipnode_t *cliphead;
+
+static clipnode_t * gld_clipnode_GetNew(void);
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end);
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle);
+static void gld_clipper_AddClipRange(angle_t start, angle_t end);
+static void gld_clipper_RemoveRange(clipnode_t * range);
+static void gld_clipnode_Free(clipnode_t *node);
+
+static clipnode_t * gld_clipnode_GetNew(void)
+{
+ if (freelist)
+ {
+ clipnode_t * p = freelist;
+ freelist = p->next;
+ return p;
+ }
+ else
+ {
+ return (clipnode_t*)malloc(sizeof(clipnode_t));
+ }
+}
+
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end)
+{
+ clipnode_t * c = gld_clipnode_GetNew();
+ c->start = start;
+ c->end = end;
+ c->next = c->prev=NULL;
+ return c;
+}
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle)
+{
+ if(startAngle > endAngle)
+ {
+ return (gld_clipper_IsRangeVisible(startAngle, ANGLE_MAX) || gld_clipper_IsRangeVisible(0, endAngle));
+ }
+
+ return gld_clipper_IsRangeVisible(startAngle, endAngle);
+}
+
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle)
+{
+ clipnode_t *ci;
+ ci = cliphead;
+
+ if (endAngle == 0 && ci && ci->start == 0)
+ return false;
+
+ while (ci != NULL && ci->start < endAngle)
+ {
+ if (startAngle >= ci->start && endAngle <= ci->end)
+ {
+ return false;
+ }
+ ci = ci->next;
+ }
+
+ return true;
+}
+
+static void gld_clipnode_Free(clipnode_t *node)
+{
+ node->next = freelist;
+ freelist = node;
+}
+
+static void gld_clipper_RemoveRange(clipnode_t *range)
+{
+ if (range == cliphead)
+ {
+ cliphead = cliphead->next;
+ }
+ else
+ {
+ if (range->prev)
+ {
+ range->prev->next = range->next;
+ }
+ if (range->next)
+ {
+ range->next->prev = range->prev;
+ }
+ }
+
+ gld_clipnode_Free(range);
+}
+
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle)
+{
+ if(startangle > endangle)
+ {
+ // The range has to added in two parts.
+ gld_clipper_AddClipRange(startangle, ANGLE_MAX);
+ gld_clipper_AddClipRange(0, endangle);
+ }
+ else
+ {
+ // Add the range as usual.
+ gld_clipper_AddClipRange(startangle, endangle);
+ }
+}
+
+static void gld_clipper_AddClipRange(angle_t start, angle_t end)
+{
+ clipnode_t *node, *temp, *prevNode, *node2, *delnode;
+
+ if (cliphead)
+ {
+ //check to see if range contains any old ranges
+ node = cliphead;
+ while (node != NULL && node->start < end)
+ {
+ if (node->start >= start && node->end <= end)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipper_RemoveRange(temp);
+ }
+ else
+ {
+ if (node->start <= start && node->end >= end)
+ {
+ return;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+ }
+
+ //check to see if range overlaps a range (or possibly 2)
+ node = cliphead;
+ while (node != NULL && node->start <= end)
+ {
+ if (node->end >= start)
+ {
+ // we found the first overlapping node
+ if (node->start > start)
+ {
+ // the new range overlaps with this node's start point
+ node->start = start;
+ }
+ if (node->end < end)
+ {
+ node->end = end;
+ }
+
+ node2 = node->next;
+ while (node2 && node2->start <= node->end)
+ {
+ if (node2->end > node->end)
+ {
+ node->end = node2->end;
+ }
+
+ delnode = node2;
+ node2 = node2->next;
+ gld_clipper_RemoveRange(delnode);
+ }
+ return;
+ }
+ node = node->next;
+ }
+
+ //just add range
+ node = cliphead;
+ prevNode = NULL;
+ temp = gld_clipnode_NewRange(start, end);
+ while (node != NULL && node->start < end)
+ {
+ prevNode = node;
+ node = node->next;
+ }
+ temp->next = node;
+ if (node == NULL)
+ {
+ temp->prev = prevNode;
+ if (prevNode)
+ {
+ prevNode->next = temp;
+ }
+ if (!cliphead)
+ {
+ cliphead = temp;
+ }
+ }
+ else
+ {
+ if (node == cliphead)
+ {
+ cliphead->prev = temp;
+ cliphead = temp;
+ }
+ else
+ {
+ temp->prev = prevNode;
+ prevNode->next = temp;
+ node->prev = temp;
+ }
+ }
+ }
+ else
+ {
+ temp = gld_clipnode_NewRange(start, end);
+ cliphead = temp;
+ return;
+ }
+}
+
+void gld_clipper_Clear(void)
+{
+ clipnode_t *node = cliphead;
+ clipnode_t *temp;
+
+ while (node != NULL)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipnode_Free(temp);
+ }
+
+ cliphead = NULL;
+}
+
+#define RMUL (1.6f/1.333333f)
+
+angle_t gld_FrustumAngle(void)
+{
+ double floatangle;
+ angle_t a1;
+
+ float tilt = (float)fabs(((double)(int)aimingangle) / ANG1);
+
+ // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
+
+ float render_fov = FIXED_TO_FLOAT(cv_grfov.value);
+ float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
+ float render_multiplier = 64.0f / render_fovratio / RMUL;
+
+ if (tilt > 90.0f)
+ {
+ tilt = 90.0f;
+ }
+
+ // If the pitch is larger than this you can look all around at a FOV of 90
+ if (abs(aimingangle) > 46 * ANG1)
+ return 0xffffffff;
+
+ // ok, this is a gross hack that barely works...
+ // but at least it doesn't overestimate too much...
+ floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * (float)render_fov * 48.0f / render_multiplier / 90.0f;
+ a1 = ANG1 * (int)floatangle;
+ if (a1 >= ANGLE_180)
+ return 0xffffffff;
+ return a1;
+}
+
+// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
+// compiler complains about (p)glGetDoublev anyway, in case anyone wants this
+// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
+// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
+#ifdef HAVE_SPHEREFRUSTRUM
+//
+// gld_FrustrumSetup
+//
+
+#define CALCMATRIX(a, b, c, d, e, f, g, h)\
+(float)(viewMatrix[a] * projMatrix[b] + \
+viewMatrix[c] * projMatrix[d] + \
+viewMatrix[e] * projMatrix[f] + \
+viewMatrix[g] * projMatrix[h])
+
+#define NORMALIZE_PLANE(i)\
+t = (float)sqrt(\
+frustum[i][0] * frustum[i][0] + \
+frustum[i][1] * frustum[i][1] + \
+frustum[i][2] * frustum[i][2]); \
+frustum[i][0] /= t; \
+frustum[i][1] /= t; \
+frustum[i][2] /= t; \
+frustum[i][3] /= t
+
+void gld_FrustrumSetup(void)
+{
+ float t;
+ float clip[16];
+
+ pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+ pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
+
+ clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
+ clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);
+ clip[2] = CALCMATRIX(0, 2, 1, 6, 2, 10, 3, 14);
+ clip[3] = CALCMATRIX(0, 3, 1, 7, 2, 11, 3, 15);
+
+ clip[4] = CALCMATRIX(4, 0, 5, 4, 6, 8, 7, 12);
+ clip[5] = CALCMATRIX(4, 1, 5, 5, 6, 9, 7, 13);
+ clip[6] = CALCMATRIX(4, 2, 5, 6, 6, 10, 7, 14);
+ clip[7] = CALCMATRIX(4, 3, 5, 7, 6, 11, 7, 15);
+
+ clip[8] = CALCMATRIX(8, 0, 9, 4, 10, 8, 11, 12);
+ clip[9] = CALCMATRIX(8, 1, 9, 5, 10, 9, 11, 13);
+ clip[10] = CALCMATRIX(8, 2, 9, 6, 10, 10, 11, 14);
+ clip[11] = CALCMATRIX(8, 3, 9, 7, 10, 11, 11, 15);
+
+ clip[12] = CALCMATRIX(12, 0, 13, 4, 14, 8, 15, 12);
+ clip[13] = CALCMATRIX(12, 1, 13, 5, 14, 9, 15, 13);
+ clip[14] = CALCMATRIX(12, 2, 13, 6, 14, 10, 15, 14);
+ clip[15] = CALCMATRIX(12, 3, 13, 7, 14, 11, 15, 15);
+
+ // Right plane
+ frustum[0][0] = clip[ 3] - clip[ 0];
+ frustum[0][1] = clip[ 7] - clip[ 4];
+ frustum[0][2] = clip[11] - clip[ 8];
+ frustum[0][3] = clip[15] - clip[12];
+ NORMALIZE_PLANE(0);
+
+ // Left plane
+ frustum[1][0] = clip[ 3] + clip[ 0];
+ frustum[1][1] = clip[ 7] + clip[ 4];
+ frustum[1][2] = clip[11] + clip[ 8];
+ frustum[1][3] = clip[15] + clip[12];
+ NORMALIZE_PLANE(1);
+
+ // Bottom plane
+ frustum[2][0] = clip[ 3] + clip[ 1];
+ frustum[2][1] = clip[ 7] + clip[ 5];
+ frustum[2][2] = clip[11] + clip[ 9];
+ frustum[2][3] = clip[15] + clip[13];
+ NORMALIZE_PLANE(2);
+
+ // Top plane
+ frustum[3][0] = clip[ 3] - clip[ 1];
+ frustum[3][1] = clip[ 7] - clip[ 5];
+ frustum[3][2] = clip[11] - clip[ 9];
+ frustum[3][3] = clip[15] - clip[13];
+ NORMALIZE_PLANE(3);
+
+ // Far plane
+ frustum[4][0] = clip[ 3] - clip[ 2];
+ frustum[4][1] = clip[ 7] - clip[ 6];
+ frustum[4][2] = clip[11] - clip[10];
+ frustum[4][3] = clip[15] - clip[14];
+ NORMALIZE_PLANE(4);
+
+ // Near plane
+ frustum[5][0] = clip[ 3] + clip[ 2];
+ frustum[5][1] = clip[ 7] + clip[ 6];
+ frustum[5][2] = clip[11] + clip[10];
+ frustum[5][3] = clip[15] + clip[14];
+ NORMALIZE_PLANE(5);
+}
+
+boolean gld_SphereInFrustum(float x, float y, float z, float radius)
+{
+ int p;
+
+ for (p = 0; p < 4; p++)
+ {
+ if (frustum[p][0] * x +
+ frustum[p][1] * y +
+ frustum[p][2] * z +
+ frustum[p][3] <= -radius)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+#endif
diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h
new file mode 100644
index 000000000..3ba26e5e5
--- /dev/null
+++ b/src/hardware/hw_clip.h
@@ -0,0 +1,24 @@
+/*
+ * hw_clip.h
+ * SRB2CB
+ *
+ * PrBoom's OpenGL clipping
+ *
+ *
+ */
+
+// OpenGL BSP clipping
+#include "../doomdef.h"
+#include "../tables.h"
+#include "../doomtype.h"
+
+//#define HAVE_SPHEREFRUSTRUM // enable if you want gld_SphereInFrustum and related code
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
+void gld_clipper_Clear(void);
+angle_t gld_FrustumAngle(void);
+#ifdef HAVE_SPHEREFRUSTRUM
+void gld_FrustrumSetup(void);
+boolean gld_SphereInFrustum(float x, float y, float z, float radius);
+#endif
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index cf9b1c536..267666749 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -323,6 +323,10 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_BMCH
&lspr[NOLIGHT], // SPR_SMCE
&lspr[NOLIGHT], // SPR_BMCE
+ &lspr[NOLIGHT], // SPR_YSPB
+ &lspr[NOLIGHT], // SPR_RSPB
+ &lspr[REDBALL_L], // SPR_SFBR
+ &lspr[REDBALL_L], // SPR_BFBR
// Arid Canyon Scenery
&lspr[NOLIGHT], // SPR_BTBL
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 3bc071f5c..d74cd0587 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -44,6 +44,10 @@
#endif
#include "hw_md2.h"
+#ifdef NEWCLIP
+#include "hw_clip.h"
+#endif
+
#define R_FAKEFLOORS
#define HWPRECIP
#define SORTING
@@ -99,8 +103,9 @@ CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NU
boolean drawsky = true;
// needs fix: walls are incorrectly clipped one column less
+#ifndef NEWCLIP
static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-
+#endif
//development variables for diverse uses
static consvar_t cv_gralpha = {"gr_alpha", "160", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -323,9 +328,6 @@ static angle_t gr_xtoviewangle[MAXVIDWIDTH+1];
// test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK
-/// \note crappy
-#define drawtextured true
-
// base values set at SetViewSize
static float gr_basecentery;
@@ -852,11 +854,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
M_ClearBox(segbbox);
M_AddToBox(segbbox,
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x),
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y));
M_AddToBox(segbbox,
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x),
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y));
splat = (wallsplat_t *)gr_curline->linedef->splats;
for (; splat; splat = splat->next)
@@ -1029,6 +1031,7 @@ static void HWR_ProjectWall(wallVert3D * wallVerts,
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment
//
+#ifndef NEWCLIP
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
{
float num, den;
@@ -1057,6 +1060,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
return num / den;
}
+#endif
//
// HWR_SplitWall
@@ -1431,7 +1435,11 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
// Anything between means the wall segment has been clipped with solidsegs,
// reducing wall overdraw to a minimum
//
+#ifdef NEWCLIP
+static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
+#else
static void HWR_StoreWallRange(double startfrac, double endfrac)
+#endif
{
wallVert3D wallVerts[4];
v2d_t vs, ve; // start, end vertices of 2d line (view from above)
@@ -1456,16 +1464,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
extracolormap_t *colormap;
FSurfaceInfo Surf;
+#ifndef NEWCLIP
if (startfrac > endfrac)
return;
+#endif
gr_sidedef = gr_curline->sidedef;
gr_linedef = gr_curline->linedef;
- vs.x = ((polyvertex_t *)gr_curline->v1)->x;
- vs.y = ((polyvertex_t *)gr_curline->v1)->y;
- ve.x = ((polyvertex_t *)gr_curline->v2)->x;
- ve.y = ((polyvertex_t *)gr_curline->v2)->y;
+ vs.x = ((polyvertex_t *)gr_curline->pv1)->x;
+ vs.y = ((polyvertex_t *)gr_curline->pv1)->y;
+ ve.x = ((polyvertex_t *)gr_curline->pv2)->x;
+ ve.y = ((polyvertex_t *)gr_curline->pv2)->y;
#ifdef ESLOPE
v1x = FLOAT_TO_FIXED(vs.x);
@@ -1473,44 +1483,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
v2x = FLOAT_TO_FIXED(ve.x);
v2y = FLOAT_TO_FIXED(ve.y);
#endif
-
- if (gr_frontsector->heightsec != -1)
- {
#ifdef ESLOPE
- worldtop = worldtopslope = sectors[gr_frontsector->heightsec].ceilingheight;
- worldbottom = worldbottomslope = sectors[gr_frontsector->heightsec].floorheight;
-#else
- worldtop = sectors[gr_frontsector->heightsec].ceilingheight;
- worldbottom = sectors[gr_frontsector->heightsec].floorheight;
-#endif
- }
- else
- {
-#ifdef ESLOPE
- if (gr_frontsector->c_slope)
- {
- worldtop = P_GetZAt(gr_frontsector->c_slope, v1x, v1y);
- worldtopslope = P_GetZAt(gr_frontsector->c_slope, v2x, v2y);
- }
- else
- {
- worldtop = worldtopslope = gr_frontsector->ceilingheight;
- }
- if (gr_frontsector->f_slope)
- {
- worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y);
- worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y);
- }
- else
- {
- worldbottom = worldbottomslope = gr_frontsector->floorheight;
- }
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight)
+ SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
#else
- worldtop = gr_frontsector->ceilingheight;
- worldbottom = gr_frontsector->floorheight;
+ worldtop = gr_frontsector->ceilingheight;
+ worldbottom = gr_frontsector->floorheight;
#endif
- }
// remember vertices ordering
// 3--2
@@ -1525,20 +1512,23 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[2].z = wallVerts[1].z = ve.y;
wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f;
- if (drawtextured)
{
// x offset the texture
fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset;
+#ifndef NEWCLIP
// clip texture s start/end coords with solidsegs
if (startfrac > 0.0f && startfrac < 1.0f)
cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac);
else
+#endif
cliplow = (float)texturehpeg;
+#ifndef NEWCLIP
if (endfrac > 0.0f && endfrac < 1.0f)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac);
else
+#endif
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
}
@@ -1554,43 +1544,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{
INT32 gr_toptexture, gr_bottomtexture;
// two sided line
- if (gr_backsector->heightsec != -1)
- {
-#ifdef ESLOPE
- worldhigh = worldhighslope = sectors[gr_backsector->heightsec].ceilingheight;
- worldlow = worldlowslope = sectors[gr_backsector->heightsec].floorheight;
-#else
- worldhigh = sectors[gr_backsector->heightsec].ceilingheight;
- worldlow = sectors[gr_backsector->heightsec].floorheight;
-#endif
- }
- else
- {
-#ifdef ESLOPE
- if (gr_backsector->c_slope)
- {
- worldhigh = P_GetZAt(gr_backsector->c_slope, v1x, v1y);
- worldhighslope = P_GetZAt(gr_backsector->c_slope, v2x, v2y);
- }
- else
- {
- worldhigh = worldhighslope = gr_backsector->ceilingheight;
- }
- if (gr_backsector->f_slope)
- {
- worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y);
- worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y);
- }
- else
- {
- worldlow = worldlowslope = gr_backsector->floorheight;
- }
+#ifdef ESLOPE
+ SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight)
+ SLOPEPARAMS(gr_backsector->f_slope, worldlow, worldlowslope, gr_backsector->floorheight)
+#undef SLOPEPARAMS
#else
- worldhigh = gr_backsector->ceilingheight;
- worldlow = gr_backsector->floorheight;
+ worldhigh = gr_backsector->ceilingheight;
+ worldlow = gr_backsector->floorheight;
#endif
- }
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
@@ -1614,7 +1576,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
worldhigh < worldtop
) && gr_toptexture)
{
- if (drawtextured)
{
fixed_t texturevpegtop; // top
@@ -1695,7 +1656,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
#endif
worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
{
- if (drawtextured)
{
fixed_t texturevpegbottom = 0; // bottom
@@ -1887,7 +1847,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
#ifdef ESLOPE
@@ -1943,7 +1902,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
@@ -2135,7 +2093,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
if (gr_midtexture)
{
- if (drawtextured)
{
fixed_t texturevpeg;
// PEGGING
@@ -2276,7 +2233,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
}
- else if (drawtextured)
+ else
{
#ifdef ESLOPE // P.S. this is better-organized than the old version
fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset;
@@ -2409,7 +2366,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
}
- else if (drawtextured)
+ else
{
grTex = HWR_GetTexture(texnum);
@@ -2482,6 +2439,110 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
//Hurdler: end of 3d-floors test
}
+// From PrBoom:
+//
+// e6y: Check whether the player can look beyond this line
+//
+#ifdef NEWCLIP
+boolean checkforemptylines = true;
+// Don't modify anything here, just check
+// Kalaron: Modified for sloped linedefs
+static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector)
+{
+ fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
+ fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
+
+ // GZDoom method of sloped line clipping
+
+#ifdef ESLOPE
+ if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope)
+ {
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight)
+ SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight)
+ SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight)
+ SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
+#undef SLOPEPARAMS
+ }
+ else
+#endif
+ {
+ frontf1 = frontf2 = afrontsector->floorheight;
+ frontc1 = frontc2 = afrontsector->ceilingheight;
+ backf1 = backf2 = abacksector->floorheight;
+ backc1 = backc2 = abacksector->ceilingheight;
+ }
+
+ // now check for closed sectors!
+ if (backc1 <= frontf1 && backc2 <= frontf2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->toptexture)
+ return false;
+
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backf1 >= frontc1 && backf2 >= frontc2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->bottomtexture)
+ return false;
+
+ // properly render skies (consider door "open" if both floors are sky):
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 <= backf1 && backc2 <= backf2)
+ {
+ checkforemptylines = false;
+ // preserve a kind of transparent door/lift special effect:
+ if (backc1 < frontc1 || backc2 < frontc2)
+ {
+ if (!seg->sidedef->toptexture)
+ return false;
+ }
+ if (backf1 > frontf1 || backf2 > frontf2)
+ {
+ if (!seg->sidedef->bottomtexture)
+ return false;
+ }
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 != frontc1 || backc2 != frontc2
+ || backf1 != frontf1 || backf2 != frontf2)
+ {
+ checkforemptylines = false;
+ return false;
+ }
+
+ return false;
+}
+#else
//Hurdler: just like in r_bsp.c
#if 1
#define MAXSEGS MAXVIDWIDTH/2+1
@@ -2553,7 +2614,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
// Now adjust the clip size.
@@ -2577,8 +2638,8 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
- highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
+ highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
next++;
@@ -2612,7 +2673,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
@@ -2675,8 +2736,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else
{
highfrac = HWR_ClipViewSegment(min(start->first + 1,
- start->last), (polyvertex_t *)gr_curline->v1,
- (polyvertex_t *)gr_curline->v2);
+ start->last), (polyvertex_t *)gr_curline->pv1,
+ (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
}
@@ -2695,8 +2756,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
- highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
+ highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
start++;
@@ -2726,8 +2787,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else
{
lowfrac = HWR_ClipViewSegment(max(start->last - 1,
- start->first), (polyvertex_t *)gr_curline->v1,
- (polyvertex_t *)gr_curline->v2);
+ start->first), (polyvertex_t *)gr_curline->pv1,
+ (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
@@ -2767,6 +2828,7 @@ static void HWR_ClearClipSegs(void)
gr_solidsegs[1].last = 0x7fffffff;
hw_newend = gr_solidsegs+2;
}
+#endif // NEWCLIP
// -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
@@ -2775,24 +2837,46 @@ static void HWR_ClearClipSegs(void)
// -----------------+
static void HWR_AddLine(seg_t * line)
{
- INT32 x1, x2;
angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 x1, x2;
angle_t span, tspan;
+#endif
// SoM: Backsector needs to be run through R_FakeFlat
sector_t tempsec;
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+#ifdef POLYOBJECTS
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
+#endif
gr_curline = line;
- // OPTIMIZE: quickly reject orthogonal back sides.
- angle1 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
- angle2 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+ // OPTIMIZE: quickly reject orthogonal back sides.
+ angle1 = R_PointToAngle(v1x, v1y);
+ angle2 = R_PointToAngle(v2x, v2y);
+
+#ifdef NEWCLIP
+ // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
+ if (angle2 - angle1 < ANGLE_180)
+ return;
+
+ // PrBoom: use REAL clipping math YAYYYYYYY!!!
+
+ if (!gld_clipper_SafeCheckRange(angle2, angle1))
+ {
+ return;
+ }
+
+ checkforemptylines = true;
+#else
// Clip to view edges.
span = angle1 - angle2;
@@ -2833,8 +2917,8 @@ static void HWR_AddLine(seg_t * line)
float fx1,fx2,fy1,fy2;
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
// do not enable this at release 4 mul and 2 div
- fx1 = ((polyvertex_t *)(line->v1))->x-gr_viewx;
- fy1 = ((polyvertex_t *)(line->v1))->y-gr_viewy;
+ fx1 = ((polyvertex_t *)(line->pv1))->x-gr_viewx;
+ fy1 = ((polyvertex_t *)(line->pv1))->y-gr_viewy;
fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin);
if (fy2 < 0)
// the point is back
@@ -2842,8 +2926,8 @@ static void HWR_AddLine(seg_t * line)
else
fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2;
- fx2 = ((polyvertex_t *)(line->v2))->x-gr_viewx;
- fy2 = ((polyvertex_t *)(line->v2))->y-gr_viewy;
+ fx2 = ((polyvertex_t *)(line->pv2))->x-gr_viewx;
+ fy2 = ((polyvertex_t *)(line->pv2))->y-gr_viewy;
fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin);
if (fy1 < 0)
// the point is back
@@ -2871,8 +2955,34 @@ static void HWR_AddLine(seg_t * line)
return;
}
*/
+#endif
+
gr_backsector = line->backsector;
+#ifdef NEWCLIP
+ if (!line->backsector)
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ }
+ else
+ {
+ gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true);
+ if (CheckClip(line, gr_frontsector, gr_backsector))
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ checkforemptylines = false;
+ }
+ // Reject empty lines used for triggers and special events.
+ // Identical floor and ceiling on both sides,
+ // identical light levels on both sides,
+ // and no middle texture.
+ if (checkforemptylines && R_IsEmptyLine(line, gr_frontsector, gr_backsector))
+ return;
+ }
+
+ HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
+ return;
+#else
// Single sided line?
if (!gr_backsector)
goto clipsolid;
@@ -2882,14 +2992,9 @@ static void HWR_AddLine(seg_t * line)
#ifdef ESLOPE
if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_backsector->c_slope)
{
- fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
- v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x);
- v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y);
- v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x);
- v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y);
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \
@@ -2910,6 +3015,13 @@ static void HWR_AddLine(seg_t * line)
goto clipsolid;
}
+ // Check for automap fix.
+ if (backc1 <= backf1 && backc2 <= backf2
+ && ((backc1 >= frontc1 && backc2 >= frontc2) || gr_curline->sidedef->toptexture)
+ && ((backf1 <= frontf1 && backf2 >= frontf2) || gr_curline->sidedef->bottomtexture)
+ && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
+ goto clipsolid;
+
// Window.
if (backc1 != frontc1 || backc2 != frontc2
|| backf1 != frontf1 || backf2 != frontf2)
@@ -2925,6 +3037,13 @@ static void HWR_AddLine(seg_t * line)
gr_backsector->floorheight >= gr_frontsector->ceilingheight)
goto clipsolid;
+ // Check for automap fix.
+ if (gr_backsector->ceilingheight <= gr_backsector->floorheight
+ && ((gr_backsector->ceilingheight >= gr_frontsector->ceilingheight) || gr_curline->sidedef->toptexture)
+ && ((gr_backsector->floorheight <= gr_backsector->floorheight) || gr_curline->sidedef->bottomtexture)
+ && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
+ goto clipsolid;
+
// Window.
if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight ||
gr_backsector->floorheight != gr_frontsector->floorheight)
@@ -2935,25 +3054,8 @@ static void HWR_AddLine(seg_t * line)
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
- if (
-#ifdef POLYOBJECTS
- !line->polyseg &&
-#endif
- gr_backsector->ceilingpic == gr_frontsector->ceilingpic
- && gr_backsector->floorpic == gr_frontsector->floorpic
-#ifdef ESLOPE
- && gr_backsector->f_slope == gr_frontsector->f_slope
- && gr_backsector->c_slope == gr_frontsector->c_slope
-#endif
- && gr_backsector->lightlevel == gr_frontsector->lightlevel
- && gr_curline->sidedef->midtexture == 0
- && !gr_backsector->ffloors && !gr_frontsector->ffloors)
- // SoM: For 3D sides... Boris, would you like to take a
- // crack at rendering 3D sides? You would need to add the
- // above check and add code to HWR_StoreWallRange...
- {
+ if (R_IsEmptyLine(gr_curline, gr_frontsector, gr_backsector))
return;
- }
clippass:
if (x1 == x2)
@@ -2965,6 +3067,7 @@ clipsolid:
if (x1 == x2)
goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1);
+#endif
}
// HWR_CheckBBox
@@ -2976,9 +3079,13 @@ clipsolid:
static boolean HWR_CheckBBox(fixed_t *bspcoord)
{
- INT32 boxpos, sx1, sx2;
+ INT32 boxpos;
fixed_t px1, py1, px2, py2;
- angle_t angle1, angle2, span, tspan;
+ angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 sx1, sx2;
+ angle_t span, tspan;
+#endif
// Find the corners of the box
// that define the edges from current viewpoint.
@@ -3004,6 +3111,11 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]];
+#ifdef NEWCLIP
+ angle1 = R_PointToAngle(px1, py1);
+ angle2 = R_PointToAngle(px2, py2);
+ return gld_clipper_SafeCheckRange(angle2, angle1);
+#else
// check clip list for an open space
angle1 = R_PointToAngle(px1, py1) - dup_viewangle;
angle2 = R_PointToAngle(px2, py2) - dup_viewangle;
@@ -3051,6 +3163,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
+#endif
}
#ifdef POLYOBJECTS
@@ -3084,8 +3197,8 @@ static inline void HWR_AddPolyObjectSegs(void)
pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x);
pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y);
- gr_fakeline->v1 = (vertex_t *)pv1;
- gr_fakeline->v2 = (vertex_t *)pv2;
+ gr_fakeline->pv1 = pv1;
+ gr_fakeline->pv2 = pv2;
HWR_AddLine(gr_fakeline);
}
@@ -5630,7 +5743,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5640,6 +5765,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5666,6 +5792,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -5860,7 +5987,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5870,6 +6009,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5896,6 +6036,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -6041,7 +6182,9 @@ static inline void HWR_AddEngineCommands(void)
{
// engine state variables
//CV_RegisterVar(&cv_grzbuffer);
+#ifndef NEWCLIP
CV_RegisterVar(&cv_grclipwalls);
+#endif
// engine development mode variables
// - usage may vary from version to version..
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 7edf02db0..df2c9f59a 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -298,8 +298,8 @@ static md2_model_t *md2_readModel(const char *filename)
// initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1
- || model->header.magic !=
- (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I'))
+ || model->header.magic != MD2_IDENT
+ || model->header.version != MD2_VERSION)
{
fclose(file);
free(model);
@@ -313,6 +313,7 @@ static md2_model_t *md2_readModel(const char *filename)
{ \
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
md2_freeModel (model); \
+ fclose(file); \
return 0; \
}
@@ -334,6 +335,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -347,6 +349,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -360,6 +363,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -372,6 +376,7 @@ static md2_model_t *md2_readModel(const char *filename)
if (!model->frames)
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
@@ -385,6 +390,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(frame, 1, model->header.frameSize, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
@@ -410,6 +416,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -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--)
{
diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h
index 5a7e6d2b3..299d12400 100644
--- a/src/hardware/hw_md2.h
+++ b/src/hardware/hw_md2.h
@@ -23,6 +23,11 @@
#include "hw_glob.h"
+// magic number "IDP2" or 844121161
+#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
+// model version
+#define MD2_VERSION 8
+
#define MD2_MAX_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c
index e9ba19efb..97d86b944 100644
--- a/src/hardware/hw_trick.c
+++ b/src/hardware/hw_trick.c
@@ -107,17 +107,17 @@ static void releaseLineChains(void)
for (i = 0; i < numsectors; i++)
{
- sector = §ors[i];
- nextElem = sector->sectorLines;
+ sector = §ors[i];
+ nextElem = sector->sectorLines;
- while (nextElem)
- {
- thisElem = nextElem;
- nextElem = thisElem->next;
- free(thisElem);
- }
+ while (nextElem)
+ {
+ thisElem = nextElem;
+ nextElem = thisElem->next;
+ free(thisElem);
+ }
- sector->sectorLines = NULL;
+ sector->sectorLines = NULL;
}
}
@@ -397,7 +397,7 @@ static void sortStacklist(sector_t *sector)
i = 0;
finished = true;
- while (NULL != *(list+i+1))
+ while (*(list+i+1))
{
sec1 = *(list+i);
sec2 = *(list+i+1);
@@ -438,7 +438,7 @@ static double calcLineoutLength(sector_t *sector)
double length = 0.0L;
chain = sector->sectorLines;
- while (NULL != chain) // sum up lengths of all lines
+ while (chain) // sum up lengths of all lines
{
length += lineLength(chain->line);
chain = chain->next;
@@ -454,7 +454,7 @@ static void calcLineouts(sector_t *sector)
size_t secCount = 0;
sector_t *encSector = *(sector->stackList);
- while (NULL != encSector)
+ while (encSector)
{
if (encSector->lineoutLength < 0.0L) // if length has not yet been calculated
{
@@ -552,7 +552,7 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
if (frontSector == backSector) // skip damn renderer tricks here
continue;
- if (frontSector == NULL || backSector == NULL)
+ if (!frontSector || !backSector)
continue;
sider = &sides[thisElem->line->sidenum[0]];
@@ -587,73 +587,12 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
static boolean isCeilingFloating(sector_t *thisSector)
{
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
- boolean floating = true;
linechain_t *thisElem, *nextElem;
if (!thisSector)
return false;
- nextElem = thisSector->sectorLines;
-
- while (NULL != nextElem) // walk through chain
- {
- thisElem = nextElem;
- nextElem = thisElem->next;
-
- frontSector = thisElem->line->frontsector;
- backSector = thisElem->line->backsector;
-
- if (frontSector == thisSector)
- adjSector = backSector;
- else
- adjSector = frontSector;
-
- if (!adjSector) // assume floating sectors have surrounding sectors
- {
- floating = false;
- break;
- }
-
- if (!refSector)
- {
- refSector = adjSector;
- continue;
- }
-
- // if adjacent sector has same height or more than one adjacent sector exists -> stop
- if (thisSector->ceilingheight == adjSector->ceilingheight ||
- refSector != adjSector)
- {
- floating = false;
- break;
- }
- }
-
- // now check for walltextures
- if (floating)
- {
- if (!areToptexturesMissing(thisSector))
- {
- floating = false;
- }
- }
- return floating;
-}
-
-//
-// check if no adjacent sector has same ceiling height
-// FIXME: throw that together with isCeilingFloating??
-//
-static boolean isFloorFloating(sector_t *thisSector)
-{
- sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
- boolean floating = true;
- linechain_t *thisElem, *nextElem;
-
- if (!thisSector)
- return false;
-
- nextElem = thisSector->sectorLines;
+ nextElem = thisSector->sectorLines;
while (nextElem) // walk through chain
{
@@ -668,36 +607,83 @@ static boolean isFloorFloating(sector_t *thisSector)
else
adjSector = frontSector;
- if (NULL == adjSector) // assume floating sectors have surrounding sectors
- {
- floating = false;
- break;
- }
+ if (!adjSector) // assume floating sectors have surrounding sectors
+ return false;
- if (NULL == refSector)
+#ifdef ESLOPE
+ if (adjSector->c_slope) // Don't bother with slopes
+ return false;
+#endif
+
+ if (!refSector)
{
refSector = adjSector;
continue;
}
// if adjacent sector has same height or more than one adjacent sector exists -> stop
- if (thisSector->floorheight == adjSector->floorheight ||
- refSector != adjSector)
- {
- floating = false;
- break;
- }
+ if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector)
+ return false;
}
// now check for walltextures
- if (floating)
+ if (!areToptexturesMissing(thisSector))
+ return false;
+
+ return true;
+}
+
+//
+// check if no adjacent sector has same ceiling height
+// FIXME: throw that together with isCeilingFloating??
+//
+static boolean isFloorFloating(sector_t *thisSector)
+{
+ sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
+ linechain_t *thisElem, *nextElem;
+
+ if (!thisSector)
+ return false;
+
+ nextElem = thisSector->sectorLines;
+
+ while (nextElem) // walk through chain
{
- if (!areBottomtexturesMissing(thisSector))
+ thisElem = nextElem;
+ nextElem = thisElem->next;
+
+ frontSector = thisElem->line->frontsector;
+ backSector = thisElem->line->backsector;
+
+ if (frontSector == thisSector)
+ adjSector = backSector;
+ else
+ adjSector = frontSector;
+
+ if (!adjSector) // assume floating sectors have surrounding sectors
+ return false;
+
+#ifdef ESLOPE
+ if (adjSector->f_slope) // Don't bother with slopes
+ return false;
+#endif
+
+ if (!refSector)
{
- floating = false;
+ refSector = adjSector;
+ continue;
}
+
+ // if adjacent sector has same height or more than one adjacent sector exists -> stop
+ if (thisSector->floorheight == adjSector->floorheight || refSector != adjSector)
+ return false;
}
- return floating;
+
+ // now check for walltextures
+ if (!areBottomtexturesMissing(thisSector))
+ return false;
+
+ return true;
}
//
@@ -707,14 +693,12 @@ static fixed_t estimateCeilHeight(sector_t *thisSector)
{
sector_t *adjSector;
- if (!thisSector ||
- !thisSector->sectorLines ||
- !thisSector->sectorLines->line)
+ if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
return 0;
adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector)
- adjSector = thisSector->sectorLines->line->backsector;
+ adjSector = thisSector->sectorLines->line->backsector;
if (!adjSector)
return 0;
@@ -729,17 +713,15 @@ static fixed_t estimateFloorHeight(sector_t *thisSector)
{
sector_t *adjSector;
- if (!thisSector ||
- !thisSector->sectorLines ||
- !thisSector->sectorLines->line)
- return 0;
+ if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
+ return 0;
adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector)
- adjSector = thisSector->sectorLines->line->backsector;
+ adjSector = thisSector->sectorLines->line->backsector;
- if (NULL == adjSector)
- return 0;
+ if (!adjSector)
+ return 0;
return adjSector->floorheight;
}
@@ -845,18 +827,12 @@ void HWR_CorrectSWTricks(void)
// correct height of floating sectors
if (isCeilingFloating(floatSector))
{
- fixed_t corrheight;
-
- corrheight = estimateCeilHeight(floatSector);
- floatSector->virtualCeilingheight = corrheight;
+ floatSector->virtualCeilingheight = estimateCeilHeight(floatSector);
floatSector->virtualCeiling = true;
}
if (isFloorFloating(floatSector))
{
- fixed_t corrheight;
-
- corrheight = estimateFloorHeight(floatSector);
- floatSector->virtualFloorheight = corrheight;
+ floatSector->virtualFloorheight = estimateFloorHeight(floatSector);
floatSector->virtualFloor = true;
}
}
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 365ea093b..e92b96995 100644
--- a/src/hu_stuff.c
+++ b/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++;
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index 9bfb42912..e757db85a 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -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)
diff --git a/src/info.c b/src/info.c
index 90bd817f4..2d6c9a3d1 100644
--- a/src/info.c
+++ b/src/info.c
@@ -211,6 +211,10 @@ char sprnames[NUMSPRITES + 1][5] =
"BMCH", // Big Mace Chain
"SMCE", // Small Mace
"BMCE", // Big Mace
+ "YSPB", // Yellow spring on a ball
+ "RSPB", // Red spring on a ball
+ "SFBR", // Small Firebar
+ "BFBR", // Big Firebar
// Arid Canyon Scenery
"BTBL", // Big tumbleweed
@@ -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
},
diff --git a/src/info.h b/src/info.h
index 540c2853b..cd79b12a9 100644
--- a/src/info.h
+++ b/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
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 93f2979fa..be1455415 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -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},
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index b688155fb..559c576f0 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -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;
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 29e4970c1..8175f1b9b 100644
--- a/src/lua_hudlib.c
+++ b/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<= 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<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);
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 622309425..b8a6ea4fd 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -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"))
diff --git a/src/m_cond.c b/src/m_cond.c
index b7735d4ce..9339c4989 100644
--- a/src/m_cond.c
+++ b/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
diff --git a/src/m_menu.c b/src/m_menu.c
index e4a8ef1a2..64255e71a 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -263,7 +263,7 @@ static void M_ConfirmTeamChange(INT32 choice);
static void M_SecretsMenu(INT32 choice);
static void M_SetupChoosePlayer(INT32 choice);
static void M_QuitSRB2(INT32 choice);
-menu_t SP_MainDef, MP_MainDef, OP_MainDef;
+menu_t SP_MainDef, OP_MainDef;
menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef;
// Single Player
@@ -286,21 +286,19 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef;
// Multiplayer
-#ifndef NONET
-static void M_StartServerMenu(INT32 choice);
-static void M_ConnectMenu(INT32 choice);
-static void M_ConnectIPMenu(INT32 choice);
-#endif
+static void M_SetupMultiPlayer(INT32 choice);
+static void M_SetupMultiPlayer2(INT32 choice);
static void M_StartSplitServerMenu(INT32 choice);
static void M_StartServer(INT32 choice);
static void M_ServerOptions(INT32 choice);
#ifndef NONET
+static void M_StartServerMenu(INT32 choice);
+static void M_ConnectMenu(INT32 choice);
static void M_Refresh(INT32 choice);
static void M_Connect(INT32 choice);
static void M_ChooseRoom(INT32 choice);
+menu_t MP_MainDef;
#endif
-static void M_SetupMultiPlayer(INT32 choice);
-static void M_SetupMultiPlayer2(INT32 choice);
// Options
// Split into multiple parts due to size
@@ -376,16 +374,13 @@ static void M_OGL_DrawColorMenu(void);
#ifndef NONET
static void M_DrawScreenshotMenu(void);
static void M_DrawConnectMenu(void);
-static void M_DrawConnectIPMenu(void);
+static void M_DrawMPMainMenu(void);
static void M_DrawRoomMenu(void);
#endif
static void M_DrawJoystick(void);
static void M_DrawSetupMultiPlayerMenu(void);
// Handling functions
-#ifndef NONET
-static boolean M_CancelConnect(void);
-#endif
static boolean M_ExitPandorasBox(void);
static boolean M_QuitMultiPlayerMenu(void);
static void M_HandleAddons(INT32 choice);
@@ -395,6 +390,7 @@ static void M_HandleImageDef(INT32 choice);
static void M_HandleLoadSave(INT32 choice);
static void M_HandleLevelStats(INT32 choice);
#ifndef NONET
+static boolean M_CancelConnect(void);
static void M_HandleConnectIP(INT32 choice);
#endif
static void M_HandleSetupMultiPlayer(INT32 choice);
@@ -497,12 +493,16 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum
// ---------
static menuitem_t MainMenu[] =
{
- {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76},
- {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84},
- {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92},
- {IT_CALL |IT_STRING, NULL, "options", M_Options, 100},
- {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108},
- {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116},
+ {IT_STRING|IT_CALL, NULL, "Secrets", M_SecretsMenu, 76},
+ {IT_STRING|IT_CALL, NULL, "1 player", M_SinglePlayerMenu, 84},
+#ifndef NONET
+ {IT_STRING|IT_SUBMENU, NULL, "multiplayer", &MP_MainDef, 92},
+#else
+ {IT_STRING|IT_CALL, NULL, "multiplayer", M_StartSplitServerMenu, 92},
+#endif
+ {IT_STRING|IT_CALL, NULL, "options", M_Options, 100},
+ {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108},
+ {IT_STRING|IT_CALL, NULL, "quit game", M_QuitSRB2, 116},
};
typedef enum
@@ -922,56 +922,56 @@ static menuitem_t SP_PlayerMenu[] =
// Multiplayer and all of its submenus
// -----------------------------------
// Prefix: MP_
+
+// Separated splitscreen and normal servers.
+static menuitem_t MP_SplitServerMenu[] =
+{
+ {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
+#ifdef NONET // In order to keep player setup accessible.
+ {IT_STRING|IT_CALL, NULL, "Player 1 setup...", M_SetupMultiPlayer, 110},
+ {IT_STRING|IT_CALL, NULL, "Player 2 setup...", M_SetupMultiPlayer2, 120},
+#endif
+ {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
+ {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
+};
+
+#ifndef NONET
+
static menuitem_t MP_MainMenu[] =
{
-#ifndef NONET
- {IT_CALL | IT_STRING, NULL, "HOST GAME", M_StartServerMenu, 10},
- {IT_CALL | IT_STRING, NULL, "JOIN GAME (Search)", M_ConnectMenu, 30},
- {IT_CALL | IT_STRING, NULL, "JOIN GAME (Specify IP)", M_ConnectIPMenu, 40},
-#endif
- {IT_CALL | IT_STRING, NULL, "TWO PLAYER GAME", M_StartSplitServerMenu, 60},
-
- {IT_CALL | IT_STRING, NULL, "PLAYER 1 SETUP", M_SetupMultiPlayer, 80},
- {IT_CALL | IT_STRING, NULL, "PLAYER 2 SETUP", M_SetupMultiPlayer2, 90},
+ {IT_HEADER, NULL, "Host a game", NULL, 0},
+ {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 12},
+ {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 22},
+ {IT_HEADER, NULL, "Join a game", NULL, 40},
+ {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 52},
+ {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 62},
+ {IT_HEADER, NULL, "Player setup", NULL, 94},
+ {IT_STRING|IT_CALL, NULL, "Player 1...", M_SetupMultiPlayer, 106},
+ {IT_STRING|IT_CALL, NULL, "Player 2... ", M_SetupMultiPlayer2, 116},
};
static menuitem_t MP_ServerMenu[] =
{
- {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0},
-#ifndef NONET
- {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10},
- {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20},
- {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46},
- {IT_STRING|IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 56},
-#endif
- {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
- {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
- {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
+ {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10},
+ {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20},
+ {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46},
+ {IT_STRING|IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 56},
+ {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
+ {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
+ {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
};
enum
{
- mp_server_dummy = 0, // exists solely so zero-indexed in both NONET and not NONET
-#ifndef NONET
- mp_server_room,
+ mp_server_room = 0,
mp_server_name,
mp_server_maxpl,
mp_server_waddl,
-#endif
mp_server_levelgt,
mp_server_options,
mp_server_start
};
-// Separated splitscreen and normal servers.
-static menuitem_t MP_SplitServerMenu[] =
-{
- {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
- {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
- {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
-};
-
-#ifndef NONET
static menuitem_t MP_ConnectMenu[] =
{
{IT_STRING | IT_CALL, NULL, "Room...", M_RoomMenu, 4},
@@ -1023,17 +1023,14 @@ static menuitem_t MP_RoomMenu[] =
{IT_DISABLED, NULL, "", M_ChooseRoom, 162},
};
-static menuitem_t MP_ConnectIPMenu[] =
-{
- {IT_KEYHANDLER | IT_STRING, NULL, " IP Address:", M_HandleConnectIP, 0},
-};
#endif
static menuitem_t MP_PlayerSetupMenu[] =
{
- {IT_KEYHANDLER | IT_STRING, NULL, "Your name", M_HandleSetupMultiPlayer, 0},
- {IT_KEYHANDLER | IT_STRING, NULL, "Your color", M_HandleSetupMultiPlayer, 16},
- {IT_KEYHANDLER | IT_STRING, NULL, "Your player", M_HandleSetupMultiPlayer, 96}, // Tails 01-18-2001
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // skin
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // colour
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // default
};
// ------------------------------------
@@ -1134,23 +1131,23 @@ static menuitem_t OP_ChangeControlsMenu[] =
static menuitem_t OP_Joystick1Menu[] =
{
{IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup1PJoystickMenu, 10},
- {IT_STRING | IT_CVAR, NULL, "Move \x1A \x1B Axis" , &cv_moveaxis , 30},
- {IT_STRING | IT_CVAR, NULL, "Move \x1C \x1D Axis" , &cv_sideaxis , 40},
- {IT_STRING | IT_CVAR, NULL, "Camera \x1A \x1B Axis" , &cv_lookaxis , 50},
- {IT_STRING | IT_CVAR, NULL, "Camera \x1C \x1D Axis" , &cv_turnaxis , 60},
- {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 70},
- {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis , 80},
+ {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis , 30},
+ {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis , 40},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis , 50},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis , 60},
+ {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 70},
+ {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis , 80},
};
static menuitem_t OP_Joystick2Menu[] =
{
{IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10},
- {IT_STRING | IT_CVAR, NULL, "Move \x1A \x1B Axis" , &cv_moveaxis2 , 30},
- {IT_STRING | IT_CVAR, NULL, "Move \x1C \x1D Axis" , &cv_sideaxis2 , 40},
- {IT_STRING | IT_CVAR, NULL, "Camera \x1A \x1B Axis" , &cv_lookaxis2 , 50},
- {IT_STRING | IT_CVAR, NULL, "Camera \x1C \x1D Axis" , &cv_turnaxis2 , 60},
- {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 70},
- {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 , 80},
+ {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis2 , 30},
+ {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis2 , 40},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis2 , 50},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis2 , 60},
+ {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 70},
+ {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 , 80},
};
static menuitem_t OP_JoystickSetMenu[] =
@@ -1393,7 +1390,7 @@ static menuitem_t OP_AddonsOptionsMenu[] =
{IT_HEADER, NULL, "Menu", NULL, 0},
{IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 12},
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 22},
- {IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 50},
+ {IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 50},
{IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 60},
{IT_HEADER, NULL, "Search", NULL, 78},
@@ -1413,7 +1410,7 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_STRING | IT_CVAR | IT_CV_STRING,
NULL, "Server name", &cv_servername, 7},
{IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21},
- {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 26},
+ {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26},
{IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31},
#endif
{IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 36},
@@ -1425,33 +1422,38 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_HEADER, NULL, "Items", NULL, 70},
{IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 76},
- {IT_STRING | IT_SUBMENU, NULL, "Random Item Box Toggles...", &OP_MonitorToggleDef, 81},
+ {IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 81},
- {IT_HEADER, NULL, "Platform (Coop, Race, Competition)", NULL, 90},
+ {IT_HEADER, NULL, "Cooperative", NULL, 90},
{IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96},
- {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 101},
- {IT_STRING | IT_CVAR, NULL, "Item Boxes", &cv_competitionboxes, 106},
+ {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101},
+ {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106},
- {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 115},
- {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 121},
- {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 126},
- {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 131},
- {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 136},
+ {IT_HEADER, NULL, "Race, Competition", NULL, 115},
+ {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 121},
+ {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 126},
- {IT_STRING | IT_CVAR, NULL, "Item Boxes", &cv_matchboxes, 146},
- {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 151},
- {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 156},
+ {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 135},
+ {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 141},
+ {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 146},
+ {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 151},
+ {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 156},
- {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 166},
- {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 171},
+ {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 166},
+ {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 171},
+ {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 176},
- {IT_STRING | IT_CVAR, NULL, "Autobalance Teams", &cv_autobalance, 181},
- {IT_STRING | IT_CVAR, NULL, "Scramble Teams on Map Change", &cv_scrambleonchange, 186},
+ {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 186},
+ {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 191},
+
+ {IT_HEADER, NULL, "Teams", NULL, 200},
+ {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 206},
+ {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 211},
#ifndef NONET
- {IT_HEADER, NULL, "Advanced", NULL, 195},
- {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 201},
- {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 215},
+ {IT_HEADER, NULL, "Advanced", NULL, 220},
+ {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 226},
+ {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 240},
#endif
};
@@ -1460,11 +1462,11 @@ static menuitem_t OP_MonitorToggleMenu[] =
// Printing handled by drawing function
{IT_STRING|IT_CALL, NULL, "Reset to defaults", M_ResetCvars, 15},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Recycler", &cv_recycler, 30},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Teleporters", &cv_teleporters, 40},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Teleport", &cv_teleporters, 40},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Ring", &cv_superring, 50},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Sneakers", &cv_supersneakers, 60},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Invincibility", &cv_invincibility, 70},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Jump Shield", &cv_jumpshield, 80},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Whirlwind Shield", &cv_jumpshield, 80},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Elemental Shield", &cv_watershield, 90},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Attraction Shield", &cv_ringshield, 100},
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Force Shield", &cv_forceshield, 110},
@@ -1711,29 +1713,16 @@ menu_t SP_PlayerDef =
};
// Multiplayer
-menu_t MP_MainDef = DEFAULTMENUSTYLE("M_MULTI", MP_MainMenu, &MainDef, 60, 40);
-
-menu_t MP_ServerDef =
-{
- "M_MULTI",
- sizeof (MP_ServerMenu)/sizeof (menuitem_t),
- &MP_MainDef,
- MP_ServerMenu,
- M_DrawServerMenu,
- 27, 30
-#ifdef NONET
- - 50
-#endif
- ,
- 0,
- NULL
-};
menu_t MP_SplitServerDef =
{
"M_MULTI",
sizeof (MP_SplitServerMenu)/sizeof (menuitem_t),
+#ifndef NONET
&MP_MainDef,
+#else
+ &MainDef,
+#endif
MP_SplitServerMenu,
M_DrawServerMenu,
27, 30 - 50,
@@ -1742,6 +1731,31 @@ menu_t MP_SplitServerDef =
};
#ifndef NONET
+
+menu_t MP_MainDef =
+{
+ "M_MULTI",
+ sizeof (MP_MainMenu)/sizeof (menuitem_t),
+ &MainDef,
+ MP_MainMenu,
+ M_DrawMPMainMenu,
+ 27, 40,
+ 0,
+ M_CancelConnect
+};
+
+menu_t MP_ServerDef =
+{
+ "M_MULTI",
+ sizeof (MP_ServerMenu)/sizeof (menuitem_t),
+ &MP_MainDef,
+ MP_ServerMenu,
+ M_DrawServerMenu,
+ 27, 30,
+ 0,
+ NULL
+};
+
menu_t MP_ConnectDef =
{
"M_MULTI",
@@ -1753,17 +1767,7 @@ menu_t MP_ConnectDef =
0,
M_CancelConnect
};
-menu_t MP_ConnectIPDef =
-{
- "M_MULTI",
- sizeof (MP_ConnectIPMenu)/sizeof (menuitem_t),
- &MP_MainDef,
- MP_ConnectIPMenu,
- M_DrawConnectIPMenu,
- 27,40,
- 0,
- M_CancelConnect
-};
+
menu_t MP_RoomDef =
{
"M_MULTI",
@@ -1781,23 +1785,23 @@ menu_t MP_PlayerSetupDef =
{
"M_SPLAYR",
sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t),
- &MP_MainDef,
+ &MainDef, // doesn't matter
MP_PlayerSetupMenu,
M_DrawSetupMultiPlayerMenu,
- 27, 40,
+ 19, 22,
0,
M_QuitMultiPlayerMenu
};
// Options
-menu_t OP_MainDef = DEFAULTMENUSTYLE("M_OPTTTL", OP_MainMenu, &MainDef, 60, 30);
+menu_t OP_MainDef = DEFAULTMENUSTYLE("M_OPTTTL", OP_MainMenu, &MainDef, 50, 30);
menu_t OP_ChangeControlsDef = CONTROLMENUSTYLE(OP_ChangeControlsMenu, &OP_MainDef);
menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P1ControlsMenu, &OP_MainDef, 50, 30);
menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P2ControlsMenu, &OP_MainDef, 50, 30);
menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_MouseOptionsMenu, &OP_P1ControlsDef, 35, 30);
menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_Mouse2OptionsMenu, &OP_P2ControlsDef, 35, 30);
-menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 60, 30);
-menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 60, 30);
+menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 50, 30);
+menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 50, 30);
menu_t OP_JoystickSetDef =
{
"M_CONTRO",
@@ -3000,7 +3004,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv)
}
// A smaller 'Thermo', with range given as percents (0-100)
-static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv)
+static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop)
{
INT32 i;
INT32 range;
@@ -3014,6 +3018,14 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv)
for (i = 1; i < SLIDER_RANGE; i++)
V_DrawScaledPatch (x+i*8, y, 0,p);
+ if (ontop)
+ {
+ V_DrawCharacter(x - 6 - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(x+i*8 + 8 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
+
p = W_CachePatchName("M_SLIDER", PU_CACHE);
V_DrawScaledPatch(x+i*8, y, 0, p);
@@ -3263,7 +3275,7 @@ static void M_DrawGenericMenu(void)
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
{
case IT_CV_SLIDER:
- M_DrawSlider(x, y, cv);
+ M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
case IT_CV_INVISSLIDER: // monitor toggles use this
break;
@@ -3278,6 +3290,13 @@ static void M_DrawGenericMenu(void)
default:
V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
break;
}
break;
@@ -3372,9 +3391,9 @@ static void M_DrawGenericScrollMenu(void)
}
if (i)
- V_DrawString(currentMenu->x - 20, currentMenu->y, V_YELLOWMAP, "\x1A"); // up arrow
+ V_DrawString(currentMenu->x - 20, currentMenu->y - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow
if (max != bottom)
- V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight, V_YELLOWMAP, "\x1B"); // down arrow
+ V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow
// draw title (or big pic)
M_DrawMenuTitle();
@@ -3412,7 +3431,7 @@ static void M_DrawGenericScrollMenu(void)
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
{
case IT_CV_SLIDER:
- M_DrawSlider(x, y, cv);
+ M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
case IT_CV_INVISSLIDER: // monitor toggles use this
break;
@@ -3441,6 +3460,13 @@ static void M_DrawGenericScrollMenu(void)
default:
V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
break;
}
break;
@@ -3668,7 +3694,7 @@ static void M_DrawCenteredMenu(void)
switch(currentMenu->menuitems[i].status & IT_CVARTYPE)
{
case IT_CV_SLIDER:
- M_DrawSlider(x, y, cv);
+ M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
break;
case IT_CV_STRING:
@@ -3682,6 +3708,13 @@ static void M_DrawCenteredMenu(void)
default:
V_DrawString(BASEVIDWIDTH - x - V_StringWidth(cv->string, 0), y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
break;
}
break;
@@ -4913,7 +4946,7 @@ static void M_DrawAddons(void)
}
if (i != 0)
- V_DrawString(19, y+4, V_YELLOWMAP, "\x1A");
+ V_DrawString(19, y+4 - (skullAnimCounter/5), V_YELLOWMAP, "\x1A");
for (; i < max; i++)
{
@@ -4948,7 +4981,7 @@ static void M_DrawAddons(void)
}
if (max != (ssize_t)sizedirmenu)
- V_DrawString(19, y-12, V_YELLOWMAP, "\x1B");
+ V_DrawString(19, y-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B");
y = BASEVIDHEIGHT - currentMenu->y + offs;
@@ -4980,7 +5013,7 @@ static void M_AddonExec(INT32 ch)
if (ch != 'y' && ch != KEY_ENTER)
return;
- S_StartSound(NULL, sfx_strpst);
+ S_StartSound(NULL, sfx_zoom);
COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
}
@@ -5382,13 +5415,21 @@ static void M_HandleChecklist(INT32 choice)
{
case KEY_DOWNARROW:
S_StartSound(NULL, sfx_menu1);
- if (checklist_cangodown)
+ if ((check_on != MAXUNLOCKABLES) && checklist_cangodown)
{
for (j = check_on+1; j < MAXUNLOCKABLES; j++)
{
- if (!(unlockables[j].name[0] == 0 //|| unlockables[j].nochecklist
- || !unlockables[j].conditionset || unlockables[j].conditionset > MAXCONDITIONSETS))
- break;
+ if (!unlockables[j].name[0])
+ continue;
+ // if (unlockables[j].nochecklist)
+ // continue;
+ if (!unlockables[j].conditionset)
+ continue;
+ if (unlockables[j].conditionset > MAXCONDITIONSETS)
+ continue;
+ if (unlockables[j].conditionset == unlockables[check_on].conditionset)
+ continue;
+ break;
}
if (j != MAXUNLOCKABLES)
check_on = j;
@@ -5397,14 +5438,25 @@ static void M_HandleChecklist(INT32 choice)
case KEY_UPARROW:
S_StartSound(NULL, sfx_menu1);
- for (j = check_on-1; j > -1; j--)
+ if (check_on)
{
- if (!(unlockables[j].name[0] == 0 //|| unlockables[j].nochecklist
- || !unlockables[j].conditionset || unlockables[j].conditionset > MAXCONDITIONSETS))
+ for (j = check_on-1; j > -1; j--)
+ {
+ if (!unlockables[j].name[0])
+ continue;
+ // if (unlockables[j].nochecklist)
+ // continue;
+ if (!unlockables[j].conditionset)
+ continue;
+ if (unlockables[j].conditionset > MAXCONDITIONSETS)
+ continue;
+ if (j && unlockables[j].conditionset == unlockables[j-1].conditionset)
+ continue;
break;
+ }
+ if (j != -1)
+ check_on = j;
}
- if (j != -1)
- check_on = j;
return;
case KEY_ESCAPE:
@@ -5430,7 +5482,7 @@ static void M_DrawChecklist(void)
M_DrawMenuTitle();
if (check_on)
- V_DrawString(10, y, V_YELLOWMAP, "\x1A");
+ V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A");
while (i < MAXUNLOCKABLES)
{
@@ -5688,7 +5740,7 @@ static void M_DrawChecklist(void)
finishchecklist:
if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks.
- V_DrawString(10, currentMenu->y+(scrollareaheight*2), V_YELLOWMAP, "\x1B");
+ V_DrawString(10, currentMenu->y+(scrollareaheight*2)+(skullAnimCounter/5), V_YELLOWMAP, "\x1B");
}
#define NUMHINTS 5
@@ -5759,6 +5811,13 @@ static void M_DrawSkyRoom(void)
return;
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y, V_YELLOWMAP, cv_soundtest.string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - V_StringWidth(cv_soundtest.string, 0) - (skullAnimCounter/5), currentMenu->y + y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y + y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
if (cv_soundtest.value)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y + 8, V_YELLOWMAP, S_sfx[cv_soundtest.value].name);
}
@@ -6661,7 +6720,7 @@ static void M_ChoosePlayer(INT32 choice)
if (startmap != spstage_start)
cursaveslot = -1;
- lastmapsaved = 0;
+ //lastmapsaved = 0;
gamecomplete = false;
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect);
@@ -6719,7 +6778,7 @@ static void M_DrawStatsMaps(int location)
boolean dotopname = true, dobottomarrow = (location < statsMax);
if (location)
- V_DrawString(10, y, V_YELLOWMAP, "\x1A");
+ V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A");
while (statsMapList[++i] != -1)
{
@@ -6796,7 +6855,7 @@ static void M_DrawStatsMaps(int location)
}
bottomarrow:
if (dobottomarrow)
- V_DrawString(10, y-8, V_YELLOWMAP, "\x1B");
+ V_DrawString(10, y-8 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B");
}
static void M_DrawLevelStats(void)
@@ -6965,6 +7024,13 @@ void M_DrawTimeAttackMenu(void)
// Should see nothing but strings
V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
}
}
@@ -7147,6 +7213,13 @@ void M_DrawNightsAttackMenu(void)
// Should see nothing but strings
V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
}
}
@@ -7936,13 +8009,18 @@ static void M_DrawServerMenu(void)
if (cv_nextmap.value)
{
+#ifndef NONET
+#define imgheight MP_ServerMenu[mp_server_levelgt].alphaKey
+#else
+#define imgheight 100
+#endif
patch_t *PictureOfLevel;
lumpnum_t lumpnum;
char headerstr[40];
sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string);
- M_DrawLevelPlatterHeader(currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey - 10 - lsheadingheight/2, (const char *)headerstr, true, false);
+ M_DrawLevelPlatterHeader(currentMenu->y + imgheight - 10 - lsheadingheight/2, (const char *)headerstr, true, false);
// A 160x100 image of the level as entry MAPxxP
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
@@ -7952,7 +8030,7 @@ static void M_DrawServerMenu(void)
else
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE);
- V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey, 0, PictureOfLevel);
+ V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + imgheight, 0, PictureOfLevel);
}
}
@@ -8017,10 +8095,10 @@ static void M_ServerOptions(INT32 choice)
{
OP_ServerOptionsMenu[ 1].status = IT_GRAYEDOUT; // Server name
OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players
- OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow WAD downloading
+ OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading
OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join
- OP_ServerOptionsMenu[30].status = IT_GRAYEDOUT; // Master server
- OP_ServerOptionsMenu[31].status = IT_GRAYEDOUT; // Attempts to resynchronise
+ OP_ServerOptionsMenu[34].status = IT_GRAYEDOUT; // Master server
+ OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Attempts to resynchronise
}
else
{
@@ -8028,11 +8106,10 @@ static void M_ServerOptions(INT32 choice)
OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR;
- if (netgame)
- OP_ServerOptionsMenu[30].status = IT_GRAYEDOUT;
- else
- OP_ServerOptionsMenu[30].status = IT_STRING | IT_CVAR | IT_CV_STRING;
- OP_ServerOptionsMenu[31].status = IT_STRING | IT_CVAR;
+ OP_ServerOptionsMenu[34].status = (netgame
+ ? IT_GRAYEDOUT
+ : (IT_STRING | IT_CVAR | IT_CV_STRING));
+ OP_ServerOptionsMenu[35].status = IT_STRING | IT_CVAR;
}
#endif
@@ -8057,30 +8134,40 @@ static void M_StartServerMenu(INT32 choice)
static char setupm_ip[16];
-// Connect using IP address Tails 11-19-2002
-static void M_ConnectIPMenu(INT32 choice)
-{
- (void)choice;
- // modified game check: no longer handled
- // we don't request a restart unless the filelist differs
-
- M_SetupNextMenu(&MP_ConnectIPDef);
-}
-
// Draw the funky Connect IP menu. Tails 11-19-2002
// So much work for such a little thing!
-static void M_DrawConnectIPMenu(void)
+static void M_DrawMPMainMenu(void)
{
+ INT32 x = currentMenu->x;
+ INT32 y = currentMenu->y;
+
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
+#if MAXPLAYERS == 32
+ V_DrawRightAlignedString(BASEVIDWIDTH-x, y+12,
+ ((itemOn == 1) ? V_YELLOWMAP : 0), "(2-32 players)");
+#else
+Update the maxplayers label...
+#endif
+
+ V_DrawRightAlignedString(BASEVIDWIDTH-x, y+22,
+ ((itemOn == 2) ? V_YELLOWMAP : 0), "(2 players)");
+
+ V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116,
+ ((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)");
+
+ y += 62;
+
+ V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159);
+
// draw name string
- V_DrawString(128,40, V_MONOSPACE, setupm_ip);
+ V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip);
// draw text cursor for name
- if (itemOn == 0 &&
- skullAnimCounter < 4) //blink cursor
- V_DrawCharacter(128+V_StringWidth(setupm_ip, V_MONOSPACE),40,'_',false);
+ if (itemOn == 5 //0
+ && skullAnimCounter < 4) //blink cursor
+ V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false);
}
// Tails 11-19-2002
@@ -8101,11 +8188,21 @@ static void M_ConnectIP(INT32 choice)
// Tails 11-19-2002
static void M_HandleConnectIP(INT32 choice)
{
- size_t l;
- boolean exitmenu = false; // exit to previous menu and send name change
+ size_t l;
+ boolean exitmenu = false; // exit to previous menu and send name change
switch (choice)
{
+ case KEY_DOWNARROW:
+ M_NextOpt();
+ S_StartSound(NULL,sfx_menu1); // Tails
+ break;
+
+ case KEY_UPARROW:
+ M_PrevOpt();
+ S_StartSound(NULL,sfx_menu1); // Tails
+ break;
+
case KEY_ENTER:
S_StartSound(NULL,sfx_menu1); // Tails
M_ClearMenus(true);
@@ -8117,29 +8214,41 @@ static void M_HandleConnectIP(INT32 choice)
break;
case KEY_BACKSPACE:
- if ((l = strlen(setupm_ip))!=0 && itemOn == 0)
+ if ((l = strlen(setupm_ip)) != 0)
{
S_StartSound(NULL,sfx_menu1); // Tails
- setupm_ip[l-1] =0;
+ setupm_ip[l-1] = 0;
+ }
+ break;
+
+ case KEY_DEL:
+ if (setupm_ip[0])
+ {
+ S_StartSound(NULL,sfx_menu1); // Tails
+ setupm_ip[0] = 0;
}
break;
default:
l = strlen(setupm_ip);
- if (l < 16-1 && (choice == 46 || (choice >= 48 && choice <= 57))) // Rudimentary number and period enforcing
+ if (l >= 16-1)
+ break;
+
+ if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing
{
S_StartSound(NULL,sfx_menu1); // Tails
- setupm_ip[l] =(char)choice;
- setupm_ip[l+1] =0;
+ setupm_ip[l] = (char)choice;
+ setupm_ip[l+1] = 0;
}
- else if (l < 16-1 && choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too!
+ else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too!
{
XBOXSTATIC char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'};
choice = keypad_translation[choice - 199];
S_StartSound(NULL,sfx_menu1); // Tails
- setupm_ip[l] =(char)choice;
- setupm_ip[l+1] =0;
+ setupm_ip[l] = (char)choice;
+ setupm_ip[l+1] = 0;
}
+
break;
}
@@ -8158,11 +8267,9 @@ static void M_HandleConnectIP(INT32 choice)
// ========================
// Tails 03-02-2002
-#define PLBOXW 8
-#define PLBOXH 9
-
static UINT8 multi_tics;
static UINT8 multi_frame;
+static UINT8 multi_spr2;
// this is set before entering the MultiPlayer setup menu,
// for either player 1 or 2
@@ -8171,38 +8278,62 @@ static player_t *setupm_player;
static consvar_t *setupm_cvskin;
static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname;
+static consvar_t *setupm_cvdefaultskin;
+static consvar_t *setupm_cvdefaultcolor;
+static consvar_t *setupm_cvdefaultname;
static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor;
static void M_DrawSetupMultiPlayerMenu(void)
{
- INT32 mx, my, flags = 0;
+ INT32 x, y, cursory = 0, flags = 0;
spritedef_t *sprdef;
spriteframe_t *sprframe;
patch_t *patch;
+ UINT8 *colormap;
- mx = MP_PlayerSetupDef.x;
- my = MP_PlayerSetupDef.y;
+ x = MP_PlayerSetupDef.x;
+ y = MP_PlayerSetupDef.y;
// use generic drawer for cursor, items and title
- M_DrawGenericMenu();
+ //M_DrawGenericMenu();
+
+ // draw title (or big pic)
+ M_DrawMenuTitle();
+
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Name", true, false);
+ if (itemOn == 0)
+ cursory = y;
+ y += 11;
// draw name string
- M_DrawTextBox(mx + 90, my - 8, MAXPLAYERNAME, 1);
- V_DrawString(mx + 98, my, V_ALLOWLOWERCASE, setupm_name);
+ V_DrawFill(x, y, 282/*(MAXPLAYERNAME+1)*8+6*/, 14, 159);
+ V_DrawString(x + 8, y + 3, V_ALLOWLOWERCASE, setupm_name);
+ if (skullAnimCounter < 4 && itemOn == 0)
+ V_DrawCharacter(x + 8 + V_StringWidth(setupm_name, V_ALLOWLOWERCASE), y + 3,
+ '_' | 0x80, false);
+
+ y += 20;
+
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Character", true, false);
+ if (itemOn == 1)
+ cursory = y;
// draw skin string
- V_DrawString(mx + 90, my + 96,
- ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|V_YELLOWMAP|V_ALLOWLOWERCASE,
+ V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
+ ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 1 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE,
skins[setupm_fakeskin].realname);
- // draw the name of the color you have chosen
- // Just so people don't go thinking that "Default" is Green.
- V_DrawString(208, 72, V_YELLOWMAP|V_ALLOWLOWERCASE, Color_Names[setupm_fakecolor]);
+ if (itemOn == 1 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skins[setupm_fakeskin].realname, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
- // draw text cursor for name
- if (!itemOn && skullAnimCounter < 4) // blink cursor
- V_DrawCharacter(mx + 98 + V_StringWidth(setupm_name, 0), my, '_',false);
+ x = BASEVIDWIDTH/2;
+ y += 11;
// anim the player in the box
if (--multi_tics <= 0)
@@ -8211,14 +8342,18 @@ static void M_DrawSetupMultiPlayerMenu(void)
multi_tics = 4;
}
- // skin 0 is default player sprite
- if (R_SkinAvailable(skins[setupm_fakeskin].name) != -1)
- sprdef = &skins[R_SkinAvailable(skins[setupm_fakeskin].name)].sprites[SPR2_WALK];
- else
- sprdef = &skins[0].sprites[SPR2_WALK];
+#define charw 74
- if (!sprdef->numframes) // No frames ??
- return; // Can't render!
+ // draw box around character
+ V_DrawFill(x-(charw/2), y, charw, 84, 159);
+
+ sprdef = &skins[setupm_fakeskin].sprites[multi_spr2];
+
+ if (!setupm_fakecolor || !sprdef->numframes) // should never happen but hey, who knows
+ goto faildraw;
+
+ // ok, draw player sprite for sure now
+ colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, 0);
if (multi_frame >= sprdef->numframes)
multi_frame = 0;
@@ -8228,38 +8363,96 @@ static void M_DrawSetupMultiPlayerMenu(void)
if (sprframe->flip & 1) // Only for first sprite
flags |= V_FLIP; // This sprite is left/right flipped!
- // draw box around guy
- M_DrawTextBox(mx + 90, my + 8, PLBOXW, PLBOXH);
+#define chary (y+64)
- // draw player sprite
- if (!setupm_fakecolor) // should never happen but hey, who knows
+ V_DrawFixedPatch(
+ x<numframes) // No frames ??
+ return; // Can't render!
+
+ sprframe = &sprdef->spriteframes[0];
+ patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
+ if (sprframe->flip & 1) // Only for first sprite
+ flags |= V_FLIP; // This sprite is left/right flipped!
+
+ V_DrawScaledPatch(x, chary, flags, patch);
+
+#undef chary
+
+colordraw:
+ x = MP_PlayerSetupDef.x;
+ y += 75;
+
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Color", true, false);
+ if (itemOn == 2)
+ cursory = y;
+
+ // draw color string
+ V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
+ (itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE,
+ Color_Names[setupm_fakecolor]);
+
+ if (itemOn == 2 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE)
{
- if (skins[setupm_fakeskin].flags & SF_HIRES)
- {
- V_DrawSciencePatch((mx+98+(PLBOXW*8/2))<= MAXSKINCOLORS)
+ col -= MAXSKINCOLORS-1;
+ x += w;
}
- else
- V_DrawMappedPatch(mx + 98 + (PLBOXW*8/2), my + 16 + (PLBOXH*8) - 12, flags, patch, colormap);
-
- Z_Free(colormap);
}
+#undef charw
+#undef indexwidth
+
+ x = MP_PlayerSetupDef.x;
+ y += 20;
+
+ V_DrawString(x, y,
+ ((R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin
+ || setupm_cvdefaultcolor->value != setupm_fakecolor
+ || strcmp(setupm_name, setupm_cvdefaultname->string))
+ ? 0
+ : V_TRANSLUCENT)
+ | ((itemOn == 3) ? V_YELLOWMAP : 0),
+ "Save as default");
+ if (itemOn == 3)
+ cursory = y;
+
+ V_DrawScaledPatch(x - 17, cursory, 0,
+ W_CachePatchName("M_CURSOR", PU_CACHE));
}
// Handle 1P/2P MP Setup
@@ -8282,7 +8475,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break;
case KEY_LEFTARROW:
- if (itemOn == 2) //player skin
+ if (itemOn == 1) //player skin
{
S_StartSound(NULL,sfx_menu1); // Tails
prev_setupm_fakeskin = setupm_fakeskin;
@@ -8293,16 +8486,30 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
setupm_fakeskin = numskins-1;
}
while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin)));
+ multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL);
}
- else if (itemOn == 1) // player color
+ else if (itemOn == 2) // player color
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor--;
}
break;
+ case KEY_ENTER:
+ if (itemOn == 3
+ && (R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin
+ || setupm_cvdefaultcolor->value != setupm_fakecolor
+ || strcmp(setupm_name, setupm_cvdefaultname->string)))
+ {
+ S_StartSound(NULL,sfx_strpst);
+ // you know what? always putting these in the buffer won't hurt anything.
+ COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name));
+ COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor));
+ COM_BufAddText (va("%s %s\n",setupm_cvdefaultname->name,setupm_name));
+ break;
+ }
case KEY_RIGHTARROW:
- if (itemOn == 2) //player skin
+ if (itemOn == 1) //player skin
{
S_StartSound(NULL,sfx_menu1); // Tails
prev_setupm_fakeskin = setupm_fakeskin;
@@ -8313,8 +8520,9 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
setupm_fakeskin = 0;
}
while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin)));
+ multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL);
}
- else if (itemOn == 1) // player color
+ else if (itemOn == 2) // player color
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor++;
@@ -8326,22 +8534,30 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break;
case KEY_BACKSPACE:
- if ((l = strlen(setupm_name))!=0 && itemOn == 0)
+ if (itemOn == 0 && (l = strlen(setupm_name))!=0)
{
S_StartSound(NULL,sfx_menu1); // Tails
- setupm_name[l-1] =0;
+ setupm_name[l-1] = 0;
+ }
+ break;
+
+ case KEY_DEL:
+ if (itemOn == 0 && (l = strlen(setupm_name))!=0)
+ {
+ S_StartSound(NULL,sfx_menu1); // Tails
+ setupm_name[0] = 0;
}
break;
default:
- if (choice < 32 || choice > 127 || itemOn != 0)
+ if (itemOn != 0 || choice < 32 || choice > 127)
break;
+ S_StartSound(NULL,sfx_menu1); // Tails
l = strlen(setupm_name);
if (l < MAXPLAYERNAME-1)
{
- S_StartSound(NULL,sfx_menu1); // Tails
- setupm_name[l] =(char)choice;
- setupm_name[l+1] =0;
+ setupm_name[l] = (char)choice;
+ setupm_name[l+1] = 0;
}
break;
}
@@ -8375,6 +8591,9 @@ static void M_SetupMultiPlayer(INT32 choice)
setupm_cvskin = &cv_skin;
setupm_cvcolor = &cv_playercolor;
setupm_cvname = &cv_playername;
+ setupm_cvdefaultskin = &cv_defaultskin;
+ setupm_cvdefaultcolor = &cv_defaultplayercolor;
+ setupm_cvdefaultname = &cv_defaultplayername;
// For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@@ -8384,9 +8603,11 @@ static void M_SetupMultiPlayer(INT32 choice)
// disable skin changes if we can't actually change skins
if (!CanChangeSkin(consoleplayer))
- MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT);
+ MP_PlayerSetupMenu[1].status = (IT_GRAYEDOUT);
else
- MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING);
+ MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER|IT_STRING);
+
+ multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL);
MP_PlayerSetupDef.prevMenu = currentMenu;
M_SetupNextMenu(&MP_PlayerSetupDef);
@@ -8406,6 +8627,9 @@ static void M_SetupMultiPlayer2(INT32 choice)
setupm_cvskin = &cv_skin2;
setupm_cvcolor = &cv_playercolor2;
setupm_cvname = &cv_playername2;
+ setupm_cvdefaultskin = &cv_defaultskin2;
+ setupm_cvdefaultcolor = &cv_defaultplayercolor2;
+ setupm_cvdefaultname = &cv_defaultplayername2;
// For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@@ -8415,9 +8639,11 @@ static void M_SetupMultiPlayer2(INT32 choice)
// disable skin changes if we can't actually change skins
if (splitscreen && !CanChangeSkin(secondarydisplayplayer))
- MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT);
+ MP_PlayerSetupMenu[1].status = (IT_GRAYEDOUT);
else
- MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING);
+ MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER | IT_STRING);
+
+ multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL);
MP_PlayerSetupDef.prevMenu = currentMenu;
M_SetupNextMenu(&MP_PlayerSetupDef);
@@ -8683,9 +8909,9 @@ static void M_DrawControl(void)
"PRESS ENTER TO CHANGE, BACKSPACE TO CLEAR"));
if (i)
- V_DrawString(currentMenu->x - 16, y, V_YELLOWMAP, "\x1A"); // up arrow
+ V_DrawString(currentMenu->x - 16, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow
if (max != currentMenu->numitems)
- V_DrawString(currentMenu->x - 16, y+(SMALLLINEHEIGHT*(controlheight-1)), V_YELLOWMAP, "\x1B"); // down arrow
+ V_DrawString(currentMenu->x - 16, y+(SMALLLINEHEIGHT*(controlheight-1))+(skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow
for (; i < max; i++)
{
@@ -8838,6 +9064,7 @@ void M_DrawSoundMenu(void)
{
const char* onstring = "ON";
const char* offstring = "OFF";
+ INT32 lengthstring;
M_DrawGenericMenu();
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x,
@@ -8854,6 +9081,20 @@ void M_DrawSoundMenu(void)
currentMenu->y+currentMenu->menuitems[4].alphaKey,
(nomidimusic ? V_REDMAP : V_YELLOWMAP),
((nomidimusic || music_disabled) ? offstring : onstring));
+
+ if (itemOn == 0)
+ lengthstring = ((nosound || sound_disabled) ? 3 : 2);
+ else if (itemOn == 2)
+ lengthstring = ((nodigimusic || digital_disabled) ? 3 : 2);
+ else if (itemOn == 4)
+ lengthstring = ((nomidimusic || music_disabled) ? 3 : 2);
+ else
+ return;
+
+ V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - (lengthstring*8) - (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].alphaKey,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].alphaKey,
+ '\x1D' | V_YELLOWMAP, false);
}
// Toggles sound systems in-game.
@@ -9227,9 +9468,9 @@ static void M_DrawColorMenu(void)
}
if (i)
- V_DrawString(currentMenu->x - 20, currentMenu->y, V_YELLOWMAP, "\x1A"); // up arrow
+ V_DrawString(currentMenu->x - 20, currentMenu->y - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow
if (max != currentMenu->numitems)
- V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight, V_YELLOWMAP, "\x1B"); // down arrow
+ V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow
// draw title (or big pic)
M_DrawMenuTitle();
@@ -9267,7 +9508,7 @@ static void M_DrawColorMenu(void)
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
{
case IT_CV_SLIDER:
- M_DrawSlider(x, y, cv);
+ M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
case IT_CV_INVISSLIDER: // monitor toggles use this
break;
@@ -9284,6 +9525,13 @@ static void M_DrawColorMenu(void)
default:
V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
break;
}
break;
@@ -9426,7 +9674,7 @@ static void M_DrawMonitorToggles(void)
continue;
y = currentMenu->y + currentMenu->menuitems[i].alphaKey;
- M_DrawSlider(currentMenu->x + 20, y, cv);
+ M_DrawSlider(currentMenu->x + 20, y, cv, (i == itemOn));
if (!cv->value)
V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? V_YELLOWMAP : 0), "None");
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 08c6eb306..0cf86b1ec 100644
--- a/src/p_enemy.c
+++ b/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)<radius>>FRACBITS;
+ hei = actor->height>>FRACBITS;
+ particle = P_SpawnMobjFromMobj(actor,
+ P_RandomRange(rad, -rad)<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;
}
diff --git a/src/p_local.h b/src/p_local.h
index 64ab47975..01d20b4ff 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -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);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 60694996c..8f9c44fdb 100644
--- a/src/p_mobj.c
+++ b/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;
-}
+}
\ No newline at end of file
diff --git a/src/p_mobj.h b/src/p_mobj.h
index f6ebd3cad..c6e1bfbf2 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
+ MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer
// free: to and including 1<<31
} mobjflag2_t;
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 3853dc7e6..2d3412e65 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -3159,7 +3159,8 @@ static inline void P_ArchiveMisc(void)
else
WRITEINT16(save_p, gamemap);
- lastmapsaved = gamemap;
+ //lastmapsaved = gamemap;
+ lastmaploaded = gamemap;
WRITEUINT16(save_p, (botskin ? (emeralds|(1<<10)) : emeralds)+357);
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
@@ -3184,7 +3185,8 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
if(!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1);
- lastmapsaved = gamemap;
+ //lastmapsaved = gamemap;
+ lastmaploaded = gamemap;
tokenlist = 0;
token = 0;
diff --git a/src/p_setup.c b/src/p_setup.c
index 6a933809a..9c4bede74 100644
--- a/src/p_setup.c
+++ b/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))<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
diff --git a/src/p_setup.h b/src/p_setup.h
index 95976d276..3443ffdb7 100644
--- a/src/p_setup.h
+++ b/src/p_setup.h
@@ -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);
diff --git a/src/p_spec.c b/src/p_spec.c
index 03ee30281..8f85c713d 100644
--- a/src/p_spec.c
+++ b/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;
}
diff --git a/src/p_tick.c b/src/p_tick.c
index 5235a1a03..a79d71ef4 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -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);
}
}
diff --git a/src/p_user.c b/src/p_user.c
index 7eafdf8ef..09cafa0b3 100644
--- a/src/p_user.c
+++ b/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)<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<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<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< ANGLE_MAX
if (!demoplayback || P_AnalogMove(player))
diff --git a/src/r_bsp.c b/src/r_bsp.c
index abb11204a..ad4975cde 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -365,6 +365,36 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
return sec;
}
+boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
+{
+ return (
+#ifdef POLYOBJECTS
+ !line->polyseg &&
+#endif
+ back->ceilingpic == front->ceilingpic
+ && back->floorpic == front->floorpic
+#ifdef ESLOPE
+ && back->f_slope == front->f_slope
+ && back->c_slope == front->c_slope
+#endif
+ && back->lightlevel == front->lightlevel
+ && !line->sidedef->midtexture
+ // Check offsets too!
+ && back->floor_xoffs == front->floor_xoffs
+ && back->floor_yoffs == front->floor_yoffs
+ && back->floorpic_angle == front->floorpic_angle
+ && back->ceiling_xoffs == front->ceiling_xoffs
+ && back->ceiling_yoffs == front->ceiling_yoffs
+ && back->ceilingpic_angle == front->ceilingpic_angle
+ // Consider altered lighting.
+ && back->floorlightsec == front->floorlightsec
+ && back->ceilinglightsec == front->ceilinglightsec
+ // Consider colormaps
+ && back->extra_colormap == front->extra_colormap
+ && ((!front->ffloors && !back->ffloors)
+ || front->tag == back->tag));
+}
+
//
// R_AddLine
// Clips the given segment and adds any visible pieces to the line list.
@@ -526,36 +556,8 @@ static void R_AddLine(seg_t *line)
// Identical floor and ceiling on both sides, identical light levels on both sides,
// and no middle texture.
- if (
-#ifdef POLYOBJECTS
- !line->polyseg &&
-#endif
- backsector->ceilingpic == frontsector->ceilingpic
- && backsector->floorpic == frontsector->floorpic
-#ifdef ESLOPE
- && backsector->f_slope == frontsector->f_slope
- && backsector->c_slope == frontsector->c_slope
-#endif
- && backsector->lightlevel == frontsector->lightlevel
- && !curline->sidedef->midtexture
- // Check offsets too!
- && backsector->floor_xoffs == frontsector->floor_xoffs
- && backsector->floor_yoffs == frontsector->floor_yoffs
- && backsector->floorpic_angle == frontsector->floorpic_angle
- && backsector->ceiling_xoffs == frontsector->ceiling_xoffs
- && backsector->ceiling_yoffs == frontsector->ceiling_yoffs
- && backsector->ceilingpic_angle == frontsector->ceilingpic_angle
- // Consider altered lighting.
- && backsector->floorlightsec == frontsector->floorlightsec
- && backsector->ceilinglightsec == frontsector->ceilinglightsec
- // Consider colormaps
- && backsector->extra_colormap == frontsector->extra_colormap
- && ((!frontsector->ffloors && !backsector->ffloors)
- || frontsector->tag == backsector->tag))
- {
+ if (R_IsEmptyLine(line, frontsector, backsector))
return;
- }
-
clippass:
R_ClipPassWallSegment(x1, x2 - 1);
@@ -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
diff --git a/src/r_bsp.h b/src/r_bsp.h
index e871b5dde..80824831b 100644
--- a/src/r_bsp.h
+++ b/src/r_bsp.h
@@ -50,6 +50,7 @@ extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back);
+boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
void R_Prep3DFloors(sector_t *sector);
diff --git a/src/r_data.c b/src/r_data.c
index e33a12ec8..791d90d94 100644
--- a/src/r_data.c
+++ b/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;
}
}
}
diff --git a/src/r_data.h b/src/r_data.h
index 2d984c1c8..53bf27835 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -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);
diff --git a/src/r_defs.h b/src/r_defs.h
index 32be7c4c8..7c8f2a73f 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -574,6 +574,9 @@ typedef struct seg_s
sector_t *backsector;
#ifdef HWRENDER
+ // new pointers so that AdjustSegs doesn't mess with v1/v2
+ void *pv1; // polyvertex_t
+ void *pv2; // polyvertex_t
float flength; // length of the seg, used by hardware renderer
lightmap_t *lightmaps; // for static lightmap
@@ -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
diff --git a/src/r_draw.c b/src/r_draw.c
index 30b60a0e0..4479cf02c 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -126,95 +126,301 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
#define BOSS_TT_CACHE_INDEX (MAXSKINS + 1)
#define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2)
#define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3)
-#define SKIN_RAMP_LENGTH 16
#define DEFAULT_STARTTRANSCOLOR 96
#define NUM_PALETTE_ENTRIES 256
static UINT8** translationtablecache[MAXSKINS + 4] = {NULL};
+const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
+ // {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE
+
+ // Greyscale ranges
+ {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11}, // SKINCOLOR_WHITE
+ {0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12}, // SKINCOLOR_BONE
+ {0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}, // SKINCOLOR_CLOUDY
+ {0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, // SKINCOLOR_GREY
+ {0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f}, // SKINCOLOR_SILVER
+ {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1c, 0x1d}, // SKINCOLOR_CARBON
+ {0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1a, 0x1b, 0x1c, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f}, // SKINCOLOR_JET
+ {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, // SKINCOLOR_BLACK
+
+ // Desaturated
+ {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AETHER
+ {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_SLATE
+ {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, // SKINCOLOR_PINK
+ {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, // SKINCOLOR_YOGURT
+ {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, // SKINCOLOR_BROWN
+ {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, // SKINCOLOR_TAN
+ {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, // SKINCOLOR_BEIGE
+ {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, // SKINCOLOR_MOSS
+ {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AZURE
+ {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, // SKINCOLOR_LAVENDER
+
+ // Viv's vivid colours (toast 21/07/17)
+ {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, // SKINCOLOR_RUBY
+ {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, // SKINCOLOR_SALMON
+ {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, // SKINCOLOR_RED
+ {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, // SKINCOLOR_CRIMSON
+ {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, // SKINCOLOR_FLAME
+ {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, // SKINCOLOR_PEACHY
+ {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, // SKINCOLOR_QUAIL
+ {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, // SKINCOLOR_SUNSET
+ {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, // SKINCOLOR_APRICOT
+ {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, // SKINCOLOR_ORANGE
+ {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_RUST
+ {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_GOLD
+ {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, // SKINCOLOR_SANDY
+ {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, // SKINCOLOR_YELLOW
+ {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, // SKINCOLOR_OLIVE
+ {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_LIME
+ {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, // SKINCOLOR_PERIDOT
+ {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_GREEN
+ {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, // SKINCOLOR_FOREST
+ {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, // SKINCOLOR_EMERALD
+ {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, // SKINCOLOR_MINT
+ {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, // SKINCOLOR_SEAFOAM
+ {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, // SKINCOLOR_AQUA
+ {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, // SKINCOLOR_TEAL
+ {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, // SKINCOLOR_WAVE
+ {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, // SKINCOLOR_CYAN
+ {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, // SKINCOLOR_SKY
+ {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, // SKINCOLOR_CERULEAN
+ {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_ICY
+ {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, // SKINCOLOR_SAPPHIRE
+ {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, // SKINCOLOR_CORNFLOWER
+ {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, // SKINCOLOR_BLUE
+ {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_COBALT
+ {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, // SKINCOLOR_VAPOR
+ {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, // SKINCOLOR_DUSK
+ {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, // SKINCOLOR_PASTEL
+ {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, // SKINCOLOR_PURPLE
+ {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, // SKINCOLOR_BUBBLEGUM
+ {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, // SKINCOLOR_MAGENTA
+ {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, // SKINCOLOR_NEON
+ {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_VIOLET
+ {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, // SKINCOLOR_LILAC
+ {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, // SKINCOLOR_PLUM
+ {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, // SKINCOLOR_ROSY
+
+ // {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_?
+
+ // super
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, // SKINCOLOR_SUPERSILVER1
+ {0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07}, // SKINCOLOR_SUPERSILVER2
+ {0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b}, // SKINCOLOR_SUPERSILVER3
+ {0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11}, // SKINCOLOR_SUPERSILVER4
+ {0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13}, // SKINCOLOR_SUPERSILVER5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2}, // SKINCOLOR_SUPERRED1
+ {0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21}, // SKINCOLOR_SUPERRED2
+ {0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23}, // SKINCOLOR_SUPERRED3
+ {0x00, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, // SKINCOLOR_SUPERRED4
+ {0xd0, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25}, // SKINCOLOR_SUPERRED5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34}, // SKINCOLOR_SUPERORANGE1
+ {0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34}, // SKINCOLOR_SUPERORANGE2
+ {0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35}, // SKINCOLOR_SUPERORANGE3
+ {0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERORANGE4
+ {0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERORANGE5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48}, // SKINCOLOR_SUPERGOLD1
+ {0x00, 0x50, 0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41}, // SKINCOLOR_SUPERGOLD2
+ {0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43}, // SKINCOLOR_SUPERGOLD3
+ {0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERGOLD4
+ {0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERGOLD5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc}, // SKINCOLOR_SUPERPERIDOT1
+ {0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe}, // SKINCOLOR_SUPERPERIDOT2
+ {0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf}, // SKINCOLOR_SUPERPERIDOT3
+ {0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f}, // SKINCOLOR_SUPERPERIDOT4
+ {0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f, 0x77}, // SKINCOLOR_SUPERPERIDOT5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84}, // SKINCOLOR_SUPERSKY1
+ {0x00, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86}, // SKINCOLOR_SUPERSKY2
+ {0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87}, // SKINCOLOR_SUPERSKY3
+ {0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a}, // SKINCOLOR_SUPERSKY4
+ {0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8b}, // SKINCOLOR_SUPERSKY5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa2}, // SKINCOLOR_SUPERPURPLE1
+ {0x00, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5}, // SKINCOLOR_SUPERPURPLE2
+ {0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6}, // SKINCOLOR_SUPERPURPLE3
+ {0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9}, // SKINCOLOR_SUPERPURPLE4
+ {0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xfd}, // SKINCOLOR_SUPERPURPLE5
+
+ {0x00, 0xd0, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x32, 0x33, 0x37, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x2e}, // SKINCOLOR_SUPERRUST1
+ {0x30, 0x31, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x47, 0x2e}, // SKINCOLOR_SUPERRUST2
+ {0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x3a, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x2e, 0x2e}, // SKINCOLOR_SUPERRUST3
+ {0x48, 0x40, 0x41, 0x42, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x2e, 0x2e, 0x2e}, // SKINCOLOR_SUPERRUST4
+ {0x41, 0x42, 0x43, 0x43, 0x44, 0x44, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef}, // SKINCOLOR_SUPERRUST5
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52}, // SKINCOLOR_SUPERTAN1
+ {0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, // SKINCOLOR_SUPERTAN2
+ {0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, // SKINCOLOR_SUPERTAN3
+ {0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, // SKINCOLOR_SUPERTAN4
+ {0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef} // SKINCOLOR_SUPERTAN5
+};
// See also the enum skincolors_t
// TODO Callum: Can this be translated?
const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] =
{
- "None", // SKINCOLOR_NONE
- "White", // SKINCOLOR_WHITE
- "Silver", // SKINCOLOR_SILVER
- "Grey", // SKINCOLOR_GREY
- "Black", // SKINCOLOR_BLACK
- "Beige", // SKINCOLOR_BEIGE
- "Peach", // SKINCOLOR_PEACH
- "Brown", // SKINCOLOR_BROWN
- "Red", // SKINCOLOR_RED
- "Crimson", // SKINCOLOR_CRIMSON
- "Orange", // SKINCOLOR_ORANGE
- "Rust", // SKINCOLOR_RUST
- "Gold", // SKINCOLOR_GOLD
- "Yellow", // SKINCOLOR_YELLOW
- "Tan", // SKINCOLOR_TAN
- "Moss", // SKINCOLOR_MOSS
- "Peridot", // SKINCOLOR_PERIDOT
- "Green", // SKINCOLOR_GREEN
- "Emerald", // SKINCOLOR_EMERALD
- "Aqua", // SKINCOLOR_AQUA
- "Teal", // SKINCOLOR_TEAL
- "Cyan", // SKINCOLOR_CYAN
- "Blue", // SKINCOLOR_BLUE
- "Azure", // SKINCOLOR_AZURE
- "Pastel", // SKINCOLOR_PASTEL
- "Purple", // SKINCOLOR_PURPLE
- "Lavender", // SKINCOLOR_LAVENDER
- "Magenta", // SKINCOLOR_MAGENTA
- "Pink", // SKINCOLOR_PINK
- "Rosy", // SKINCOLOR_ROSY
+ "None", // SKINCOLOR_NONE,
+
+ // Greyscale ranges
+ "White", // SKINCOLOR_WHITE,
+ "Bone", // SKINCOLOR_BONE,
+ "Cloudy", // SKINCOLOR_CLOUDY,
+ "Grey", // SKINCOLOR_GREY,
+ "Silver", // SKINCOLOR_SILVER,
+ "Carbon", // SKINCOLOR_CARBON,
+ "Jet", // SKINCOLOR_JET,
+ "Black", // SKINCOLOR_BLACK,
+
+ // Desaturated
+ "Aether", // SKINCOLOR_AETHER,
+ "Slate", // SKINCOLOR_SLATE,
+ "Pink", // SKINCOLOR_PINK,
+ "Yogurt", // SKINCOLOR_YOGURT,
+ "Brown", // SKINCOLOR_BROWN,
+ "Tan", // SKINCOLOR_TAN,
+ "Beige", // SKINCOLOR_BEIGE,
+ "Moss", // SKINCOLOR_MOSS,
+ "Azure", // SKINCOLOR_AZURE,
+ "Lavender", // SKINCOLOR_LAVENDER,
+
+ // Viv's vivid colours (toast 21/07/17)
+ "Ruby", // SKINCOLOR_RUBY,
+ "Salmon", // SKINCOLOR_SALMON,
+ "Red", // SKINCOLOR_RED,
+ "Crimson", // SKINCOLOR_CRIMSON,
+ "Flame", // SKINCOLOR_FLAME,
+ "Peachy", // SKINCOLOR_PEACHY,
+ "Quail", // SKINCOLOR_QUAIL,
+ "Sunset", // SKINCOLOR_SUNSET,
+ "Apricot", // SKINCOLOR_APRICOT,
+ "Orange", // SKINCOLOR_ORANGE,
+ "Rust", // SKINCOLOR_RUST,
+ "Gold", // SKINCOLOR_GOLD,
+ "Sandy", // SKINCOLOR_SANDY,
+ "Yellow", // SKINCOLOR_YELLOW,
+ "Olive", // SKINCOLOR_OLIVE,
+ "Lime", // SKINCOLOR_LIME,
+ "Peridot", // SKINCOLOR_PERIDOT,
+ "Green", // SKINCOLOR_GREEN,
+ "Forest", // SKINCOLOR_FOREST,
+ "Emerald", // SKINCOLOR_EMERALD,
+ "Mint", // SKINCOLOR_MINT,
+ "Seafoam", // SKINCOLOR_SEAFOAM,
+ "Aqua", // SKINCOLOR_AQUA,
+ "Teal", // SKINCOLOR_TEAL,
+ "Wave", // SKINCOLOR_WAVE,
+ "Cyan", // SKINCOLOR_CYAN,
+ "Sky", // SKINCOLOR_SKY,
+ "Cerulean", // SKINCOLOR_CERULEAN,
+ "Icy", // SKINCOLOR_ICY,
+ "Sapphire", // SKINCOLOR_SAPPHIRE,
+ "Cornflower", // SKINCOLOR_CORNFLOWER,
+ "Blue", // SKINCOLOR_BLUE,
+ "Cobalt", // SKINCOLOR_COBALT,
+ "Vapor", // SKINCOLOR_VAPOR,
+ "Dusk", // SKINCOLOR_DUSK,
+ "Pastel", // SKINCOLOR_PASTEL,
+ "Purple", // SKINCOLOR_PURPLE,
+ "Bubblegum", // SKINCOLOR_BUBBLEGUM,
+ "Magenta", // SKINCOLOR_MAGENTA,
+ "Neon", // SKINCOLOR_NEON,
+ "Violet", // SKINCOLOR_VIOLET,
+ "Lilac", // SKINCOLOR_LILAC,
+ "Plum", // SKINCOLOR_PLUM,
+ "Rosy", // SKINCOLOR_ROSY,
+
// Super behaves by different rules (one name per 5 colours), and will be accessed exclusively via R_GetSuperColorByName instead of R_GetColorByName.
- "Silver", // SKINCOLOR_SUPERSILVER1
- "Red", // SKINCOLOR_SUPERRED1
- "Orange", // SKINCOLOR_SUPERORANGE1
- "Gold", // SKINCOLOR_SUPERGOLD1
- "Peridot", // SKINCOLOR_SUPERPERIDOT1
- "Cyan", // SKINCOLOR_SUPERCYAN1
- "Purple", // SKINCOLOR_SUPERPURPLE1
- "Rust", // SKINCOLOR_SUPERRUST1
- "Tan" // SKINCOLOR_SUPERTAN1
+ "Silver", // SKINCOLOR_SUPERSILVER1,
+ "Red", // SKINCOLOR_SUPERRED1,
+ "Orange", // SKINCOLOR_SUPERORANGE1,
+ "Gold", // SKINCOLOR_SUPERGOLD1,
+ "Peridot", // SKINCOLOR_SUPERPERIDOT1,
+ "Sky", // SKINCOLOR_SUPERSKY1,
+ "Purple", // SKINCOLOR_SUPERPURPLE1,
+ "Rust", // SKINCOLOR_SUPERRUST1,
+ "Tan" // SKINCOLOR_SUPERTAN1,
};
/*
A word of warning: If the following array is non-symmetrical,
A_SignPlayer's prefoppositecolor behaviour will break.
*/
-const UINT8 Color_Opposite[MAXSKINCOLORS*2] =
+const UINT8 Color_Opposite[(MAXSKINCOLORS - 1)*2] =
{
- SKINCOLOR_NONE,8, // SKINCOLOR_NONE
- SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE
- SKINCOLOR_GREY,4, // SKINCOLOR_SILVER
- SKINCOLOR_SILVER,12, // SKINCOLOR_GREY
- SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK
- SKINCOLOR_BEIGE,8, // SKINCOLOR_BEIGE - needs new offset
- SKINCOLOR_BROWN,8, // SKINCOLOR_PEACH - ditto
- SKINCOLOR_PEACH,8, // SKINCOLOR_BROWN - ditto
- SKINCOLOR_GREEN,5, // SKINCOLOR_RED
- SKINCOLOR_CYAN,8, // SKINCOLOR_CRIMSON - ditto
- SKINCOLOR_BLUE,11, // SKINCOLOR_ORANGE
- SKINCOLOR_TAN,8, // SKINCOLOR_RUST - ditto
- SKINCOLOR_LAVENDER,8, // SKINCOLOR_GOLD
- SKINCOLOR_TEAL,8, // SKINCOLOR_YELLOW - ditto
- SKINCOLOR_RUST,8, // SKINCOLOR_TAN - ditto
- SKINCOLOR_MAGENTA,3, // SKINCOLOR_MOSS
- SKINCOLOR_PURPLE,8, // SKINCOLOR_PERIDOT - ditto
- SKINCOLOR_RED,11, // SKINCOLOR_GREEN
- SKINCOLOR_PASTEL,8, // SKINCOLOR_EMERALD - ditto
- SKINCOLOR_ROSY,8, // SKINCOLOR_AQUA - ditto
- SKINCOLOR_YELLOW,8, // SKINCOLOR_TEAL - ditto
- SKINCOLOR_CRIMSON,8, // SKINCOLOR_CYAN - ditto
- SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE
- SKINCOLOR_PINK,8, // SKINCOLOR_AZURE - ditto
- SKINCOLOR_EMERALD,8, // SKINCOLOR_PASTEL - ditto
- SKINCOLOR_PERIDOT,10, // SKINCOLOR_PURPLE
- SKINCOLOR_GOLD,10, // SKINCOLOR_LAVENDER
- SKINCOLOR_MOSS,8, // SKINCOLOR_MAGENTA - ditto
- SKINCOLOR_AZURE,8, // SKINCOLOR_PINK - ditto
- SKINCOLOR_AQUA,14 // SKINCOLOR_ROSY
+ // SKINCOLOR_NONE,8, // SKINCOLOR_NONE
+
+ // Greyscale ranges
+ SKINCOLOR_BLACK,5, // SKINCOLOR_WHITE,
+ SKINCOLOR_JET,7, // SKINCOLOR_BONE,
+ SKINCOLOR_CARBON,7, // SKINCOLOR_CLOUDY,
+ SKINCOLOR_AETHER,12, // SKINCOLOR_GREY,
+ SKINCOLOR_SLATE,12, // SKINCOLOR_SILVER,
+ SKINCOLOR_CLOUDY,7, // SKINCOLOR_CARBON,
+ SKINCOLOR_BONE,7, // SKINCOLOR_JET,
+ SKINCOLOR_WHITE,7, // SKINCOLOR_BLACK,
+
+ // Desaturated
+ SKINCOLOR_GREY,15, // SKINCOLOR_AETHER,
+ SKINCOLOR_SILVER,12, // SKINCOLOR_SLATE,
+ SKINCOLOR_AZURE,9, // SKINCOLOR_PINK,
+ SKINCOLOR_RUST,7, // SKINCOLOR_YOGURT,
+ SKINCOLOR_TAN,2, // SKINCOLOR_BROWN,
+ SKINCOLOR_BROWN,12, // SKINCOLOR_TAN,
+ SKINCOLOR_MOSS,5, // SKINCOLOR_BEIGE,
+ SKINCOLOR_BEIGE,13, // SKINCOLOR_MOSS,
+ SKINCOLOR_PINK,5, // SKINCOLOR_AZURE,
+ SKINCOLOR_GOLD,4, // SKINCOLOR_LAVENDER,
+
+ // Viv's vivid colours (toast 21/07/17)
+ SKINCOLOR_EMERALD,10, // SKINCOLOR_RUBY,
+ SKINCOLOR_FOREST,6, // SKINCOLOR_SALMON,
+ SKINCOLOR_GREEN,10, // SKINCOLOR_RED,
+ SKINCOLOR_ICY,10, // SKINCOLOR_CRIMSON,
+ SKINCOLOR_PURPLE,8, // SKINCOLOR_FLAME,
+ SKINCOLOR_TEAL,7, // SKINCOLOR_PEACHY,
+ SKINCOLOR_WAVE,5, // SKINCOLOR_QUAIL,
+ SKINCOLOR_SAPPHIRE,5, // SKINCOLOR_SUNSET,
+ SKINCOLOR_CYAN,4, // SKINCOLOR_APRICOT,
+ SKINCOLOR_BLUE,4, // SKINCOLOR_ORANGE,
+ SKINCOLOR_YOGURT,8, // SKINCOLOR_RUST,
+ SKINCOLOR_LAVENDER,10, // SKINCOLOR_GOLD,
+ SKINCOLOR_SKY,8, // SKINCOLOR_SANDY,
+ SKINCOLOR_CORNFLOWER,8, // SKINCOLOR_YELLOW,
+ SKINCOLOR_DUSK,3, // SKINCOLOR_OLIVE,
+ SKINCOLOR_MAGENTA,9, // SKINCOLOR_LIME,
+ SKINCOLOR_COBALT,2, // SKINCOLOR_PERIDOT,
+ SKINCOLOR_RED,6, // SKINCOLOR_GREEN,
+ SKINCOLOR_SALMON,9, // SKINCOLOR_FOREST,
+ SKINCOLOR_RUBY,4, // SKINCOLOR_EMERALD,
+ SKINCOLOR_VIOLET,5, // SKINCOLOR_MINT,
+ SKINCOLOR_PLUM,6, // SKINCOLOR_SEAFOAM,
+ SKINCOLOR_ROSY,7, // SKINCOLOR_AQUA,
+ SKINCOLOR_PEACHY,7, // SKINCOLOR_TEAL,
+ SKINCOLOR_QUAIL,5, // SKINCOLOR_WAVE,
+ SKINCOLOR_APRICOT,6, // SKINCOLOR_CYAN,
+ SKINCOLOR_SANDY,1, // SKINCOLOR_SKY,
+ SKINCOLOR_NEON,4, // SKINCOLOR_CERULEAN,
+ SKINCOLOR_CRIMSON,0, // SKINCOLOR_ICY,
+ SKINCOLOR_SUNSET,5, // SKINCOLOR_SAPPHIRE,
+ SKINCOLOR_YELLOW,4, // SKINCOLOR_CORNFLOWER,
+ SKINCOLOR_ORANGE,5, // SKINCOLOR_BLUE,
+ SKINCOLOR_PERIDOT,5, // SKINCOLOR_COBALT,
+ SKINCOLOR_LILAC,4, // SKINCOLOR_VAPOR,
+ SKINCOLOR_OLIVE,0, // SKINCOLOR_DUSK,
+ SKINCOLOR_BUBBLEGUM,9, // SKINCOLOR_PASTEL,
+ SKINCOLOR_FLAME,7, // SKINCOLOR_PURPLE,
+ SKINCOLOR_PASTEL,8, // SKINCOLOR_BUBBLEGUM,
+ SKINCOLOR_LIME,6, // SKINCOLOR_MAGENTA,
+ SKINCOLOR_CERULEAN,2, // SKINCOLOR_NEON,
+ SKINCOLOR_MINT,6, // SKINCOLOR_VIOLET,
+ SKINCOLOR_VAPOR,4, // SKINCOLOR_LILAC,
+ SKINCOLOR_MINT,7, // SKINCOLOR_PLUM,
+ SKINCOLOR_AQUA,1 // SKINCOLOR_ROSY,
};
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
@@ -258,40 +464,7 @@ void R_InitTranslationTables(void)
*/
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
{
- // Table of indices into the palette of the first entries of each translated ramp
- const UINT8 skinbasecolors[] = {
- 0x00, // SKINCOLOR_WHITE
- 0x03, // SKINCOLOR_SILVER
- 0x08, // SKINCOLOR_GREY
- 0x18, // SKINCOLOR_BLACK
- 0xf0, // SKINCOLOR_BEIGE
- 0xd8, // SKINCOLOR_PEACH
- 0xe0, // SKINCOLOR_BROWN
- 0x21, // SKINCOLOR_RED
- 0x28, // SKINCOLOR_CRIMSON
- 0x31, // SKINCOLOR_ORANGE
- 0x3a, // SKINCOLOR_RUST
- 0x40, // SKINCOLOR_GOLD
- 0x48, // SKINCOLOR_YELLOW
- 0x54, // SKINCOLOR_TAN
- 0x58, // SKINCOLOR_MOSS
- 0xbc, // SKINCOLOR_PERIDOT
- 0x60, // SKINCOLOR_GREEN
- 0x70, // SKINCOLOR_EMERALD
- 0x78, // SKINCOLOR_AQUA
- 0x8c, // SKINCOLOR_TEAL
- 0x80, // SKINCOLOR_CYAN
- 0x92, // SKINCOLOR_BLUE
- 0xaa, // SKINCOLOR_AZURE
- 0xa0, // SKINCOLOR_PASTEL
- 0xa0, // SKINCOLOR_PURPLE
- 0xc0, // SKINCOLOR_LAVENDER
- 0xb3, // SKINCOLOR_MAGENTA
- 0xd0, // SKINCOLOR_PINK
- 0xc8, // SKINCOLOR_ROSY
- };
- INT32 i;
- INT32 starttranscolor;
+ INT32 i, starttranscolor, skinramplength;
// Handle a couple of simple special cases
if (skinnum == TC_BOSS || skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || color == SKINCOLOR_NONE)
@@ -311,776 +484,28 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
return;
}
+ if (color >= MAXTRANSLATIONS)
+ I_Error("Invalid skin color #%hu.", (UINT16)color);
+
starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR;
// Fill in the entries of the palette that are fixed
for (i = 0; i < starttranscolor; i++)
dest_colormap[i] = (UINT8)i;
- for (i = (UINT8)(starttranscolor + 16); i < NUM_PALETTE_ENTRIES; i++)
- dest_colormap[i] = (UINT8)i;
+ i = starttranscolor + 16;
+ if (i < NUM_PALETTE_ENTRIES)
+ {
+ for (i = (UINT8)i; i < NUM_PALETTE_ENTRIES; i++)
+ dest_colormap[i] = (UINT8)i;
+ skinramplength = 16;
+ }
+ else
+ skinramplength = i - NUM_PALETTE_ENTRIES;
// Build the translated ramp
- switch (color)
- {
- case SKINCOLOR_SILVER:
- case SKINCOLOR_GREY:
- case SKINCOLOR_BROWN:
- case SKINCOLOR_GREEN:
- // 16 color ramp
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
- break;
-
- case SKINCOLOR_WHITE:
- case SKINCOLOR_CYAN:
- // 12 color ramp
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (12*i/SKIN_RAMP_LENGTH));
- break;
-
- case SKINCOLOR_BLACK:
- case SKINCOLOR_MOSS:
- case SKINCOLOR_EMERALD:
- case SKINCOLOR_LAVENDER:
- case SKINCOLOR_PINK:
- // 8 color ramp
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
- break;
-
- case SKINCOLOR_BEIGE:
- // 13 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 15)
- dest_colormap[starttranscolor + i] = 0xed; // Darkest
- else if (i <= 6)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i + 1) >> 1)); // Brightest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 3);
- }
- break;
-
- case SKINCOLOR_PEACH:
- // 11 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 0)
- dest_colormap[starttranscolor + i] = 0xD0; // Lightest 1
- else if (i == 1)
- dest_colormap[starttranscolor + i] = 0x30; // Lightest 2
- else if (i <= 11)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 7); // Darkest
- }
- break;
-
- case SKINCOLOR_RED:
- // 16 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 13)
- dest_colormap[starttranscolor + i] = 0x47; // Semidark
- else if (i > 13)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 1); // Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
- }
- break;
-
- case SKINCOLOR_CRIMSON:
- // 9 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i/2 == 6)
- dest_colormap[starttranscolor + i] = 0x47; // Semidark
- else if (i/2 == 7)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 8); // Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
- }
- break;
-
- case SKINCOLOR_ORANGE:
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 15)
- dest_colormap[starttranscolor + i] = 0x2c; // Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
- }
- break;
-
- case SKINCOLOR_RUST:
- // 10 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i <= 11)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
- else if (i == 12)
- dest_colormap[starttranscolor + i] = 0x2c;
- else if (i <= 14)
- dest_colormap[starttranscolor + i] = 0x2d;
- else
- dest_colormap[starttranscolor + i] = 0x48;
- }
- break;
-
- case SKINCOLOR_GOLD:
- // 10 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 0)
- dest_colormap[starttranscolor + i] = 0x50; // Lightest 1
- else if (i == 1)
- dest_colormap[starttranscolor + i] = 0x53; // Lightest 2
- else if (i/2 == 7)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 8); //Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
- }
- break;
-
- case SKINCOLOR_YELLOW:
- // 10 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 0)
- dest_colormap[starttranscolor + i] = 0x53; // Lightest
- else if (i == 15)
- dest_colormap[starttranscolor + i] = 0xed; // Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
- }
- break;
-
- case SKINCOLOR_TAN:
- // 8 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i/2 == 0)
- dest_colormap[starttranscolor + i] = 0x51; // Lightest
- else if (i/2 == 5)
- dest_colormap[starttranscolor + i] = 0xf5; // Darkest 1
- else if (i/2 == 6)
- dest_colormap[starttranscolor + i] = 0xf9; // Darkest 2
- else if (i/2 == 7)
- dest_colormap[starttranscolor + i] = 0xed; // Darkest 3
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
- }
- break;
-
- case SKINCOLOR_PERIDOT:
- // 8 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i/2 == 0)
- dest_colormap[starttranscolor + i] = 0x58; // Lightest
- else if (i/2 == 7)
- dest_colormap[starttranscolor + i] = 0x77; // Darkest
- else if (i/2 >= 5)
- dest_colormap[starttranscolor + i] = (UINT8)(0x5e + (i >> 1) - 5); // Semidark
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
- }
- break;
-
- case SKINCOLOR_AQUA:
- // 10 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 0)
- dest_colormap[starttranscolor + i] = 0x78; // Lightest
- else if (i >= 14)
- dest_colormap[starttranscolor + i] = (UINT8)(0x76 + i - 14); // Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 1);
- }
- break;
-
- case SKINCOLOR_TEAL:
- // 6 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i <= 1)
- dest_colormap[starttranscolor + i] = 0x78; // Lightest
- else if (i >= 13)
- dest_colormap[starttranscolor + i] = 0x8a; // Darkest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i - 1)/3));
- }
- break;
-
- case SKINCOLOR_AZURE:
- // 8 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i <= 3)
- dest_colormap[starttranscolor + i] = (UINT8)(0x90 + i/2); // Lightest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 2);
- }
- break;
-
- case SKINCOLOR_BLUE:
- // 16 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 15)
- dest_colormap[starttranscolor + i] = 0xfe; //Darkest 1
- else if (i == 14)
- dest_colormap[starttranscolor + i] = 0xfd; //Darkest 2
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
- }
- break;
-
- case SKINCOLOR_PASTEL:
- // 10 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i >= 12)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 7); // Darkest
- else if (i <= 1)
- dest_colormap[starttranscolor + i] = 0x90; // Lightest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
- }
- break;
-
- case SKINCOLOR_PURPLE:
- // 10 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i <= 3)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); // Lightest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 2);
- }
- break;
-
- case SKINCOLOR_MAGENTA:
- // 9 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- if (i == 0)
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1]); // Lightest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 1);
- break;
-
- case SKINCOLOR_ROSY:
- // 9 colors
- for (i = 0; i < SKIN_RAMP_LENGTH; i++)
- {
- if (i == 0)
- dest_colormap[starttranscolor + i] = 0xfc; // Lightest
- else
- dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i - 1) >> 1));
- }
- break;
-
- // Super colors, from lightest to darkest!
-
- // Super silvers.
- case SKINCOLOR_SUPERSILVER1:
- for (i = 0; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)1;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(i-12);
- break;
-
- case SKINCOLOR_SUPERSILVER2:
- for (i = 0; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(i);
- dest_colormap[starttranscolor + (i++)] = (UINT8)2;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)3;
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)4;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(i-9);
- break;
-
- case SKINCOLOR_SUPERSILVER3:
- dest_colormap[starttranscolor] = (UINT8)1;
- for (i = 1; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)2;
- for (; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)3;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)4;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(5 + ((i-12)*2));
- break;
-
- case SKINCOLOR_SUPERSILVER4:
- dest_colormap[starttranscolor] = (UINT8)2;
- for (i = 1; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)3;
- for (; i < 9; i++)
- dest_colormap[starttranscolor + i] = (UINT8)4;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(5 + ((i-9)*2));
- break;
-
- case SKINCOLOR_SUPERSILVER5:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)3;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)4;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(5 + ((i-8)*2));
- break;
-
- // Super reds.
- case SKINCOLOR_SUPERRED1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(208 + ((i-10) >> 1));
- break;
-
- case SKINCOLOR_SUPERRED2:
- for (i = 0; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(208 + ((i-3) / 3));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-12) >> 1));
- break;
-
- case SKINCOLOR_SUPERRED3:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(208 + ((i-2) >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-8) >> 1));
- break;
-
- case SKINCOLOR_SUPERRED4:
- dest_colormap[starttranscolor] = (UINT8)0;
- for (i = 1; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(208 + (i >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-6) >> 1));
- break;
-
- case SKINCOLOR_SUPERRED5:
- dest_colormap[starttranscolor] = (UINT8)208;
- for (i = 1; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(209 + (i >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-4) >> 1));
- break;
-
- // Super oranges.
- case SKINCOLOR_SUPERORANGE1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- dest_colormap[starttranscolor + (i++)] = (UINT8)208;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(48 + (i-11));
- break;
-
- case SKINCOLOR_SUPERORANGE2:
- for (i = 0; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)208;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(48 + ((i-6) >> 1));
- break;
-
- case SKINCOLOR_SUPERORANGE3:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)208;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(48 + ((i-4) >> 1));
- break;
-
- case SKINCOLOR_SUPERORANGE4:
- dest_colormap[starttranscolor] = (UINT8)0;
- dest_colormap[starttranscolor + 1] = (UINT8)208;
- for (i = 2; i < 13; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(48 + (i-2));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-13));
- break;
-
- case SKINCOLOR_SUPERORANGE5:
- dest_colormap[starttranscolor] = (UINT8)208;
- for (i = 1; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(48 + (i-1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-12));
- break;
-
- // Super golds.
- case SKINCOLOR_SUPERGOLD1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0; // True white
- for (; i < 12; i++) // White-yellow fade
- dest_colormap[starttranscolor + i] = (UINT8)80;
- for (; i < 15; i++) // White-yellow fade
- dest_colormap[starttranscolor + i] = (UINT8)(81 + (i-12));
- dest_colormap[starttranscolor + 15] = (UINT8)72;
- break;
-
- case SKINCOLOR_SUPERGOLD2:
- dest_colormap[starttranscolor] = (UINT8)(0);
- for (i = 1; i < 4; i++) // White-yellow fade
- dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-1));
- for (; i < 6; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)83;
- for (; i < 8; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)72;
- for (; i < 14; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)73;
- for (; i < 16; i++) // With a fine golden finish! :3
- dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-14));
- break;
-
- case SKINCOLOR_SUPERGOLD3:
- for (i = 0; i < 2; i++) // White-yellow fade
- dest_colormap[starttranscolor + i] = (UINT8)(81 + i);
- for (; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)83;
- for (; i < 6; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)72;
- for (; i < 12; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)73;
- for (; i < 16; i++) // With a fine golden finish! :3
- dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-12));
- break;
-
- case SKINCOLOR_SUPERGOLD4: // "The SSNTails"
- dest_colormap[starttranscolor] = (UINT8)83; // Golden shine
- for (i = 1; i < 3; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)(72);
- for (; i < 9; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)(73);
- for (; i < 16; i++) // With a fine golden finish! :3
- dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-9));
- break;
-
- case SKINCOLOR_SUPERGOLD5: // Golden Delicious
- for (i = 0; i < 2; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)(72);
- for (; i < 8; i++) // Yellow
- dest_colormap[starttranscolor + i] = (UINT8)(73);
- for (; i < 16; i++) // With a fine golden finish! :3
- dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-8));
- break;
-
- // Super peridots. (nyeheheheh)
- case SKINCOLOR_SUPERPERIDOT1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 13; i++)
- dest_colormap[starttranscolor + i] = (UINT8)88;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)188;
- break;
-
- case SKINCOLOR_SUPERPERIDOT2:
- dest_colormap[starttranscolor] = (UINT8)(0);
- for (i = 1; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)88;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)188;
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)189;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)190;
- break;
-
- case SKINCOLOR_SUPERPERIDOT3:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)88;
- for (; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)188;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)189;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(190 + ((i-12) >> 1));
- break;
-
- case SKINCOLOR_SUPERPERIDOT4:
- dest_colormap[starttranscolor] = (UINT8)88;
- for (i = 1; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)188;
- for (; i < 9; i++)
- dest_colormap[starttranscolor + i] = (UINT8)189;
- for (; i < 13; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(190 + ((i-9) >> 1));
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)94;
- dest_colormap[starttranscolor + i] = (UINT8)95;
- break;
-
- case SKINCOLOR_SUPERPERIDOT5:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)188;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)189;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(190 + ((i-8) >> 1));
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)94;
- dest_colormap[starttranscolor + (i++)] = (UINT8)95;
- dest_colormap[starttranscolor + i] = (UINT8)119;
- break;
-
- // Super cyans.
- case SKINCOLOR_SUPERCYAN1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)128;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(129 + (i-12));
- break;
-
- case SKINCOLOR_SUPERCYAN2:
- dest_colormap[starttranscolor] = (UINT8)0;
- for (i = 1; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(128 + (i-1));
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(131 + ((i-4) >> 1));
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)133;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)134;
- break;
-
- case SKINCOLOR_SUPERCYAN3:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(129 + i);
- for (; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(131 + ((i-2) >> 1));
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)133;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(134 + ((i-12) >> 1));
- break;
-
- case SKINCOLOR_SUPERCYAN4:
- dest_colormap[starttranscolor] = (UINT8)131;
- for (i = 1; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)132;
- for (; i < 9; i++)
- dest_colormap[starttranscolor + i] = (UINT8)133;
- for (; i < 13; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(134 + ((i-9) >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(136 + (i-13));
- break;
-
- case SKINCOLOR_SUPERCYAN5:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)132;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)133;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(134 + ((i-8) >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(136 + (i-12));
- break;
-
- // Super purples.
- case SKINCOLOR_SUPERPURPLE1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)144;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(160 + (i-12));
- break;
-
- case SKINCOLOR_SUPERPURPLE2:
- dest_colormap[starttranscolor] = (UINT8)0;
- dest_colormap[starttranscolor + 1] = (UINT8)144;
- for (i = 2; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(160 + (i-2));
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(162 + ((i-4) >> 1));
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)164;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)165;
- break;
-
- case SKINCOLOR_SUPERPURPLE3:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(160 + i);
- for (; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(162 + ((i-2) >> 1));
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)164;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(165 + ((i-12) >> 1));
- break;
-
- case SKINCOLOR_SUPERPURPLE4:
- dest_colormap[starttranscolor] = (UINT8)162;
- for (i = 1; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)163;
- for (; i < 9; i++)
- dest_colormap[starttranscolor + i] = (UINT8)164;
- for (; i < 13; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(165 + ((i-9) >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(167 + (i-13));
- break;
-
- case SKINCOLOR_SUPERPURPLE5:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)163;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)164;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(165 + ((i-8) >> 1));
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(167 + (i-12));
- dest_colormap[starttranscolor + i] = (UINT8)253;
- break;
-
- // Super rusts.
- case SKINCOLOR_SUPERRUST1:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 5; i++)
- dest_colormap[starttranscolor + i] = (UINT8)208;
- for (; i < 7; i++)
- dest_colormap[starttranscolor + i] = (UINT8)48;
- for (; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(49 + (i-7));
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(55 + ((i-10)*3));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-11));
- break;
-
- case SKINCOLOR_SUPERRUST2:
- for (i = 0; i < 4; i++)
- dest_colormap[starttranscolor + i] = (UINT8)48;
- for (; i < 9; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(49 + (i-4));
- for (; i < 11; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(56 + ((i-9)*2));
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-11));
- dest_colormap[starttranscolor + i] = (UINT8)71;
- break;
-
- case SKINCOLOR_SUPERRUST3:
- dest_colormap[starttranscolor] = (UINT8)49;
- for (i = 1; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)50;
- for (; i < 5; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(51 + (i-3));
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(54 + (i-5));
- dest_colormap[starttranscolor + (i++)] = (UINT8)58;
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(68 + ((i-7) >> 1));
- dest_colormap[starttranscolor + i] = (UINT8)46;
- break;
-
- case SKINCOLOR_SUPERRUST4:
- dest_colormap[starttranscolor] = (UINT8)83;
- dest_colormap[starttranscolor + 1] = (UINT8)72;
- for (i = 2; i < 6; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-2));
- for (; i < 14; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(68 + ((i-6) >> 1));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)46;
- break;
-
- case SKINCOLOR_SUPERRUST5:
- for (i = 0; i < 3; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(64 + i);
- for (; i < 7; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(67 + ((i-3) >> 1));
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(233 + (i-7));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(238 + ((i-12) >> 1));
- break;
-
- // Super tans.
- case SKINCOLOR_SUPERTAN1:
- for (i = 0; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)0;
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-10) >> 1));
- break;
-
- case SKINCOLOR_SUPERTAN2:
- dest_colormap[starttranscolor] = (UINT8)0;
- for (i = 1; i < 7; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-1) >> 1));
- dest_colormap[starttranscolor + (i++)] = (UINT8)82;
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)84;
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-12));
- dest_colormap[starttranscolor + i] = (UINT8)245;
- break;
-
- case SKINCOLOR_SUPERTAN3:
- dest_colormap[starttranscolor] = (UINT8)80;
- for (i = 1; i < 5; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(81 + ((i-1) >> 1));
- dest_colormap[starttranscolor + (i++)] = (UINT8)82;
- for (; i < 10; i++)
- dest_colormap[starttranscolor + i] = (UINT8)84;
- for (; i < 13; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-10));
- for (; i < 16; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(245 + ((i-13)*2));
- break;
-
- case SKINCOLOR_SUPERTAN4:
- dest_colormap[starttranscolor] = (UINT8)81;
- for (i = 1; i < 5; i++)
- dest_colormap[starttranscolor + i] = (UINT8)82;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)84;
- for (; i < 11; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-8));
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(245 + ((i-11)*2));
- dest_colormap[starttranscolor + i] = (UINT8)237;
- break;
-
- case SKINCOLOR_SUPERTAN5:
- for (i = 0; i < 2; i++)
- dest_colormap[starttranscolor + i] = (UINT8)82;
- for (; i < 5; i++)
- dest_colormap[starttranscolor + i] = (UINT8)84;
- for (; i < 8; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-5));
- for (; i < 12; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(245 + (i-8));
- for (; i < 15; i++)
- dest_colormap[starttranscolor + i] = (UINT8)(237 + (i-12));
- dest_colormap[starttranscolor + i] = (UINT8)239;
- break;
-
- default:
- I_Error("Invalid skin color #%hu.", (UINT16)color);
- break;
- }
+ for (i = 0; i < skinramplength; i++)
+ dest_colormap[starttranscolor + i] = (UINT8)Color_Index[color-1][i];
}
@@ -1155,7 +580,7 @@ UINT8 R_GetColorByName(const char *name)
for (color = 1; color < MAXSKINCOLORS; color++)
if (!stricmp(Color_Names[color], name))
return color;
- return 0;
+ return SKINCOLOR_GREEN;
}
UINT8 R_GetSuperColorByName(const char *name)
@@ -1166,7 +591,7 @@ UINT8 R_GetSuperColorByName(const char *name)
for (color = 0; color < NUMSUPERCOLORS; color++)
if (!stricmp(Color_Names[color + MAXSKINCOLORS], name))
return ((color*5) + MAXSKINCOLORS);
- return 0;
+ return SKINCOLOR_SUPERGOLD1;
}
// ==========================================================================
diff --git a/src/r_plane.c b/src/r_plane.c
index cf7b679bb..670152eda 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -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)
{
diff --git a/src/r_things.c b/src/r_things.c
index 53dcc3314..b2437d4ac 100644
--- a/src/r_things.c
+++ b/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
+ 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)<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)<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
diff --git a/src/r_things.h b/src/r_things.h
index c6eed746d..18cc701ab 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -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);
diff --git a/src/sounds.c b/src/sounds.c
index 2f5f6acf0..2c1c5f3af 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -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"},
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 8e40f138c..4515495af 100644
--- a/src/st_stuff.c
+++ b/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) Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot
-#define NUMLINKCOLORS 13
+// 2.2 indev list: (unix time 1470866042) 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] Ruby > Red > Flame > Sunset > Orange > Gold > Yellow > Lime > Green > Aqua > cyan > Sky > Blue > Pastel > Purple > Bubblegum > Magenta > Rosy > repeat
+// [20:00:25] Also Icy for the link freeze text color
+// [20:04:03] 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."));
}
}
diff --git a/src/st_stuff.h b/src/st_stuff.h
index c11559d2b..ddb119fb8 100644
--- a/src/st_stuff.h
+++ b/src/st_stuff.h
@@ -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);
diff --git a/src/v_video.c b/src/v_video.c
index f7a5c2841..6ac101f2d 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -865,11 +865,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
//
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor)
{
- if (skins[skinnum].flags & SF_HIRES
-#ifdef HWRENDER
-// || (rendermode != render_soft && rendermode != render_none)
-#endif
- )
+ if (skins[skinnum].flags & SF_HIRES)
V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE));
else
{
diff --git a/src/w_wad.c b/src/w_wad.c
index cf8e7aab0..22e1836c7 100644
--- a/src/w_wad.c
+++ b/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".
*
diff --git a/src/w_wad.h b/src/w_wad.h
index a9ca29b35..d3ce20e20 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -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.