Merge remote-tracking branch 'origin/master' into map-by-name

This commit is contained in:
James R 2019-10-10 11:38:48 -07:00
commit de5a7d88d4
123 changed files with 11367 additions and 5379 deletions

View file

@ -107,7 +107,7 @@ matrix:
- p7zip-full
- gcc-8
compiler: gcc-8
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow -Wno-error=format-truncation" GCC81=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0
- os: linux

View file

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
# Version change is fine.
project(SRB2
VERSION 1.0.4
VERSION 1.1.0
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})

View file

@ -1,4 +1,4 @@
version: 1.0.4.{branch}-{build}
version: 1.1.0.{branch}-{build}
os: MinGW
environment:
@ -29,7 +29,7 @@ environment:
##############################
DPL_ENABLED: 0
DPL_TAG_ENABLED: 0
DPL_INSTALLER_NAME: srb2kart-v104
DPL_INSTALLER_NAME: srb2kart-v110
# Asset handling is barebones vs. Travis Deployer. We operate on 7z only.
# Include the README files and the OpenGL batch in the main and patch archives.
# The x86/x64 archives contain the DLL binaries.

View file

@ -401,7 +401,11 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c
)
set (SRB2_HWRENDER_HEADERS
@ -415,6 +419,10 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h
)
set(SRB2_R_OPENGL_SOURCES

View file

@ -282,7 +282,8 @@ ifndef DC
endif
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.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 \
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
endif
ifdef NOHS
@ -741,16 +742,18 @@ 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 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 \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 $@
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 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 \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 $@
endif
@ -902,24 +905,27 @@ 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 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 \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 $@
$(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 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 \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 $@
$(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 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 \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 $@
endif

View file

@ -222,6 +222,7 @@ endif
ifdef GCC71
WFLAGS+=-Wno-error=implicit-fallthrough
WFLAGS+=-Wno-implicit-fallthrough
WFLAGS+=-Wno-error=format-truncation
endif
ifdef GCC80
WFLAGS+=-Wno-error=format-overflow

View file

@ -96,6 +96,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -140,3 +171,44 @@ void I_SetMusicVolume(INT32 volume)
{
(void)volume;
}
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View file

@ -271,13 +271,7 @@ void B_RespawnBot(INT32 playernum)
player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol];
P_TeleportMove(tails, x, y, z);
if (player->charability == CA_FLY)
{
P_SetPlayerMobjState(tails, S_KART_STND1); // SRB2kart - was S_PLAY_ABL1
tails->player->powers[pw_tailsfly] = (UINT16)-1;
}
else
P_SetPlayerMobjState(tails, S_KART_STND1); // SRB2kart - was S_PLAY_FALL1
P_SetPlayerMobjState(tails, S_KART_STND1); // SRB2kart - was S_PLAY_FALL1
P_SetScale(tails, sonic->scale);
tails->destscale = sonic->destscale;
}

View file

@ -50,6 +50,7 @@ static void COM_Exec_f(void);
static void COM_Wait_f(void);
static void COM_Help_f(void);
static void COM_Toggle_f(void);
static void COM_Add_f(void);
static void CV_EnforceExecVersion(void);
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
@ -156,6 +157,20 @@ void COM_BufInsertText(const char *ptext)
}
}
/** Progress the wait timer and flush waiting console commands when ready.
*/
void
COM_BufTicker(void)
{
if (com_wait)
{
com_wait--;
return;
}
COM_BufExecute();
}
/** Flushes (executes) console commands in the buffer.
*/
void COM_BufExecute(void)
@ -165,12 +180,6 @@ void COM_BufExecute(void)
char line[1024] = "";
INT32 quotes;
if (com_wait)
{
com_wait--;
return;
}
while (com_text.cursize)
{
// find a '\n' or; line break
@ -291,6 +300,7 @@ void COM_Init(void)
COM_AddCommand("wait", COM_Wait_f);
COM_AddCommand("help", COM_Help_f);
COM_AddCommand("toggle", COM_Toggle_f);
COM_AddCommand("add", COM_Add_f);
RegisterNetXCmd(XD_NETVAR, Got_NetVar);
}
@ -537,10 +547,41 @@ static void COM_ExecuteString(char *ptext)
{
CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n"));
recursion = 0;
return;
}
recursion++;
COM_BufInsertText(a->value);
else
{
char buf[1024];
char *write = buf, *read = a->value, *seek = read;
while ((seek = strchr(seek, '$')) != NULL)
{
memcpy(write, read, seek-read);
write += seek-read;
seek++;
if (*seek >= '1' && *seek <= '9')
{
if (com_argc > (size_t)(*seek - '0'))
{
memcpy(write, com_argv[*seek - '0'], strlen(com_argv[*seek - '0']));
write += strlen(com_argv[*seek - '0']);
}
seek++;
}
else
{
*write = '$';
write++;
}
read = seek;
}
WRITESTRING(write, read);
recursion++;
COM_BufInsertText(buf);
}
return;
}
}
@ -563,8 +604,6 @@ static void COM_ExecuteString(char *ptext)
static void COM_Alias_f(void)
{
cmdalias_t *a;
char cmd[1024];
size_t i, c;
if (COM_Argc() < 3)
{
@ -577,19 +616,9 @@ static void COM_Alias_f(void)
com_alias = a;
a->name = Z_StrDup(COM_Argv(1));
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
c = COM_Argc();
for (i = 2; i < c; i++)
{
strcat(cmd, COM_Argv(i));
if (i != c)
strcat(cmd, " ");
}
strcat(cmd, "\n");
a->value = Z_StrDup(cmd);
// Just use arg 2 if it's the only other argument, in case the alias is wrapped in quotes (backward compat, or multiple commands in one string).
// Otherwise pull the whole string and seek to the end of the alias name. The strctr is in case the alias is quoted.
a->value = Z_StrDup(COM_Argc() == 3 ? COM_Argv(2) : (strchr(COM_Args() + strlen(a->name), ' ') + 1));
}
/** Prints a line of text to the console.
@ -855,6 +884,30 @@ static void COM_Toggle_f(void)
CV_AddValue(cvar, +1);
}
/** Command variant of CV_AddValue
*/
static void COM_Add_f(void)
{
consvar_t *cvar;
if (COM_Argc() != 3)
{
CONS_Printf(M_GetText("Add <cvar_name> <value>: Add to the value of a cvar. Negative values work too!\n"));
return;
}
cvar = CV_FindVar(COM_Argv(1));
if (!cvar)
{
CONS_Alert(CONS_NOTICE, M_GetText("%s is not a cvar\n"), COM_Argv(1));
return;
}
if (( cvar->flags & CV_FLOAT ))
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
else
CV_AddValue(cvar, atoi(COM_Argv(2)));
}
// =========================================================================
// VARIABLE SIZE BUFFERS
// =========================================================================
@ -1356,7 +1409,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
Setvalue(cvar, svalue, stealth);
}
void CV_SaveNetVars(UINT8 **p)
void CV_SaveNetVars(UINT8 **p, boolean isdemorecording)
{
consvar_t *cvar;
UINT8 *count_p = *p;
@ -1366,10 +1419,32 @@ void CV_SaveNetVars(UINT8 **p)
// the client will reset all netvars to default before loading
WRITEUINT16(*p, 0x0000);
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar))
if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (isdemorecording && cvar->netid == cv_numlaps.netid))
{
WRITEUINT16(*p, cvar->netid);
WRITESTRING(*p, cvar->string);
// UGLY HACK: Save proper lap count in net replays
if (isdemorecording && cvar->netid == cv_numlaps.netid)
{
if (cv_basenumlaps.value &&
(!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))
)
{
WRITESTRING(*p, cv_basenumlaps.string);
}
else
{
char buf[9];
sprintf(buf, "%d", mapheaderinfo[gamemap - 1]->numlaps);
WRITESTRING(*p, buf);
}
}
else
{
WRITESTRING(*p, cvar->string);
}
WRITEUINT8(*p, false);
++count;
}

View file

@ -45,6 +45,9 @@ void COM_ImmedExecute(const char *ptext);
// Execute commands in buffer, flush them
void COM_BufExecute(void);
// As above; and progress the wait timer.
void COM_BufTicker(void);
// setup command buffer, at game tartup
void COM_Init(void);
@ -161,7 +164,7 @@ void CV_AddValue(consvar_t *var, INT32 increment);
void CV_SaveVariables(FILE *f);
// load/save gamesate (load and save option and for network join in game)
void CV_SaveNetVars(UINT8 **p);
void CV_SaveNetVars(UINT8 **p, boolean isdemorecording);
void CV_LoadNetVars(UINT8 **p);
// reset cheat netvars after cheats is deactivated

View file

@ -37,7 +37,7 @@
* Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb
* Last updated 2018 / 12 / 23 - SRB2 v2.1.22 - patch.dta
* Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets
* Last updated 2019 / 03 / 11 - Kart v1.0.4 - patch.kart
* Last updated 2019 / 05 / 06 - Kart v1.1.0 - patch.kart
*/
// Base SRB2 hashes
@ -52,7 +52,7 @@
#define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964"
#define ASSET_HASH_MAPS_KART "1335cd064656aedca359cfbb5233ac4a"
#ifdef USE_PATCH_KART
#define ASSET_HASH_PATCH_KART "b5f48e1abccfa47a5745199182e2fef4"
#define ASSET_HASH_PATCH_KART "7093231f2c3c1cca1a909a708be85d9a"
#endif
#endif

View file

@ -96,6 +96,7 @@ static size_t input_len; // length of current line, used to bound cursor and suc
// protos.
static void CON_InputInit(void);
static void CON_RecalcSize(void);
static void CON_ChangeHeight(void);
static void CONS_hudlines_Change(void);
static void CONS_backcolor_Change(void);
@ -467,6 +468,12 @@ static void CON_RecalcSize(void)
con_destlines = vid.height;
}
if (con_destlines > 0) // Resize console if already open
{
CON_ChangeHeight();
con_curlines = con_destlines;
}
// check for change of video width
if (conw == con_width)
return; // didn't change
@ -516,6 +523,20 @@ static void CON_RecalcSize(void)
Z_Free(tmp_buffer);
}
static void CON_ChangeHeight(void)
{
INT32 minheight = 20 * con_scalefactor; // 20 = 8+8+4
// toggle console in
con_destlines = (cons_height.value*vid.height)/100;
if (con_destlines < minheight)
con_destlines = minheight;
else if (con_destlines > vid.height)
con_destlines = vid.height;
con_destlines &= ~0x3; // multiple of text row height
}
// Handles Console moves in/out of screen (per frame)
//
static void CON_MoveConsole(void)
@ -620,16 +641,7 @@ void CON_Ticker(void)
CON_ClearHUD();
}
else
{
// toggle console in
con_destlines = (cons_height.value*vid.height)/100;
if (con_destlines < minheight)
con_destlines = minheight;
else if (con_destlines > vid.height)
con_destlines = vid.height;
con_destlines &= ~0x3; // multiple of text row height
}
CON_ChangeHeight();
}
// console movement
@ -1149,6 +1161,7 @@ static void CON_Print(char *msg)
{
size_t l;
INT32 controlchars = 0; // for color changing
char color = '\x80'; // keep color across lines
if (msg == NULL)
return;
@ -1174,7 +1187,7 @@ static void CON_Print(char *msg)
{
if (*msg & 0x80)
{
con_line[con_cx++] = *(msg++);
color = con_line[con_cx++] = *(msg++);
controlchars++;
continue;
}
@ -1182,12 +1195,14 @@ static void CON_Print(char *msg)
{
con_cy--;
CON_Linefeed();
color = '\x80';
controlchars = 0;
}
else if (*msg == '\n') // linefeed
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
else if (*msg == ' ') // space
{
@ -1195,7 +1210,8 @@ static void CON_Print(char *msg)
if (con_cx - controlchars >= con_width-11)
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
}
else if (*msg == '\t')
@ -1210,7 +1226,8 @@ static void CON_Print(char *msg)
if (con_cx - controlchars >= con_width-11)
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
}
msg++;
@ -1227,7 +1244,8 @@ static void CON_Print(char *msg)
if ((con_cx - controlchars) + l > con_width-11)
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
// a word at a time
@ -1582,8 +1600,7 @@ static void CON_DrawConsole(void)
i = con_cy - con_scrollup;
// skip the last empty line due to the cursor being at the start of a new line
if (!con_scrollup && !con_cx)
i--;
i--;
i -= (con_curlines - minheight) / charheight;

View file

@ -21,6 +21,7 @@
#include "i_system.h"
#include "i_video.h"
#include "d_net.h"
#include "d_netfil.h" // fileneedednum
#include "d_main.h"
#include "d_event.h"
#include "g_game.h"
@ -91,12 +92,10 @@ tic_t jointimeout = (3*TICRATE);
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
#ifdef NEWPING
UINT16 pingmeasurecount = 1;
UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
tic_t servermaxping = 800; // server's max ping. Defaults to 800
#endif
SINT8 nodetoplayer[MAXNETNODES];
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
SINT8 nodetoplayer3[MAXNETNODES]; // say the numplayer for this node if any (splitscreen == 2)
@ -140,6 +139,7 @@ static UINT8 localtextcmd3[MAXTEXTCMD]; // splitscreen == 2
static UINT8 localtextcmd4[MAXTEXTCMD]; // splitscreen == 3
static tic_t neededtic;
SINT8 servernode = 0; // the number of the server node
char connectedservername[MAXSERVERNAME];
/// \brief do we accept new players?
/// \todo WORK!
boolean acceptnewnode = true;
@ -167,7 +167,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}};
consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -585,21 +585,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->kartspeed = (UINT8)players[i].kartspeed;
rsp->kartweight = (UINT8)players[i].kartweight;
//
rsp->normalspeed = (fixed_t)LONG(players[i].normalspeed);
rsp->runspeed = (fixed_t)LONG(players[i].runspeed);
rsp->thrustfactor = players[i].thrustfactor;
rsp->accelstart = players[i].accelstart;
rsp->acceleration = players[i].acceleration;
rsp->charability = players[i].charability;
rsp->charability2 = players[i].charability2;
rsp->charflags = (UINT32)LONG(players[i].charflags);
rsp->thokitem = (UINT32)LONG(players[i].thokitem); //mobjtype_t
rsp->spinitem = (UINT32)LONG(players[i].spinitem); //mobjtype_t
rsp->revitem = (UINT32)LONG(players[i].revitem); //mobjtype_t
rsp->actionspd = (fixed_t)LONG(players[i].actionspd);
rsp->mindash = (fixed_t)LONG(players[i].mindash);
rsp->maxdash = (fixed_t)LONG(players[i].maxdash);
rsp->jumpfactor = (fixed_t)LONG(players[i].jumpfactor);
rsp->speed = (fixed_t)LONG(players[i].speed);
rsp->jumping = players[i].jumping;
@ -722,21 +708,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].kartspeed = (UINT8)rsp->kartspeed;
players[i].kartweight = (UINT8)rsp->kartweight;
players[i].normalspeed = (fixed_t)LONG(rsp->normalspeed);
players[i].runspeed = (fixed_t)LONG(rsp->runspeed);
players[i].thrustfactor = rsp->thrustfactor;
players[i].accelstart = rsp->accelstart;
players[i].acceleration = rsp->acceleration;
players[i].charability = rsp->charability;
players[i].charability2 = rsp->charability2;
players[i].charflags = (UINT32)LONG(rsp->charflags);
players[i].thokitem = (UINT32)LONG(rsp->thokitem); //mobjtype_t
players[i].spinitem = (UINT32)LONG(rsp->spinitem); //mobjtype_t
players[i].revitem = (UINT32)LONG(rsp->revitem); //mobjtype_t
players[i].actionspd = (fixed_t)LONG(rsp->actionspd);
players[i].mindash = (fixed_t)LONG(rsp->mindash);
players[i].maxdash = (fixed_t)LONG(rsp->maxdash);
players[i].jumpfactor = (fixed_t)LONG(rsp->jumpfactor);
players[i].speed = (fixed_t)LONG(rsp->speed);
players[i].jumping = rsp->jumping;
@ -1129,6 +1101,7 @@ typedef enum
#endif
CL_CONNECTED,
CL_ABORTED,
CL_ASKFULLFILELIST,
CL_ASKDOWNLOADFILES,
CL_WAITDOWNLOADFILESRESPONSE,
CL_CHALLENGE
@ -1139,6 +1112,7 @@ static void GetPackets(void);
static cl_mode_t cl_mode = CL_SEARCHING;
static boolean cl_needsdownload = false;
static UINT16 cl_lastcheckedfilecount = 0;
static UINT8 cl_challengenum = 0;
static UINT8 cl_challengequestion[MD5_LEN+1];
static char cl_challengepassword[65];
@ -1256,6 +1230,9 @@ static inline void CL_DrawConnectionStatus(void)
cltext = M_GetText("Waiting to download game state...");
break;
#endif
case CL_ASKFULLFILELIST:
cltext = M_GetText("This server has a LOT of files!");
break;
case CL_ASKJOIN:
case CL_WAITJOINRESPONSE:
cltext = M_GetText("Requesting to join...");
@ -1315,6 +1292,14 @@ static inline void CL_DrawConnectionStatus(void)
}
#endif
static boolean CL_AskFileList(INT32 firstfile)
{
netbuffer->packettype = PT_TELLFILESNEEDED;
netbuffer->u.filesneedednum = firstfile;
return HSendPacket(servernode, true, 0, sizeof (INT32));
}
/** Sends a special packet to declare how many players in local
* Used only in arbitratrenetstart()
* Sends a PT_CLIENTJOIN packet to the server
@ -1433,7 +1418,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
netbuffer->u.serverinfo.actnum = 0; //mapheaderinfo[gamemap-1]->actnum
p = PutFileNeeded();
p = PutFileNeeded(0);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
}
@ -1443,8 +1428,14 @@ static void SV_SendPlayerInfo(INT32 node)
UINT8 i;
netbuffer->packettype = PT_PLAYERINFO;
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
{
if (i >= MAXPLAYERS)
{
netbuffer->u.playerinfo[i].node = 255;
continue;
}
if (!playeringame[i])
{
netbuffer->u.playerinfo[i].node = 255; // This slot is empty.
@ -1492,7 +1483,7 @@ static void SV_SendPlayerInfo(INT32 node)
netbuffer->u.playerinfo[i].data |= 0x80;
}
HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS);
HSendPacket(node, false, 0, sizeof(plrinfo) * MSCOMPAT_MAXPLAYERS);
}
/** Sends a PT_SERVERCFG packet
@ -1542,7 +1533,7 @@ static boolean SV_SendServerConfig(INT32 node)
op = p = netbuffer->u.servercfg.varlengthinputs;
CV_SavePlayerNames(&p);
CV_SaveNetVars(&p);
CV_SaveNetVars(&p, false);
{
const size_t len = sizeof (serverconfig_pak) + (size_t)(p - op);
@ -1721,8 +1712,8 @@ static void CL_LoadReceivedSavegame(void)
}
paused = false;
demoplayback = false;
titledemo = false;
demo.playback = false;
demo.title = false;
automapactive = false;
// load a base level
@ -1904,6 +1895,66 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
#endif // ifndef NONET
static boolean CL_FinishedFileList(void)
{
INT32 i;
CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
if (i == 3) // too many files
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart SRB2Kart before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have WAD files loaded or have\n"
"modified the game in some way, and\n"
"your file list does not match\n"
"the server's file list.\n"
"Please restart SRB2Kart before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 1)
cl_mode = CL_ASKJOIN;
else
{
// must download something
// can we, though?
if (!CL_CheckDownloadable()) // nope!
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You cannot connect to this server\n"
"because you cannot download the files\n"
"that you are missing from the server.\n\n"
"See the console or log file for\n"
"more details.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
cl_mode = CL_ASKDOWNLOADFILES;
}
return true;
}
/** Called by CL_ServerConnectionTicker
*
* \param viams ???
@ -1947,66 +1998,16 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
if (client)
{
D_ParseFileneeded(serverlist[i].info.fileneedednum,
serverlist[i].info.fileneeded);
CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
if (i == 3) // too many files
D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded, 0);
if (serverlist[i].info.kartvars & SV_LOTSOFADDONS)
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart SRB2Kart before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
cl_mode = CL_ASKFULLFILELIST;
cl_lastcheckedfilecount = 0;
return true;
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have WAD files loaded or have\n"
"modified the game in some way, and\n"
"your file list does not match\n"
"the server's file list.\n"
"Please restart SRB2Kart before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 1)
cl_mode = CL_ASKJOIN;
else
{
// must download something
// can we, though?
if (!CL_CheckDownloadable()) // nope!
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You cannot connect to this server\n"
"because you cannot download the files\n"
"that you are missing from the server.\n\n"
"See the console or log file for\n"
"more details.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
cl_mode = CL_ASKDOWNLOADFILES;
// no problem if can't send packet, we will retry later
//if (CL_SendRequestFile())
// cl_mode = CL_DOWNLOADFILES;
}
if (!CL_FinishedFileList())
return false;
}
else
cl_mode = CL_ASKJOIN; // files need not be checked for the server.
@ -2057,6 +2058,22 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
return false;
break;
case CL_ASKFULLFILELIST:
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
{
if (!CL_FinishedFileList())
return false;
}
else if (fileneedednum != cl_lastcheckedfilecount || *asksent + NEWTICRATE < I_GetTime())
{
if (CL_AskFileList(fileneedednum))
{
cl_lastcheckedfilecount = fileneedednum;
*asksent = I_GetTime();
}
}
break;
case CL_DOWNLOADFILES:
waitmore = false;
for (i = 0; i < fileneedednum; i++)
@ -2298,17 +2315,14 @@ static void CL_ConnectToServer(boolean viams)
if (i != -1)
{
INT32 j;
UINT8 num = serverlist[i].info.gametype;
const char *gametypestr = NULL;
strncpy(connectedservername, serverlist[i].info.servername, MAXSERVERNAME);
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
for (j = 0; gametype_cons_t[j].strvalue; j++)
{
if (gametype_cons_t[j].value == serverlist[i].info.gametype)
{
gametypestr = gametype_cons_t[j].strvalue;
break;
}
}
if (num < NUMGAMETYPES)
gametypestr = Gametype_Names[num];
if (gametypestr)
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100,
@ -2345,7 +2359,7 @@ static void CL_ConnectToServer(boolean viams)
#endif
DEBFILE(va("Synchronisation Finished\n"));
displayplayer = consoleplayer;
displayplayers[0] = consoleplayer;
}
#ifndef NONET
@ -2517,7 +2531,7 @@ static void Command_connect(void)
return;
}
if (Playing() || titledemo)
if (Playing() || demo.title)
{
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
return;
@ -2609,14 +2623,16 @@ void CL_ClearPlayer(INT32 playernum)
//
// Removes a player from the current game
//
static void CL_RemovePlayer(INT32 playernum, INT32 reason)
void CL_RemovePlayer(INT32 playernum, INT32 reason)
{
// Sanity check: exceptional cases (i.e. c-fails) can cause multiple
// kick commands to be issued for the same player.
if (!playeringame[playernum])
return;
if (server && !demoplayback)
demo_extradata[playernum] |= DXD_PLAYSTATE;
if (server && !demo.playback)
{
INT32 node = playernode[playernum];
//playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one
@ -2691,8 +2707,8 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
RemoveAdminPlayer(playernum); // don't stay admin after you're gone
}
if (playernum == displayplayer)
displayplayer = consoleplayer; // don't look through someone's view who isn't there
if (playernum == displayplayers[0] && !demo.playback)
displayplayers[0] = consoleplayer; // don't look through someone's view who isn't there
#ifdef HAVE_BLUA
LUA_InvalidatePlayer(&players[playernum]);
@ -2712,7 +2728,7 @@ void CL_Reset(void)
G_StopMetalRecording();
if (metalplayback)
G_StopMetalDemo();
if (demorecording)
if (demo.recording)
G_CheckDemoStatus();
// reset client/server code
@ -3074,12 +3090,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
kickreason = KR_KICK;
break;
#ifdef NEWPING
case KICK_MSG_PING_HIGH:
HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
kickreason = KR_PINGLIMIT;
break;
#endif
case KICK_MSG_CON_FAIL:
HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
kickreason = KR_SYNCH;
@ -3152,10 +3166,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
D_StartTitle();
if (msg == KICK_MSG_CON_FAIL)
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
#ifdef NEWPING
else if (msg == KICK_MSG_PING_HIGH)
M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING);
#endif
else if (msg == KICK_MSG_BANNED)
M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
else if (msg == KICK_MSG_CUSTOM_KICK)
@ -3199,15 +3211,15 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = {"netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
#ifdef VANILLAJOINNEXTROUND
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
#endif
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {MAXPLAYERS, "MAX"}, {0, NULL}};
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
consvar_t cv_resynchattempts = {"resynchattempts", "5", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
// max file size to send to a player (in kilobytes)
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
@ -3250,12 +3262,6 @@ void D_ClientServerInit(void)
RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer);
RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
#ifdef VANILLAJOINNEXTROUND
CV_RegisterVar(&cv_joinnextround);
#endif
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_blamecfail);
#ifdef DUMPCONSISTENCY
CV_RegisterVar(&cv_dumpconsistency);
#endif
@ -3422,6 +3428,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
{
INT16 node, newplayernum;
UINT8 splitscreenplayer = 0;
UINT8 i;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
@ -3455,34 +3462,19 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (node == mynode)
{
playernode[newplayernum] = 0; // for information only
if (splitscreenplayer)
{
if (splitscreenplayer == 1)
{
secondarydisplayplayer = newplayernum;
DEBFILE("spawning my brother\n");
if (botingame)
players[newplayernum].bot = 1;
// Same goes for player 2 when relevant
}
else if (splitscreenplayer == 2)
{
thirddisplayplayer = newplayernum;
DEBFILE("spawning my sister\n");
}
else if (splitscreenplayer == 3)
{
fourthdisplayplayer = newplayernum;
DEBFILE("spawning my trusty pet dog\n");
}
displayplayers[splitscreenplayer] = newplayernum;
DEBFILE(va("spawning one of my sister number %d\n", splitscreenplayer));
if (splitscreenplayer == 1 && botingame)
players[newplayernum].bot = 1;
}
else
{
consoleplayer = newplayernum;
displayplayer = newplayernum;
secondarydisplayplayer = newplayernum;
thirddisplayplayer = newplayernum;
fourthdisplayplayer = newplayernum;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
displayplayers[i] = newplayernum;
DEBFILE("spawning me\n");
}
D_SendPlayerConfig();
@ -3631,7 +3623,7 @@ boolean Playing(void)
boolean SV_SpawnServer(void)
{
if (demoplayback)
if (demo.playback)
G_StopDemo(); // reset engine parameter
if (metalplayback)
G_StopMetalDemo();
@ -3939,6 +3931,39 @@ static void HandlePacketFromAwayNode(SINT8 node)
#endif
break;
case PT_TELLFILESNEEDED:
if (server && serverrunning)
{
UINT8 *p;
INT32 firstfile = netbuffer->u.filesneedednum;
netbuffer->packettype = PT_MOREFILESNEEDED;
netbuffer->u.filesneededcfg.first = firstfile;
netbuffer->u.filesneededcfg.more = 0;
p = PutFileNeeded(firstfile);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
}
else // Shouldn't get this if you aren't the server...?
Net_CloseConnection(node);
break;
case PT_MOREFILESNEEDED:
if (server && serverrunning)
{ // But wait I thought I'm the server?
Net_CloseConnection(node);
break;
}
SERVERONLY
if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum)
{
D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first);
if (!netbuffer->u.filesneededcfg.more)
cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list
}
break;
case PT_ASKINFO:
if (server && serverrunning)
{
@ -4610,7 +4635,6 @@ FILESTAMP
resynch_local_inprogress = true;
CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
break;
#ifdef NEWPING
case PT_PING:
// Only accept PT_PING from the server.
if (node != servernode)
@ -4640,7 +4664,6 @@ FILESTAMP
}
break;
#endif
case PT_SERVERCFG:
break;
case PT_FILEFRAGMENT:
@ -5212,16 +5235,16 @@ void TryRunTics(tic_t realtics)
if (realtics >= 1)
{
COM_BufExecute();
COM_BufTicker();
if (mapchangepending)
D_MapChange(-1, 0, encoremode, false, 2, false, fromlevelselect); // finish the map change
}
NetUpdate();
if (demoplayback)
if (demo.playback)
{
neededtic = gametic + (realtics * cv_playbackspeed.value);
neededtic = gametic + realtics * (gamestate == GS_LEVEL ? cv_playbackspeed.value : 1);
// start a game after a demo
maketic += realtics;
firstticstosend = maketic;
@ -5278,7 +5301,6 @@ void TryRunTics(tic_t realtics)
}
}
#ifdef NEWPING
/* Ping Update except better:
We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out.
@ -5362,11 +5384,9 @@ static inline void PingUpdate(void)
pingmeasurecount = 1; //Reset count
}
#endif
static tic_t gametime = 0;
#ifdef NEWPING
static void UpdatePingTable(void)
{
INT32 i;
@ -5381,7 +5401,6 @@ static void UpdatePingTable(void)
pingmeasurecount++;
}
}
#endif
// Handle timeouts to prevent definitive freezes from happenning
static void HandleNodeTimeouts(void)
@ -5406,9 +5425,7 @@ void NetKeepAlive(void)
if (realtics <= 0) // nothing new to update
return;
#ifdef NEWPING
UpdatePingTable();
#endif
if (server)
CL_SendClientKeepAlive();
@ -5455,9 +5472,7 @@ void NetUpdate(void)
gametime = nowtime;
#ifdef NEWPING
UpdatePingTable();
#endif
if (client)
maketic = neededtic;
@ -5482,7 +5497,7 @@ FILESTAMP
}
else
{
if (!demoplayback)
if (!demo.playback)
{
INT32 counts;

View file

@ -93,9 +93,11 @@ typedef enum
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
PT_RESYNCHING, // Packet sent to resync players.
// Blocks game advance until synched.
#ifdef NEWPING
PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?"
PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)"
PT_PING, // Packet sent to tell clients the other client's latency to server.
#endif
NUMPACKETTYPE
} packettype_t;
@ -224,21 +226,7 @@ typedef struct
UINT8 kartspeed;
UINT8 kartweight;
//
fixed_t normalspeed;
fixed_t runspeed;
UINT8 thrustfactor;
UINT8 accelstart;
UINT8 acceleration;
UINT8 charability;
UINT8 charability2;
UINT32 charflags;
UINT32 thokitem; // mobjtype_t
UINT32 spinitem; // mobjtype_t
UINT32 revitem; // mobjtype_t
fixed_t actionspd;
fixed_t mindash;
fixed_t maxdash;
fixed_t jumpfactor;
fixed_t speed;
UINT8 jumping;
@ -371,6 +359,7 @@ typedef struct
} ATTRPACK joinchallenge_pak;
#define SV_SPEEDMASK 0x03
#define SV_LOTSOFADDONS 0x20
#define SV_DEDICATED 0x40
#define SV_PASSWORD 0x80
@ -441,6 +430,14 @@ typedef struct
UINT8 ctfteam;
} ATTRPACK plrconfig;
typedef struct
{
INT32 first;
UINT8 num;
UINT8 more;
UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK filesneededconfig_pak;
//
// Network packet data
//
@ -471,11 +468,11 @@ typedef struct
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
askinfo_pak askinfo; // 61 bytes
msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];// 576 bytes(?)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
#ifdef NEWPING
INT32 filesneedednum; // 4 bytes
filesneededconfig_pak filesneededcfg; // ??? bytes
UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
#endif
} u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t;
@ -509,9 +506,7 @@ extern consvar_t cv_playbackspeed;
#define KICK_MSG_PLAYER_QUIT 3
#define KICK_MSG_TIMEOUT 4
#define KICK_MSG_BANNED 5
#ifdef NEWPING
#define KICK_MSG_PING_HIGH 6
#endif
#define KICK_MSG_CUSTOM_KICK 7
#define KICK_MSG_CUSTOM_BAN 8
@ -532,16 +527,15 @@ extern boolean dedicated; // For dedicated server
extern UINT16 software_MAXPACKETLENGTH;
extern boolean acceptnewnode;
extern SINT8 servernode;
extern char connectedservername[MAXSERVERNAME];
void Command_Ping_f(void);
extern tic_t connectiontimeout;
extern tic_t jointimeout;
#ifdef NEWPING
extern UINT16 pingmeasurecount;
extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
#endif
extern consvar_t
#ifdef VANILLAJOINNEXTROUND
@ -573,6 +567,7 @@ void CL_AddSplitscreenPlayer(void);
void CL_RemoveSplitscreenPlayer(UINT8 p);
void CL_Reset(void);
void CL_ClearPlayer(INT32 playernum);
void CL_RemovePlayer(INT32 playernum, INT32 reason);
void CL_UpdateServerList(boolean internetsearch, INT32 room);
boolean CL_Responder(event_t *ev);
// Is there a game running

View file

@ -74,7 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "m_cond.h" // condition initialization
#include "fastcmp.h"
#include "keys.h"
#include "filesrch.h" // refreshdirmenu, mainwadstally
#include "filesrch.h" // refreshdirmenu
#ifdef CMAKECONFIG
#include "config.h"
@ -118,14 +118,8 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo
boolean lastdraw = false;
postimg_t postimgtype = postimg_none;
INT32 postimgparam;
postimg_t postimgtype2 = postimg_none;
INT32 postimgparam2;
postimg_t postimgtype3 = postimg_none;
INT32 postimgparam3;
postimg_t postimgtype4 = postimg_none;
INT32 postimgparam4;
postimg_t postimgtype[MAXSPLITSCREENPLAYERS];
INT32 postimgparam[MAXSPLITSCREENPLAYERS];
// These variables are only true if
// whether the respective sound system is disabled
@ -248,6 +242,12 @@ void D_ProcessEvents(void)
continue;
}
if (demo.savemode == DSM_TITLEENTRY)
{
if (G_DemoTitleResponder(ev))
continue;
}
// Menu input
if (M_Responder(ev))
continue; // menu ate the event
@ -274,6 +274,7 @@ static void D_Display(void)
boolean forcerefresh = false;
static boolean wipe = false;
INT32 wipedefindex = 0;
UINT8 i;
if (dedicated)
return;
@ -422,109 +423,77 @@ static void D_Display(void)
// draw the view directly
if (cv_renderview.value && !automapactive)
{
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
for (i = 0; i <= splitscreen; i++)
{
viewwindowy = 0;
viewwindowx = 0;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
if (players[displayplayers[i]].mo || players[displayplayers[i]].playerstate == PST_DEAD)
{
if (splitscreen > 1)
if (i == 0) // Initialize for P1
{
viewwindowx = viewwidth;
viewwindowy = 0;
}
else
{
viewwindowx = 0;
viewwindowy = viewheight;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
}
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
viewssnum = i;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// render the third screen
if (splitscreen > 1 && players[thirddisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(2, &players[thirddisplayplayer]);
else
if (rendermode != render_soft)
HWR_RenderPlayerView(i, &players[displayplayers[i]]);
else
#endif
if (rendermode != render_none)
{
viewwindowx = 0;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
if (rendermode != render_none)
{
if (i > 0) // Splitscreen-specific
{
switch (i)
{
case 1:
if (splitscreen > 1)
{
viewwindowx = viewwidth;
viewwindowy = 0;
}
else
{
viewwindowx = 0;
viewwindowy = viewheight;
}
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
break;
case 2:
viewwindowx = 0;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
break;
case 3:
viewwindowx = viewwidth;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
default:
break;
}
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
}
R_RenderPlayerView(&players[thirddisplayplayer]);
R_RenderPlayerView(&players[displayplayers[i]]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
if (splitscreen > 2 && players[fourthdisplayplayer].mo) // render the fourth screen
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(3, &players[fourthdisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowx = viewwidth;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[fourthdisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
if (i > 0)
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
}
if (rendermode == render_soft)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
if (postimgtype3)
V_DoPostProcessor(2, postimgtype3, postimgparam3);
if (postimgtype4)
V_DoPostProcessor(3, postimgtype4, postimgparam4);
for (i = 0; i <= splitscreen; i++)
{
if (postimgtype[i])
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
}
}
}
@ -550,7 +519,7 @@ static void D_Display(void)
wipegamestate = gamestate;
// draw pause pic
if (paused && cv_showhud.value)
if (paused && cv_showhud.value && !demo.playback)
{
INT32 py;
patch_t *patch;
@ -562,6 +531,9 @@ static void D_Display(void)
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch);
}
if (demo.rewinding)
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
// vid size change is now finished if it was on...
vid.recalc = 0;
@ -619,6 +591,9 @@ static void D_Display(void)
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
}
if (cv_shittyscreen.value)
V_DrawVhsEffect(cv_shittyscreen.value == 2);
I_FinishUpdate(); // page flip or blit buffer
}
}
@ -636,9 +611,6 @@ void D_SRB2Loop(void)
if (dedicated)
server = true;
if (M_CheckParm("-voodoo")) // 256x256 Texture Limiter
COM_BufAddText("gr_voodoocompatibility on\n");
// Pushing of + parameters is now done back in D_SRB2Main, not here.
CONS_Printf("I_StartupKeyboard()...\n");
@ -735,7 +707,7 @@ void D_SRB2Loop(void)
M_DoScreenShot();
}
// consoleplayer -> displayplayer (hear sounds from viewpoint)
// consoleplayer -> displayplayers (hear sounds from viewpoint)
S_UpdateSounds(); // move positional sounds
// check for media change, loop music..
@ -814,13 +786,13 @@ void D_StartTitle(void)
maptol = 0;
gameaction = ga_nothing;
displayplayer = consoleplayer = 0;
memset(displayplayers, 0, sizeof(displayplayers));
consoleplayer = 0;
//demosequence = -1;
gametype = GT_RACE; // SRB2kart
paused = false;
advancedemo = false;
F_StartTitleScreen();
CON_ToggleOff();
// Reset the palette -- SRB2Kart: actually never mind let's do this in the middle of every fade
/*if (rendermode != render_none)
@ -1217,6 +1189,10 @@ void D_SRB2Main(void)
// Setup default unlockable conditions
M_SetupDefaultConditionSets();
// Setup character tables
// Have to be done here before files are loaded
M_InitCharacterTables();
// load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
if (!W_InitMultipleFiles(startupwadfiles, false))
@ -1257,8 +1233,6 @@ void D_SRB2Main(void)
#endif //ifndef DEVELOP
mainwadstally = packetsizetally;
//
// search for maps
//
@ -1390,10 +1364,9 @@ void D_SRB2Main(void)
midi_disabled = true;
#endif
}
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
{
sound_disabled = true;
digital_disabled = true;
#ifndef NO_MIDI
midi_disabled = true;
@ -1401,12 +1374,24 @@ void D_SRB2Main(void)
}
else
{
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
{
digital_disabled = true;
#ifndef NO_MIDI
if (M_CheckParm("-nomidimusic"))
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
midi_disabled = true;
#endif
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
else
{
#ifndef NO_MIDI
if (M_CheckParm("-nomidimusic"))
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
#endif
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
}
if (!( sound_disabled && digital_disabled
#ifndef NO_MIDI
@ -1502,7 +1487,7 @@ void D_SRB2Main(void)
if (M_CheckParm("-playdemo"))
{
singledemo = true; // quit after one demo
demo.quitafterplaying = true; // quit after one demo
G_DeferedPlayDemo(tmp);
}
else
@ -1529,6 +1514,8 @@ void D_SRB2Main(void)
// as having been modified for the first game.
M_PushSpecialParameters(); // push all "+" parameter at the command buffer
strncpy(connectedservername, cv_servername.string, MAXSERVERNAME);
if (M_CheckParm("-gametype") && M_IsNextParm())
{
// from Command_Map_f
@ -1536,13 +1523,9 @@ void D_SRB2Main(void)
INT16 newgametype = -1;
const char *sgametype = M_GetNextParm();
for (j = 0; gametype_cons_t[j].strvalue; j++)
if (!strcasecmp(gametype_cons_t[j].strvalue, sgametype))
{
newgametype = (INT16)gametype_cons_t[j].value;
break;
}
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
newgametype = G_GetGametypeByName(sgametype);
if (newgametype == -1) // reached end of the list with no match
{
j = atoi(sgametype); // assume they gave us a gametype number, which is okay too
if (j >= 0 && j < NUMGAMETYPES)
@ -1597,13 +1580,13 @@ void D_SRB2Main(void)
}
else if (M_CheckParm("-skipintro"))
{
CON_ToggleOff();
CON_ClearHUD();
F_StartTitleScreen();
}
else
F_StartIntro(); // Tails 03-03-2002
CON_ToggleOff();
if (dedicated && server)
{
pagename = "TITLESKY";

View file

@ -185,22 +185,10 @@ typedef struct
UINT8 nextacknum;
UINT8 flags;
#ifndef NEWPING
// jacobson tcp timeout evaluation algorithm (Karn variation)
fixed_t ping;
fixed_t varping;
INT32 timeout; // computed with ping and varping
#endif
} node_t;
static node_t nodes[MAXNETNODES];
#ifndef NEWPING
#define PINGDEFAULT ((200*TICRATE*FRACUNIT)/1000)
#define VARPINGDEFAULT ((50*TICRATE*FRACUNIT)/1000)
#define TIMEOUT(p,v) (p+4*v+FRACUNIT/2)>>FRACBITS;
#else
#define NODETIMEOUT 14 //What the above boiled down to...
#endif
#define NODETIMEOUT 14
#ifndef NONET
// return <0 if a < b (mod 256)
@ -320,19 +308,7 @@ static UINT8 GetAcktosend(INT32 node)
static void RemoveAck(INT32 i)
{
INT32 node = ackpak[i].destinationnode;
#ifndef NEWPING
fixed_t trueping = (I_GetTime() - ackpak[i].senttime)<<FRACBITS;
if (ackpak[i].resentnum)
{
// +FRACUNIT/2 for round
nodes[node].ping = (nodes[node].ping*7 + trueping)/8;
nodes[node].varping = (nodes[node].varping*7 + abs(nodes[node].ping-trueping))/8;
nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
}
DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",ackpak[i].acknum,trueping>>FRACBITS,(double)FIXED_TO_FLOAT(nodes[node].ping),(double)FIXED_TO_FLOAT(nodes[node].varping),nodes[node].timeout));
#else
DEBFILE(va("Remove ack %d\n",ackpak[i].acknum));
#endif
ackpak[i].acknum = 0;
if (nodes[node].flags & NF_CLOSE)
Net_CloseConnection(node);
@ -519,11 +495,7 @@ void Net_AckTicker(void)
{
const INT32 nodei = ackpak[i].destinationnode;
node_t *node = &nodes[nodei];
#ifdef NEWPING
if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime())
#else
if (ackpak[i].acknum && ackpak[i].senttime + node->timeout < I_GetTime())
#endif
{
if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE))
{
@ -534,13 +506,8 @@ void Net_AckTicker(void)
ackpak[i].acknum = 0;
continue;
}
#ifdef NEWPING
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
NODETIMEOUT, I_GetTime()));
#else
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
node->timeout, I_GetTime()));
#endif
M_Memcpy(netbuffer, ackpak[i].pak.raw, ackpak[i].length);
ackpak[i].senttime = I_GetTime();
ackpak[i].resentnum++;
@ -658,11 +625,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
static void InitNode(node_t *node)
{
node->acktosend_head = node->acktosend_tail = 0;
#ifndef NEWPING
node->ping = PINGDEFAULT;
node->varping = VARPINGDEFAULT;
node->timeout = TIMEOUT(node->ping, node->varping);
#endif
node->firstacktosend = 0;
node->nextacknum = 1;
node->remotefirstack = 0;
@ -854,9 +816,7 @@ static const char *packettypename[NUMPACKETTYPE] =
"CLIENTJOIN",
"NODETIMEOUT",
"RESYNCHING",
#ifdef NEWPING
"PING"
#endif
};
static void DebugPrintpacket(const char *header)
@ -1410,30 +1370,73 @@ boolean D_CheckNetGame(void)
return ret;
}
struct pingcell
{
INT32 num;
INT32 ms;
};
static int pingcellcmp(const void *va, const void *vb)
{
const struct pingcell *a, *b;
a = va;
b = vb;
return ( a->ms - b->ms );
}
/*
New ping command formatted nicely to present ping in
ascending order. And with equally spaced columns.
The caller's ping is presented at the bottom too, for
convenience.
*/
void Command_Ping_f(void)
{
#ifndef NEWPING
if(server)
struct pingcell pingv[MAXPLAYERS];
INT32 pingc;
int name_width = 0;
int ms_width = 0;
int n;
INT32 i;
pingc = 0;
for (i = 1; i < MAXPLAYERS; ++i)
if (playeringame[i])
{
#endif
INT32 i;
for (i = 0; i < MAXPLAYERS;i++)
{
#ifndef NEWPING
const INT32 node = playernode[i];
if (playeringame[i] && node != 0)
CONS_Printf(M_GetText("%.2d : %s\n %d tics, %d ms.\n"), i, player_names[i],
GetLag(node), G_TicsToMilliseconds(GetLag(node)));
#else
if (playeringame[i] && i != 0)
CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]);
#endif
}
#ifndef NEWPING
n = strlen(player_names[i]);
if (n > name_width)
name_width = n;
n = playerpingtable[i];
if (n > ms_width)
ms_width = n;
pingv[pingc].num = i;
pingv[pingc].ms = playerpingtable[i];
pingc++;
}
if (ms_width < 10) ms_width = 1;
else if (ms_width < 100) ms_width = 2;
else ms_width = 3;
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
for (i = 0; i < pingc; ++i)
{
CONS_Printf("%02d : %-*s %*d ms\n",
pingv[i].num,
name_width, player_names[pingv[i].num],
ms_width, pingv[i].ms);
}
if (!server && playeringame[consoleplayer])
{
CONS_Printf("\nYour ping is %d ms\n", playerpingtable[consoleplayer]);
}
else
CONS_Printf(M_GetText("Only the server can use this.\n"));
#endif
}
void D_CloseConnection(void)

View file

@ -21,7 +21,6 @@
// Max computers in a game
#define MAXNETNODES (MAXPLAYERS+4)
#define BROADCASTADDR MAXNETNODES
#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer
#define NETSPLITSCREEN // Kart's splitscreen netgame feature
#define STATLENGTH (TICRATE*2)

View file

@ -129,6 +129,9 @@ static void Command_StopMovie_f(void);
static void Command_Map_f(void);
static void Command_ResetCamera_f(void);
static void Command_View_f (void);
static void Command_SetViews_f(void);
static void Command_Addfile(void);
static void Command_ListWADS_f(void);
#ifdef DELFILE
@ -423,7 +426,7 @@ consvar_t cv_numlaps = {"numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceskin = {"forceskin", "-1", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceskin = {"forceskin", "Off", CV_NETVAR|CV_CALL|CV_CHEAT, Forceskin_cons_t, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -434,7 +437,6 @@ static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE
consvar_t cv_nettimeout = {"nettimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
//static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_jointimeout = {"jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
#ifdef NEWPING
static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}};
consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -445,7 +447,6 @@ consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NU
static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}};
consvar_t cv_showping = {"showping", "Always", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#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};
@ -514,6 +515,24 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
*/
void D_RegisterServerCommands(void)
{
INT32 i;
Forceskin_cons_t[0].value = -1;
Forceskin_cons_t[0].strvalue = "Off";
for (i = 0; i < NUMGAMETYPES; i++)
{
gametype_cons_t[i].value = i;
gametype_cons_t[i].strvalue = Gametype_Names[i];
}
gametype_cons_t[NUMGAMETYPES].value = 0;
gametype_cons_t[NUMGAMETYPES].strvalue = NULL;
// Set the values to 0/NULL, it will be overwritten later when a skin is assigned to the slot.
for (i = 1; i < MAXSKINS; i++)
{
Forceskin_cons_t[i].value = 0;
Forceskin_cons_t[i].strvalue = NULL;
}
RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor);
RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref);
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
@ -667,6 +686,14 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
#ifdef VANILLAJOINNEXTROUND
CV_RegisterVar(&cv_joinnextround);
#endif
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_blamecfail);
#endif
COM_AddCommand("ping", Command_Ping_f);
CV_RegisterVar(&cv_nettimeout);
@ -674,11 +701,9 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_skipmapcheck);
CV_RegisterVar(&cv_sleep);
#ifdef NEWPING
CV_RegisterVar(&cv_maxping);
CV_RegisterVar(&cv_pingtimeout);
CV_RegisterVar(&cv_showping);
#endif
#ifdef SEENAMES
CV_RegisterVar(&cv_allowseenames);
@ -726,6 +751,13 @@ void D_RegisterClientCommands(void)
COM_AddCommand("resetcamera", Command_ResetCamera_f);
COM_AddCommand("view", Command_View_f);
COM_AddCommand("view2", Command_View_f);
COM_AddCommand("view3", Command_View_f);
COM_AddCommand("view4", Command_View_f);
COM_AddCommand("setviews", Command_SetViews_f);
COM_AddCommand("setcontrol", Command_Setcontrol_f);
COM_AddCommand("setcontrol2", Command_Setcontrol2_f);
COM_AddCommand("setcontrol3", Command_Setcontrol3_f);
@ -800,6 +832,9 @@ void D_RegisterClientCommands(void)
COM_AddCommand("displayplayer", Command_Displayplayer_f);
CV_RegisterVar(&cv_recordmultiplayerdemos);
CV_RegisterVar(&cv_netdemosyncquality);
// FIXME: not to be here.. but needs be done for config loading
CV_RegisterVar(&cv_usegamma);
@ -853,6 +888,10 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_driftaxis2);
CV_RegisterVar(&cv_driftaxis3);
CV_RegisterVar(&cv_driftaxis4);
CV_RegisterVar(&cv_deadzone);
CV_RegisterVar(&cv_deadzone2);
CV_RegisterVar(&cv_deadzone3);
CV_RegisterVar(&cv_deadzone4);
// filesrch.c
CV_RegisterVar(&cv_addons_option);
@ -919,6 +958,8 @@ void D_RegisterClientCommands(void)
// screen.c
CV_RegisterVar(&cv_fullscreen);
CV_RegisterVar(&cv_renderview);
CV_RegisterVar(&cv_vhseffect);
CV_RegisterVar(&cv_shittyscreen);
CV_RegisterVar(&cv_scr_depth);
CV_RegisterVar(&cv_scr_width);
CV_RegisterVar(&cv_scr_height);
@ -1130,11 +1171,11 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
// spaces may have been removed
if (playernum == consoleplayer)
CV_StealthSet(&cv_playername, tmpname);
else if (playernum == secondarydisplayplayer || (!netgame && playernum == 1))
else if (playernum == displayplayers[1] || (!netgame && playernum == 1))
CV_StealthSet(&cv_playername2, tmpname);
else if (playernum == thirddisplayplayer || (!netgame && playernum == 2))
else if (playernum == displayplayers[2] || (!netgame && playernum == 2))
CV_StealthSet(&cv_playername3, tmpname);
else if (playernum == fourthdisplayplayer || (!netgame && playernum == 3))
else if (playernum == displayplayers[3] || (!netgame && playernum == 3))
CV_StealthSet(&cv_playername4, tmpname);
else I_Assert(((void)"CleanupPlayerName used on non-local player", 0));
@ -1166,6 +1207,7 @@ static void SetPlayerName(INT32 playernum, char *newname)
HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
strcpy(player_names[playernum], newname);
demo_extradata[playernum] |= DXD_NAME;
}
}
else
@ -1241,11 +1283,11 @@ static void ForceAllSkins(INT32 forcedskin)
{
if (i == consoleplayer)
CV_StealthSet(&cv_skin, skins[forcedskin].name);
else if (i == secondarydisplayplayer)
else if (i == displayplayers[1])
CV_StealthSet(&cv_skin2, skins[forcedskin].name);
else if (i == thirddisplayplayer)
else if (i == displayplayers[2])
CV_StealthSet(&cv_skin3, skins[forcedskin].name);
else if (i == fourthdisplayplayer)
else if (i == displayplayers[3])
CV_StealthSet(&cv_skin4, skins[forcedskin].name);
}
}
@ -1380,8 +1422,8 @@ static void SendNameAndColor2(void)
if (splitscreen < 1 && !botingame)
return; // can happen if skin2/color2/name2 changed
if (secondarydisplayplayer != consoleplayer)
secondplaya = secondarydisplayplayer;
if (displayplayers[1] != consoleplayer)
secondplaya = displayplayers[1];
else if (!netgame) // HACK
secondplaya = 1;
@ -1430,7 +1472,7 @@ static void SendNameAndColor2(void)
CleanupPlayerName(secondplaya, cv_playername2.zstring);
strcpy(player_names[secondplaya], cv_playername2.zstring);
// don't use secondarydisplayplayer: the second player must be 1
// don't use displayplayers[1]: the second player must be 1
players[secondplaya].skincolor = cv_playercolor2.value;
if (players[secondplaya].mo)
players[secondplaya].mo->color = players[secondplaya].skincolor;
@ -1469,14 +1511,14 @@ static void SendNameAndColor2(void)
snac2pending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(secondarydisplayplayer)))
CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]);
if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[1])))
CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]);
else // Cleanup name if changing it
CleanupPlayerName(secondarydisplayplayer, cv_playername2.zstring);
CleanupPlayerName(displayplayers[1], cv_playername2.zstring);
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(secondarydisplayplayer))
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name);
if (!CanChangeSkin(displayplayers[1]))
CV_StealthSet(&cv_skin2, skins[players[displayplayers[1]].skin].name);
// check if player has the skin loaded (cv_skin2 may have
// the name of a skin that was available in the previous game)
@ -1503,8 +1545,8 @@ static void SendNameAndColor3(void)
if (splitscreen < 2)
return; // can happen if skin3/color3/name3 changed
if (thirddisplayplayer != consoleplayer)
thirdplaya = thirddisplayplayer;
if (displayplayers[2] != consoleplayer)
thirdplaya = displayplayers[2];
else if (!netgame) // HACK
thirdplaya = 2;
@ -1545,7 +1587,7 @@ static void SendNameAndColor3(void)
CleanupPlayerName(thirdplaya, cv_playername3.zstring);
strcpy(player_names[thirdplaya], cv_playername3.zstring);
// don't use thirddisplayplayer: the third player must be 2
// don't use displayplayers[2]: the third player must be 2
players[thirdplaya].skincolor = cv_playercolor3.value;
if (players[thirdplaya].mo)
players[thirdplaya].mo->color = players[thirdplaya].skincolor;
@ -1584,14 +1626,14 @@ static void SendNameAndColor3(void)
snac3pending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(thirddisplayplayer)))
CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]);
if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[2])))
CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]);
else // Cleanup name if changing it
CleanupPlayerName(thirddisplayplayer, cv_playername3.zstring);
CleanupPlayerName(displayplayers[2], cv_playername3.zstring);
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(thirddisplayplayer))
CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].skin].name);
if (!CanChangeSkin(displayplayers[2]))
CV_StealthSet(&cv_skin3, skins[players[displayplayers[2]].skin].name);
// check if player has the skin loaded (cv_skin3 may have
// the name of a skin that was available in the previous game)
@ -1618,8 +1660,8 @@ static void SendNameAndColor4(void)
if (splitscreen < 3)
return; // can happen if skin4/color4/name4 changed
if (fourthdisplayplayer != consoleplayer)
fourthplaya = fourthdisplayplayer;
if (displayplayers[3] != consoleplayer)
fourthplaya = displayplayers[3];
else if (!netgame) // HACK
fourthplaya = 3;
@ -1668,7 +1710,7 @@ static void SendNameAndColor4(void)
CleanupPlayerName(fourthplaya, cv_playername4.zstring);
strcpy(player_names[fourthplaya], cv_playername4.zstring);
// don't use fourthdisplayplayer: the second player must be 4
// don't use displayplayers[3]: the second player must be 4
players[fourthplaya].skincolor = cv_playercolor4.value;
if (players[fourthplaya].mo)
players[fourthplaya].mo->color = players[fourthplaya].skincolor;
@ -1707,14 +1749,14 @@ static void SendNameAndColor4(void)
snac4pending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(fourthdisplayplayer)))
CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]);
if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[3])))
CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]);
else // Cleanup name if changing it
CleanupPlayerName(fourthdisplayplayer, cv_playername4.zstring);
CleanupPlayerName(displayplayers[3], cv_playername4.zstring);
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(fourthdisplayplayer))
CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].skin].name);
if (!CanChangeSkin(displayplayers[3]))
CV_StealthSet(&cv_skin4, skins[players[displayplayers[3]].skin].name);
// check if player has the skin loaded (cv_skin4 may have
// the name of a skin that was available in the previous game)
@ -1744,12 +1786,12 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
#endif
if (playernum == consoleplayer)
snacpending--;
else if (playernum == secondarydisplayplayer)
snacpending--; // TODO: make snacpending an array instead of 4 separate vars?
else if (playernum == displayplayers[1])
snac2pending--;
else if (playernum == thirddisplayplayer)
else if (playernum == displayplayers[2])
snac3pending--;
else if (playernum == fourthdisplayplayer)
else if (playernum == displayplayers[3])
snac4pending--;
#ifdef PARANOIA
@ -1769,10 +1811,11 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
p->skincolor = color % MAXSKINCOLORS;
if (p->mo)
p->mo->color = (UINT8)p->skincolor;
demo_extradata[playernum] |= DXD_COLOR;
// normal player colors
if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer]
&& p != &players[thirddisplayplayer] && p != &players[fourthdisplayplayer]))
if (server && (p != &players[consoleplayer] && p != &players[displayplayers[1]]
&& p != &players[displayplayers[2]] && p != &players[displayplayers[3]]))
{
boolean kick = false;
@ -1809,11 +1852,11 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
if (playernum == consoleplayer)
CV_StealthSet(&cv_skin, skins[forcedskin].name);
else if (playernum == secondarydisplayplayer)
else if (playernum == displayplayers[1])
CV_StealthSet(&cv_skin2, skins[forcedskin].name);
else if (playernum == thirddisplayplayer)
else if (playernum == displayplayers[2])
CV_StealthSet(&cv_skin3, skins[forcedskin].name);
else if (playernum == fourthdisplayplayer)
else if (playernum == displayplayers[3])
CV_StealthSet(&cv_skin4, skins[forcedskin].name);
}
else
@ -1900,7 +1943,198 @@ void D_SendPlayerConfig(void)
// Only works for displayplayer, sorry!
static void Command_ResetCamera_f(void)
{
P_ResetCamera(&players[displayplayer], &camera);
P_ResetCamera(&players[displayplayers[0]], &camera[0]);
}
/* Consider replacing nametonum with this */
static INT32 LookupPlayer(const char *s)
{
INT32 playernum;
if (*s == '0')/* clever way to bypass atoi */
return 0;
if (( playernum = atoi(s) ))
{
playernum = max(min(playernum, MAXPLAYERS-1), 0);/* not out of range */
return playernum;
}
for (playernum = 0; playernum < MAXPLAYERS; ++playernum)
{
/* Match name case-insensitively: fully, or partially the start. */
if (playeringame[playernum])
if (strnicmp(player_names[playernum], s, strlen(s)) == 0)
{
return playernum;
}
}
return -1;
}
static INT32 FindPlayerByPlace(INT32 place)
{
INT32 playernum;
for (playernum = 0; playernum < MAXPLAYERS; ++playernum)
if (playeringame[playernum])
{
if (players[playernum].kartstuff[k_position] == place)
{
return playernum;
}
}
return -1;
}
//
// GetViewablePlayerPlaceRange
// Return in first and last, that player available to view, sorted by placement
// in the race.
//
static void GetViewablePlayerPlaceRange(INT32 *first, INT32 *last)
{
INT32 i;
INT32 place;
(*first) = MAXPLAYERS;
(*last) = 0;
for (i = 0; i < MAXPLAYERS; ++i)
if (G_CouldView(i))
{
place = players[i].kartstuff[k_position];
if (place < (*first))
(*first) = place;
if (place > (*last))
(*last) = place;
}
}
#define PRINTVIEWPOINT( pre,suf ) \
CONS_Printf(pre"viewing \x84(%d) \x83%s\x80"suf".\n",\
(*displayplayerp), player_names[(*displayplayerp)]);
static void Command_View_f(void)
{
INT32 *displayplayerp;
INT32 olddisplayplayer;
int viewnum;
const char *playerparam;
INT32 placenum;
INT32 playernum;
INT32 firstplace, lastplace;
char c;
/* easy peasy */
c = COM_Argv(0)[strlen(COM_Argv(0))-1];/* may be digit */
switch (c)
{
case '2': viewnum = 2; break;
case '3': viewnum = 3; break;
case '4': viewnum = 4; break;
default: viewnum = 1;
}
if (viewnum > 1 && !( multiplayer && demo.playback ))
{
CONS_Alert(CONS_NOTICE,
"You must be viewing a multiplayer replay to use this.\n");
return;
}
displayplayerp = &displayplayers[viewnum-1];
if (COM_Argc() > 1)/* switch to player */
{
playerparam = COM_Argv(1);
if (playerparam[0] == '#')/* search by placement */
{
placenum = atoi(&playerparam[1]);
playernum = FindPlayerByPlace(placenum);
if (playernum == -1 || !G_CouldView(playernum))
{
GetViewablePlayerPlaceRange(&firstplace, &lastplace);
if (playernum == -1)
{
CONS_Alert(CONS_WARNING, "There is no player in that place! ");
}
else
{
CONS_Alert(CONS_WARNING,
"That player cannot be viewed currently! "
"The first player that you can view is \x82#%d\x80; ",
firstplace);
}
CONS_Printf("Last place is \x82#%d\x80.\n", lastplace);
return;
}
}
else
{
if (( playernum = LookupPlayer(COM_Argv(1)) ) == -1)
{
CONS_Alert(CONS_WARNING, "There is no player by that name!\n");
return;
}
if (!playeringame[playernum])
{
CONS_Alert(CONS_WARNING, "There is no player using that slot!\n");
return;
}
}
olddisplayplayer = (*displayplayerp);
G_ResetView(viewnum, playernum, false);
/* The player we wanted was corrected to who it already was. */
if ((*displayplayerp) == olddisplayplayer)
return;
if ((*displayplayerp) != playernum)/* differ parameter */
{
/* skipped some */
CONS_Alert(CONS_NOTICE, "That player cannot be viewed currently.\n");
PRINTVIEWPOINT ("Now "," instead")
}
else
PRINTVIEWPOINT ("Now ",)
}
else/* print current view */
{
if (splitscreen < viewnum-1)/* We can't see those guys! */
return;
PRINTVIEWPOINT ("Currently ",)
}
}
#undef PRINTVIEWPOINT
static void Command_SetViews_f(void)
{
UINT8 splits;
UINT8 newsplits;
if (!( demo.playback && multiplayer ))
{
CONS_Alert(CONS_NOTICE,
"You must be viewing a multiplayer replay to use this.\n");
return;
}
if (COM_Argc() != 2)
{
CONS_Printf("setviews <views>: set the number of split screens\n");
return;
}
splits = splitscreen+1;
newsplits = atoi(COM_Argv(1));
newsplits = min(max(newsplits, 1), 4);
if (newsplits > splits)
G_AdjustView(newsplits, 0, true);
else
{
splitscreen = newsplits-1;
R_ExecuteSetViewSize();
}
}
// ========================================================================
@ -1913,9 +2147,14 @@ static void Command_Playdemo_f(void)
{
char name[256];
if (COM_Argc() != 2)
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("playdemo <demoname>: playback a demo\n"));
CONS_Printf("playdemo <demoname> [-addfiles / -force]:\n");
CONS_Printf(M_GetText(
"Play back a demo file. The full path from your Kart directory must be given.\n\n"
"* With \"-addfiles\", any required files are added from a list contained within the demo file.\n"
"* With \"-force\", the demo is played even if the necessary files have not been added.\n"));
return;
}
@ -1926,7 +2165,7 @@ static void Command_Playdemo_f(void)
}
// disconnect from server here?
if (demoplayback)
if (demo.playback)
G_StopDemo();
if (metalplayback)
G_StopMetalDemo();
@ -1937,6 +2176,9 @@ static void Command_Playdemo_f(void)
CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name);
demo.loadfiles = strcmp(COM_Argv(2), "-addfiles") == 0;
demo.ignorefiles = strcmp(COM_Argv(2), "-force") == 0;
// Internal if no extension, external if one exists
// If external, convert the file name to a path in SRB2's home directory
if (FIL_CheckExtension(name))
@ -1962,7 +2204,7 @@ static void Command_Timedemo_f(void)
}
// disconnect from server here?
if (demoplayback)
if (demo.playback)
G_StopDemo();
if (metalplayback)
G_StopMetalDemo();
@ -2086,7 +2328,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
{
//CL_AddSplitscreenPlayer();
botingame = true;
secondarydisplayplayer = 1;
displayplayers[1] = 1;
playeringame[1] = true;
players[1].bot = 1;
SendNameAndColor2();
@ -2138,12 +2380,8 @@ void D_ModifyClientVote(SINT8 voted, UINT8 splitplayer)
char *p = buf;
UINT8 player = consoleplayer;
if (splitplayer == 1)
player = secondarydisplayplayer;
else if (splitplayer == 2)
player = thirddisplayplayer;
else if (splitplayer == 3)
player = fourthdisplayplayer;
if (splitplayer > 0)
player = displayplayers[splitplayer];
WRITESINT8(p, voted);
WRITEUINT8(p, player);
@ -2481,10 +2719,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
CON_LogMessage(M_GetText("Speeding off to level...\n"));
}
CON_ToggleOff();
CON_ClearHUD();
if (demoplayback && !timingdemo)
if (demo.playback && !demo.timing)
precache = false;
if (resetplayer)
@ -2501,17 +2736,19 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
LUAh_MapChange(mapnumber);
#endif*/
demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING;
demo.savebutton = 0;
G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene);
if (demoplayback && !timingdemo)
if (demo.playback && !demo.timing)
precache = true;
if (timingdemo)
if (demo.timing)
G_DoneLevelLoad();
if (metalrecording)
G_BeginMetal();
if (demorecording) // Okay, level loaded, character spawned and skinned,
if (demo.recording) // Okay, level loaded, character spawned and skinned,
G_BeginRecording(); // I AM NOW READY TO RECORD.
demo_start = true;
demo.deferstart = true;
}
static void Command_Pause(void)
@ -2561,13 +2798,13 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
return;
}
if (modeattacking)
if (modeattacking && !demo.playback)
return;
paused = READUINT8(*cp);
dedicatedpause = READUINT8(*cp);
if (!demoplayback)
if (!demo.playback)
{
if (netgame)
{
@ -2654,6 +2891,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
if (players[respawnplayer].mo)
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000);
demo_extradata[playernum] |= DXD_RESPAWN;
}
/** Deals with an ::XD_RANDOMSEED message in a netgame.
@ -2875,11 +3113,11 @@ static void Command_Teamchange2_f(void)
return;
}
if (players[secondarydisplayplayer].spectator)
error = !(NetPacket.packet.newteam || (players[secondarydisplayplayer].pflags & PF_WANTSTOJOIN));
if (players[displayplayers[1]].spectator)
error = !(NetPacket.packet.newteam || (players[displayplayers[1]].pflags & PF_WANTSTOJOIN));
else if (G_GametypeHasTeams())
error = (NetPacket.packet.newteam == (unsigned)players[secondarydisplayplayer].ctfteam);
else if (G_GametypeHasSpectators() && !players[secondarydisplayplayer].spectator)
error = (NetPacket.packet.newteam == (unsigned)players[displayplayers[1]].ctfteam);
else if (G_GametypeHasSpectators() && !players[displayplayers[1]].spectator)
error = (NetPacket.packet.newteam == 3);
#ifdef PARANOIA
else
@ -2966,11 +3204,11 @@ static void Command_Teamchange3_f(void)
return;
}
if (players[thirddisplayplayer].spectator)
error = !(NetPacket.packet.newteam || (players[thirddisplayplayer].pflags & PF_WANTSTOJOIN));
if (players[displayplayers[2]].spectator)
error = !(NetPacket.packet.newteam || (players[displayplayers[2]].pflags & PF_WANTSTOJOIN));
else if (G_GametypeHasTeams())
error = (NetPacket.packet.newteam == (unsigned)players[thirddisplayplayer].ctfteam);
else if (G_GametypeHasSpectators() && !players[thirddisplayplayer].spectator)
error = (NetPacket.packet.newteam == (unsigned)players[displayplayers[2]].ctfteam);
else if (G_GametypeHasSpectators() && !players[displayplayers[2]].spectator)
error = (NetPacket.packet.newteam == 3);
#ifdef PARANOIA
else
@ -3057,11 +3295,11 @@ static void Command_Teamchange4_f(void)
return;
}
if (players[fourthdisplayplayer].spectator)
error = !(NetPacket.packet.newteam || (players[fourthdisplayplayer].pflags & PF_WANTSTOJOIN));
if (players[displayplayers[3]].spectator)
error = !(NetPacket.packet.newteam || (players[displayplayers[3]].pflags & PF_WANTSTOJOIN));
else if (G_GametypeHasTeams())
error = (NetPacket.packet.newteam == (unsigned)players[fourthdisplayplayer].ctfteam);
else if (G_GametypeHasSpectators() && !players[fourthdisplayplayer].spectator)
error = (NetPacket.packet.newteam == (unsigned)players[displayplayers[3]].ctfteam);
else if (G_GametypeHasSpectators() && !players[displayplayers[3]].spectator)
error = (NetPacket.packet.newteam == 3);
#ifdef PARANOIA
else
@ -3458,8 +3696,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame
//reset view if you are changed, or viewing someone who was changed.
if (playernum == consoleplayer || displayplayer == playernum)
displayplayer = consoleplayer;
if (playernum == consoleplayer || displayplayers[0] == playernum)
displayplayers[0] = consoleplayer;
if (G_GametypeHasTeams())
{
@ -3467,11 +3705,11 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
{
if (playernum == consoleplayer) //CTF and Team Match colors.
CV_SetValue(&cv_playercolor, NetPacket.packet.newteam + 5);
else if (playernum == secondarydisplayplayer)
else if (playernum == displayplayers[1])
CV_SetValue(&cv_playercolor2, NetPacket.packet.newteam + 5);
else if (playernum == thirddisplayplayer)
else if (playernum == displayplayers[2])
CV_SetValue(&cv_playercolor3, NetPacket.packet.newteam + 5);
else if (playernum == fourthdisplayplayer)
else if (playernum == displayplayers[3])
CV_SetValue(&cv_playercolor4, NetPacket.packet.newteam + 5);
}
}
@ -3479,6 +3717,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
if (gamestate != GS_LEVEL)
return;
demo_extradata[playernum] |= DXD_PLAYSTATE;
// Clear player score and rings if a spectator.
if (players[playernum].spectator)
{
@ -4133,14 +4373,6 @@ static void Command_Addfile(void)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
WRITESTRINGN(buf_p,p,240);
@ -4255,8 +4487,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
}
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8)))
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename,md5sum,true);
@ -4456,12 +4687,22 @@ static void Command_ModDetails_f(void)
//
static void Command_ShowGametype_f(void)
{
const char *gametypestr = NULL;
if (!(netgame || multiplayer)) // print "Single player" instead of "Race"
{
CONS_Printf(M_GetText("Current gametype is %s\n"), "Single Player");
return;
}
CONS_Printf(M_GetText("Current gametype is %s\n"), gametype_cons_t[gametype].strvalue);
// get name string for current gametype
if (gametype >= 0 && gametype < NUMGAMETYPES)
gametypestr = Gametype_Names[gametype];
if (gametypestr)
CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr);
else // string for current gametype was not found above (should never happen)
CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype);
}
/** Plays the intro.
@ -4537,7 +4778,7 @@ static void PointLimit_OnChange(void)
static void NumLaps_OnChange(void)
{
if (!G_RaceGametype() || (modeattacking || demoplayback))
if (!G_RaceGametype() || (modeattacking || demo.playback))
return;
if (server && Playing()
@ -4605,9 +4846,18 @@ static void TimeLimit_OnChange(void)
*/
void D_GameTypeChanged(INT32 lastgametype)
{
if (multiplayer)
CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), gametype_cons_t[lastgametype].strvalue, gametype_cons_t[gametype].strvalue);
if (netgame)
{
const char *oldgt = NULL, *newgt = NULL;
if (lastgametype >= 0 && lastgametype < NUMGAMETYPES)
oldgt = Gametype_Names[lastgametype];
if (gametype >= 0 && lastgametype < NUMGAMETYPES)
newgt = Gametype_Names[gametype];
if (oldgt && newgt)
CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt);
}
// Only do the following as the server, not as remote admin.
// There will always be a server, and this only needs to be done once.
if (server && (multiplayer || netgame))
@ -4977,7 +5227,7 @@ static void Command_ExitLevel_f(void)
CONS_Printf(M_GetText("This only works in a netgame.\n"));
else if (!(server || (IsPlayerAdmin(consoleplayer))))
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
else if (gamestate != GS_LEVEL || demoplayback)
else if (gamestate != GS_LEVEL || demo.playback)
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
@ -5075,13 +5325,13 @@ static void Got_PickVotecmd(UINT8 **cp, INT32 playernum)
Y_SetupVoteFinish(pick, level);
}
/** Prints the number of the displayplayer.
/** Prints the number of displayplayers[0].
*
* \todo Possibly remove this; it was useful for debugging at one point.
*/
static void Command_Displayplayer_f(void)
{
CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayer);
CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayers[0]);
}
/** Quits a game and returns to the title screen.
@ -5240,27 +5490,11 @@ static void Command_Archivetest_f(void)
/** Makes a change to ::cv_forceskin take effect immediately.
*
* \todo Move the enforcement code out of SendNameAndColor() so this hack
* isn't needed.
* \sa Command_SetForcedSkin_f, cv_forceskin, forcedskin
* \author Graue <graue@oceanbase.org>
*/
static void ForceSkin_OnChange(void)
{
if ((server || IsPlayerAdmin(consoleplayer)) && (cv_forceskin.value < -1 || cv_forceskin.value >= numskins))
{
if (cv_forceskin.value == -2)
CV_SetValue(&cv_forceskin, numskins-1);
else
{
// hack because I can't restrict this and still allow added skins to be used with forceskin.
if (!menuactive)
CONS_Printf(M_GetText("Valid skin numbers are 0 to %d (-1 disables)\n"), numskins - 1);
CV_SetValue(&cv_forceskin, -1);
}
return;
}
// NOT in SP, silly!
if (!(netgame || multiplayer))
return;
@ -5269,7 +5503,7 @@ static void ForceSkin_OnChange(void)
CONS_Printf("The server has lifted the forced skin restrictions.\n");
else
{
CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name);
CONS_Printf("The server is restricting all players to skin \"%s\".\n",cv_forceskin.string);
ForceAllSkins(cv_forceskin.value);
}
}
@ -5292,7 +5526,7 @@ static void Name2_OnChange(void)
if (cv_mute.value) //Secondary player can't be admin.
{
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]);
CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]);
}
else
SendNameAndColor2();
@ -5303,7 +5537,7 @@ static void Name3_OnChange(void)
if (cv_mute.value) //Third player can't be admin.
{
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]);
CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]);
}
else
SendNameAndColor3();
@ -5314,7 +5548,7 @@ static void Name4_OnChange(void)
if (cv_mute.value) //Secondary player can't be admin.
{
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]);
CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]);
}
else
SendNameAndColor4();
@ -5355,12 +5589,12 @@ static void Skin2_OnChange(void)
if (!Playing() || !splitscreen)
return; // do whatever you want
if (CanChangeSkin(secondarydisplayplayer) && !P_PlayerMoving(secondarydisplayplayer))
if (CanChangeSkin(displayplayers[1]) && !P_PlayerMoving(displayplayers[1]))
SendNameAndColor2();
else
{
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name);
CV_StealthSet(&cv_skin2, skins[players[displayplayers[1]].skin].name);
}
}
@ -5369,12 +5603,12 @@ static void Skin3_OnChange(void)
if (!Playing() || splitscreen < 2)
return; // do whatever you want
if (CanChangeSkin(thirddisplayplayer) && !P_PlayerMoving(thirddisplayplayer))
if (CanChangeSkin(displayplayers[2]) && !P_PlayerMoving(displayplayers[2]))
SendNameAndColor3();
else
{
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].skin].name);
CV_StealthSet(&cv_skin3, skins[players[displayplayers[2]].skin].name);
}
}
@ -5383,12 +5617,12 @@ static void Skin4_OnChange(void)
if (!Playing() || splitscreen < 3)
return; // do whatever you want
if (CanChangeSkin(fourthdisplayplayer) && !P_PlayerMoving(fourthdisplayplayer))
if (CanChangeSkin(displayplayers[3]) && !P_PlayerMoving(displayplayers[3]))
SendNameAndColor4();
else
{
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].skin].name);
CV_StealthSet(&cv_skin4, skins[players[displayplayers[3]].skin].name);
}
}
@ -5429,7 +5663,7 @@ static void Color2_OnChange(void)
if (!Playing() || !splitscreen)
return; // do whatever you want
if (!P_PlayerMoving(secondarydisplayplayer))
if (!P_PlayerMoving(displayplayers[1]))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor2();
@ -5437,7 +5671,7 @@ static void Color2_OnChange(void)
else
{
CV_StealthSetValue(&cv_playercolor2,
players[secondarydisplayplayer].skincolor);
players[displayplayers[1]].skincolor);
}
}
@ -5446,7 +5680,7 @@ static void Color3_OnChange(void)
if (!Playing() || splitscreen < 2)
return; // do whatever you want
if (!P_PlayerMoving(thirddisplayplayer))
if (!P_PlayerMoving(displayplayers[2]))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor3();
@ -5454,7 +5688,7 @@ static void Color3_OnChange(void)
else
{
CV_StealthSetValue(&cv_playercolor3,
players[thirddisplayplayer].skincolor);
players[displayplayers[2]].skincolor);
}
}
@ -5463,7 +5697,7 @@ static void Color4_OnChange(void)
if (!Playing() || splitscreen < 3)
return; // do whatever you want
if (!P_PlayerMoving(fourthdisplayplayer))
if (!P_PlayerMoving(displayplayers[3]))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor4();
@ -5471,7 +5705,7 @@ static void Color4_OnChange(void)
else
{
CV_StealthSetValue(&cv_playercolor4,
players[fourthdisplayplayer].skincolor);
players[displayplayers[3]].skincolor);
}
}

View file

@ -143,11 +143,9 @@ extern consvar_t cv_ringslinger, cv_soundtest;
extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
#ifdef NEWPING
extern consvar_t cv_maxping;
extern consvar_t cv_pingtimeout;
extern consvar_t cv_showping;
#endif
extern consvar_t cv_skipmapcheck;

View file

@ -107,19 +107,40 @@ INT32 lastfilenum = -1;
* Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c
*
*/
UINT8 *PutFileNeeded(void)
UINT8 *PutFileNeeded(UINT16 firstfile)
{
size_t i, count = 0;
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
size_t i;
UINT8 count = 0;
UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded;
UINT8 *p = p_start;
char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus;
for (i = 0; i < numwadfiles; i++)
for (i = mainwads; i < numwadfiles; i++)
{
// If it has only music/sound lumps, don't put it in the list
if (!wadfiles[i]->important)
continue;
if (firstfile)
{ // Skip files until we reach the first file.
firstfile--;
continue;
}
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
// Look below at the WRITE macros to understand what these numbers mean.
if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED)
{
// Too many files to send all at once
if (netbuffer->packettype == PT_MOREFILESNEEDED)
netbuffer->u.filesneededcfg.more = 1;
else
netbuffer->u.serverinfo.kartvars |= SV_LOTSOFADDONS;
break;
}
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
// Store in the upper four bits
@ -134,30 +155,32 @@ UINT8 *PutFileNeeded(void)
count++;
WRITEUINT32(p, wadfiles[i]->filesize);
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
WRITESTRINGN(p, wadfilename, MAX_WADPATH);
WRITEMEM(p, wadfiles[i]->md5sum, 16);
}
netbuffer->u.serverinfo.fileneedednum = (UINT8)count;
if (netbuffer->packettype == PT_MOREFILESNEEDED)
netbuffer->u.filesneededcfg.num = count;
else
netbuffer->u.serverinfo.fileneedednum = count;
return p;
}
/** Parses the serverinfo packet and fills the fileneeded table on client
*
* \param fileneedednum_parm The number of files needed to join the server
* \param fileneedednum_parm The number of files (sent in this page) needed to join the server
* \param fileneededstr The memory block containing the list of needed files
*
* \param firstfile The first file index to read from
*/
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile)
{
INT32 i;
UINT8 *p;
UINT8 filestatus;
fileneedednum = fileneedednum_parm;
fileneedednum = firstfile + fileneedednum_parm;
p = (UINT8 *)fileneededstr;
for (i = 0; i < fileneedednum; i++)
for (i = firstfile; i < fileneedednum; i++)
{
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
filestatus = READUINT8(p); // The first byte is the file status
@ -338,7 +361,8 @@ INT32 CL_CheckFiles(void)
// the first is the iwad (the main wad file)
// we don't care if it's called srb2.srb or srb2.wad.
// Never download the IWAD, just assume it's there and identical
fileneeded[0].status = FS_OPEN;
// ...No! Why were we sending the base wads to begin with??
//fileneeded[0].status = FS_OPEN;
// Modified game handling -- check for an identical file list
// must be identical in files loaded AND in order
@ -346,7 +370,7 @@ INT32 CL_CheckFiles(void)
if (modifiedgame)
{
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;)
{
if (j < numwadfiles && !wadfiles[j]->important)
{
@ -373,15 +397,12 @@ INT32 CL_CheckFiles(void)
return 1;
}
// See W_LoadWadFile in w_wad.c
packetsize = packetsizetally;
for (i = 1; i < fileneedednum; i++)
for (i = 0; i < fileneedednum; i++)
{
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
// Check in already loaded files
for (j = 1; wadfiles[j]; j++)
for (j = mainwads; wadfiles[j]; j++)
{
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) &&
@ -397,8 +418,7 @@ INT32 CL_CheckFiles(void)
packetsize += nameonlylength(fileneeded[i].filename) + 22;
if ((numwadfiles+filestoget >= MAX_WADFILES)
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
if (mainwads+filestoget >= MAX_WADFILES)
return 3;
filestoget++;

View file

@ -53,8 +53,8 @@ extern char downloaddir[512];
extern INT32 lastfilenum;
#endif
UINT8 *PutFileNeeded(void);
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr);
UINT8 *PutFileNeeded(UINT16 firstfile);
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile);
void CL_PrepareDownloadSaveGame(const char *tmpsave);
INT32 CL_CheckFiles(void);

View file

@ -35,33 +35,6 @@ typedef enum
SF_HIRES = 1, // Draw the sprite 2x as small?
} skinflags_t;
//Primary and secondary skin abilities
typedef enum
{
CA_NONE=0,
CA_THOK,
CA_FLY,
CA_GLIDEANDCLIMB,
CA_HOMINGTHOK,
CA_SWIM,
CA_DOUBLEJUMP,
CA_FLOAT,
CA_SLOWFALL,
CA_TELEKINESIS,
CA_FALLSWITCH,
CA_JUMPBOOST,
CA_AIRDRILL,
CA_JUMPTHOK
} charability_t;
//Secondary skin abilities
typedef enum
{
CA2_NONE=0,
CA2_SPINDASH,
CA2_MULTIABILITY
} charability2_t;
//
// Player states.
//
@ -300,6 +273,7 @@ typedef enum
k_boostpower, // Base boost value, for offroad
k_speedboost, // Boost value smoothing for max speed
k_accelboost, // Boost value smoothing for acceleration
k_boostangle, // angle set when not spun out OR boosted to determine what direction you should keep going at if you're spun out and boosted.
k_boostcam, // Camera push forward on boost
k_destboostcam, // Ditto
k_timeovercam, // Camera timer for leaving behind or not
@ -442,29 +416,8 @@ typedef struct player_s
UINT8 kartweight; // Kart weight stat between 1 and 9
//
fixed_t normalspeed; // Normal ground
fixed_t runspeed; // Speed you break into the run animation
UINT8 thrustfactor; // Thrust = thrustfactor * acceleration
UINT8 accelstart; // Starting acceleration if speed = 0.
UINT8 acceleration; // Acceleration
// See charability_t and charability2_t for more information.
UINT8 charability; // Ability definition
UINT8 charability2; // Secondary ability definition
UINT32 charflags; // Extra abilities/settings for skins (combinable stuff)
// See SF_ flags
mobjtype_t thokitem; // Object # to spawn for the thok
mobjtype_t spinitem; // Object # to spawn for spindash/spinning
mobjtype_t revitem; // Object # to spawn for spindash/spinning
fixed_t actionspd; // Speed of thok/glide/fly
fixed_t mindash; // Minimum spindash speed
fixed_t maxdash; // Maximum spindash speed
fixed_t jumpfactor; // How high can the player jump?
SINT8 lives;
SINT8 continues; // continues that player has acquired

View file

@ -1221,6 +1221,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
#endif
else if (fastcmp(word, "MUSICTRACK"))
mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1);
else if (fastcmp(word, "MUSICPOS"))
mapheaderinfo[num-1]->muspos = (UINT32)get_number(word2);
else if (fastcmp(word, "MUSICINTERFADEOUT"))
mapheaderinfo[num-1]->musinterfadeout = (UINT32)get_number(word2);
else if (fastcmp(word, "MUSICINTER"))
deh_strlcpy(mapheaderinfo[num-1]->musintername, word2,
sizeof(mapheaderinfo[num-1]->musintername), va("Level header %d: intermission music", num));
else if (fastcmp(word, "FORCECHARACTER"))
{
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
@ -1544,6 +1551,11 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
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, "MUSICPOS"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchposition), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2);
}
else if (fastcmp(word, "MUSICLOOP"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
@ -2147,11 +2159,12 @@ 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
if (fasticmp(s, "gamedata.dat")) return false; // Vanilla SRB2 gamedata
if (fasticmp(s, "main.dat")) return false; // Vanilla SRB2 time attack replay folder
if (fasticmp(s, "kartdata.dat")) return false; // SRB2Kart gamedata
if (fasticmp(s, "kart.dat")) return false; // SRB2Kart time attack replay folder
if (fasticmp(s, "online.dat")) return false; // SRB2Kart online replay folder
return true;
}
@ -8140,29 +8153,35 @@ 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[] = { // Rejigged for Kart.
static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"NONE", // SKINCOLOR_NONE
"WHITE", // SKINCOLOR_WHITE
"SILVER", // SKINCOLOR_SILVER
"GREY", // SKINCOLOR_GREY
"NICKEL", // SKINCOLOR_NICKEL
"BLACK", // SKINCOLOR_BLACK
"SKUNK", // SKINCOLOR_SKUNK
"FAIRY", // SKINCOLOR_FAIRY
"POPCORN", // SKINCOLOR_POPCORN
"ARTICHOKE", // SKINCOLOR_ARTICHOKE
"PIGEON", // SKINCOLOR_PIGEON
"SEPIA", // SKINCOLOR_SEPIA
"BEIGE", // SKINCOLOR_BEIGE
"WALNUT", // SKINCOLOR_WALNUT
"BROWN", // SKINCOLOR_BROWN
"LEATHER", // SKINCOLOR_LEATHER
"SALMON", // SKINCOLOR_SALMON
"PINK", // SKINCOLOR_PINK
"ROSE", // SKINCOLOR_ROSE
"BRICK", // SKINCOLOR_BRICK
"CINNAMON", // SKINCOLOR_CINNAMON
"RUBY", // SKINCOLOR_RUBY
"RASPBERRY", // SKINCOLOR_RASPBERRY
"CHERRY", // SKINCOLOR_CHERRY
"RED", // SKINCOLOR_RED
"CRIMSON", // SKINCOLOR_CRIMSON
"MAROON", // SKINCOLOR_MAROON
"LEMONADE", // SKINCOLOR_LEMONADE
"FLAME", // SKINCOLOR_FLAME
"SCARLET", // SKINCOLOR_SCARLET
"KETCHUP", // SKINCOLOR_KETCHUP
@ -8181,8 +8200,10 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"ROYAL", // SKINCOLOR_ROYAL
"BRONZE", // SKINCOLOR_BRONZE
"COPPER", // SKINCOLOR_COPPER
"QUARRY", // SKINCOLOR_QUARRY
"YELLOW", // SKINCOLOR_YELLOW
"MUSTARD", // SKINCOLOR_MUSTARD
"CROCODILE", // SKINCOLOR_CROCODILE
"OLIVE", // SKINCOLOR_OLIVE
"VOMIT", // SKINCOLOR_VOMIT
"GARDEN", // SKINCOLOR_GARDEN
@ -8202,6 +8223,7 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"PLAGUE", // SKINCOLOR_PLAGUE
"ALGAE", // SKINCOLOR_ALGAE
"CARIBBEAN", // SKINCOLOR_CARIBBEAN
"AZURE", // SKINCOLOR_AZURE
"AQUA", // SKINCOLOR_AQUA
"TEAL", // SKINCOLOR_TEAL
"CYAN", // SKINCOLOR_CYAN
@ -8211,7 +8233,9 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"PLATINUM", // SKINCOLOR_PLATINUM
"SLATE", // SKINCOLOR_SLATE
"STEEL", // SKINCOLOR_STEEL
"THUNDER", // SKINCOLOR_THUNDER
"RUST", // SKINCOLOR_RUST
"WRISTWATCH", // SKINCOLOR_WRISTWATCH
"JET", // SKINCOLOR_JET
"SAPPHIRE", // SKINCOLOR_SAPPHIRE
"PERIWINKLE", // SKINCOLOR_PERIWINKLE
@ -8232,10 +8256,6 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"POMEGRANATE", // SKINCOLOR_POMEGRANATE
"LILAC", // SKINCOLOR_LILAC
// Special super colors
// Super Sonic Yellow
"SUPER1", // SKINCOLOR_SUPER1
@ -8376,6 +8396,7 @@ static const char *const KARTSTUFF_LIST[] = {
"BOOSTPOWER",
"SPEEDBOOST",
"ACCELBOOST",
"BOOSTANGLE",
"BOOSTCAM",
"DESTBOOSTCAM",
"TIMEOVERCAM",
@ -8495,6 +8516,7 @@ struct {
// doomdef.h constants
{"TICRATE",TICRATE},
{"MUSICRATE",MUSICRATE},
{"RING_DIST",RING_DIST},
{"PUSHACCEL",PUSHACCEL},
{"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
@ -8647,27 +8669,6 @@ struct {
// Character flags (skinflags_t)
{"SF_HIRES",SF_HIRES},
// Character abilities!
// Primary
{"CA_NONE",CA_NONE}, // now slot 0!
{"CA_THOK",CA_THOK},
{"CA_FLY",CA_FLY},
{"CA_GLIDEANDCLIMB",CA_GLIDEANDCLIMB},
{"CA_HOMINGTHOK",CA_HOMINGTHOK},
{"CA_DOUBLEJUMP",CA_DOUBLEJUMP},
{"CA_FLOAT",CA_FLOAT},
{"CA_SLOWFALL",CA_SLOWFALL},
{"CA_SWIM",CA_SWIM},
{"CA_TELEKINESIS",CA_TELEKINESIS},
{"CA_FALLSWITCH",CA_FALLSWITCH},
{"CA_JUMPBOOST",CA_JUMPBOOST},
{"CA_AIRDRILL",CA_AIRDRILL},
{"CA_JUMPTHOK",CA_JUMPTHOK},
// Secondary
{"CA2_NONE",CA2_NONE}, // now slot 0!
{"CA2_SPINDASH",CA2_SPINDASH},
{"CA2_MULTIABILITY",CA2_MULTIABILITY},
// Sound flags
{"SF_TOTALLYSINGLE",SF_TOTALLYSINGLE},
{"SF_NOMULTIPLESOUND",SF_NOMULTIPLESOUND},
@ -9804,7 +9805,7 @@ static inline int lib_getenum(lua_State *L)
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
// You know, like consoleplayer, displayplayers, or gametime.
if (fastcmp(word,"gamemap")) {
lua_pushinteger(L, gamemap);
return 1;
@ -9877,8 +9878,11 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"mapmusflags")) {
lua_pushinteger(L, mapmusflags);
return 1;
} else if (fastcmp(word,"mapmusposition")) {
lua_pushinteger(L, mapmusposition);
return 1;
} else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer])
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
@ -9930,6 +9934,9 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"mapobjectscale")) {
lua_pushinteger(L, mapobjectscale);
return 1;
} else if (fastcmp(word,"numlaps")) {
lua_pushinteger(L, cv_numlaps.value);
return 1;
}
return 0;
}

View file

@ -438,6 +438,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -545,3 +576,44 @@ int I_QrySongPlaying(int handle)
return (midi_pos==-1);
}
#endif
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View file

@ -149,14 +149,18 @@ extern FILE *logstream;
// most interface strings are ignored in development mode.
// we use comprevision and compbranch instead.
#else
#define VERSION 100 // Game version
#define SUBVERSION 4 // more precise version number
#define VERSIONSTRING "v1.0.4"
#define VERSIONSTRINGW L"v1.0.4"
// Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates!
#define VERSION 110 // Game version
#define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v1.1"
#define VERSIONSTRINGW L"v1.1"
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt, for CMake users!
// AND appveyor.yml, for the build bots!
#endif
// Maintain compatibility with 1.0.x record attack replays?
#define DEMO_COMPAT_100
// Does this version require an added patch file?
// Comment or uncomment this as necessary.
//#define USE_PATCH_DTA
@ -221,7 +225,7 @@ extern FILE *logstream;
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 4
#define MODVERSION 5
// Filter consvars by version
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
@ -248,6 +252,9 @@ extern FILE *logstream;
#define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21
// Master Server compatibility ONLY
#define MSCOMPAT_MAXPLAYERS (32)
typedef enum
{
SKINCOLOR_NONE = 0,
@ -256,22 +263,28 @@ typedef enum
SKINCOLOR_GREY,
SKINCOLOR_NICKEL,
SKINCOLOR_BLACK,
SKINCOLOR_SKUNK,
SKINCOLOR_FAIRY,
SKINCOLOR_POPCORN,
SKINCOLOR_ARTICHOKE,
SKINCOLOR_PIGEON,
SKINCOLOR_SEPIA,
SKINCOLOR_BEIGE,
SKINCOLOR_WALNUT,
SKINCOLOR_BROWN,
SKINCOLOR_LEATHER,
SKINCOLOR_SALMON,
SKINCOLOR_PINK,
SKINCOLOR_ROSE,
SKINCOLOR_BRICK,
SKINCOLOR_CINNAMON,
SKINCOLOR_RUBY,
SKINCOLOR_RASPBERRY,
SKINCOLOR_CHERRY,
SKINCOLOR_RED,
SKINCOLOR_CRIMSON,
SKINCOLOR_MAROON,
SKINCOLOR_LEMONADE,
SKINCOLOR_FLAME,
SKINCOLOR_SCARLET,
SKINCOLOR_KETCHUP,
@ -290,8 +303,10 @@ typedef enum
SKINCOLOR_ROYAL,
SKINCOLOR_BRONZE,
SKINCOLOR_COPPER,
SKINCOLOR_QUARRY,
SKINCOLOR_YELLOW,
SKINCOLOR_MUSTARD,
SKINCOLOR_CROCODILE,
SKINCOLOR_OLIVE,
SKINCOLOR_VOMIT,
SKINCOLOR_GARDEN,
@ -311,6 +326,7 @@ typedef enum
SKINCOLOR_PLAGUE,
SKINCOLOR_ALGAE,
SKINCOLOR_CARIBBEAN,
SKINCOLOR_AZURE,
SKINCOLOR_AQUA,
SKINCOLOR_TEAL,
SKINCOLOR_CYAN,
@ -320,7 +336,9 @@ typedef enum
SKINCOLOR_PLATINUM,
SKINCOLOR_SLATE,
SKINCOLOR_STEEL,
SKINCOLOR_THUNDER,
SKINCOLOR_RUST,
SKINCOLOR_WRISTWATCH,
SKINCOLOR_JET,
SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl
SKINCOLOR_PERIWINKLE,
@ -418,6 +436,8 @@ typedef enum
#define NEWTICRATERATIO 1 // try 4 for 140 fps :)
#define NEWTICRATE (TICRATE*NEWTICRATERATIO)
#define MUSICRATE 1000 // sound timing is calculated by milliseconds
#define RING_DIST 1280*FRACUNIT // how close you need to be to a ring to attract it
#define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items.
@ -602,9 +622,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Polyobject fake flat code
#define POLYOBJECTS_PLANES
/// Improved way of dealing with ping values and a ping limit.
#define NEWPING
/// See name of player in your crosshair
#define SEENAMES

View file

@ -33,8 +33,10 @@
extern INT16 gamemap;
extern char mapmusname[7];
extern UINT16 mapmusflags;
extern UINT32 mapmusposition;
#define MUSIC_TRACKMASK 0x0FFF // ----************
#define MUSIC_RELOADRESET 0x8000 // *---------------
#define MUSIC_FORCERESET 0x4000 // -*--------------
// Use other bits if necessary.
extern INT16 maptol;
@ -77,7 +79,10 @@ extern boolean addedtogame; // true after the server has added you
extern boolean multiplayer;
extern INT16 gametype;
#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer
extern UINT8 splitscreen;
extern boolean circuitmap; // Does this level have 'circuit mode'?
extern boolean fromlevelselect;
extern boolean forceresetplayers, deferencoremode;
@ -106,14 +111,8 @@ extern UINT8 window_notinfocus; // are we in focus? (backend independant -- hand
extern boolean nodrawers;
extern boolean noblit;
extern boolean lastdraw;
extern postimg_t postimgtype;
extern INT32 postimgparam;
extern postimg_t postimgtype2;
extern INT32 postimgparam2;
extern postimg_t postimgtype3;
extern INT32 postimgparam3;
extern postimg_t postimgtype4;
extern INT32 postimgparam4;
extern postimg_t postimgtype[MAXSPLITSCREENPLAYERS];
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
extern INT32 viewwindowx, viewwindowy;
extern INT32 viewwidth, scaledviewwidth;
@ -122,10 +121,7 @@ extern boolean gamedataloaded;
// Player taking events, and displaying.
extern INT32 consoleplayer;
extern INT32 displayplayer;
extern INT32 secondarydisplayplayer; // for splitscreen
extern INT32 thirddisplayplayer;
extern INT32 fourthdisplayplayer;
extern INT32 displayplayers[MAXSPLITSCREENPLAYERS];
// Maps of special importance
extern INT16 spstage_start;
@ -156,6 +152,7 @@ typedef struct
char musswitch[7];
UINT16 musswitchflags;
UINT32 musswitchposition;
UINT8 fadecolor; // Color number for fade, 0 means don't do the first fade
UINT8 fadeinid; // ID of the first fade, to a color -- ignored if fadecolor is 0
@ -228,6 +225,7 @@ typedef struct
char keyword[33]; ///< Keywords separated by space to search for. 32 characters.
char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to.
char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
INT16 skynum; ///< Sky number to use.
@ -261,6 +259,10 @@ typedef struct
//boolean automap; ///< Displays a level's white map outline in modified games
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
// Music stuff.
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
char musintername[7]; ///< Intermission screen music.
// Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
@ -331,7 +333,10 @@ enum GameType // SRB2Kart
GT_HIDEANDSEEK,
GT_CTF
};
// If you alter this list, update gametype_cons_t in m_menu.c
// If you alter this list, update dehacked.c, and Gametype_Names in g_game.c
// String names for gametypes
extern const char *Gametype_Names[NUMGAMETYPES];
extern tic_t totalplaytime;
extern UINT32 matchesplayed;
@ -544,9 +549,7 @@ extern consvar_t cv_forceskin; // force clients to use the server's skin
extern consvar_t cv_downloading; // allow clients to downloading WADs.
extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu
extern consvar_t cv_jointimeout;
#ifdef NEWPING
extern consvar_t cv_maxping;
#endif
extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
extern INT32 serverplayer;
extern INT32 adminplayers[MAXPLAYERS];

View file

@ -369,16 +369,18 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Miscellaneous types that don't fit anywhere else (Can this be changed?) */
typedef struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} byteColor_t;
union FColorRGBA
{
UINT32 rgba;
struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} s;
byteColor_t s;
} ATTRPACK;
typedef union FColorRGBA RGBA_t;

View file

@ -95,6 +95,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -142,4 +173,45 @@ boolean I_SetSongTrack(int track)
{
(void)track;
return false;
}
}
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View file

@ -238,7 +238,6 @@ void F_StartIntro(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
F_NewCutscene(introtext[0]);
intro_scenenum = 0;
@ -439,6 +438,7 @@ static const char *credits[] = {
"",
"\1Support Programming",
"Colette \"fickleheart\" Bordelon",
"James R.",
"\"Lat\'\"",
"\"Monster Iestyn\"",
"\"Shuffle\"",
@ -460,9 +460,13 @@ static const char *credits[] = {
"\"ZarroTsu\"",
"",
"\1External Artists",
"\"1-Up Mason\"",
"\"Chengi\"",
"\"Chrispy\"",
"\"DirkTheHusky\"",
"\"LJSTAR\"",
"\"MotorRoach\"",
"\"Mr. McScrewup\"",
"\"Nev3r\"",
"\"Ritz\"",
"\"Rob\"",
@ -471,6 +475,7 @@ static const char *credits[] = {
"\"Spherallic\"",
"\"VAdaPEGA\"",
"\"Virt\"",
"\"Voltrix\"",
"\"zxyspku\"",
"",
"\1Sound Design",
@ -497,13 +502,18 @@ static const char *credits[] = {
"\"DrTapeworm\"",
"Paul \"Boinciel\" Clempson",
"Sherman \"CoatRack\" DesJardins",
"Colette \"fickleheart\" Bordelon",
"Vivian \"toaster\" Grannell",
"James \"SeventhSentinel\" Hall",
"\"Lat\'\"",
"\"MK\"",
"\"Ninferno\"",
"Sean \"Sryder\" Ryder",
"\"Ryuspark\"",
"\"Simsmagic\"",
"\"SP47\"",
"\"TG\"",
"\"Victor Rush Turbo\"",
"\"ZarroTsu\"",
"",
"\1Testing",
@ -556,7 +566,7 @@ static struct {
// This Tyler52 gag is troublesome
// Alignment should be ((spaces+1 * 100) + (headers+1 * 38) + (lines * 15))
// Current max image spacing: (200*17)
{112, (15*100)+(17*38)+(72*15), "TYLER52", SKINCOLOR_NONE},
{112, (15*100)+(17*38)+(86*15), "TYLER52", SKINCOLOR_NONE},
{0, 0, NULL, SKINCOLOR_NONE}
};
@ -580,10 +590,10 @@ void F_StartCredits(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
S_StopMusic();
S_ChangeMusicInternal("credit", false);
S_ShowMusicCredit();
finalecount = 0;
animtimer = 0;
@ -773,7 +783,6 @@ void F_StartGameEvaluation(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
finalecount = 0;
}
@ -883,7 +892,6 @@ void F_StartGameEnd(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
S_StopMusic();
// In case menus are still up?!!
@ -927,9 +935,9 @@ void F_StartTitleScreen(void)
// IWAD dependent stuff.
// music is started in the ticker
if (!fromtitledemo) // SRB2Kart: Don't reset music if the right track is already playing
if (!demo.fromtitle) // SRB2Kart: Don't reset music if the right track is already playing
S_StopMusic();
fromtitledemo = false;
demo.fromtitle = false;
animtimer = 0;
@ -1042,11 +1050,29 @@ void F_TitleScreenTicker(boolean run)
// is it time?
if (!(--demoIdleLeft))
{
//static boolean use_netreplay = false;
char dname[9];
lumpnum_t l;
const char *mapname;
UINT8 numstaff;
//@TODO uncomment this when this goes into vanilla
/*if ((use_netreplay = !use_netreplay))*/
{
numstaff = 1;
while ((l = W_CheckNumForName(va("TDEMO%03u", numstaff))) != LUMPERROR)
numstaff++;
numstaff--;
if (numstaff)
{
numstaff = M_RandomKey(numstaff)+1;
snprintf(dname, 9, "TDEMO%03u", numstaff);
goto loadreplay;
}
}
// prevent console spam if failed
demoIdleLeft = demoIdleTime;
@ -1097,7 +1123,10 @@ void F_TitleScreenTicker(boolean run)
return;
}*/
titledemo = fromtitledemo = true;
loadreplay:
demo.title = demo.fromtitle = true;
demo.ignorefiles = true;
demo.loadfiles = false;
G_DoPlayDemo(dname);
}
}
@ -1177,7 +1206,6 @@ void F_StartContinue(void)
keypressed = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
// In case menus are still up?!!
M_ClearMenus(true);
@ -1297,9 +1325,10 @@ static void F_AdvanceToNextScene(void)
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musswitch,
S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch,
cutscenes[cutnum]->scene[scenenum].musswitchflags,
cutscenes[cutnum]->scene[scenenum].musicloop);
cutscenes[cutnum]->scene[scenenum].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
// Fade to the next
dofadenow = true;
@ -1348,8 +1377,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
F_NewCutscene(cutscenes[cutscenenum]->scene[0].text);
CON_ClearHUD();
cutsceneover = false;
runningprecutscene = precutscene;
precutresetplayer = resetplayer;
@ -1370,9 +1397,10 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
stoptimer = 0;
if (cutscenes[cutnum]->scene[0].musswitch[0])
S_ChangeMusic(cutscenes[cutnum]->scene[0].musswitch,
S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch,
cutscenes[cutnum]->scene[0].musswitchflags,
cutscenes[cutnum]->scene[0].musicloop);
cutscenes[cutnum]->scene[0].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
else
S_StopMusic();
}

View file

@ -341,8 +341,6 @@ size_t dir_on[menudepth];
UINT8 refreshdirmenu = 0;
char *refreshdirname = NULL;
size_t packetsizetally = 0;
size_t mainwadstally = 0;
#if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
@ -368,9 +366,10 @@ void searchfilemenu(char *tempname)
return;
}
boolean preparefilemenu(boolean samedepth)
boolean preparefilemenu(boolean samedepth, boolean replayhut)
{
(void)samedepth;
(void)replayhut;
return false;
}
@ -437,9 +436,10 @@ void searchfilemenu(char *tempname)
return;
}
boolean preparefilemenu(boolean samedepth)
boolean preparefilemenu(boolean samedepth, boolean replayhut)
{
(void)samedepth;
(void)replayhut;
return false;
}
@ -710,7 +710,7 @@ void searchfilemenu(char *tempname)
}
}
boolean preparefilemenu(boolean samedepth)
boolean preparefilemenu(boolean samedepth, boolean replayhut)
{
DIR *dirhandle;
struct dirent *dent;
@ -759,9 +759,13 @@ boolean preparefilemenu(boolean samedepth)
{
if (!S_ISDIR(fsstat.st_mode)) // file
{
if (!cv_addons_showall.value)
size_t len = strlen(dent->d_name)+1;
if (replayhut)
{
if (strcasecmp(".lmp", dent->d_name+len-5)) continue; // Not a replay
}
else if (!cv_addons_showall.value)
{
size_t len = strlen(dent->d_name)+1;
UINT8 ext;
for (ext = 0; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
@ -829,40 +833,49 @@ boolean preparefilemenu(boolean samedepth)
if (!S_ISDIR(fsstat.st_mode)) // file
{
if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention
for (; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
ext += EXT_START; // moving to be appropriate position
if (ext >= EXT_LOADSTART)
if (replayhut)
{
size_t i;
for (i = 0; i < numwadfiles; i++)
if (strcasecmp(".lmp", dent->d_name+len-5)) continue; // Not a replay
ext = EXT_TXT; // This isn't used anywhere but better safe than sorry for messing with this...
}
else
{
for (; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
ext += EXT_START; // moving to be appropriate position
if (ext >= EXT_LOADSTART)
{
if (!filenamebuf[i][0])
size_t i;
for (i = 0; i < numwadfiles; i++)
{
strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
filenamebuf[i][MAX_WADPATH - 1] = '\0';
nameonly(filenamebuf[i]);
if (!filenamebuf[i][0])
{
strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
filenamebuf[i][MAX_WADPATH - 1] = '\0';
nameonly(filenamebuf[i]);
}
if (strcmp(dent->d_name, filenamebuf[i]))
continue;
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
continue;
ext |= EXT_LOADED;
}
if (strcmp(dent->d_name, filenamebuf[i]))
continue;
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
continue;
ext |= EXT_LOADED;
}
}
else if (ext == EXT_TXT)
{
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
else if (ext == EXT_TXT)
{
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
ext |= EXT_LOADED;
}
if (!strcmp(dent->d_name, configfile))
ext |= EXT_LOADED;
}
if (!strcmp(dent->d_name, configfile))
ext |= EXT_LOADED;
folder = 0;
}
else // directory
@ -881,6 +894,8 @@ boolean preparefilemenu(boolean samedepth)
strcpy(temp+len, PATHSEP);
coredirmenu[folderpos++] = temp;
}
else if (replayhut) // Reverse-alphabetical on just the files; acts as a fake "most recent first" with the current filename format
coredirmenu[sizecoredirmenu - 1 - pos++] = temp;
else
coredirmenu[numfolders + pos++] = temp;
}

View file

@ -42,9 +42,6 @@ extern size_t dir_on[menudepth];
extern UINT8 refreshdirmenu;
extern char *refreshdirname;
extern size_t packetsizetally;
extern size_t mainwadstally;
typedef enum
{
EXT_FOLDER = 0,
@ -94,6 +91,6 @@ typedef enum
void closefilemenu(boolean validsize);
void searchfilemenu(char *tempname);
boolean preparefilemenu(boolean samedepth);
boolean preparefilemenu(boolean samedepth, boolean replayhut);
#endif // __FILESRCH_H__

File diff suppressed because it is too large Load diff

View file

@ -36,11 +36,61 @@ extern boolean playeringame[MAXPLAYERS];
// ======================================
// demoplaying back and demo recording
extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo;
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality;
// Publicly-accessible demo vars
struct demovars_s {
char titlename[65];
boolean recording, playback, timing;
UINT16 version; // Current file format of the demo being played
boolean title; // Title Screen demo can be cancelled by any key
boolean rewinding; // Rewind in progress
boolean loadfiles, ignorefiles; // Demo file loading options
boolean fromtitle; // SRB2Kart: Don't stop the music
boolean inreplayhut; // Go back to replayhut after demos
boolean quitafterplaying; // quit after playing a demo from cmdline
boolean deferstart; // don't start playing demo right away
tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going
enum {
DSM_NOTSAVING,
DSM_WILLAUTOSAVE,
DSM_TITLEENTRY,
DSM_WILLSAVE,
DSM_SAVED
} savemode;
};
extern struct demovars_s demo;
typedef enum {
MD_NOTLOADED,
MD_LOADED,
MD_SUBDIR,
MD_OUTDATED,
MD_INVALID
} menudemotype_e;
typedef struct menudemo_s {
char filepath[256];
menudemotype_e type;
char title[65]; // Null-terminated for string prints
UINT16 map;
UINT8 addonstatus; // What do we need to do addon-wise to play this demo?
UINT8 gametype;
UINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk
UINT8 numlaps;
struct {
UINT8 ranking;
char name[17];
UINT8 skin, color;
UINT32 timeorscore;
} standings[MAXPLAYERS];
} menudemo_t;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
extern boolean demo_start;
extern mobj_t *metalplayback;
@ -62,10 +112,10 @@ extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mouse
extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/;
extern consvar_t cv_useranalog, cv_useranalog2, cv_useranalog3, cv_useranalog4;
extern consvar_t cv_analog, cv_analog2, cv_analog3, cv_analog4;
extern consvar_t cv_turnaxis,cv_moveaxis,cv_brakeaxis,cv_aimaxis,cv_lookaxis,cv_fireaxis,cv_driftaxis;
extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis2,cv_fireaxis2,cv_driftaxis2;
extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3;
extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4;
extern consvar_t cv_turnaxis,cv_moveaxis,cv_brakeaxis,cv_aimaxis,cv_lookaxis,cv_fireaxis,cv_driftaxis,cv_deadzone;
extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis2,cv_fireaxis2,cv_driftaxis2,cv_deadzone2;
extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3,cv_deadzone3;
extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4,cv_deadzone4;
extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff;
typedef enum
@ -102,9 +152,9 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
boolean InputDown(INT32 gc, UINT8 p);
INT32 JoyAxis(axis_input_e axissel, UINT8 p);
extern angle_t localangle, localangle2, localangle3, localangle4;
extern INT32 localaiming, localaiming2, localaiming3, localaiming4; // should be an angle_t but signed
extern boolean camspin, camspin2, camspin3, camspin4; // SRB2Kart
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
extern boolean camspin[MAXSPLITSCREENPLAYERS]; // SRB2Kart
//
// GAME
@ -149,6 +199,7 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar
UINT8 ssplayers, boolean FLS);
void G_DoLoadLevel(boolean resetplayer);
void G_LoadDemoInfo(menudemo_t *pdemo);
void G_DeferedPlayDemo(const char *demo);
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
@ -165,6 +216,7 @@ void G_BeginRecording(void);
void G_BeginMetal(void);
// Only called by shutdown code.
void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val);
void G_SetDemoTime(UINT32 ptime, UINT32 plap);
UINT8 G_CmpDemoTime(char *oldname, char *newname);
@ -176,19 +228,41 @@ typedef enum
GHC_INVINCIBLE
} ghostcolor_t;
extern UINT8 demo_extradata[MAXPLAYERS];
extern UINT8 demo_writerng;
#define DXD_RESPAWN 0x01 // "respawn" command in console
#define DXD_SKIN 0x02 // skin changed
#define DXD_NAME 0x04 // name changed
#define DXD_COLOR 0x08 // color changed
#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game
#define DXD_PST_PLAYING 0x01
#define DXD_PST_SPECTATING 0x02
#define DXD_PST_LEFT 0x03
// Record/playback tics
void G_ReadDemoExtraData(void);
void G_WriteDemoExtraData(void);
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
void G_GhostAddThok(void);
void G_GhostAddSpin(void);
void G_GhostAddRev(void);
void G_GhostAddColor(ghostcolor_t color);
void G_GhostAddFlip(void);
void G_GhostAddScale(fixed_t scale);
void G_GhostAddHit(mobj_t *victim);
void G_WriteGhostTic(mobj_t *ghost);
void G_ConsGhostTic(void);
void G_GhostAddThok(INT32 playernum);
void G_GhostAddSpin(INT32 playernum);
void G_GhostAddRev(INT32 playernum);
void G_GhostAddColor(INT32 playernum, ghostcolor_t color);
void G_GhostAddFlip(INT32 playernum);
void G_GhostAddScale(INT32 playernum, fixed_t scale);
void G_GhostAddHit(INT32 playernum, mobj_t *victim);
void G_WriteAllGhostTics(void);
void G_WriteGhostTic(mobj_t *ghost, INT32 playernum);
void G_ConsAllGhostTics(void);
void G_ConsGhostTic(INT32 playernum);
void G_GhostTicker(void);
void G_InitDemoRewind(void);
void G_StoreRewindInfo(void);
void G_PreviewRewind(tic_t previewtime);
void G_ConfirmRewind(tic_t rewindtime);
void G_ReadMetalTic(mobj_t *metal);
void G_WriteMetalTic(mobj_t *metal);
void G_SaveMetal(UINT8 **buffer);
@ -205,6 +279,13 @@ typedef struct demoghost {
} demoghost;
extern demoghost *ghosts;
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
#define DFILE_ERROR_NOTLOADED 0x01 // Files are not loaded, but can be without a restart.
#define DFILE_ERROR_OUTOFORDER 0x02 // Files are loaded, but out of order.
#define DFILE_ERROR_INCOMPLETEOUTOFORDER 0x03 // Some files are loaded out of order, but others are not.
#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded.
#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded.
void G_DoPlayDemo(char *defdemoname);
void G_TimeDemo(const char *name);
void G_AddGhost(char *defdemoname);
@ -215,7 +296,10 @@ void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);
void G_SaveDemo(void);
boolean G_DemoTitleResponder(event_t *ev);
INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);
@ -235,6 +319,16 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed
void G_Ticker(boolean run);
boolean G_Responder(event_t *ev);
boolean G_CouldView(INT32 playernum);
boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive);
INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive, boolean reverse);
INT32 G_CountPlayersPotentiallyViewable(boolean active);
void G_ResetViews(void);
void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive);
void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive);
void G_AddPlayer(INT32 playernum);
void G_SetExitGameFlag(void);

View file

@ -296,7 +296,7 @@ static void HW3S_FillSourceParameters
data->max_distance = MAX_DISTANCE;
data->min_distance = MIN_DISTANCE;
if (origin && origin != players[displayplayer].mo)
if (origin && origin != players[displayplayers[0]].mo)
{
data->head_relative = false;
@ -356,10 +356,10 @@ INT32 HW3S_I_StartSound(const void *origin_p, source3D_data_t *source_parm, chan
source3D_data_t source3d_data;
INT32 s_num = 0;
source_t *source = NULL;
mobj_t *listenmobj = players[displayplayer].mo;
mobj_t *listenmobj = players[displayplayers[0]].mo; // TODO: Kart 4P does not support sounds properly here
mobj_t *listenmobj2 = NULL;
if (splitscreen) listenmobj2 = players[secondarydisplayplayer].mo;
if (splitscreen) listenmobj2 = players[displayplayers[1]].mo;
if (sound_disabled)
return -1;
@ -876,12 +876,12 @@ static void HW3S_Update3DSource(source_t *src)
void HW3S_UpdateSources(void)
{
mobj_t *listener = players[displayplayer].mo;
mobj_t *listener = players[displayplayers[0]].mo;
mobj_t *listener2 = NULL;
source_t *src;
INT32 audible, snum, volume, sep, pitch;
if (splitscreen) listener2 = players[secondarydisplayplayer].mo;
if (splitscreen) listener2 = players[displayplayers[1]].mo;
HW3S_UpdateListener2(listener2);
HW3S_UpdateListener(listener);

View file

@ -241,43 +241,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else if (cv_voodoocompatibility.value)
{
if (originalwidth > 256 || originalheight > 256)
{
blockwidth = 256;
while (originalwidth < blockwidth)
blockwidth >>= 1;
if (blockwidth < 1)
I_Error("3D GenerateTexture : too small");
blockheight = 256;
while (originalheight < blockheight)
blockheight >>= 1;
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else
{
//size up to nearest power of 2
blockwidth = 1;
while (blockwidth < originalwidth)
blockwidth <<= 1;
// scale down the original graphics to fit in 256
if (blockwidth > 256)
blockwidth = 256;
//I_Error("3D GenerateTexture : too big");
//size up to nearest power of 2
blockheight = 1;
while (blockheight < originalheight)
blockheight <<= 1;
// scale down the original graphics to fit in 256
if (blockheight > 256)
blockheight = 255;
//I_Error("3D GenerateTexture : too big");
}
}
else
{
//size up to nearest power of 2
@ -508,18 +471,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
newwidth = blockwidth;
newheight = blockheight;
}
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(grPatch->width, blockwidth);
newheight = min(grPatch->height, blockheight);
if (newwidth > 256 || newheight > 256)
{
newwidth = blockwidth;
newheight = blockheight;
}
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'
@ -935,18 +886,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
newwidth = blockwidth;
newheight = blockheight;
}
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(SHORT(pic->width),blockwidth);
newheight = min(SHORT(pic->height),blockheight);
if (newwidth > 256 || newheight > 256)
{
newwidth = blockwidth;
newheight = blockheight;
}
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'

View file

@ -78,8 +78,8 @@
#include "r_opengl/r_opengl.h"
#ifdef HAVE_SPHEREFRUSTRUM
static GLdouble viewMatrix[16];
static GLdouble projMatrix[16];
static GLfloat viewMatrix[16];
static GLfloat projMatrix[16];
float frustum[6][4];
#endif
@ -381,8 +381,8 @@ void gld_FrustrumSetup(void)
float t;
float clip[16];
pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix);
pglGetFloatv(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);

View file

@ -101,15 +101,29 @@ typedef struct
//Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
// Kart features
#define USE_FTRANSFORM_ANGLEZ
#define USE_FTRANSFORM_MIRROR
// Vanilla features
//#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
#else
FLOAT anglex,angley; // aimingangle / viewangle
#endif
FLOAT scalex,scaley,scalez;
FLOAT fovxangle, fovyangle;
UINT8 splitscreen;
boolean flip; // screenflip
#ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode
#endif
} FTransform;
// Transformed vector, as passed to HWR API
@ -152,7 +166,7 @@ enum EPolyFlags
// When set, pass the color constant into the FSurfaceInfo -> FlatColor
PF_NoTexture = 0x00002000, // Use the small white texture
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
PF_MD2 = 0x00008000, // Tell the rendrer we are drawing an MD2
PF_Unused = 0x00008000, // Unused
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
@ -210,8 +224,6 @@ enum hwdsetspecialstate
HWD_SET_FOG_COLOR,
HWD_SET_FOG_DENSITY,
HWD_SET_FOV,
HWD_SET_POLYGON_SMOOTH,
HWD_SET_PALETTECOLOR,
HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE,
HWD_NUMSTATE

View file

@ -58,20 +58,18 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale);
EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
#ifdef SHUFFLE
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
#endif
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void);
EXPORT void HWRAPI(DoScreenWipe) (float alpha);
EXPORT void HWRAPI(DoScreenWipe) (void);
EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void);
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
@ -96,8 +94,8 @@ struct hwdriver_s
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
DrawMD2 pfnDrawMD2;
DrawMD2i pfnDrawMD2i;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
GetTextureUsed pfnGetTextureUsed;
GetRenderVersion pfnGetRenderVersion;
@ -107,9 +105,7 @@ struct hwdriver_s
#ifndef HAVE_SDL
Shutdown pfnShutdown;
#endif
#ifdef SHUFFLE
PostImgRedraw pfnPostImgRedraw;
#endif
FlushScreenTextures pfnFlushScreenTextures;
StartScreenWipe pfnStartScreenWipe;
EndScreenWipe pfnEndScreenWipe;

File diff suppressed because it is too large Load diff

View file

@ -58,7 +58,6 @@ void HWR_AddCommands(void);
void HWR_CorrectSWTricks(void);
void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
void HWR_SetPaletteColor(INT32 palcolor);
INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void);
@ -80,7 +79,8 @@ extern consvar_t cv_grstaticlighting;
extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize;
#endif
extern consvar_t cv_grmd2;
extern consvar_t cv_grmdls;
extern consvar_t cv_grfallbackplayermodel;
extern consvar_t cv_grfog;
extern consvar_t cv_grfogcolor;
extern consvar_t cv_grfogdensity;
@ -91,9 +91,9 @@ extern consvar_t cv_grgammablue;
extern consvar_t cv_grfiltermode;
extern consvar_t cv_granisotropicmode;
extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowx, gr_baseviewwindowy;

View file

@ -43,6 +43,7 @@
#include "../r_draw.h"
#include "../p_tick.h"
#include "../k_kart.h" // colortranslations
#include "hw_model.h"
#include "hw_main.h"
#include "../v_video.h"
@ -75,172 +76,6 @@
#include "errno.h"
#endif
#define NUMVERTEXNORMALS 162
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
md2_t md2_models[NUMSPRITES];
md2_t md2_playermodels[MAXSKINS];
@ -248,198 +83,29 @@ md2_t md2_playermodels[MAXSKINS];
/*
* free model
*/
static void md2_freeModel (md2_model_t *model)
#if 0
static void md2_freeModel (model_t *model)
{
if (model)
{
if (model->skins)
free(model->skins);
if (model->texCoords)
free(model->texCoords);
if (model->triangles)
free(model->triangles);
if (model->frames)
{
size_t i;
for (i = 0; i < model->header.numFrames; i++)
{
if (model->frames[i].vertices)
free(model->frames[i].vertices);
}
free(model->frames);
}
if (model->glCommandBuffer)
free(model->glCommandBuffer);
free(model);
}
UnloadModel(model);
}
#endif
//
// load model
//
// Hurdler: the current path is the Legacy.exe path
static md2_model_t *md2_readModel(const char *filename)
static model_t *md2_readModel(const char *filename)
{
FILE *file;
md2_model_t *model;
UINT8 buffer[MD2_MAX_FRAMESIZE];
size_t i;
model = calloc(1, sizeof (*model));
if (model == NULL)
return 0;
//Filename checking fixed ~Monster Iestyn and Golden
file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb");
if (!file)
{
file = fopen(va("%s"PATHSEP"%s", srb2path, filename), "rb");
if (!file)
{
free(model);
return 0;
}
}
// initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1
|| model->header.magic != MD2_IDENT
|| model->header.version != MD2_VERSION)
{
fclose(file);
free(model);
return 0;
}
model->header.numSkins = 1;
#define MD2LIMITCHECK(field, max, msgname) \
if (field > max) \
{ \
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; \
}
// Uncomment if these are actually needed
// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins")
// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates")
MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles")
MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames")
MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices")
#undef MD2LIMITCHECK
// read skins
fseek(file, model->header.offsetSkins, SEEK_SET);
if (model->header.numSkins > 0)
{
model->skins = calloc(sizeof (md2_skin_t), model->header.numSkins);
if (!model->skins || model->header.numSkins !=
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read texture coordinates
fseek(file, model->header.offsetTexCoords, SEEK_SET);
if (model->header.numTexCoords > 0)
{
model->texCoords = calloc(sizeof (md2_textureCoordinate_t), model->header.numTexCoords);
if (!model->texCoords || model->header.numTexCoords !=
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read triangles
fseek(file, model->header.offsetTriangles, SEEK_SET);
if (model->header.numTriangles > 0)
{
model->triangles = calloc(sizeof (md2_triangle_t), model->header.numTriangles);
if (!model->triangles || model->header.numTriangles !=
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read alias frames
fseek(file, model->header.offsetFrames, SEEK_SET);
if (model->header.numFrames > 0)
{
model->frames = calloc(sizeof (md2_frame_t), model->header.numFrames);
if (!model->frames)
{
md2_freeModel (model);
fclose(file);
return 0;
}
for (i = 0; i < model->header.numFrames; i++)
{
md2_alias_frame_t *frame = (md2_alias_frame_t *)(void *)buffer;
size_t j;
model->frames[i].vertices = calloc(sizeof (md2_triangleVertex_t), model->header.numVertices);
if (!model->frames[i].vertices || model->header.frameSize !=
fread(frame, 1, model->header.frameSize, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
strcpy(model->frames[i].name, frame->name);
for (j = 0; j < model->header.numVertices; j++)
{
model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0];
model->frames[i].vertices[j].vertex[2] = -1* ((float) ((INT32) frame->alias_vertices[j].vertex[1]) * frame->scale[1] + frame->translate[1]);
model->frames[i].vertices[j].vertex[1] = (float) ((INT32) frame->alias_vertices[j].vertex[2]) * frame->scale[2] + frame->translate[2];
model->frames[i].vertices[j].normal[0] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][0];
model->frames[i].vertices[j].normal[1] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][1];
model->frames[i].vertices[j].normal[2] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][2];
}
}
}
// read gl commands
fseek(file, model->header.offsetGlCommands, SEEK_SET);
if (model->header.numGlCommands)
{
model->glCommandBuffer = calloc(sizeof (INT32), model->header.numGlCommands);
if (!model->glCommandBuffer || model->header.numGlCommands !=
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
fclose(file);
return model;
if (FIL_FileExists(va("%s"PATHSEP"%s", srb2home, filename)))
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
else if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename)))
return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC);
return NULL;
}
static inline void md2_printModelInfo (md2_model_t *model)
static inline void md2_printModelInfo (model_t *model)
{
#if 0
INT32 i;
@ -498,13 +164,13 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
#endif
volatile png_FILE_p png_FILE;
//Filename checking fixed ~Monster Iestyn and Golden
char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
char *pngfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2home, filename);
FIL_ForceExtension(pngfilename, ".png");
png_FILE = fopen(pngfilename, "rb");
if (!png_FILE)
{
pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2path, filename);
pngfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2path, filename);
FIL_ForceExtension(pngfilename, ".png");
png_FILE = fopen(pngfilename, "rb");
//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
@ -631,13 +297,13 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
INT32 ch, rep;
FILE *file;
//Filename checking fixed ~Monster Iestyn and Golden
char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
char *pcxfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2home, filename);
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
if (!file)
{
pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2path, filename);
pcxfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2path, filename);
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
if (!file)
@ -826,16 +492,16 @@ void HWR_InitMD2(void)
md2_models[i].error = false;
}
// read the md2.dat file
// read the mdls.dat file
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt");
if (!f)
{
f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno));
nomd2s = true;
return;
}
@ -844,7 +510,7 @@ void HWR_InitMD2(void)
{
/*if (stricmp(name, "PLAY") == 0)
{
CONS_Printf("MD2 for sprite PLAY detected in kmd2.dat, use a player skin instead!\n");
CONS_Printf("MD2 for sprite PLAY detected in mdls.dat, use a player skin instead!\n");
continue;
}*/
// 8/1/19: Allow PLAY to load for default MD2.
@ -879,7 +545,7 @@ void HWR_InitMD2(void)
}
}
// no sprite/player skin name found?!?
CONS_Printf("Unknown sprite/player skin %s detected in kmd2.dat\n", name);
CONS_Printf("Unknown sprite/player skin %s detected in mdls.dat\n", name);
md2found:
// move on to next line...
continue;
@ -898,16 +564,16 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
CONS_Printf("AddPlayerMD2()...\n");
// read the md2.dat file
// read the mdls.dat file
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt");
if (!f)
{
f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno));
nomd2s = true;
return;
}
@ -937,7 +603,7 @@ playermd2found:
void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startup
{
FILE *f;
// name[18] is used to check for names in the kmd2.dat file that match with sprites or player skins
// name[18] is used to check for names in the mdls.dat file that match with sprites or player skins
// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
char name[18], filename[32];
float scale, offset;
@ -950,20 +616,20 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
// Read the md2.dat file
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt");
if (!f)
{
f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno));
nomd2s = true;
return;
}
}
// Check for any MD2s that match the names of player skins!
// Check for any MD2s that match the names of sprite names!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, sprnames[spritenum]) == 0)
@ -1195,12 +861,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
FSurfaceInfo Surf;
char filename[64];
INT32 frame;
INT32 frame = 0;
INT32 nextFrame = -1;
FTransform p;
md2_t *md2;
UINT8 color[4];
if (!cv_grmd2.value)
if (!cv_grmdls.value)
return;
if (spr->precip)
@ -1248,10 +915,9 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// Look at HWR_ProjectSprite for more
{
GLPatch_t *gpatch;
INT32 *buff;
INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics;
md2_frame_t *curr, *next = NULL;
//mdlframe_t *next = NULL;
const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP);
spritedef_t *sprdef;
spriteframe_t *sprframe;
@ -1285,13 +951,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
return; // we already failed loading this before :(
if (!md2->model)
{
CONS_Debug(DBG_RENDER, "Loading MD2... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename);
sprintf(filename, "md2/%s", md2->filename);
CONS_Debug(DBG_RENDER, "Loading model... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename);
sprintf(filename, "mdls/%s", md2->filename);
md2->model = md2_readModel(filename);
if (md2->model)
{
md2_printModelInfo(md2->model);
HWD.pfnCreateModelVBOs(md2->model);
}
else
{
@ -1364,27 +1031,27 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
}
//FIXME: this is not yet correct
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
buff = md2->model->glCommandBuffer;
curr = &md2->model->frames[frame];
#if 0
if (cv_grmd2.value == 1 && tics <= durs)
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
#ifdef USE_MODEL_NEXTFRAME
if (cv_grmdls.value == 1 && tics <= durs)
{
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
if (spr->mobj->frame & FF_ANIMATE)
{
UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextframe >= (UINT32)spr->mobj->state->var1)
nextframe = (spr->mobj->state->frame & FF_FRAMEMASK);
nextframe %= md2->model->header.numFrames;
next = &md2->model->frames[nextframe];
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= spr->mobj->state->var1)
nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK);
nextFrame %= md2->model->meshes[0].numFrames;
//next = &md2->model->meshes[0].frames[nextFrame];
}
else
{
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL)
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
{
const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
next = &md2->model->frames[nextframe];
nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
//next = &md2->model->meshes[0].frames[nextFrame];
}
}
}
@ -1421,6 +1088,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
p.angley = FIXED_TO_FLOAT(anglef);
}
p.anglex = 0.0f;
#ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
p.anglez = 0.0f;
if (spr->mobj->standingslope)
{
@ -1432,7 +1101,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));
p.anglex = FIXED_TO_FLOAT(tempangle);
}
#endif
color[0] = Surf.FlatColor.s.red;
color[1] = Surf.FlatColor.s.green;
@ -1443,9 +1112,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
p.flip = atransform.flip;
p.mirror = atransform.mirror;
#ifdef USE_FTRANSFORM_MIRROR
p.mirror = atransform.mirror; // from Kart
#endif
HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color);
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color);
}
}

View file

@ -22,97 +22,7 @@
#define _HW_MD2_H_
#include "hw_glob.h"
// magic number "IDP2" or 844121161
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
#define MD2_MAX_TRIANGLES 16384
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
#define MD2_MAX_FRAMES 512
#define MD2_MAX_SKINS 32
#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128)
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct
{
UINT32 magic;
UINT32 version;
UINT32 skinWidth;
UINT32 skinHeight;
UINT32 frameSize;
UINT32 numSkins;
UINT32 numVertices;
UINT32 numTexCoords;
UINT32 numTriangles;
UINT32 numGlCommands;
UINT32 numFrames;
UINT32 offsetSkins;
UINT32 offsetTexCoords;
UINT32 offsetTriangles;
UINT32 offsetFrames;
UINT32 offsetGlCommands;
UINT32 offsetEnd;
} ATTRPACK md2_header_t; //NOTE: each of md2_header's members are 4 unsigned bytes
typedef struct
{
UINT8 vertex[3];
UINT8 lightNormalIndex;
} ATTRPACK md2_alias_triangleVertex_t;
typedef struct
{
float vertex[3];
float normal[3];
} ATTRPACK md2_triangleVertex_t;
typedef struct
{
INT16 vertexIndices[3];
INT16 textureIndices[3];
} ATTRPACK md2_triangle_t;
typedef struct
{
INT16 s, t;
} ATTRPACK md2_textureCoordinate_t;
typedef struct
{
float scale[3];
float translate[3];
char name[16];
md2_alias_triangleVertex_t alias_vertices[1];
} ATTRPACK md2_alias_frame_t;
typedef struct
{
char name[16];
md2_triangleVertex_t *vertices;
} ATTRPACK md2_frame_t;
typedef char md2_skin_t[64];
typedef struct
{
float s, t;
INT32 vertexIndex;
} ATTRPACK md2_glCommandVertex_t;
typedef struct
{
md2_header_t header;
md2_skin_t *skins;
md2_textureCoordinate_t *texCoords;
md2_triangle_t *triangles;
md2_frame_t *frames;
INT32 *glCommandBuffer;
} ATTRPACK md2_model_t;
#include "hw_model.h"
#if defined(_MSC_VER)
#pragma pack()
@ -123,7 +33,7 @@ typedef struct
char filename[32];
float scale;
float offset;
md2_model_t *model;
model_t *model;
void *grpatch;
void *blendgrpatch;
boolean notfound;

564
src/hardware/hw_md2load.c Normal file
View file

@ -0,0 +1,564 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md2load.h"
#include "hw_model.h"
#include "../z_zone.h"
#define NUMVERTEXNORMALS 162
// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and
// you'll have your normals.
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
typedef struct
{
int ident; // A "magic number" that's used to identify the .md2 file
int version; // The version of the file, always 8
int skinwidth; // Width of the skin(s) in pixels
int skinheight; // Height of the skin(s) in pixels
int framesize; // Size of each frame in bytes
int numSkins; // Number of skins with the model
int numXYZ; // Number of vertices in each frame
int numST; // Number of texture coordinates in each frame.
int numTris; // Number of triangles in each frame
int numGLcmds; // Number of dwords (4 bytes) in the gl command list.
int numFrames; // Number of frames
int offsetSkins; // Offset, in bytes from the start of the file, to the list of skin names.
int offsetST; // Offset, in bytes from the start of the file, to the list of texture coordinates
int offsetTris; // Offset, in bytes from the start of the file, to the list of triangles
int offsetFrames; // Offset, in bytes from the start of the file, to the list of frames
int offsetGLcmds; // Offset, in bytes from the start of the file, to the list of gl commands
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md2header_t;
typedef struct
{
unsigned short meshIndex[3]; // indices into the array of vertices in each frames
unsigned short stIndex[3]; // indices into the array of texture coordinates
} md2triangle_t;
typedef struct
{
short s;
short t;
} md2texcoord_t;
typedef struct
{
unsigned char v[3]; // Scaled vertices. You'll need to multiply them with scale[x] to make them normal.
unsigned char lightNormalIndex; // Index to the array of normals
} md2vertex_t;
typedef struct
{
float scale[3]; // Used by the v member in the md2framePoint structure
float translate[3]; // Used by the v member in the md2framePoint structure
char name[16]; // Name of the frame
} md2frame_t;
// Load the model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
FILE *f;
model_t *retModel = NULL;
md2header_t *header;
size_t fileLen;
int i, j;
size_t namelen;
char *texturefilename;
const char *texPos;
char *buffer;
const float WUNITS = 1.0f;
float dataScale = WUNITS;
md2triangle_t *tris;
md2texcoord_t *texcoords;
md2frame_t *frames;
int t;
// MD2 currently does not work with tinyframes, so force useFloat = true
//
// <SSNTails>
// the UV coordinates in MD2 are not compatible with glDrawElements like MD3 is. So they need to be loaded as full float.
//
// MD2 is intended to be draw in triangle strips and fans
// not very compatible with a modern GL implementation, either
// so the idea would be to full float expand it, and put it in a vertex buffer object
// I'm sure there's a way to convert the UVs to 'tinyframes', but maybe that's a job for someone else.
// You'd have to decompress the model, then recompress, reindexing the triangles and weeding out duplicate coordinates
// I already have the decompression work done
useFloat = true;
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
//size_t fileLen;
//int i, j;
//size_t namelen;
//char *texturefilename;
texPos = strchr(fileName, '/');
if (texPos)
{
texPos++;
namelen = strlen(texPos) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, texPos);
}
else
{
namelen = strlen(fileName) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, fileName);
}
texturefilename[namelen - 2] = 'z';
texturefilename[namelen - 3] = 'u';
texturefilename[namelen - 4] = 'b';
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error
fclose(f);
// get pointer to file header
header = (md2header_t*)buffer;
retModel->numMeshes = 1; // MD2 only has one mesh
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, 0);
retModel->meshes[0].numFrames = header->numFrames;
// const float WUNITS = 1.0f;
// float dataScale = WUNITS;
// Tris and ST are simple structures that can be straight-copied
tris = (md2triangle_t*)&buffer[header->offsetTris];
texcoords = (md2texcoord_t*)&buffer[header->offsetST];
frames = (md2frame_t*)&buffer[header->offsetFrames];
// Read in textures
retModel->numMaterials = header->numSkins;
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
// int t;
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.8f;
retModel->materials[t].ambient[1] = 0.8f;
retModel->materials[t].ambient[2] = 0.8f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8f;
retModel->materials[t].diffuse[1] = 0.8f;
retModel->materials[t].diffuse[2] = 0.8f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.0f;
retModel->materials[t].specular[1] = 0.0f;
retModel->materials[t].specular[2] = 0.0f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 0.0f;
retModel->materials[t].spheremap = false;
/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, texturefilename);
size_t len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[0].numTriangles = header->numTris;
if (!useFloat) // Decompress to MD3 'tinyframe' space
{
char *ptr;
md2triangle_t *trisPtr;
unsigned short *indexptr;
float *uvptr;
dataScale = 0.015624f; // 1 / 64.0f
retModel->meshes[0].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].numVertices = header->numXYZ;
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
short *vertptr;
char *normptr;
// char *tanptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, 0);
retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag);
retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, 0);
vertptr = retModel->meshes[0].tinyframes[i].vertices;
normptr = retModel->meshes[0].tinyframes[i].normals;
// tanptr = retModel->meshes[0].tinyframes[i].tangents;
retModel->meshes[0].tinyframes[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numXYZ; j++, vertex++)
{
*vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale);
vertptr++;
*vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale);
vertptr++;
*vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale);
vertptr++;
// Normal
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127);
}
}
// This doesn't need to be done every frame!
trisPtr = tris;
indexptr = retModel->meshes[0].indices;
uvptr = (float*)retModel->meshes[0].uvs;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*indexptr = trisPtr->meshIndex[0];
indexptr++;
*indexptr = trisPtr->meshIndex[1];
indexptr++;
*indexptr = trisPtr->meshIndex[2];
indexptr++;
uvptr[trisPtr->meshIndex[0] * 2] = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[0] * 2 + 1] = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[1] * 2] = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[1] * 2 + 1] = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[2] * 2] = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[2] * 2 + 1] = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
}
else // Full float loading method
{
md2triangle_t *trisPtr;
float *uvptr;
char *ptr;
retModel->meshes[0].numVertices = header->numTris * 3;
retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
trisPtr = tris;
uvptr = retModel->meshes[0].uvs;
for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++)
{
*uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
float *vertptr, *normptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag);
//float *vertptr, *normptr;
normptr = (float*)retModel->meshes[0].frames[i].normals;
vertptr = (float*)retModel->meshes[0].frames[i].vertices;
trisPtr = tris;
retModel->meshes[0].frames[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[0]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[1]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[2]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1];
}
}
}
free(buffer);
return retModel;
}

19
src/hardware/hw_md2load.h Normal file
View file

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD2LOAD_H_
#define _HW_MD2LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

510
src/hardware/hw_md3load.c Normal file
View file

@ -0,0 +1,510 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md3load.h"
#include "hw_model.h"
#include "../z_zone.h"
typedef struct
{
int ident; // A "magic number" that's used to identify the .md3 file
int version; // The version of the file, always 15
char name[64];
int flags;
int numFrames; // Number of frames
int numTags;
int numSurfaces;
int numSkins; // Number of skins with the model
int offsetFrames;
int offsetTags;
int offsetSurfaces;
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md3modelHeader;
typedef struct
{
float minBounds[3]; // First corner of the bounding box
float maxBounds[3]; // Second corner of the bounding box
float localOrigin[3]; // Local origin, usually (0, 0, 0)
float radius; // Radius of bounding sphere
char name[16]; // Name of frame
} md3Frame;
typedef struct
{
char name[64]; // Name of tag
float origin[3]; // Coordinates of tag
float axis[9]; // Orientation of tag object
} md3Tag;
typedef struct
{
int ident;
char name[64]; // Name of this surface
int flags;
int numFrames; // # of keyframes
int numShaders; // # of shaders
int numVerts; // # of vertices
int numTriangles; // # of triangles
int offsetTriangles; // Relative offset from start of this struct to where the list of Triangles start
int offsetShaders; // Relative offset from start of this struct to where the list of Shaders start
int offsetST; // Relative offset from start of this struct to where the list of tex coords start
int offsetXYZNormal; // Relative offset from start of this struct to where the list of vertices start
int offsetEnd; // Relative offset from start of this struct to where this surface ends
} md3Surface;
typedef struct
{
char name[64]; // Name of this shader
int shaderIndex; // Shader index number
} md3Shader;
typedef struct
{
int index[3]; // List of offset values into the list of Vertex objects that constitute the corners of the Triangle object.
} md3Triangle;
typedef struct
{
float st[2];
} md3TexCoord;
typedef struct
{
short x, y, z, n;
} md3Vertex;
static float latlnglookup[256][256][3];
static void GetNormalFromLatLong(short latlng, float *out)
{
float *lookup = latlnglookup[(unsigned char)(latlng >> 8)][(unsigned char)(latlng & 255)];
out[0] = *lookup++;
out[1] = *lookup++;
out[2] = *lookup++;
}
#if 0
static void NormalToLatLng(float *n, short *out)
{
// Special cases
if (0.0f == n[0] && 0.0f == n[1])
{
if (n[2] > 0.0f)
*out = 0;
else
*out = 128;
}
else
{
char x, y;
x = (char)(57.2957795f * (atan2(n[1], n[0])) * (255.0f / 360.0f));
y = (char)(57.2957795f * (acos(n[2])) * (255.0f / 360.0f));
*out = (x << 8) + y;
}
}
#endif
static inline void LatLngToNormal(short n, float *out)
{
const float PI = (3.1415926535897932384626433832795f);
float lat = (float)(n >> 8);
float lng = (float)(n & 255);
lat *= PI / 128.0f;
lng *= PI / 128.0f;
out[0] = cosf(lat) * sinf(lng);
out[1] = sinf(lat) * sinf(lng);
out[2] = cosf(lng);
}
static void LatLngInit(void)
{
int i, j;
for (i = 0; i < 256; i++)
{
for (j = 0; j < 256; j++)
LatLngToNormal((short)((i << 8) + j), latlnglookup[i][j]);
}
}
static boolean latlnginit = false;
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
const float WUNITS = 1.0f;
model_t *retModel = NULL;
md3modelHeader *mdh;
long fileLen;
long fileReadLen;
char *buffer;
int surfEnd;
int i, t;
int matCount;
FILE *f;
if (!latlnginit)
{
LatLngInit();
latlnginit = true;
}
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
fileReadLen = fread(buffer, fileLen, 1, f);
fclose(f);
(void)fileReadLen; // intentionally ignore return value, per buildbot
// get pointer to file header
mdh = (md3modelHeader*)buffer;
retModel->numMeshes = mdh->numSurfaces;
retModel->numMaterials = 0;
surfEnd = 0;
for (i = 0; i < mdh->numSurfaces; i++)
{
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces];
surfEnd += mdS->offsetEnd;
retModel->numMaterials += mdS->numShaders;
}
// Initialize materials
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.3686f;
retModel->materials[t].ambient[1] = 0.3684f;
retModel->materials[t].ambient[2] = 0.3684f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8863f;
retModel->materials[t].diffuse[1] = 0.8850f;
retModel->materials[t].diffuse[2] = 0.8850f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.4902f;
retModel->materials[t].specular[1] = 0.4887f;
retModel->materials[t].specular[2] = 0.4887f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 25.0f;
retModel->materials[t].spheremap = false;
}
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0);
matCount = 0;
for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++)
{
int j;
md3Shader *mdShader;
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd];
surfEnd += mdS->offsetEnd;
mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders);
for (j = 0; j < mdS->numShaders; j++, matCount++)
{
size_t len = strlen(mdShader[j].name);
mdShader[j].name[len-1] = 'z';
mdShader[j].name[len-2] = 'u';
mdShader[j].name[len-3] = 'b';
// Load material
/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, mdShader[j].name);
len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[i].numFrames = mdS->numFrames;
retModel->meshes[i].numTriangles = mdS->numTriangles;
if (!useFloat) // 'tinyframe' mode with indices
{
float tempNormal[3];
float *uvptr;
md3TexCoord *mdST;
unsigned short *indexptr;
md3Triangle *mdT;
retModel->meshes[i].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].numVertices = mdS->numVerts;
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numVerts, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
short *vertptr;
char *normptr;
// char *tanptr;
int k;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, 0);
retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag);
retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, 0);
vertptr = retModel->meshes[i].tinyframes[j].vertices;
normptr = retModel->meshes[i].tinyframes[j].normals;
// tanptr = retModel->meshes[i].tinyframes[j].tangents;
retModel->meshes[i].tinyframes[j].material = &retModel->materials[i];
for (k = 0; k < mdS->numVerts; k++)
{
// Vertex
*vertptr = mdV[k].x;
vertptr++;
*vertptr = mdV[k].z;
vertptr++;
*vertptr = 1.0f - mdV[k].y;
vertptr++;
// Normal
GetNormalFromLatLong(mdV[k].n, tempNormal);
*normptr = (char)(tempNormal[0] * 127);
normptr++;
*normptr = (char)(tempNormal[2] * 127);
normptr++;
*normptr = (char)(tempNormal[1] * 127);
normptr++;
}
}
uvptr = (float*)retModel->meshes[i].uvs;
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
for (j = 0; j < mdS->numVerts; j++)
{
*uvptr = mdST[j].st[0];
uvptr++;
*uvptr = mdST[j].st[1];
uvptr++;
}
indexptr = retModel->meshes[i].indices;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (j = 0; j < mdS->numTriangles; j++, mdT++)
{
// Indices
*indexptr = (unsigned short)mdT->index[0];
indexptr++;
*indexptr = (unsigned short)mdT->index[1];
indexptr++;
*indexptr = (unsigned short)mdT->index[2];
indexptr++;
}
}
else // Traditional full-float loading method
{
float dataScale = 0.015624f * WUNITS;
float tempNormal[3];
md3TexCoord *mdST;
md3Triangle *mdT;
float *uvptr;
int k;
retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts;
retModel->meshes[i].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numTriangles*3, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
float *vertptr;
float *normptr;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
// if (retModel->materials[i].lightmap)
// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag);
vertptr = retModel->meshes[i].frames[j].vertices;
normptr = retModel->meshes[i].frames[j].normals;
retModel->meshes[i].frames[j].material = &retModel->materials[i];
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
// Vertex 1
*vertptr = mdV[mdT->index[0]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[0]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 2
*vertptr = mdV[mdT->index[1]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[1]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 3
*vertptr = mdV[mdT->index[2]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[2]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[2]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
mdT++; // Advance to next triangle
}
}
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
uvptr = (float*)retModel->meshes[i].uvs;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
*uvptr = mdST[mdT->index[0]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[0]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[1];
uvptr++;
mdT++; // Advance to next triangle
}
}
}
/*
// Tags?
retModel->numTags = mdh->numTags;
retModel->maxNumFrames = mdh->numFrames;
retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag);
md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags];
tag_t *curTag = retModel->tags;
for (i = 0; i < mdh->numFrames; i++)
{
int j;
for (j = 0; j < retModel->numTags; j++, mdTag++)
{
strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char));
curTag->transform.m[0][0] = mdTag->axis[0];
curTag->transform.m[0][1] = mdTag->axis[1];
curTag->transform.m[0][2] = mdTag->axis[2];
curTag->transform.m[1][0] = mdTag->axis[3];
curTag->transform.m[1][1] = mdTag->axis[4];
curTag->transform.m[1][2] = mdTag->axis[5];
curTag->transform.m[2][0] = mdTag->axis[6];
curTag->transform.m[2][1] = mdTag->axis[7];
curTag->transform.m[2][2] = mdTag->axis[8];
curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS;
curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS;
curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS;
curTag->transform.m[3][3] = 1.0f;
Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis);
curTag++;
}
}*/
free(buffer);
return retModel;
}

19
src/hardware/hw_md3load.h Normal file
View file

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD3LOAD_H_
#define _HW_MD3LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

593
src/hardware/hw_model.c Normal file
View file

@ -0,0 +1,593 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "../z_zone.h"
#include "../doomdef.h"
#include "hw_model.h"
#include "hw_md2load.h"
#include "hw_md3load.h"
#include "u_list.h"
#include <string.h>
static float PI = (3.1415926535897932384626433832795f);
static float U_Deg2Rad(float deg)
{
return deg * ((float)PI / 180.0f);
}
vector_t vectorXaxis = { 1.0f, 0.0f, 0.0f };
vector_t vectorYaxis = { 0.0f, 1.0f, 0.0f };
vector_t vectorZaxis = { 0.0f, 0.0f, 1.0f };
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle)
{
float ux, uy, uz, vx, vy, vz, wx, wy, wz, sa, ca;
angle = U_Deg2Rad(angle);
// Rotate the point (x,y,z) around the vector (u,v,w)
ux = axisVec->x * rotVec->x;
uy = axisVec->x * rotVec->y;
uz = axisVec->x * rotVec->z;
vx = axisVec->y * rotVec->x;
vy = axisVec->y * rotVec->y;
vz = axisVec->y * rotVec->z;
wx = axisVec->z * rotVec->x;
wy = axisVec->z * rotVec->y;
wz = axisVec->z * rotVec->z;
sa = sinf(angle);
ca = cosf(angle);
rotVec->x = axisVec->x*(ux + vy + wz) + (rotVec->x*(axisVec->y*axisVec->y + axisVec->z*axisVec->z) - axisVec->x*(vy + wz))*ca + (-wy + vz)*sa;
rotVec->y = axisVec->y*(ux + vy + wz) + (rotVec->y*(axisVec->x*axisVec->x + axisVec->z*axisVec->z) - axisVec->y*(ux + wz))*ca + (wx - uz)*sa;
rotVec->z = axisVec->z*(ux + vy + wz) + (rotVec->z*(axisVec->x*axisVec->x + axisVec->y*axisVec->y) - axisVec->z*(ux + vy))*ca + (-vx + uy)*sa;
}
void UnloadModel(model_t *model)
{
// Wouldn't it be great if C just had destructors?
int i;
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->frames[j].normals)
Z_Free(mesh->frames[j].normals);
if (mesh->frames[j].tangents)
Z_Free(mesh->frames[j].tangents);
if (mesh->frames[j].vertices)
Z_Free(mesh->frames[j].vertices);
if (mesh->frames[j].colors)
Z_Free(mesh->frames[j].colors);
}
Z_Free(mesh->frames);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->tinyframes[j].normals)
Z_Free(mesh->tinyframes[j].normals);
if (mesh->tinyframes[j].tangents)
Z_Free(mesh->tinyframes[j].tangents);
if (mesh->tinyframes[j].vertices)
Z_Free(mesh->tinyframes[j].vertices);
}
if (mesh->indices)
Z_Free(mesh->indices);
Z_Free(mesh->tinyframes);
}
if (mesh->uvs)
Z_Free(mesh->uvs);
if (mesh->lightuvs)
Z_Free(mesh->lightuvs);
}
if (model->meshes)
Z_Free(model->meshes);
if (model->tags)
Z_Free(model->tags);
if (model->materials)
Z_Free(model->materials);
DeleteVBOs(model);
Z_Free(model);
}
tag_t *GetTagByName(model_t *model, char *name, int frame)
{
if (frame < model->maxNumFrames)
{
tag_t *iterator = &model->tags[frame * model->numTags];
int i;
for (i = 0; i < model->numTags; i++)
{
if (!stricmp(iterator[i].name, name))
return &iterator[i];
}
}
return NULL;
}
//
// LoadModel
//
// Load a model and
// convert it to the
// internal format.
//
model_t *LoadModel(const char *filename, int ztag)
{
model_t *model;
// What type of file?
const char *extension = NULL;
int i;
for (i = (int)strlen(filename)-1; i >= 0; i--)
{
if (filename[i] != '.')
continue;
extension = &filename[i];
break;
}
if (!extension)
{
CONS_Printf("Model %s is lacking a file extension, unable to determine type!\n", filename);
return NULL;
}
if (!strcmp(extension, ".md3"))
{
if (!(model = MD3_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats
{
if (!(model = MD3_LoadModel(filename, ztag, true)))
return NULL;
}
else if (!strcmp(extension, ".md2"))
{
if (!(model = MD2_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md2s"))
{
if (!(model = MD2_LoadModel(filename, ztag, true)))
return NULL;
}
else
{
CONS_Printf("Unknown model format: %s\n", extension);
return NULL;
}
model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0);
strcpy(model->mdlFilename, filename);
Optimize(model);
GeneratePolygonNormals(model, ztag);
// Default material properties
for (i = 0 ; i < model->numMaterials; i++)
{
material_t *material = &model->materials[i];
material->ambient[0] = 0.7686f;
material->ambient[1] = 0.7686f;
material->ambient[2] = 0.7686f;
material->ambient[3] = 1.0f;
material->diffuse[0] = 0.5863f;
material->diffuse[1] = 0.5863f;
material->diffuse[2] = 0.5863f;
material->diffuse[3] = 1.0f;
material->specular[0] = 0.4902f;
material->specular[1] = 0.4902f;
material->specular[2] = 0.4902f;
material->specular[3] = 1.0f;
material->shininess = 25.0f;
}
return model;
}
//
// GenerateVertexNormals
//
// Creates a new normal for a vertex using the average of all of the polygons it belongs to.
//
void GenerateVertexNormals(model_t *model)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
int memTag = PU_STATIC;
float *newNormals = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag, 0);
int k;
float *vertPtr = frame->vertices;
float *oldNormals;
M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3);
/* if (!systemSucks)
{
memTag = Z_GetTag(frame->tangents);
float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag);
M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3);
}*/
for (k = 0; k < mesh->numVertices; k++)
{
float x, y, z;
int vCount = 0;
vector_t normal;
int l;
float *testPtr = frame->vertices;
x = *vertPtr++;
y = *vertPtr++;
z = *vertPtr++;
normal.x = normal.y = normal.z = 0;
for (l = 0; l < mesh->numVertices; l++)
{
float testX, testY, testZ;
testX = *testPtr++;
testY = *testPtr++;
testZ = *testPtr++;
if (fabsf(x - testX) > FLT_EPSILON
|| fabsf(y - testY) > FLT_EPSILON
|| fabsf(z - testZ) > FLT_EPSILON)
continue;
// Found a vertex match! Add it...
normal.x += frame->normals[3 * l + 0];
normal.y += frame->normals[3 * l + 1];
normal.z += frame->normals[3 * l + 2];
vCount++;
}
if (vCount > 1)
{
// Vector::Normalize(&normal);
newNormals[3 * k + 0] = (float)normal.x;
newNormals[3 * k + 1] = (float)normal.y;
newNormals[3 * k + 2] = (float)normal.z;
/* if (!systemSucks)
{
Vector::vector_t tangent;
Vector::Tangent(&normal, &tangent);
newTangents[3 * k + 0] = tangent.x;
newTangents[3 * k + 1] = tangent.y;
newTangents[3 * k + 2] = tangent.z;
}*/
}
}
oldNormals = frame->normals;
frame->normals = newNormals;
Z_Free(oldNormals);
/* if (!systemSucks)
{
float *oldTangents = frame->tangents;
frame->tangents = newTangents;
Z_Free(oldTangents);
}*/
}
}
}
typedef struct materiallist_s
{
struct materiallist_s *next;
struct materiallist_s *prev;
material_t *material;
} materiallist_t;
static boolean AddMaterialToList(materiallist_t **head, material_t *material)
{
materiallist_t *node, *newMatNode;
for (node = *head; node; node = node->next)
{
if (node->material == material)
return false;
}
// Didn't find it, so add to the list
newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0);
newMatNode->material = material;
ListAdd(newMatNode, (listitem_t**)head);
return true;
}
//
// Optimize
//
// Groups triangles from meshes in the model
// Only works for models with 1 frame
//
void Optimize(model_t *model)
{
int numMeshes = 0;
int i;
materiallist_t *matListHead = NULL;
int memTag;
mesh_t *newMeshes;
materiallist_t *node;
if (model->numMeshes <= 1)
return; // No need
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *curMesh = &model->meshes[i];
if (curMesh->numFrames > 1)
return; // Can't optimize models with > 1 frame
if (!curMesh->frames)
return; // Don't optimize tinyframe models (no need)
// We are condensing to 1 mesh per material, so
// the # of materials we use will be the new
// # of meshes
if (AddMaterialToList(&matListHead, curMesh->frames[0].material))
numMeshes++;
}
memTag = PU_STATIC;
newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0);
i = 0;
for (node = matListHead; node; node = node->next)
{
material_t *curMat = node->material;
mesh_t *newMesh = &newMeshes[i];
mdlframe_t *curFrame;
int uvCount;
int vertCount;
int colorCount;
// Find all triangles with this material and count them
int numTriangles = 0;
int j;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
numTriangles += curMesh->numTriangles;
}
newMesh->numFrames = 1;
newMesh->numTriangles = numTriangles;
newMesh->numVertices = numTriangles * 3;
newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
// if (node->material->lightmap)
// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0);
curFrame = &newMesh->frames[0];
curFrame->material = curMat;
curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
// if (!systemSucks)
// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0);
// Now traverse the meshes of the model, adding in
// vertices/normals/uvs that match the current material
uvCount = 0;
vertCount = 0;
colorCount = 0;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
{
float *dest;
float *src;
char *destByte;
char *srcByte;
M_Memcpy(&newMesh->uvs[uvCount],
curMesh->uvs,
sizeof(float)*2*curMesh->numTriangles*3);
/* if (node->material->lightmap)
{
M_Memcpy(&newMesh->lightuvs[uvCount],
curMesh->lightuvs,
sizeof(float)*2*curMesh->numTriangles*3);
}*/
uvCount += 2*curMesh->numTriangles*3;
dest = (float*)newMesh->frames[0].vertices;
src = (float*)curMesh->frames[0].vertices;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
dest = (float*)newMesh->frames[0].normals;
src = (float*)curMesh->frames[0].normals;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
/* if (!systemSucks)
{
dest = (float*)newMesh->frames[0].tangents;
src = (float*)curMesh->frames[0].tangents;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
}*/
vertCount += 3 * curMesh->numTriangles * 3;
destByte = (char*)newMesh->frames[0].colors;
srcByte = (char*)curMesh->frames[0].colors;
if (srcByte)
{
M_Memcpy(&destByte[colorCount],
srcByte,
sizeof(char)*4*curMesh->numTriangles*3);
}
else
{
memset(&destByte[colorCount],
255,
sizeof(char)*4*curMesh->numTriangles*3);
}
colorCount += 4 * curMesh->numTriangles * 3;
}
}
i++;
}
CONS_Printf("Model::Optimize(): Model reduced from %d to %d meshes.\n", model->numMeshes, numMeshes);
model->meshes = newMeshes;
model->numMeshes = numMeshes;
}
void GeneratePolygonNormals(model_t *model, int ztag)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
int k;
mdlframe_t *frame = &mesh->frames[j];
const float *vertices = frame->vertices;
vector_t *polyNormals;
frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0);
polyNormals = frame->polyNormals;
for (k = 0; k < mesh->numTriangles; k++)
{
// Vector::Normal(vertices, polyNormals);
vertices += 3 * 3;
polyNormals++;
}
}
}
}
//
// Reload
//
// Reload VBOs
//
#if 0
static void Reload(void)
{
/* model_t *node;
for (node = modelHead; node; node = node->next)
{
int i;
for (i = 0; i < node->numMeshes; i++)
{
mesh_t *mesh = &node->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->frames[j]);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->tinyframes[j]);
}
}
}*/
}
#endif
void DeleteVBOs(model_t *model)
{
(void)model;
/* for (int i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
for (int j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
else if (mesh->tinyframes)
{
for (int j = 0; j < mesh->numFrames; j++)
{
tinyframe_t *frame = &mesh->tinyframes[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
}*/
}

104
src/hardware/hw_model.h Normal file
View file

@ -0,0 +1,104 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MODEL_H_
#define _HW_MODEL_H_
#include "../doomtype.h"
typedef struct
{
float x, y, z;
} vector_t;
extern vector_t vectorXaxis;
extern vector_t vectorYaxis;
extern vector_t vectorZaxis;
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle);
typedef struct
{
float ambient[4], diffuse[4], specular[4], emissive[4];
float shininess;
boolean spheremap;
// Texture::texture_t *texture;
// Texture::texture_t *lightmap;
} material_t;
typedef struct
{
material_t *material; // Pointer to the allocated 'materials' list in model_t
float *vertices;
float *normals;
float *tangents;
char *colors;
unsigned int vboID;
vector_t *polyNormals;
} mdlframe_t;
typedef struct
{
material_t *material;
short *vertices;
char *normals;
char *tangents;
unsigned int vboID;
} tinyframe_t;
// Equivalent to MD3's many 'surfaces'
typedef struct mesh_s
{
int numVertices;
int numTriangles;
float *uvs;
float *lightuvs;
int numFrames;
mdlframe_t *frames;
tinyframe_t *tinyframes;
unsigned short *indices;
} mesh_t;
typedef struct tag_s
{
char name[64];
// matrix_t transform;
} tag_t;
typedef struct model_s
{
int maxNumFrames;
int numMaterials;
material_t *materials;
int numMeshes;
mesh_t *meshes;
int numTags;
tag_t *tags;
char *mdlFilename;
boolean unloaded;
} model_t;
extern int numModels;
extern model_t *modelHead;
tag_t *GetTagByName(model_t *model, char *name, int frame);
model_t *LoadModel(const char *filename, int ztag);
void UnloadModel(model_t *model);
void Optimize(model_t *model);
void GenerateVertexNormals(model_t *model);
void GeneratePolygonNormals(model_t *model, int ztag);
void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
void CreateVBO(mesh_t *mesh, mdlframe_t *frame);
void DeleteVBOs(model_t *model);
#endif

View file

@ -347,13 +347,6 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
DBG_Printf("oglflags : 0x%X\n", oglflags);
#ifdef USE_PALETTED_TEXTURE
if (isExtAvailable("GL_EXT_paletted_texture",gl_extensions))
glColorTableEXT = GetGLFunc("glColorTableEXT");
else
glColorTableEXT = NULL;
#endif
#ifdef USE_WGL_SWAP
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
wglSwapIntervalEXT = GetGLFunc("wglSwapIntervalEXT");
@ -582,19 +575,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *pal, RGBA_t *gamma)
myPaletteData[i].s.blue = (UINT8)MIN((pal[i].s.blue*gamma->s.blue)/127, 255);
myPaletteData[i].s.alpha = pal[i].s.alpha;
}
#ifdef USE_PALETTED_TEXTURE
if (glColorTableEXT)
{
for (i = 0; i < 256; i++)
{
palette_tex[3*i+0] = pal[i].s.red;
palette_tex[3*i+1] = pal[i].s.green;
palette_tex[3*i+2] = pal[i].s.blue;
}
glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex);
}
#endif
// on a chang<6E> de palette, il faut recharger toutes les textures
// on a palette change, you have to reload all of the textures
Flush();
}

File diff suppressed because it is too large Load diff

View file

@ -37,13 +37,11 @@
#include <GL/gl.h>
#include <GL/glu.h>
#ifndef MINI_GL_COMPATIBILITY
#ifdef STATIC_OPENGL // Because of the 1.3 functions, you'll need GLext to compile it if static
#define GL_GLEXT_PROTOTYPES
#include <GL/glext.h>
#endif
#endif
#endif
#define _CREATE_DLL_ // necessary for Unix AND Windows
#include "../../doomdef.h"
@ -73,7 +71,6 @@ extern FILE *gllogstream;
#endif
#ifndef DRIVER_STRING
// #define USE_PALETTED_TEXTURE
#define DRIVER_STRING "HWRAPI Init(): SRB2Kart OpenGL renderer" // Tails
#endif
@ -91,10 +88,6 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
void SetModelView(GLint w, GLint h);
void SetStates(void);
FUNCMATH float byteasfloat(UINT8 fbyte);
#ifdef USE_PALETTED_TEXTURE
extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
extern GLubyte palette_tex[256*3];
#endif
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
@ -120,6 +113,10 @@ typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params);
extern PFNglGetIntegerv pglGetIntegerv;
typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name);
extern PFNglGetString pglGetString;
#if 0
typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c
static PFNglEnableClientState pglEnableClientState;
#endif
#endif
// ==========================================================================

View file

@ -0,0 +1,52 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _R_VBO_H_
#define _R_VBO_H_
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
} vbo32_t;
typedef struct
{
float x, y, z; // Vertex
float s0, t0; // Texcoord0
unsigned char r, g, b, a; // Color
float pad[2]; // Pad
} vbo2d32_t;
typedef struct
{
float x, y; // Vertex
float s0, t0; // Texcoord0
} vbofont_t;
typedef struct
{
short x, y, z; // Vertex
char nx, ny, nz; // Normal
char tanx, tany, tanz; // Tangent
float s0, t0; // Texcoord0
} vbotiny_t;
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
float s1, t1; // Texcoord1
float s2, t2; // Texcoord2
float tan0, tan1, tan2; // Tangent
unsigned char r, g, b, a; // Color
} vbo64_t;
#endif

230
src/hardware/u_list.c Normal file
View file

@ -0,0 +1,230 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "u_list.h"
#include "../z_zone.h"
// Utility for managing
// structures in a linked
// list.
//
// Struct must have "next" and "prev" pointers
// as its first two variables.
//
//
// ListAdd
//
// Adds an item to the list
//
void ListAdd(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
listitem_t *tail;
tail = *itemHead;
while (tail->next != NULL)
tail = tail->next;
tail->next = item;
tail->next->prev = tail;
item->next = NULL;
}
}
//
// ListAddFront
//
// Adds an item to the front of the list
// (This is much faster)
//
void ListAddFront(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
(*itemHead)->prev = item;
item->next = (*itemHead);
item->prev = NULL;
*itemHead = item;
}
}
//
// ListAddBefore
//
// Adds an item before the item specified in the list
//
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *prev = spot->prev;
if (!prev)
ListAddFront(pItem, itemHead);
else
{
item->next = spot;
spot->prev = item;
item->prev = prev;
prev->next = item;
}
}
//
// ListAddAfter
//
// Adds an item after the item specified in the list
//
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *next = spot->next;
if (!next)
ListAdd(pItem, itemHead);
else
{
item->prev = spot;
spot->next = item;
item->next = next;
next->prev = item;
}
}
//
// ListRemove
//
// Take an item out of the list and free its memory.
//
void ListRemove(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
Z_Free (item);
}
//
// ListRemoveAll
//
// Removes all items from the list, freeing their memory.
//
void ListRemoveAll(listitem_t **itemHead)
{
listitem_t *item;
listitem_t *next;
for (item = *itemHead; item; item = next)
{
next = item->next;
ListRemove(item, itemHead);
}
}
//
// ListRemoveNoFree
//
// Take an item out of the list, but don't free its memory.
//
void ListRemoveNoFree(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
}
//
// ListGetCount
//
// Counts the # of items in a list
// Should not be used in performance-minded code
//
unsigned int ListGetCount(void *itemHead)
{
listitem_t *item = (listitem_t*)itemHead;
unsigned int count = 0;
for (; item; item = item->next)
count++;
return count;
}
//
// ListGetByIndex
//
// Gets an item in the list by its index
// Should not be used in performance-minded code
//
listitem_t *ListGetByIndex(void *itemHead, unsigned int index)
{
listitem_t *head = (listitem_t*)itemHead;
unsigned int count = 0;
listitem_t *node;
for (node = head; node; node = node->next)
{
if (count == index)
return node;
count++;
}
return NULL;
}

29
src/hardware/u_list.h Normal file
View file

@ -0,0 +1,29 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _U_LIST_H_
#define _U_LIST_H_
typedef struct listitem_s
{
struct listitem_s *next;
struct listitem_s *prev;
} listitem_t;
void ListAdd(void *pItem, listitem_t **itemHead);
void ListAddFront(void *pItem, listitem_t **itemHead);
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead);
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead);
void ListRemove(void *pItem, listitem_t **itemHead);
void ListRemoveAll(listitem_t **itemHead);
void ListRemoveNoFree(void *pItem, listitem_t **itemHead);
unsigned int ListGetCount(void *itemHead);
listitem_t *ListGetByIndex(void *itemHead, unsigned int index);
#endif

View file

@ -39,7 +39,7 @@
#include "am_map.h"
#include "d_main.h"
#include "p_local.h" // camera, camera2, camera3, camera4
#include "p_local.h" // camera[]
#include "p_tick.h"
#ifdef HWRENDER
@ -793,14 +793,17 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
case SKINCOLOR_GREY:
case SKINCOLOR_NICKEL:
case SKINCOLOR_BLACK:
case SKINCOLOR_SKUNK:
case SKINCOLOR_JET:
cstart = "\x86"; // V_GRAYMAP
break;
case SKINCOLOR_SEPIA:
case SKINCOLOR_BEIGE:
case SKINCOLOR_WALNUT:
case SKINCOLOR_BROWN:
case SKINCOLOR_LEATHER:
case SKINCOLOR_RUST:
case SKINCOLOR_WRISTWATCH:
cstart = "\x8e"; // V_BROWNMAP
break;
case SKINCOLOR_FAIRY:
@ -808,10 +811,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
case SKINCOLOR_PINK:
case SKINCOLOR_ROSE:
case SKINCOLOR_BRICK:
case SKINCOLOR_LEMONADE:
case SKINCOLOR_BUBBLEGUM:
case SKINCOLOR_LILAC:
cstart = "\x8d"; // V_PINKMAP
break;
case SKINCOLOR_CINNAMON:
case SKINCOLOR_RUBY:
case SKINCOLOR_RASPBERRY:
case SKINCOLOR_CHERRY:
@ -842,14 +847,18 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
case SKINCOLOR_ROYAL:
case SKINCOLOR_BRONZE:
case SKINCOLOR_COPPER:
case SKINCOLOR_THUNDER:
cstart = "\x8A"; // V_GOLDMAP
break;
case SKINCOLOR_POPCORN:
case SKINCOLOR_QUARRY:
case SKINCOLOR_YELLOW:
case SKINCOLOR_MUSTARD:
case SKINCOLOR_CROCODILE:
case SKINCOLOR_OLIVE:
cstart = "\x82"; // V_YELLOWMAP
break;
case SKINCOLOR_ARTICHOKE:
case SKINCOLOR_VOMIT:
case SKINCOLOR_GARDEN:
case SKINCOLOR_TEA:
@ -872,6 +881,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
cstart = "\x83"; // V_GREENMAP
break;
case SKINCOLOR_CARIBBEAN:
case SKINCOLOR_AZURE:
case SKINCOLOR_AQUA:
case SKINCOLOR_TEAL:
case SKINCOLOR_CYAN:
@ -881,6 +891,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
case SKINCOLOR_SAPPHIRE:
cstart = "\x88"; // V_SKYMAP
break;
case SKINCOLOR_PIGEON:
case SKINCOLOR_PLATINUM:
case SKINCOLOR_STEEL:
cstart = "\x8c"; // V_STEELMAP
@ -1987,7 +1998,7 @@ static void HU_DrawChat_Old(void)
if (!i)
return;
if ((netgame || multiplayer) && players[displayplayer].spectator)
if ((netgame || multiplayer) && players[displayplayers[0]].spectator)
return;
#ifdef HWRENDER
@ -2014,7 +2025,7 @@ static inline void HU_DrawCrosshair2(void)
if (!i)
return;
if ((netgame || multiplayer) && players[secondarydisplayplayer].spectator)
if ((netgame || multiplayer) && players[displayplayers[1]].spectator)
return;
#ifdef HWRENDER
@ -2061,7 +2072,7 @@ static inline void HU_DrawCrosshair3(void)
if (!i)
return;
if ((netgame || multiplayer) && players[thirddisplayplayer].spectator)
if ((netgame || multiplayer) && players[displayplayers[2]].spectator)
return;
#ifdef HWRENDER
@ -2098,7 +2109,7 @@ static inline void HU_DrawCrosshair4(void)
if (!i)
return;
if ((netgame || multiplayer) && players[fourthdisplayplayer].spectator)
if ((netgame || multiplayer) && players[displayplayers[3]].spectator)
return;
#ifdef HWRENDER
@ -2199,8 +2210,16 @@ UINT32 hu_demolap;
static void HU_DrawDemoInfo(void)
{
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Replay:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[0]);
if (!multiplayer)/* netreplay */
{
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Replay:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[0]);
}
else
{
V_DrawRightAlignedThinString(BASEVIDWIDTH-2, BASEVIDHEIGHT-10, V_ALLOWLOWERCASE, demo.titlename);
}
if (modeattacking)
{
V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:");
@ -2227,7 +2246,7 @@ static void HU_DrawDemoInfo(void)
//
// Song credits
//
static void HU_DrawSongCredits(void)
void HU_DrawSongCredits(void)
{
char *str;
INT32 len, destx;
@ -2273,6 +2292,9 @@ static void HU_DrawSongCredits(void)
//
void HU_Drawer(void)
{
if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1)))
V_DrawVhsEffect(demo.rewinding);
#ifndef NONET
// draw chat string plus cursor
if (chat_on)
@ -2318,10 +2340,7 @@ void HU_Drawer(void)
if (cechotimer)
HU_DrawCEcho();
if (demoplayback && hu_showscores)
HU_DrawDemoInfo();
if (!Playing()
if (!( Playing() || demo.playback )
|| gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION
|| gamestate == GS_GAMEEND
@ -2341,24 +2360,28 @@ void HU_Drawer(void)
LUAh_ScoresHUD();
#endif
}
if (demo.playback)
{
HU_DrawDemoInfo();
}
}
if (gamestate != GS_LEVEL)
return;
// draw the crosshair, not when viewing demos nor with chasecam
/*if (!automapactive && !demoplayback)
/*if (!automapactive && !demo.playback)
{
if (cv_crosshair.value && !camera.chase && !players[displayplayer].spectator)
if (cv_crosshair.value && !camera[0].chase && !players[displayplayers[0]].spectator)
HU_DrawCrosshair();
if (cv_crosshair2.value && !camera2.chase && !players[secondarydisplayplayer].spectator)
if (cv_crosshair2.value && !camera[1].chase && !players[displayplayers[1]].spectator)
HU_DrawCrosshair2();
if (cv_crosshair3.value && !camera3.chase && !players[thirddisplayplayer].spectator)
if (cv_crosshair3.value && !camera[2].chase && !players[displayplayers[2]].spectator)
HU_DrawCrosshair3();
if (cv_crosshair4.value && !camera4.chase && !players[fourthdisplayplayer].spectator)
if (cv_crosshair4.value && !camera[3].chase && !players[displayplayers[3]].spectator)
HU_DrawCrosshair4();
}*/
@ -3000,7 +3023,7 @@ static void HU_DrawRankings(void)
// When you play, you quickly see your score because your name is displayed in white.
// When playing back a demo, you quickly see who's the view.
if (!splitscreen)
whiteplayer = demoplayback ? displayplayer : consoleplayer;
whiteplayer = demo.playback ? displayplayers[0] : consoleplayer;
scorelines = 0;
memset(completed, 0, sizeof (completed));

View file

@ -109,6 +109,7 @@ void HU_Start(void);
boolean HU_Responder(event_t *ev);
void HU_Ticker(void);
void HU_DrawSongCredits(void);
void HU_Drawer(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);

View file

@ -146,6 +146,18 @@ boolean I_SongPaused(void);
boolean I_SetSongSpeed(float speed);
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void);
boolean I_SetSongLoopPoint(UINT32 looppoint);
UINT32 I_GetSongLoopPoint(void);
boolean I_SetSongPosition(UINT32 position);
UINT32 I_GetSongPosition(void);
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -216,6 +228,17 @@ void I_SetMusicVolume(UINT8 volume);
boolean I_SetSongTrack(INT32 track);
/// ------------------------
/// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume);
void I_StopFadingSong(void);
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
boolean I_FadeOutStopSong(UINT32 ms);
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
/// ------------------------
// CD MUSIC I/O
/// ------------------------

View file

@ -813,6 +813,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#endif
#endif
mysockaddr_t straddr;
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (s == (SOCKET_TYPE)ERRSOCKET)
return (SOCKET_TYPE)ERRSOCKET;
@ -906,12 +908,16 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
}
if (getsockname(s, (struct sockaddr *)&sin, &len) == -1)
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
else
current_port = (UINT16)ntohs(sin.sin_port);
return s;
}
static boolean UDP_Socket(void)
{
const char *sock_port = NULL;
size_t s;
struct my_addrinfo *ai, *runp, hints;
int gaie;
@ -933,20 +939,11 @@ static boolean UDP_Socket(void)
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if (M_CheckParm("-clientport"))
{
if (!M_IsNextParm())
I_Error("syntax: -clientport <portnum>");
sock_port = M_GetNextParm();
}
else
sock_port = port_name;
if (M_CheckParm("-bindaddr"))
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -967,7 +964,7 @@ static boolean UDP_Socket(void)
}
else
{
gaie = I_getaddrinfo("0.0.0.0", sock_port, &hints, &ai);
gaie = I_getaddrinfo("0.0.0.0", port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -982,8 +979,8 @@ static boolean UDP_Socket(void)
#ifdef HAVE_MINIUPNPC
if (UPNP_support)
{
I_UPnP_rem(sock_port, "UDP");
I_UPnP_add(NULL, sock_port, "UDP");
I_UPnP_rem(port_name, "UDP");
I_UPnP_add(NULL, port_name, "UDP");
}
#endif
}
@ -1000,7 +997,7 @@ static boolean UDP_Socket(void)
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -1021,7 +1018,7 @@ static boolean UDP_Socket(void)
}
else
{
gaie = I_getaddrinfo("::", sock_port, &hints, &ai);
gaie = I_getaddrinfo("::", port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -1314,7 +1311,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
int gaie;
if (!port || !port[0])
port = port_name;
port = DEFAULTPORT;
DEBFILE(va("Creating new node: %s@%s\n", address, port));
@ -1478,14 +1475,15 @@ boolean I_InitTcpNetwork(void)
if (!I_InitTcpDriver())
return false;
if (M_CheckParm("-udpport"))
if (M_CheckParm("-port"))
// Combined -udpport and -clientport into -port
// As it was really redundant having two seperate parms that does the same thing
{
if (M_IsNextParm())
strcpy(port_name, M_GetNextParm());
else
strcpy(port_name, "0");
}
current_port = (UINT16)atoi(port_name);
// parse network game options,
if (M_CheckParm("-server") || dedicated)

File diff suppressed because it is too large Load diff

View file

@ -163,6 +163,7 @@ static int lib_pRandomFixed(lua_State *L)
{
NOHUD
lua_pushfixed(L, P_RandomFixed());
demo_writerng = 2;
return 1;
}
@ -170,6 +171,7 @@ static int lib_pRandomByte(lua_State *L)
{
NOHUD
lua_pushinteger(L, P_RandomByte());
demo_writerng = 2;
return 1;
}
@ -181,6 +183,7 @@ static int lib_pRandomKey(lua_State *L)
if (a > 65536)
LUA_UsageWarning(L, "P_RandomKey: range > 65536 is undefined behavior");
lua_pushinteger(L, P_RandomKey(a));
demo_writerng = 2;
return 1;
}
@ -198,6 +201,7 @@ static int lib_pRandomRange(lua_State *L)
if ((b-a+1) > 65536)
LUA_UsageWarning(L, "P_RandomRange: range > 65536 is undefined behavior");
lua_pushinteger(L, P_RandomRange(a, b));
demo_writerng = 2;
return 1;
}
@ -207,6 +211,7 @@ static int lib_pRandom(lua_State *L)
NOHUD
LUA_Deprecated(L, "P_Random", "P_RandomByte");
lua_pushinteger(L, P_RandomByte());
demo_writerng = 2;
return 1;
}
@ -214,6 +219,7 @@ static int lib_pSignedRandom(lua_State *L)
{
NOHUD
lua_pushinteger(L, P_SignedRandom());
demo_writerng = 2;
return 1;
}
@ -222,6 +228,7 @@ static int lib_pRandomChance(lua_State *L)
fixed_t p = luaL_checkfixed(L, 1);
NOHUD
lua_pushboolean(L, P_RandomChance(p));
demo_writerng = 2;
return 1;
}
@ -769,7 +776,8 @@ static int lib_pRestoreMusic(lua_State *L)
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_RestoreMusic(player);
if (P_IsLocalPlayer(player))
P_RestoreMusic(player);
return 0;
}
@ -946,40 +954,6 @@ static int lib_pHomingAttack(lua_State *L)
return 1;
}*/
static int lib_pDoJump(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean soundandstate = (boolean)lua_opttrueboolean(L, 2);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoJump(player, soundandstate);
return 0;
}
static int lib_pSpawnThokMobj(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_SpawnThokMobj(player);
return 0;
}
static int lib_pSpawnSpinMobj(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobjtype_t type = luaL_checkinteger(L, 2);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (type >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
P_SpawnSpinMobj(player, type);
return 0;
}
static int lib_pTelekinesis(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -1836,7 +1810,7 @@ static int lib_sChangeMusic(lua_State *L)
{
#ifdef MUSICSLOT_COMPATIBILITY
const char *music_name;
UINT32 music_num;
UINT32 music_num, position, prefadems, fadeinms;
char music_compat_name[7];
boolean looping;
@ -1864,7 +1838,6 @@ static int lib_sChangeMusic(lua_State *L)
music_name = luaL_checkstring(L, 1);
}
looping = (boolean)lua_opttrueboolean(L, 2);
#else
@ -1889,8 +1862,12 @@ static int lib_sChangeMusic(lua_State *L)
#endif
music_flags = (UINT16)luaL_optinteger(L, 4, 0);
position = (UINT32)luaL_optinteger(L, 5, 0);
prefadems = (UINT32)luaL_optinteger(L, 6, 0);
fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
if (!player || P_IsLocalPlayer(player))
S_ChangeMusic(music_name, music_flags, looping);
S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
return 0;
}
@ -1907,10 +1884,8 @@ static int lib_sSpeedMusic(lua_State *L)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SpeedMusic(speed));
else
lua_pushboolean(L, false);
return 1;
S_SpeedMusic(speed);
return 0;
}
static int lib_sStopMusic(lua_State *L)
@ -1928,6 +1903,110 @@ static int lib_sStopMusic(lua_State *L)
return 0;
}
static int lib_sSetInternalMusicVolume(lua_State *L)
{
UINT32 volume = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_SetInternalMusicVolume(volume);
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sStopFadingMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_StopFadingMusic();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sFadeMusic(lua_State *L)
{
UINT32 target_volume = (UINT32)luaL_checkinteger(L, 1);
UINT32 ms;
INT32 source_volume;
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
{
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
ms = (UINT32)luaL_checkinteger(L, 2);
source_volume = -1;
}
else if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
{
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
source_volume = (INT32)luaL_checkinteger(L, 2);
ms = (UINT32)luaL_checkinteger(L, 3);
}
else if (luaL_optinteger(L, 3, INT32_MAX) == INT32_MAX)
{
ms = (UINT32)luaL_checkinteger(L, 2);
source_volume = -1;
}
else
{
source_volume = (INT32)luaL_checkinteger(L, 2);
ms = (UINT32)luaL_checkinteger(L, 3);
}
NOHUD
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms));
else
lua_pushnil(L);
return 1;
}
static int lib_sFadeOutStopMusic(lua_State *L)
{
UINT32 ms = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
lua_pushboolean(L, S_FadeOutStopMusic(ms));
}
else
lua_pushnil(L);
return 1;
}
static int lib_sOriginPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2645,9 +2724,6 @@ static luaL_Reg lib[] = {
{"P_NukeEnemies",lib_pNukeEnemies},
{"P_HomingAttack",lib_pHomingAttack},
//{"P_SuperReady",lib_pSuperReady},
{"P_DoJump",lib_pDoJump},
{"P_SpawnThokMobj",lib_pSpawnThokMobj},
{"P_SpawnSpinMobj",lib_pSpawnSpinMobj},
{"P_Telekinesis",lib_pTelekinesis},
// p_map
@ -2727,6 +2803,10 @@ static luaL_Reg lib[] = {
{"S_ChangeMusic",lib_sChangeMusic},
{"S_SpeedMusic",lib_sSpeedMusic},
{"S_StopMusic",lib_sStopMusic},
{"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume},
{"S_StopFadingMusic",lib_sStopFadingMusic},
{"S_FadeMusic",lib_sFadeMusic},
{"S_FadeOutStopMusic",lib_sFadeOutStopMusic},
{"S_OriginPlaying",lib_sOriginPlaying},
{"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying},
@ -2752,7 +2832,7 @@ static luaL_Reg lib[] = {
// k_kart
{"K_PlayAttackTaunt", lib_kAttackSound},
{"K_PlayBoostTaunt", lib_kBoostSound},
{"K_PlayPowerGloatSund", lib_kGloatSound},
{"K_PlayPowerGloatSound", lib_kGloatSound},
{"K_PlayOvertakeSound", lib_kOvertakeSound},
{"K_PlayLossSound", lib_kLossSound},
{"K_PlayHitEmSound", lib_kHitEmSound},

View file

@ -118,14 +118,14 @@ void COM_Lua_f(void)
flags = (UINT8)lua_tointeger(gL, -1);
lua_pop(gL, 1); // pop flags
if (flags & 2) // flag 2: splitscreen player command.
if (flags & 2) // flag 2: splitscreen player command. TODO: support 4P
{
if (!splitscreen)
{
lua_pop(gL, 1); // pop command info table
return; // can't execute splitscreen command without player 2!
}
playernum = secondarydisplayplayer;
playernum = displayplayers[1];
}
if (netgame)

View file

@ -51,6 +51,7 @@ enum hook {
hook_PlayerExplode, //SRB2KART
hook_PlayerSquish, //SRB2KART
hook_PlayerCmd, //SRB2KART
hook_IntermissionThinker, //SRB2KART
hook_MAX // last hook
};
@ -99,4 +100,6 @@ boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source);
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
#endif

View file

@ -62,6 +62,7 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerExplode",
"PlayerSquish",
"PlayerCmd",
"IntermissionThinker",
NULL
};
@ -420,6 +421,28 @@ void LUAh_ThinkFrame(void)
}
}
// Hook for Y_Ticker
void LUAh_IntermissionThinker(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8))))
return;
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_IntermissionThinker)
{
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
if (lua_pcall(gL, 0, 0, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
}
}
}
// Hook for mobj collisions
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
{

View file

@ -21,6 +21,8 @@ enum hud {
hud_position,
hud_minirankings, // Rankings to the left
hud_battlebumpers, // mini rankings battle bumpers.
hud_battlefullscreen, // battle huge text (WAIT, WIN, LOSE ...) + karma comeback time
hud_battlecomebacktimer, // comeback timer in battlefullscreen. separated for ease of use.
hud_wanted,
hud_speedometer,
hud_freeplay,

View file

@ -48,6 +48,8 @@ static const char *const hud_disable_options[] = {
"position",
"minirankings", // Gametype rankings to the left
"battlerankingsbumpers", // bumper drawer for battle. Useful if you want to make a custom battle gamemode without bumpers being involved.
"battlefullscreen", // battlefullscreen func (WAIT, ATTACK OR PROTECT ...)
"battlecomebacktimer", // come back timer in battlefullscreen
"wanted",
"speedometer",
"freeplay",
@ -381,6 +383,179 @@ static int libd_drawScaled(lua_State *L)
return 0;
}
// KART: draw patch on minimap from x, y coordinates on the map
static int libd_drawOnMinimap(lua_State *L)
{
fixed_t x, y, scale; // coordinates of the object
patch_t *patch; // patch we want to draw
const UINT8 *colormap = NULL; // do we want to colormap this patch?
boolean centered; // the patch is centered and doesn't need readjusting on x/y coordinates.
// variables used to replicate k_kart's mmap drawer:
INT32 lumpnum;
patch_t *AutomapPic;
INT32 mx, my;
INT32 splitflags, minimaptrans;
// base position of the minimap which also takes splits into account:
INT32 MM_X, MM_Y;
// variables used for actually drawing the icon:
fixed_t amnumxpos, amnumypos;
INT32 amxpos, amypos;
node_t *bsp = &nodes[numnodes-1];
fixed_t maxx, minx, maxy, miny;
fixed_t mapwidth, mapheight;
fixed_t xoffset, yoffset;
fixed_t xscale, yscale, zoom;
fixed_t patchw, patchh;
HUDONLY // only run this function in hud hooks
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
scale = luaL_checkinteger(L, 3);
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
centered = lua_optboolean(L, 6);
// replicate exactly what source does for its minimap drawer; AKA hardcoded garbo.
// first, check what position the mmap is supposed to be in (pasted from k_kart.c):
MM_X = BASEVIDWIDTH - 50; // 270
MM_Y = (BASEVIDHEIGHT/2)-16; // 84
if (splitscreen)
{
MM_Y = (BASEVIDHEIGHT/2);
if (splitscreen > 1) // 3P : bottom right
{
MM_X = (3*BASEVIDWIDTH/4);
MM_Y = (3*BASEVIDHEIGHT/4);
if (splitscreen > 2) // 4P: centered
{
MM_X = (BASEVIDWIDTH/2);
MM_Y = (BASEVIDHEIGHT/2);
}
}
}
// splitscreen flags
splitflags = (splitscreen == 3 ? 0 : V_SNAPTORIGHT); // flags should only be 0 when it's centered (4p split)
// translucency:
if (timeinmap > 105)
{
minimaptrans = cv_kartminimap.value;
if (timeinmap <= 113)
minimaptrans = ((((INT32)timeinmap) - 105)*minimaptrans)/(113-105);
if (!minimaptrans)
return 0;
}
else
return 0;
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
splitflags |= minimaptrans;
if (!(splitscreen == 2))
{
splitflags &= ~minimaptrans;
splitflags |= V_HUDTRANSHALF;
}
splitflags &= ~V_HUDTRANSHALF;
splitflags |= V_HUDTRANS;
// Draw the HUD only when playing in a level.
// hu_stuff needs this, unlike st_stuff.
if (gamestate != GS_LEVEL)
return 0;
if (stplyr != &players[displayplayers[0]])
return 0;
lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap)));
if (lumpnum != -1)
AutomapPic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_HUDGFX);
else
return 0; // no pic, just get outta here
mx = MM_X - (AutomapPic->width/2);
my = MM_Y - (AutomapPic->height/2);
// let offsets transfer to the heads, too!
if (encoremode)
mx += SHORT(AutomapPic->leftoffset);
else
mx -= SHORT(AutomapPic->leftoffset);
my -= SHORT(AutomapPic->topoffset);
// now that we have replicated this behavior, we can draw an icon from our supplied x, y coordinates by replicating k_kart.c's totally understandable uncommented code!!!
// get map boundaries using nodes
maxx = maxy = INT32_MAX;
minx = miny = INT32_MIN;
minx = bsp->bbox[0][BOXLEFT];
maxx = bsp->bbox[0][BOXRIGHT];
miny = bsp->bbox[0][BOXBOTTOM];
maxy = bsp->bbox[0][BOXTOP];
if (bsp->bbox[1][BOXLEFT] < minx)
minx = bsp->bbox[1][BOXLEFT];
if (bsp->bbox[1][BOXRIGHT] > maxx)
maxx = bsp->bbox[1][BOXRIGHT];
if (bsp->bbox[1][BOXBOTTOM] < miny)
miny = bsp->bbox[1][BOXBOTTOM];
if (bsp->bbox[1][BOXTOP] > maxy)
maxy = bsp->bbox[1][BOXTOP];
// You might be wondering why these are being bitshift here
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
// map boundaries and sizes will ALWAYS be whole numbers thankfully
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
minx >>= FRACBITS;
maxx >>= FRACBITS;
miny >>= FRACBITS;
maxy >>= FRACBITS;
// these are our final map boundaries:
mapwidth = maxx - minx;
mapheight = maxy - miny;
// These should always be small enough to be bitshift back right now
xoffset = (minx + mapwidth/2)<<FRACBITS;
yoffset = (miny + mapheight/2)<<FRACBITS;
xscale = FixedDiv(AutomapPic->width, mapwidth);
yscale = FixedDiv(AutomapPic->height, mapheight);
zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20);
amnumxpos = (FixedMul(x, zoom) - FixedMul(xoffset, zoom));
amnumypos = -(FixedMul(y, zoom) - FixedMul(yoffset, zoom));
if (encoremode)
amnumxpos = -amnumxpos;
// scale patch coords
patchw = patch->width*scale /2;
patchh = patch->height*scale /2;
if (centered)
patchw = patchh = 0; // patch is supposedly already centered, don't butt in.
amxpos = amnumxpos + ((mx + AutomapPic->width/2)<<FRACBITS) - patchw;
amypos = amnumypos + ((my + AutomapPic->height/2)<<FRACBITS) - patchh;
// and NOW we can FINALLY DRAW OUR GOD DAMN PATCH :V
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
return 0;
}
static int libd_drawNum(lua_State *L)
{
INT32 x, y, flags, num;
@ -644,6 +819,7 @@ static luaL_Reg lib_draw[] = {
{"dupy", libd_dupy},
{"renderer", libd_renderer},
{"localTransFlag", libd_getlocaltransflag},
{"drawOnMinimap", libd_drawOnMinimap},
{NULL, NULL}
};
@ -797,24 +973,24 @@ void LUAh_GameHUD(player_t *stplayr)
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen > 2 && stplayr == &players[fourthdisplayplayer])
if (splitscreen > 2 && stplayr == &players[displayplayers[3]])
{
LUA_PushUserdata(gL, &camera4, META_CAMERA);
LUA_PushUserdata(gL, &camera[3], META_CAMERA);
camnum = 4;
}
else if (splitscreen > 1 && stplayr == &players[thirddisplayplayer])
else if (splitscreen > 1 && stplayr == &players[displayplayers[2]])
{
LUA_PushUserdata(gL, &camera3, META_CAMERA);
LUA_PushUserdata(gL, &camera[2], META_CAMERA);
camnum = 3;
}
else if (splitscreen && stplayr == &players[secondarydisplayplayer])
else if (splitscreen && stplayr == &players[displayplayers[1]])
{
LUA_PushUserdata(gL, &camera2, META_CAMERA);
LUA_PushUserdata(gL, &camera[1], META_CAMERA);
camnum = 2;
}
else
{
LUA_PushUserdata(gL, &camera, META_CAMERA);
LUA_PushUserdata(gL, &camera[0], META_CAMERA);
camnum = 1;
}

View file

@ -1479,6 +1479,12 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushstring(L, header->musname);
else if (fastcmp(field,"mustrack"))
lua_pushinteger(L, header->mustrack);
else if (fastcmp(field,"muspos"))
lua_pushinteger(L, header->muspos);
else if (fastcmp(field,"musinterfadeout"))
lua_pushinteger(L, header->musinterfadeout);
else if (fastcmp(field,"musintername"))
lua_pushstring(L, header->musintername);
else if (fastcmp(field,"forcecharacter"))
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))

View file

@ -421,13 +421,13 @@ static int mobj_set(lua_State *L)
case mobj_angle:
mo->angle = luaL_checkangle(L, 3);
if (mo->player == &players[consoleplayer])
localangle = mo->angle;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle;
else if (mo->player == &players[thirddisplayplayer])
localangle3 = mo->angle;
else if (mo->player == &players[fourthdisplayplayer])
localangle4 = mo->angle;
localangle[0] = mo->angle;
else if (mo->player == &players[displayplayers[1]])
localangle[1] = mo->angle;
else if (mo->player == &players[displayplayers[2]])
localangle[2] = mo->angle;
else if (mo->player == &players[displayplayers[3]])
localangle[3] = mo->angle;
break;
case mobj_sprite:
mo->sprite = luaL_checkinteger(L, 3);

View file

@ -155,36 +155,8 @@ static int player_get(lua_State *L)
else if (fastcmp(field,"kartweight"))
lua_pushinteger(L, plr->kartweight);
//
else if (fastcmp(field,"normalspeed"))
lua_pushfixed(L, plr->normalspeed);
else if (fastcmp(field,"runspeed"))
lua_pushfixed(L, plr->runspeed);
else if (fastcmp(field,"thrustfactor"))
lua_pushinteger(L, plr->thrustfactor);
else if (fastcmp(field,"accelstart"))
lua_pushinteger(L, plr->accelstart);
else if (fastcmp(field,"acceleration"))
lua_pushinteger(L, plr->acceleration);
else if (fastcmp(field,"charability"))
lua_pushinteger(L, plr->charability);
else if (fastcmp(field,"charability2"))
lua_pushinteger(L, plr->charability2);
else if (fastcmp(field,"charflags"))
lua_pushinteger(L, plr->charflags);
else if (fastcmp(field,"thokitem"))
lua_pushinteger(L, plr->thokitem);
else if (fastcmp(field,"spinitem"))
lua_pushinteger(L, plr->spinitem);
else if (fastcmp(field,"revitem"))
lua_pushinteger(L, plr->revitem);
else if (fastcmp(field,"actionspd"))
lua_pushfixed(L, plr->actionspd);
else if (fastcmp(field,"mindash"))
lua_pushfixed(L, plr->mindash);
else if (fastcmp(field,"maxdash"))
lua_pushfixed(L, plr->maxdash);
else if (fastcmp(field,"jumpfactor"))
lua_pushfixed(L, plr->jumpfactor);
else if (fastcmp(field,"lives"))
lua_pushinteger(L, plr->lives);
else if (fastcmp(field,"continues"))
@ -382,13 +354,13 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"aiming")) {
plr->aiming = luaL_checkangle(L, 3);
if (plr == &players[consoleplayer])
localaiming = plr->aiming;
else if (plr == &players[secondarydisplayplayer])
localaiming2 = plr->aiming;
else if (plr == &players[thirddisplayplayer])
localaiming3 = plr->aiming;
else if (plr == &players[fourthdisplayplayer])
localaiming4 = plr->aiming;
localaiming[0] = plr->aiming;
else if (plr == &players[displayplayers[1]])
localaiming[1] = plr->aiming;
else if (plr == &players[displayplayers[2]])
localaiming[2] = plr->aiming;
else if (plr == &players[displayplayers[3]])
localaiming[3] = plr->aiming;
}
else if (fastcmp(field,"health"))
plr->health = (INT32)luaL_checkinteger(L, 3);
@ -431,36 +403,8 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"kartweight"))
plr->kartweight = (UINT8)luaL_checkinteger(L, 3);
//
else if (fastcmp(field,"normalspeed"))
plr->normalspeed = luaL_checkfixed(L, 3);
else if (fastcmp(field,"runspeed"))
plr->runspeed = luaL_checkfixed(L, 3);
else if (fastcmp(field,"thrustfactor"))
plr->thrustfactor = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"accelstart"))
plr->accelstart = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"acceleration"))
plr->acceleration = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"charability"))
plr->charability = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"charability2"))
plr->charability2 = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"charflags"))
plr->charflags = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"thokitem"))
plr->thokitem = luaL_checkinteger(L, 3);
else if (fastcmp(field,"spinitem"))
plr->spinitem = luaL_checkinteger(L, 3);
else if (fastcmp(field,"revitem"))
plr->revitem = luaL_checkinteger(L, 3);
else if (fastcmp(field,"actionspd"))
plr->actionspd = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"mindash"))
plr->mindash = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"maxdash"))
plr->maxdash = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"jumpfactor"))
plr->jumpfactor = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lives"))
plr->lives = (SINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"continues"))

View file

@ -273,7 +273,7 @@ boolean cht_Responder(event_t *ev)
#define REQUIRE_OBJECTPLACE if (!objectplacing)\
{ CONS_Printf(M_GetText("OBJECTPLACE must be enabled.\n")); return; }
#define REQUIRE_INLEVEL if (gamestate != GS_LEVEL || demoplayback)\
#define REQUIRE_INLEVEL if (gamestate != GS_LEVEL || demo.playback)\
{ CONS_Printf(M_GetText("You must be in a level to use this.\n")); return; }
#define REQUIRE_SINGLEPLAYER if (netgame || multiplayer)\

View file

@ -56,7 +56,7 @@ fixed_t FixedDiv2(fixed_t a, fixed_t b)
if (b == 0)
I_Error("FixedDiv: divide by zero");
ret = (((INT64)a * FRACUNIT) ) / b;
ret = (((INT64)a * FRACUNIT)) / b;
if ((ret > INT32_MAX) || (ret < INT32_MIN))
I_Error("FixedDiv: divide by zero");
@ -117,7 +117,7 @@ fixed_t FixedHypot(fixed_t x, fixed_t y)
yx = FixedDiv(y, x); // (x/y)
}
yx2 = FixedMul(yx, yx); // (x/y)^2
yx1 = FixedSqrt(1*FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
}
@ -191,8 +191,8 @@ vector2_t *FV2_Divide(vector2_t *a_i, fixed_t a_c)
// Vector Complex Math
vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a_o)
{
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
a_o->x = a_1->x + a_o->x;
a_o->y = a_1->y + a_o->y;
return a_o;
@ -200,16 +200,16 @@ vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a
fixed_t FV2_Distance(const vector2_t *p1, const vector2_t *p2)
{
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
return FixedSqrt(xs+ys);
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
return FixedSqrt(xs + ys);
}
fixed_t FV2_Magnitude(const vector2_t *a_normal)
{
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
return FixedSqrt(xs+ys);
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
return FixedSqrt(xs + ys);
}
// Also returns the magnitude
@ -240,7 +240,7 @@ vector2_t *FV2_Negate(vector2_t *a_1)
boolean FV2_Equal(const vector2_t *a_1, const vector2_t *a_2)
{
fixed_t Epsilon = FRACUNIT/FRACUNIT;
fixed_t Epsilon = FRACUNIT / FRACUNIT;
if ((abs(a_2->x - a_1->x) > Epsilon) ||
(abs(a_2->y - a_1->y) > Epsilon))
@ -261,7 +261,7 @@ fixed_t FV2_Dot(const vector2_t *a_1, const vector2_t *a_2)
//
// Given two points, create a vector between them.
//
vector2_t *FV2_Point2Vec (const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
vector2_t *FV2_Point2Vec(const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
{
a_o->x = point1->x - point2->x;
a_o->y = point1->y - point2->y;
@ -344,9 +344,9 @@ vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c)
// Vector Complex Math
vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
{
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
a_o->z = FixedDiv(a_2->z - a_1->z, 2*FRACUNIT);
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT);
a_o->x = a_1->x + a_o->x;
a_o->y = a_1->y + a_o->y;
a_o->z = a_1->z + a_o->z;
@ -355,18 +355,18 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a
fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
{
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
fixed_t zs = FixedMul(p2->z-p1->z,p2->z-p1->z);
return FixedSqrt(xs+ys+zs);
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z);
return FixedSqrt(xs + ys + zs);
}
fixed_t FV3_Magnitude(const vector3_t *a_normal)
{
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
fixed_t zs = FixedMul(a_normal->z,a_normal->z);
return FixedSqrt(xs+ys+zs);
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
fixed_t zs = FixedMul(a_normal->z, a_normal->z);
return FixedSqrt(xs + ys + zs);
}
// Also returns the magnitude
@ -399,7 +399,7 @@ vector3_t *FV3_Negate(vector3_t *a_1)
boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
{
fixed_t Epsilon = FRACUNIT/FRACUNIT;
fixed_t Epsilon = FRACUNIT / FRACUNIT;
if ((abs(a_2->x - a_1->x) > Epsilon) ||
(abs(a_2->y - a_1->y) > Epsilon) ||
@ -458,6 +458,20 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
return FV3_AddEx(&Line[0], &V, out);
}
//
// ClosestPointOnVector
//
// Similar to ClosestPointOnLine, but uses a vector instead of two points.
//
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out)
{
fixed_t t = FV3_Dot(dir, p);
// Return the point on the line closest
FV3_MulEx(dir, t, out);
return;
}
//
// ClosestPointOnTriangle
//
@ -465,7 +479,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
// the closest point on the edge of
// the triangle is returned.
//
void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, vector3_t *result)
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result)
{
UINT8 i;
fixed_t dist, closestdist;
@ -506,7 +520,7 @@ void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, v
//
// Given two points, create a vector between them.
//
vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
{
a_o->x = point1->x - point2->x;
a_o->y = point1->y - point2->y;
@ -519,7 +533,7 @@ vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vect
//
// Calculates the normal of a polygon.
//
void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal)
{
vector3_t a_1;
vector3_t a_2;
@ -529,7 +543,28 @@ void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
FV3_Cross(&a_1, &a_2, a_normal);
FV3_NormalizeEx(a_normal, a_normal);
return FV3_NormalizeEx(a_normal, a_normal);
}
//
// Strength
//
// Measures the 'strength' of a vector in a particular direction.
//
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir)
{
vector3_t normal;
fixed_t dist = FV3_NormalizeEx(a_1, &normal);
fixed_t dot = FV3_Dot(&normal, dir);
FV3_ClosestPointOnVector(dir, a_1, &normal);
dist = FV3_Magnitude(&normal);
if (dot < 0) // Not facing same direction, so negate result.
dist = -dist;
return dist;
}
//
@ -550,11 +585,11 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
*originDistance = FV3_PlaneDistance(a_normal, &a_triangle[0]);
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
// Positive or zero number means no intersection
if (FixedMul(distance1, distance2) >= 0)
@ -575,8 +610,8 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector)
{
fixed_t d = -(FV3_Dot(pNormal, pOrigin));
fixed_t number = FV3_Dot(pNormal,rOrigin) + d;
fixed_t denom = FV3_Dot(pNormal,rVector);
fixed_t number = FV3_Dot(pNormal, rOrigin) + d;
fixed_t denom = FV3_Dot(pNormal, rVector);
return -FixedDiv(number, denom);
}
@ -597,11 +632,11 @@ fixed_t FV3_IntersectRaySphere(const vector3_t *rO, const vector3_t *rV, const v
c = FV3_Magnitude(&Q);
v = FV3_Dot(&Q, rV);
d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v));
d = FixedMul(sR, sR) - (FixedMul(c, c) - FixedMul(v, v));
// If there was no intersection, return -1
if (d < 0*FRACUNIT)
return (-1*FRACUNIT);
if (d < 0 * FRACUNIT)
return (-1 * FRACUNIT);
// Return the distance to the [first] intersecting point
return (v - FixedSqrt(d));
@ -629,9 +664,9 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
// Here I just chose a arbitrary point as the point to find that distance. You notice we negate that
// distance. We negate the distance because we want to eventually go BACKWARDS from our point to the plane.
// By doing this is will basically bring us back to the plane to find our intersection point.
Numerator = - (FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
FixedMul(vNormal->y, vLine[0].y) +
FixedMul(vNormal->z, vLine[0].z) + distance);
Numerator = -(FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
FixedMul(vNormal->y, vLine[0].y) +
FixedMul(vNormal->z, vLine[0].z) + distance);
// 3) If we take the dot product between our line vector and the normal of the polygon,
// this will give us the cosine of the angle between the 2 (since they are both normalized - length 1).
@ -643,7 +678,7 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
// on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)).
// In this case, we should just return any point on the line.
if( Denominator == 0*FRACUNIT) // Check so we don't divide by zero
if (Denominator == 0 * FRACUNIT) // Check so we don't divide by zero
{
ReturnVec->x = vLine[0].x;
ReturnVec->y = vLine[0].y;
@ -686,8 +721,8 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
//
UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line)
{
fixed_t s1 = FixedMul((point->y - line[0].y),(line[1].x - line[0].x));
fixed_t s2 = FixedMul((point->x - line[0].x),(line[1].y - line[0].y));
fixed_t s1 = FixedMul((point->y - line[0].y), (line[1].x - line[0].x));
fixed_t s2 = FixedMul((point->x - line[0].x), (line[1].y - line[0].y));
return (UINT8)(s1 - s2 < 0);
}
@ -752,7 +787,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
matrix->m[0] = upcross.x;
matrix->m[1] = upcross.y;
matrix->m[2] = upcross.z;
matrix->m[3] = 0*FRACUNIT;
matrix->m[3] = 0 * FRACUNIT;
matrix->m[4] = upx;
matrix->m[5] = upy;
@ -764,9 +799,9 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
matrix->m[10] = anglez;
matrix->m[11] = 0;
matrix->m[12] = x - FixedMul(upx,radius);
matrix->m[13] = y - FixedMul(upy,radius);
matrix->m[14] = z - FixedMul(upz,radius);
matrix->m[12] = x - FixedMul(upx, radius);
matrix->m[13] = y - FixedMul(upy, radius);
matrix->m[14] = z - FixedMul(upz, radius);
matrix->m[15] = FRACUNIT;
}
@ -778,20 +813,20 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
{
#define M(row,col) matrix->m[col * 4 + row]
out->x = FixedMul(vec->x,M(0, 0))
+ FixedMul(vec->y,M(0, 1))
+ FixedMul(vec->z,M(0, 2))
+ M(0, 3);
out->x = FixedMul(vec->x, M(0, 0))
+ FixedMul(vec->y, M(0, 1))
+ FixedMul(vec->z, M(0, 2))
+ M(0, 3);
out->y = FixedMul(vec->x,M(1, 0))
+ FixedMul(vec->y,M(1, 1))
+ FixedMul(vec->z,M(1, 2))
+ M(1, 3);
out->y = FixedMul(vec->x, M(1, 0))
+ FixedMul(vec->y, M(1, 1))
+ FixedMul(vec->z, M(1, 2))
+ M(1, 3);
out->z = FixedMul(vec->x,M(2, 0))
+ FixedMul(vec->y,M(2, 1))
+ FixedMul(vec->z,M(2, 2))
+ M(2, 3);
out->z = FixedMul(vec->x, M(2, 0))
+ FixedMul(vec->y, M(2, 1))
+ FixedMul(vec->z, M(2, 2))
+ M(2, 3);
#undef M
}
@ -811,7 +846,7 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
R(i, j) = FixedMul(D(i, 0),M(0, j)) + FixedMul(D(i, 1),M(1, j)) + FixedMul(D(i, 2),M(2, j)) + FixedMul(D(i, 3),M(3, j));
R(i, j) = FixedMul(D(i, 0), M(0, j)) + FixedMul(D(i, 1), M(1, j)) + FixedMul(D(i, 2), M(2, j)) + FixedMul(D(i, 3), M(3, j));
}
M_Memcpy(dest, &result, sizeof(matrix_t));
@ -869,8 +904,8 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
static inline void M_print(INT64 a)
{
const fixed_t w = (a>>FRACBITS);
fixed_t f = a%FRACUNIT;
const fixed_t w = (a >> FRACBITS);
fixed_t f = a % FRACUNIT;
fixed_t d = FRACUNIT;
if (f == 0)
@ -878,7 +913,7 @@ static inline void M_print(INT64 a)
printf("%d", (fixed_t)w);
return;
}
else while (f != 1 && f/2 == f>>1)
else while (f != 1 && f / 2 == f >> 1)
{
d /= 2;
f /= 2;
@ -892,7 +927,7 @@ static inline void M_print(INT64 a)
FUNCMATH FUNCINLINE static inline fixed_t FixedMulC(fixed_t a, fixed_t b)
{
return (fixed_t)((((INT64)a * b) ) / FRACUNIT);
return (fixed_t)((((INT64)a * b)) / FRACUNIT);
}
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
@ -902,7 +937,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
if (b == 0)
I_Error("FixedDiv: divide by zero");
ret = (((INT64)a * FRACUNIT) ) / b;
ret = (((INT64)a * FRACUNIT)) / b;
if ((ret > INT32_MAX) || (ret < INT32_MIN))
I_Error("FixedDiv: divide by zero");
@ -911,7 +946,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC(fixed_t a, fixed_t b)
{
if ((abs(a) >> (FRACBITS-2)) >= abs(b))
if ((abs(a) >> (FRACBITS - 2)) >= abs(b))
return (a^b) < 0 ? INT32_MIN : INT32_MAX;
return FixedDivC2(a, b);
@ -938,43 +973,43 @@ int main(int argc, char** argv)
#ifdef MULDIV_TEST
for (a = 1; a <= INT32_MAX; a += FRACUNIT)
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
{
c = FixedMul(a, b);
d = FixedMulC(a, b);
if (c != d)
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
{
printf("(");
M_print(a);
printf(") * (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(") \n");
n--;
printf("%d != %d\n", c, d);
c = FixedMul(a, b);
d = FixedMulC(a, b);
if (c != d)
{
printf("(");
M_print(a);
printf(") * (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(") \n");
n--;
printf("%d != %d\n", c, d);
}
c = FixedDiv(a, b);
d = FixedDivC(a, b);
if (c != d)
{
printf("(");
M_print(a);
printf(") / (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(")\n");
n--;
printf("%d != %d\n", c, d);
}
if (n <= 0)
exit(-1);
}
c = FixedDiv(a, b);
d = FixedDivC(a, b);
if (c != d)
{
printf("(");
M_print(a);
printf(") / (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(")\n");
n--;
printf("%d != %d\n", c, d);
}
if (n <= 0)
exit(-1);
}
#endif
#ifdef SQRT_TEST
@ -982,7 +1017,7 @@ int main(int argc, char** argv)
{
c = FixedSqrt(a);
d = FixedSqrtC(a);
b = abs(c-d);
b = abs(c - d);
if (b > 1)
{
printf("sqrt(");

View file

@ -394,9 +394,11 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2);
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2);
vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o);
vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result);
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o);
void FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir);
fixed_t FV3_PlaneDistance(const vector3_t *a_normal, const vector3_t *a_point);
boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_line, vector3_t *a_normal, fixed_t *originDistance);
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector);

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,9 @@ void M_Drawer(void);
// Called by D_SRB2Main, loads the config file.
void M_Init(void);
// Called by D_SRB2Main also, sets up the playermenu and description tables.
void M_InitCharacterTables(void);
// Called by intro code to force menu up upon a keypress,
// does nothing if menu is already up.
void M_StartControlPanel(void);
@ -210,7 +213,7 @@ typedef struct
UINT8 netgame;
} saveinfo_t;
extern description_t description[32];
extern description_t description[MAXSKINS];
extern consvar_t cv_showfocuslost;
extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
@ -235,6 +238,9 @@ void Screenshot_option_Onchange(void);
// Addons menu updating
void Addons_option_Onchange(void);
void M_ReplayHut(INT32 choice);
void M_SetPlaybackMenuPointer(void);
INT32 HU_GetHighlightColor(void);
// These defines make it a little easier to make menus

View file

@ -743,12 +743,12 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png
else
snprintf(lvlttltext, 48, "Unknown");
if (gamestate == GS_LEVEL && &players[displayplayer] && players[displayplayer].mo)
if (gamestate == GS_LEVEL && &players[displayplayers[0]] && players[displayplayers[0]].mo)
snprintf(locationtxt, 40, "X:%d Y:%d Z:%d A:%d",
players[displayplayer].mo->x>>FRACBITS,
players[displayplayer].mo->y>>FRACBITS,
players[displayplayer].mo->z>>FRACBITS,
FixedInt(AngleFixed(players[displayplayer].mo->angle)));
players[displayplayers[0]].mo->x>>FRACBITS,
players[displayplayers[0]].mo->y>>FRACBITS,
players[displayplayers[0]].mo->z>>FRACBITS,
FixedInt(AngleFixed(players[displayplayers[0]].mo->angle)));
else
snprintf(locationtxt, 40, "Unknown");

View file

@ -700,7 +700,13 @@ static INT32 AddToMasterServer(boolean firstadd)
return MS_CONNECT_ERROR;
}
retry = 0;
if (res == ERRSOCKET)
/*
Somehow we can still select our old socket despite it being closed(?).
Atleast, that's what I THINK is happening. Anyway, we have to check that we
haven't open a socket, and actually open it!
*/
/*if (res == ERRSOCKET)*//* wtf? no! */
if (socket_fd == (SOCKET_TYPE)ERRSOCKET)
{
if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
{
@ -714,6 +720,13 @@ static INT32 AddToMasterServer(boolean firstadd)
// ok, or bad... let see that!
j = (socklen_t)sizeof (i);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j);
/*
This is also wrong. If getsockopt fails, i doesn't have to be set. Plus, if
it is set (which it appearantly is on linux), we check errno anyway. And in
the case that i is returned as normal, we don't even report the correct
value! So we accomplish NOTHING, except returning due to dumb luck.
If you care, fix this--I don't. -James (R.)
*/
if (i) // it was bad
{
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));

View file

@ -3079,7 +3079,7 @@ void A_Invincibility(mobj_t *actor)
{
S_StopMusic();
if (mariomode)
G_GhostAddColor(GHC_INVINCIBLE);
G_GhostAddColor((INT32) (player - players), GHC_INVINCIBLE);
S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false);
}
}
@ -4174,12 +4174,12 @@ void A_OverlayThink(mobj_t *actor)
{
angle_t viewingangle;
if (players[displayplayer].awayviewtics)
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo)
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, camera.x, camera.y);
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, camera[0].x, camera[0].y);
destx = actor->target->x + P_ReturnThrustX(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale));
desty = actor->target->y + P_ReturnThrustY(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale));
@ -4781,8 +4781,8 @@ void A_DetonChase(mobj_t *actor)
actor->reactiontime = -42;
exact = actor->movedir>>ANGLETOFINESHIFT;
xyspeed = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINECOSINE(exact));
actor->momz = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINESINE(exact));
xyspeed = FixedMul(FixedMul(K_GetKartSpeed(actor->tracer->player, false),3*FRACUNIT/4), FINECOSINE(exact));
actor->momz = FixedMul(FixedMul(K_GetKartSpeed(actor->tracer->player, false),3*FRACUNIT/4), FINESINE(exact));
exact = actor->angle>>ANGLETOFINESHIFT;
actor->momx = FixedMul(xyspeed, FINECOSINE(exact));
@ -8355,6 +8355,7 @@ void A_SPBChase(mobj_t *actor)
actor->lastlook = -1;
spbplace = -1;
P_InstaThrust(actor, actor->angle, wspeed);
actor->flags &= ~MF_NOCLIPTHING; // just in case.
return;
}
@ -8384,10 +8385,14 @@ void A_SPBChase(mobj_t *actor)
{
if (actor->tracer && actor->tracer->health)
{
fixed_t defspeed = wspeed;
fixed_t range = (160*actor->tracer->scale);
fixed_t cx = 0, cy =0;
// we're tailing a player, now's a good time to regain our damage properties
actor->flags &= ~MF_NOCLIPTHING;
// Play the intimidating gurgle
if (!S_SoundPlaying(actor, actor->info->activesound))
S_StartSound(actor, actor->info->activesound);
@ -8434,6 +8439,9 @@ void A_SPBChase(mobj_t *actor)
wspeed = (3*defspeed)/2;
if (wspeed < 20*actor->tracer->scale)
wspeed = 20*actor->tracer->scale;
if (actor->tracer->player->pflags & PF_SLIDING)
wspeed = actor->tracer->player->speed/2;
// ^^^^ current section: These are annoying, and grand metropolis in particular needs this.
hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z);
@ -8512,6 +8520,9 @@ void A_SPBChase(mobj_t *actor)
{
actor->momx = actor->momy = actor->momz = 0; // Stoooop
// don't hurt players that have nothing to do with this:
actor->flags |= MF_NOCLIPTHING;
if (actor->lastlook != -1
&& playeringame[actor->lastlook]
&& !players[actor->lastlook].spectator
@ -8547,6 +8558,10 @@ void A_SPBChase(mobj_t *actor)
}
// Found someone, now get close enough to initiate the slaughter...
// don't hurt players that have nothing to do with this:
actor->flags |= MF_NOCLIPTHING;
P_SetTarget(&actor->tracer, player->mo);
spbplace = bestrank;

View file

@ -2536,9 +2536,9 @@ void T_CameraScanner(elevator_t *elevator)
lastleveltime = leveltime;
}
if (players[displayplayer].mo)
if (players[displayplayers[0]].mo)
{
if (players[displayplayer].mo->subsector->sector == elevator->actionsector)
if (players[displayplayers[0]].mo->subsector->sector == elevator->actionsector)
{
if (t_cam_dist == -42)
t_cam_dist = cv_cam_dist.value;
@ -2564,9 +2564,9 @@ void T_CameraScanner(elevator_t *elevator)
}
}
if (splitscreen && players[secondarydisplayplayer].mo)
if (splitscreen && players[displayplayers[1]].mo)
{
if (players[secondarydisplayplayer].mo->subsector->sector == elevator->actionsector)
if (players[displayplayers[1]].mo->subsector->sector == elevator->actionsector)
{
if (t_cam2_rotate == -42)
t_cam2_dist = cv_cam2_dist.value;
@ -2592,9 +2592,9 @@ void T_CameraScanner(elevator_t *elevator)
}
}
if (splitscreen > 1 && players[thirddisplayplayer].mo)
if (splitscreen > 1 && players[displayplayers[2]].mo)
{
if (players[thirddisplayplayer].mo->subsector->sector == elevator->actionsector)
if (players[displayplayers[2]].mo->subsector->sector == elevator->actionsector)
{
if (t_cam3_rotate == -42)
t_cam3_dist = cv_cam3_dist.value;
@ -2620,9 +2620,9 @@ void T_CameraScanner(elevator_t *elevator)
}
}
if (splitscreen > 2 && players[fourthdisplayplayer].mo)
if (splitscreen > 2 && players[displayplayers[3]].mo)
{
if (players[fourthdisplayplayer].mo->subsector->sector == elevator->actionsector)
if (players[displayplayers[3]].mo->subsector->sector == elevator->actionsector)
{
if (t_cam4_rotate == -42)
t_cam4_dist = cv_cam4_dist.value;

View file

@ -62,11 +62,11 @@ void P_ForceConstant(const BasicFF_t *FFInfo)
ConstantQuake.Magnitude = FFInfo->Magnitude;
if (FFInfo->player == &players[consoleplayer])
I_Tactile(ConstantForce, &ConstantQuake);
else if (splitscreen && FFInfo->player == &players[secondarydisplayplayer])
else if (splitscreen && FFInfo->player == &players[displayplayers[1]])
I_Tactile2(ConstantForce, &ConstantQuake);
else if (splitscreen > 1 && FFInfo->player == &players[thirddisplayplayer])
else if (splitscreen > 1 && FFInfo->player == &players[displayplayers[2]])
I_Tactile3(ConstantForce, &ConstantQuake);
else if (splitscreen > 2 && FFInfo->player == &players[fourthdisplayplayer])
else if (splitscreen > 2 && FFInfo->player == &players[displayplayers[3]])
I_Tactile4(ConstantForce, &ConstantQuake);
}
void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
@ -83,11 +83,11 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
RampQuake.End = End;
if (FFInfo->player == &players[consoleplayer])
I_Tactile(ConstantForce, &RampQuake);
else if (splitscreen && FFInfo->player == &players[secondarydisplayplayer])
else if (splitscreen && FFInfo->player == &players[displayplayers[1]])
I_Tactile2(ConstantForce, &RampQuake);
else if (splitscreen > 1 && FFInfo->player == &players[thirddisplayplayer])
else if (splitscreen > 1 && FFInfo->player == &players[displayplayers[2]])
I_Tactile3(ConstantForce, &RampQuake);
else if (splitscreen > 2 && FFInfo->player == &players[fourthdisplayplayer])
else if (splitscreen > 2 && FFInfo->player == &players[displayplayers[3]])
I_Tactile4(ConstantForce, &RampQuake);
}
@ -218,7 +218,7 @@ void P_DoNightsScore(player_t *player)
dummymo->fuse = 3*TICRATE;
// What?! NO, don't use the camera! Scale up instead!
//P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera.x, camera.y), 3*FRACUNIT);
//P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera[0].x, camera[0].y), 3*FRACUNIT);
dummymo->scalespeed = FRACUNIT/25;
dummymo->destscale = 2*FRACUNIT;
}
@ -851,7 +851,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Secret emblem thingy
case MT_EMBLEM:
{
if (demoplayback || player->bot)
if (demo.playback || player->bot)
return;
emblemlocations[special->health-1].collected = true;
@ -1180,13 +1180,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->angle = special->angle;
if (player == &players[consoleplayer])
localangle = toucher->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = toucher->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = toucher->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = toucher->angle;
localangle[0] = toucher->angle;
else if (player == &players[displayplayers[1]])
localangle[1] = toucher->angle;
else if (player == &players[displayplayers[2]])
localangle[2] = toucher->angle;
else if (player == &players[displayplayers[3]])
localangle[3] = toucher->angle;
P_ResetPlayer(player);
@ -1209,7 +1209,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
// CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap))
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
@ -1231,7 +1231,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
// CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap))
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
@ -1263,7 +1263,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
// CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap))
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
@ -1293,7 +1293,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
// CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap))
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
@ -1321,7 +1321,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
// CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap))
if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{
HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4);
@ -1433,7 +1433,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
player->powers[pw_shield] |= SH_FIREFLOWER;
toucher->color = SKINCOLOR_WHITE;
G_GhostAddColor(GHC_FIREFLOWER);
G_GhostAddColor(player - players, GHC_FIREFLOWER);
break;
// *************** //
@ -1837,6 +1837,9 @@ void P_CheckTimeLimit(void)
}
}
if (playercount > MAXPLAYERS)
playercount = MAXPLAYERS;
//Sort 'em.
for (i = 1; i < playercount; i++)
{
@ -2324,17 +2327,17 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
AM_Stop();
//added : 22-02-98: recenter view for next life...
localaiming = 0;
localaiming[0] = 0;
}
if (target->player == &players[secondarydisplayplayer])
if (target->player == &players[displayplayers[1]])
{
// added : 22-02-98: recenter view for next life...
localaiming2 = 0;
localaiming[1] = 0;
}
if (target->player == &players[thirddisplayplayer])
localaiming3 = 0;
if (target->player == &players[fourthdisplayplayer])
localaiming4 = 0;
if (target->player == &players[displayplayers[2]])
localaiming[2] = 0;
if (target->player == &players[displayplayers[3]])
localaiming[3] = 0;
//tag deaths handled differently in suicide cases. Don't count spectators!
/*if (G_TagGametype()
@ -2978,7 +2981,7 @@ void P_RemoveShield(player_t *player)
if (!player->powers[pw_super])
{
player->mo->color = player->skincolor;
G_GhostAddColor(GHC_NORMAL);
G_GhostAddColor((INT32) (player - players), GHC_NORMAL);
}
}
else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them!
@ -3409,7 +3412,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
target->health -= damage;
if (source && source->player && target)
G_GhostAddHit(target);
G_GhostAddHit((INT32) (source->player - players), target);
if (target->health <= 0)
{

View file

@ -22,6 +22,7 @@
#include "p_tick.h"
#include "r_defs.h"
#include "p_maputl.h"
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#define FLOATSPEED (FRACUNIT*4)
@ -108,7 +109,7 @@ typedef struct camera_s
fixed_t pan;
} camera_t;
extern camera_t camera, camera2, camera3, camera4;
extern camera_t camera[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height;
extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed;
@ -137,6 +138,7 @@ boolean P_PlayerInPain(player_t *player);
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player);
boolean P_IsLocalPlayer(player_t *player);
boolean P_IsDisplayPlayer(player_t *player);
boolean P_SpectatorJoinGame(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo);
@ -178,7 +180,6 @@ boolean P_LookForEnemies(player_t *player);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
//boolean P_SuperReady(player_t *player);
void P_DoJump(player_t *player, boolean soundandstate);
boolean P_AnalogMove(player_t *player);
/*boolean P_TransferToNextMare(player_t *player);
UINT8 P_FindLowestMare(void);*/
@ -187,8 +188,6 @@ UINT8 P_FindHighestLap(void);
void P_FindEmerald(void);
//void P_TransferToAxis(player_t *player, INT32 axisnum);
boolean P_PlayerMoving(INT32 pnum);
void P_SpawnThokMobj(player_t *player);
void P_SpawnSpinMobj(player_t *player, mobjtype_t type);
void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range);
void P_PlayLivesJingle(player_t *player);

View file

@ -212,16 +212,16 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
object->angle = spring->angle;
if (!demoplayback || P_AnalogMove(object->player))
if (!demo.playback || P_AnalogMove(object->player))
{
if (object->player == &players[consoleplayer])
localangle = spring->angle;
else if (object->player == &players[secondarydisplayplayer])
localangle2 = spring->angle;
else if (object->player == &players[thirddisplayplayer])
localangle3 = spring->angle;
else if (object->player == &players[fourthdisplayplayer])
localangle4 = spring->angle;
localangle[0] = spring->angle;
else if (object->player == &players[displayplayers[1]])
localangle[1] = spring->angle;
else if (object->player == &players[displayplayers[2]])
localangle[2] = spring->angle;
else if (object->player == &players[displayplayers[3]])
localangle[3] = spring->angle;
}
}
@ -1076,7 +1076,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
S_StartSound(tmthing, sfx_bsnipe);
// Player Damage
K_SpinPlayer(tmthing->player, thing->target, 0, tmthing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD));
K_SpinPlayer(tmthing->player, thing->target, 0, thing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD));
// Other Item Damage
if (thing->eflags & MFE_VERTICALFLIP)
@ -1111,7 +1111,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->state == &states[S_MINEEXPLOSION1])
K_ExplodePlayer(tmthing->player, thing->target, thing);
else
K_SpinPlayer(tmthing->player, thing->target, 0, tmthing, false);
K_SpinPlayer(tmthing->player, thing->target, 0, thing, false);
return true;
}
@ -1264,16 +1264,16 @@ static boolean PIT_CheckThing(mobj_t *thing)
thing->angle = tmthing->angle;
if (!demoplayback || P_AnalogMove(thing->player))
if (!demo.playback || P_AnalogMove(thing->player))
{
if (thing->player == &players[consoleplayer])
localangle = thing->angle;
else if (thing->player == &players[secondarydisplayplayer])
localangle2 = thing->angle;
else if (thing->player == &players[thirddisplayplayer])
localangle3 = thing->angle;
else if (thing->player == &players[fourthdisplayplayer])
localangle4 = thing->angle;
localangle[0] = thing->angle;
else if (thing->player == &players[displayplayers[1]])
localangle[1] = thing->angle;
else if (thing->player == &players[displayplayers[2]])
localangle[2] = thing->angle;
else if (thing->player == &players[displayplayers[3]])
localangle[3] = thing->angle;
}
return true;
@ -1580,12 +1580,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (G_BattleGametype())
{
if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]))
if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible
{
K_StealBumper(thing->player, tmthing->player, false);
K_SpinPlayer(tmthing->player, thing, 0, tmthing, false);
}
else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]))
else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing]))
{
K_StealBumper(tmthing->player, thing->player, false);
K_SpinPlayer(thing->player, tmthing, 0, thing, false);
@ -2504,41 +2504,46 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
subsector_t *s = R_PointInSubsector(x, y);
boolean retval = true;
boolean itsatwodlevel = false;
UINT8 i;
floatok = false;
if (twodlevel
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera3 && players[thirddisplayplayer].mo && (players[thirddisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera4 && players[fourthdisplayplayer].mo && (players[fourthdisplayplayer].mo->flags2 & MF2_TWOD)))
if (twodlevel)
itsatwodlevel = true;
else
{
for (i = 0; i <= splitscreen; i++)
{
if (thiscam == &camera[i] && players[displayplayers[i]].mo
&& (players[displayplayers[i]].mo->flags2 & MF2_TWOD))
{
itsatwodlevel = true;
break;
}
}
}
if (!itsatwodlevel && players[displayplayer].mo)
if (!itsatwodlevel && players[displayplayers[0]].mo)
{
fixed_t tryx = thiscam->x;
fixed_t tryy = thiscam->y;
for (i = 0; i <= splitscreen; i++)
{
#ifndef NOCLIPCAM
if ((thiscam == &camera && (players[displayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera3 && (players[thirddisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP))
|| (leveltime < introtime))
if ((thiscam == &camera[i] && (players[displayplayers[i]].pflags & PF_NOCLIP)) || (leveltime < introtime)) // Noclipping player camera noclips too!!
#else
if ((thiscam == &camera && !(players[displayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera2 && !(players[secondarydisplayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera3 && !(players[thirddisplayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera4 && !(players[fourthdisplayplayer].pflags & PF_TIMEOVER)))
if (thiscam == &camera[i] && !(players[displayplayers[i]].pflags & PF_TIMEOVER)) // Time Over should not clip through walls
#endif
{ // Noclipping player camera noclips too!!
floatok = true;
thiscam->floorz = thiscam->z;
thiscam->ceilingz = thiscam->z + thiscam->height;
thiscam->x = x;
thiscam->y = y;
thiscam->subsector = s;
return true;
{
floatok = true;
thiscam->floorz = thiscam->z;
thiscam->ceilingz = thiscam->z + thiscam->height;
thiscam->x = x;
thiscam->y = y;
thiscam->subsector = s;
return true;
}
}
do {

View file

@ -339,9 +339,9 @@ void P_CameraLineOpening(line_t *linedef)
frontceiling = sectors[front->camsec].ceilingheight;
#ifdef ESLOPE
if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y);
frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera[0].x, camera[0].y);
if (sectors[front->camsec].c_slope)
frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y);
frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera[0].x, camera[0].y);
#endif
}
@ -351,9 +351,9 @@ void P_CameraLineOpening(line_t *linedef)
frontceiling = sectors[front->heightsec].ceilingheight;
#ifdef ESLOPE
if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y);
frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera[0].x, camera[0].y);
if (sectors[front->heightsec].c_slope)
frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y);
frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera[0].x, camera[0].y);
#endif
}
else
@ -367,9 +367,9 @@ void P_CameraLineOpening(line_t *linedef)
backceiling = sectors[back->camsec].ceilingheight;
#ifdef ESLOPE
if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y);
frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera[0].x, camera[0].y);
if (sectors[back->camsec].c_slope)
frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y);
frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera[0].x, camera[0].y);
#endif
}
else if (back->heightsec >= 0)
@ -378,9 +378,9 @@ void P_CameraLineOpening(line_t *linedef)
backceiling = sectors[back->heightsec].ceilingheight;
#ifdef ESLOPE
if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y);
frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera[0].x, camera[0].y);
if (sectors[back->heightsec].c_slope)
frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y);
frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera[0].x, camera[0].y);
#endif
}
else

View file

@ -1125,7 +1125,7 @@ static void P_PlayerFlip(mobj_t *mo)
if (!mo->player)
return;
G_GhostAddFlip();
G_GhostAddFlip((INT32) (mo->player - players));
// Flip aiming to match!
if (mo->player->pflags & PF_NIGHTSMODE) // NiGHTS doesn't use flipcam
@ -1135,45 +1135,21 @@ static void P_PlayerFlip(mobj_t *mo)
}
else if (mo->player->pflags & PF_FLIPCAM)
{
UINT8 i;
mo->player->aiming = InvAngle(mo->player->aiming);
if (mo->player-players == displayplayer)
for (i = 0; i <= splitscreen; i++)
{
localaiming = mo->player->aiming;
if (camera.chase) {
camera.aiming = InvAngle(camera.aiming);
camera.z = mo->z - camera.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera.z += FixedMul(20*FRACUNIT, mo->scale);
}
}
else if (mo->player-players == secondarydisplayplayer)
{
localaiming2 = mo->player->aiming;
if (camera2.chase) {
camera2.aiming = InvAngle(camera2.aiming);
camera2.z = mo->z - camera2.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera2.z += FixedMul(20*FRACUNIT, mo->scale);
}
}
else if (mo->player-players == thirddisplayplayer)
{
localaiming3 = mo->player->aiming;
if (camera3.chase) {
camera3.aiming = InvAngle(camera3.aiming);
camera3.z = mo->z - camera3.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera3.z += FixedMul(20*FRACUNIT, mo->scale);
}
}
else if (mo->player-players == fourthdisplayplayer)
{
localaiming4 = mo->player->aiming;
if (camera4.chase) {
camera4.aiming = InvAngle(camera4.aiming);
camera4.z = mo->z - camera4.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera4.z += FixedMul(20*FRACUNIT, mo->scale);
if (mo->player-players == displayplayers[i])
{
localaiming[i] = mo->player->aiming;
if (camera[i].chase) {
camera[i].aiming = InvAngle(camera[i].aiming);
camera[i].z = mo->z - camera[i].z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera[i].z += FixedMul(20*FRACUNIT, mo->scale);
}
}
}
}
@ -1932,7 +1908,7 @@ void P_XYMovement(mobj_t *mo)
if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG) //(mo->type == MT_JAWZ && !mo->tracer))
return;
if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= mo->player->normalspeed/2)
if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2)
return;
//}
@ -3546,17 +3522,26 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
{
boolean itsatwodlevel = false;
postimg_t postimg = postimg_none;
UINT8 i;
// This can happen when joining
if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL)
return true;
if (twodlevel
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera3 && players[thirddisplayplayer].mo && (players[thirddisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera4 && players[fourthdisplayplayer].mo && (players[fourthdisplayplayer].mo->flags2 & MF2_TWOD)))
if (twodlevel)
itsatwodlevel = true;
else
{
for (i = 0; i <= splitscreen; i++)
{
if (thiscam == &camera[i] && players[displayplayers[i]].mo
&& (players[displayplayers[i]].mo->flags2 & MF2_TWOD))
{
itsatwodlevel = true;
break;
}
}
}
if (encoremode)
postimg = postimg_mirror;
@ -3588,14 +3573,11 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
if (postimg != postimg_none)
{
if (splitscreen && player == &players[secondarydisplayplayer])
postimgtype2 = postimg;
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
postimgtype3 = postimg;
else if (splitscreen > 2 && player == &players[fourthdisplayplayer])
postimgtype4 = postimg;
else
postimgtype = postimg;
for (i = 0; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
postimgtype[i] = postimg;
}
}
if (thiscam->momx || thiscam->momy)
@ -3641,11 +3623,11 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
fixed_t cam_height = cv_cam_height.value;
thiscam->z = thiscam->floorz;
if (player == &players[secondarydisplayplayer])
if (player == &players[displayplayers[1]])
cam_height = cv_cam2_height.value;
if (player == &players[thirddisplayplayer])
if (player == &players[displayplayers[2]])
cam_height = cv_cam3_height.value;
if (player == &players[fourthdisplayplayer])
if (player == &players[displayplayers[3]])
cam_height = cv_cam4_height.value;
if (thiscam->z > player->mo->z + player->mo->height + FixedMul(cam_height*FRACUNIT + 16*FRACUNIT, player->mo->scale))
{
@ -5897,7 +5879,7 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale)
if (player)
{
G_GhostAddScale(newscale);
G_GhostAddScale((INT32) (player - players), newscale);
player->viewheight = FixedMul(FixedDiv(player->viewheight, oldscale), newscale); // Nonono don't calculate viewheight elsewhere, this is the best place for it!
player->dashspeed = FixedMul(FixedDiv(player->dashspeed, oldscale), newscale); // Prevents the player from having to re-charge up spindash if the player grew in size
}
@ -6101,12 +6083,12 @@ void P_RunOverlays(void)
{
angle_t viewingangle;
if (players[displayplayer].awayviewtics)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera.x, camera.y);
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera[0].x, camera[0].y);
if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
viewingangle += ANGLE_180;
@ -6680,7 +6662,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->target && mobj->target->health
&& mobj->target->player && !mobj->target->player->spectator
&& mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD
/*&& players[displayplayer].mo && !players[displayplayer].spectator*/)
/*&& players[displayplayers[0]].mo && !players[displayplayers[0]].spectator*/)
{
fixed_t scale = 3*mobj->target->scale;
mobj->color = mobj->target->color;
@ -6688,7 +6670,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0)
#if 1 // Set to 0 to test without needing to host
|| ((mobj->target->player == &players[displayplayer]) || P_IsLocalPlayer(mobj->target->player))
|| ((mobj->target->player == &players[displayplayers[0]]) || P_IsLocalPlayer(mobj->target->player))
#endif
)
mobj->flags2 |= MF2_DONTDRAW;
@ -6699,10 +6681,10 @@ void P_MobjThinker(mobj_t *mobj)
mobj->angle = R_PointToAngle(mobj->x, mobj->y) + ANGLE_90; // literally only happened because i wanted to ^L^R the SPR_ITEM's
if (!splitscreen && players[displayplayer].mo)
if (!splitscreen && players[displayplayers[0]].mo)
{
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x,
players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x,
players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
if (scale > 16*mobj->target->scale)
scale = 16*mobj->target->scale;
}
@ -6887,7 +6869,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->target && mobj->target->health && mobj->tracer
&& mobj->target->player && !mobj->target->player->spectator
&& mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD
&& players[displayplayer].mo && !players[displayplayer].spectator)
&& players[displayplayers[0]].mo && !players[displayplayers[0]].spectator)
{
fixed_t scale = 3*mobj->target->scale;
@ -6909,8 +6891,8 @@ void P_MobjThinker(mobj_t *mobj)
if (!splitscreen)
{
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x,
players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x,
players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
if (scale > 16*mobj->target->scale)
scale = 16*mobj->target->scale;
}
@ -8296,12 +8278,12 @@ void P_MobjThinker(mobj_t *mobj)
angle_t viewingangle;
statenum_t curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states)));
if (players[displayplayer].awayviewtics)
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo)
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera.x, camera.y);
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y);
if (curstate > S_THUNDERSHIELD15)
viewingangle += ANGLE_180;
@ -10562,13 +10544,13 @@ void P_PrecipitationEffects(void)
// Local effects from here on out!
// If we're not in game fully yet, we don't worry about them.
if (!playeringame[displayplayer] || !players[displayplayer].mo)
if (!playeringame[displayplayers[0]] || !players[displayplayers[0]].mo)
return;
if (sound_disabled)
return; // Sound off? D'aw, no fun.
if (players[displayplayer].mo->subsector->sector->ceilingpic == skyflatnum)
if (players[displayplayers[0]].mo->subsector->sector->ceilingpic == skyflatnum)
volume = 255; // Sky above? We get it full blast.
else
{
@ -10576,17 +10558,17 @@ void P_PrecipitationEffects(void)
fixed_t closedist, newdist;
// Essentially check in a 1024 unit radius of the player for an outdoor area.
yl = players[displayplayer].mo->y - 1024*FRACUNIT;
yh = players[displayplayer].mo->y + 1024*FRACUNIT;
xl = players[displayplayer].mo->x - 1024*FRACUNIT;
xh = players[displayplayer].mo->x + 1024*FRACUNIT;
yl = players[displayplayers[0]].mo->y - 1024*FRACUNIT;
yh = players[displayplayers[0]].mo->y + 1024*FRACUNIT;
xl = players[displayplayers[0]].mo->x - 1024*FRACUNIT;
xh = players[displayplayers[0]].mo->x + 1024*FRACUNIT;
closedist = 2048*FRACUNIT;
for (y = yl; y <= yh; y += FRACUNIT*64)
for (x = xl; x <= xh; x += FRACUNIT*64)
{
if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors!
{
newdist = S_CalculateSoundDistance(players[displayplayer].mo->x, players[displayplayer].mo->y, 0, x, y, 0);
newdist = S_CalculateSoundDistance(players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y, 0, x, y, 0);
if (newdist < closedist)
closedist = newdist;
}
@ -10601,7 +10583,7 @@ void P_PrecipitationEffects(void)
volume = 255;
if (sounds_rain && (!leveltime || leveltime % 80 == 1))
S_StartSoundAtVolume(players[displayplayer].mo, sfx_rainin, volume);
S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_rainin, volume);
if (!sounds_thunder)
return;
@ -10609,7 +10591,7 @@ void P_PrecipitationEffects(void)
if (effects_lightning && lightningStrike && volume)
{
// Large, close thunder sounds to go with our lightning.
S_StartSoundAtVolume(players[displayplayer].mo, sfx_litng1 + M_RandomKey(4), volume);
S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_litng1 + M_RandomKey(4), volume);
}
else if (thunderchance < 20)
{
@ -10617,7 +10599,7 @@ void P_PrecipitationEffects(void)
if (volume < 80)
volume = 80;
S_StartSoundAtVolume(players[displayplayer].mo, sfx_athun1 + M_RandomKey(2), volume);
S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_athun1 + M_RandomKey(2), volume);
}
}
@ -10789,7 +10771,8 @@ void P_SpawnPlayer(INT32 playernum)
}
// spawn as spectator determination
if (!G_GametypeHasSpectators())
if (multiplayer && demo.playback); // Don't mess with spectator values since the demo setup handles them already.
else if (!G_GametypeHasSpectators())
p->spectator = false;
else if (netgame && p->jointime <= 1 && pcount)
{
@ -10923,15 +10906,21 @@ void P_AfterPlayerSpawn(INT32 playernum)
{
player_t *p = &players[playernum];
mobj_t *mobj = p->mo;
UINT8 i;
if (playernum == consoleplayer)
localangle = mobj->angle;
else if (playernum == secondarydisplayplayer)
localangle2 = mobj->angle;
else if (playernum == thirddisplayplayer)
localangle3 = mobj->angle;
else if (playernum == fourthdisplayplayer)
localangle4 = mobj->angle;
localangle[0] = mobj->angle;
else if (splitscreen)
{
for (i = 1; i <= splitscreen; i++)
{
if (playernum == displayplayers[i])
{
localangle[i] = mobj->angle;
break;
}
}
}
p->viewheight = 32<<FRACBITS;
@ -10953,25 +10942,13 @@ void P_AfterPlayerSpawn(INT32 playernum)
SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle);
if (camera.chase)
for (i = 0; i <= splitscreen; i++)
{
if (displayplayer == playernum)
P_ResetCamera(p, &camera);
}
if (camera2.chase && splitscreen)
{
if (secondarydisplayplayer == playernum)
P_ResetCamera(p, &camera2);
}
if (camera3.chase && splitscreen > 1)
{
if (thirddisplayplayer == playernum)
P_ResetCamera(p, &camera3);
}
if (camera4.chase && splitscreen > 2)
{
if (fourthdisplayplayer == playernum)
P_ResetCamera(p, &camera4);
if (camera[i].chase)
{
if (displayplayers[i] == playernum)
P_ResetCamera(p, &camera[i]);
}
}
if (CheckForReverseGravity)

View file

@ -1336,13 +1336,13 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta;
if (mo->player == &players[consoleplayer])
localangle = mo->angle;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle;
else if (mo->player == &players[thirddisplayplayer])
localangle3 = mo->angle;
else if (mo->player == &players[fourthdisplayplayer])
localangle4 = mo->angle;
localangle[0] += delta;
else if (mo->player == &players[displayplayers[1]])
localangle[1] += delta;
else if (mo->player == &players[displayplayers[2]])
localangle[2] += delta;
else if (mo->player == &players[displayplayers[3]])
localangle[3] += delta;
}
}
}

View file

@ -265,25 +265,11 @@ static void P_NetArchivePlayers(void)
if (flags & AWAYVIEW)
WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum);
WRITEUINT8(save_p, players[i].charability);
WRITEUINT8(save_p, players[i].charability2);
WRITEUINT32(save_p, players[i].charflags);
WRITEUINT32(save_p, (UINT32)players[i].thokitem);
WRITEUINT32(save_p, (UINT32)players[i].spinitem);
WRITEUINT32(save_p, (UINT32)players[i].revitem);
WRITEFIXED(save_p, players[i].actionspd);
WRITEFIXED(save_p, players[i].mindash);
WRITEFIXED(save_p, players[i].maxdash);
// SRB2kart
WRITEUINT8(save_p, players[i].kartspeed);
WRITEUINT8(save_p, players[i].kartweight);
//
WRITEFIXED(save_p, players[i].normalspeed);
WRITEFIXED(save_p, players[i].runspeed);
WRITEUINT8(save_p, players[i].thrustfactor);
WRITEUINT8(save_p, players[i].accelstart);
WRITEUINT8(save_p, players[i].acceleration);
WRITEFIXED(save_p, players[i].jumpfactor);
for (j = 0; j < MAXPREDICTTICS; j++)
{
@ -447,25 +433,11 @@ static void P_NetUnArchivePlayers(void)
players[i].viewheight = 32<<FRACBITS;
//SetPlayerSkinByNum(i, players[i].skin);
players[i].charability = READUINT8(save_p);
players[i].charability2 = READUINT8(save_p);
players[i].charflags = READUINT32(save_p);
players[i].thokitem = (mobjtype_t)READUINT32(save_p);
players[i].spinitem = (mobjtype_t)READUINT32(save_p);
players[i].revitem = (mobjtype_t)READUINT32(save_p);
players[i].actionspd = READFIXED(save_p);
players[i].mindash = READFIXED(save_p);
players[i].maxdash = READFIXED(save_p);
// SRB2kart
players[i].kartspeed = READUINT8(save_p);
players[i].kartweight = READUINT8(save_p);
//
players[i].normalspeed = READFIXED(save_p);
players[i].runspeed = READFIXED(save_p);
players[i].thrustfactor = READUINT8(save_p);
players[i].accelstart = READUINT8(save_p);
players[i].acceleration = READUINT8(save_p);
players[i].jumpfactor = READFIXED(save_p);
for (j = 0; j < MAXPREDICTTICS; j++)
{
@ -2106,13 +2078,13 @@ static void LoadMobjThinker(actionf_p1 thinker)
mobj->player->mo = mobj;
// added for angle prediction
if (consoleplayer == i)
localangle = mobj->angle;
if (secondarydisplayplayer == i)
localangle2 = mobj->angle;
if (thirddisplayplayer == i)
localangle3 = mobj->angle;
if (fourthdisplayplayer == i)
localangle4 = mobj->angle;
localangle[0] = mobj->angle;
if (displayplayers[1] == i)
localangle[1] = mobj->angle;
if (displayplayers[2] == i)
localangle[2] = mobj->angle;
if (displayplayers[3] == i)
localangle[3] = mobj->angle;
}
if (diff & MD_MOVEDIR)
mobj->movedir = READANGLE(save_p);
@ -3451,7 +3423,7 @@ void P_SaveNetGame(void)
mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p);
CV_SaveNetVars(&save_p, false);
P_NetArchiveMisc();
// Assign the mobjnumber for pointer tracking

View file

@ -65,6 +65,10 @@
#include "lua_script.h"
#include "lua_hook.h"
#if !defined (UNDER_CE)
#include <time.h>
#endif
#if defined (_WIN32) || defined (_WIN32_WCE)
#include <malloc.h>
#include <math.h>
@ -195,6 +199,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->musname[6] = 0;
DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
mapheaderinfo[num]->mustrack = 0;
DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE);
mapheaderinfo[num]->muspos = 0;
DEH_WriteUndoline("MUSICINTERFADEOUT", va("%d", mapheaderinfo[num]->musinterfadeout), UNDO_NONE);
mapheaderinfo[num]->musinterfadeout = 0;
DEH_WriteUndoline("MUSICINTER", mapheaderinfo[num]->musintername, UNDO_NONE);
mapheaderinfo[num]->musintername[0] = '\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);
@ -1546,19 +1556,33 @@ static void P_LoadRawSideDefs2(void *data)
{
M_Memcpy(process,msd->bottomtexture,8);
process[8] = '\0';
sd->bottomtexture = get_number(process)-1;
sd->bottomtexture = get_number(process);
}
M_Memcpy(process,msd->toptexture,8);
process[8] = '\0';
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
// If they type in O_ or D_ and their music name, just shrug,
// then copy the rest instead.
if ((process[0] == 'O' || process[0] == 'D') && process[7])
M_Memcpy(sd->text, process+2, 6);
else // Assume it's a proper music name.
M_Memcpy(sd->text, process, 6);
sd->text[6] = 0;
if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0')
{
M_Memcpy(process,msd->midtexture,8);
process[8] = '\0';
sd->midtexture = get_number(process);
}
// always process if back sidedef, because we need that - symbol
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0')
{
M_Memcpy(process,msd->toptexture,8);
process[8] = '\0';
// If they type in O_ or D_ and their music name, just shrug,
// then copy the rest instead.
if ((process[0] == 'O' || process[0] == 'D') && process[7])
M_Memcpy(sd->text, process+2, 6);
else // Assume it's a proper music name.
M_Memcpy(sd->text, process, 6);
sd->text[6] = 0;
}
else
sd->text[0] = 0;
break;
}
@ -2267,7 +2291,7 @@ static void P_LevelInitStuff(void)
leveltime = 0;
localaiming = localaiming2 = localaiming3 = localaiming4 = 0;
memset(localaiming, 0, sizeof(localaiming));
// map object scale
mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale;
@ -2534,29 +2558,29 @@ static void P_ForceCharacter(const char *forcecharskin)
{
if (splitscreen)
{
SetPlayerSkin(secondarydisplayplayer, forcecharskin);
if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin].prefcolor && !modeattacking)
SetPlayerSkin(displayplayers[1], forcecharskin);
if ((unsigned)cv_playercolor2.value != skins[players[displayplayers[1]].skin].prefcolor && !modeattacking)
{
CV_StealthSetValue(&cv_playercolor2, skins[players[secondarydisplayplayer].skin].prefcolor);
players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin].prefcolor;
CV_StealthSetValue(&cv_playercolor2, skins[players[displayplayers[1]].skin].prefcolor);
players[displayplayers[1]].skincolor = skins[players[displayplayers[1]].skin].prefcolor;
}
if (splitscreen > 1)
{
SetPlayerSkin(thirddisplayplayer, forcecharskin);
if ((unsigned)cv_playercolor3.value != skins[players[thirddisplayplayer].skin].prefcolor && !modeattacking)
SetPlayerSkin(displayplayers[2], forcecharskin);
if ((unsigned)cv_playercolor3.value != skins[players[displayplayers[2]].skin].prefcolor && !modeattacking)
{
CV_StealthSetValue(&cv_playercolor3, skins[players[thirddisplayplayer].skin].prefcolor);
players[thirddisplayplayer].skincolor = skins[players[thirddisplayplayer].skin].prefcolor;
CV_StealthSetValue(&cv_playercolor3, skins[players[displayplayers[2]].skin].prefcolor);
players[displayplayers[2]].skincolor = skins[players[displayplayers[2]].skin].prefcolor;
}
if (splitscreen > 2)
{
SetPlayerSkin(fourthdisplayplayer, forcecharskin);
if ((unsigned)cv_playercolor4.value != skins[players[fourthdisplayplayer].skin].prefcolor && !modeattacking)
SetPlayerSkin(displayplayers[3], forcecharskin);
if ((unsigned)cv_playercolor4.value != skins[players[displayplayers[3]].skin].prefcolor && !modeattacking)
{
CV_StealthSetValue(&cv_playercolor4, skins[players[fourthdisplayplayer].skin].prefcolor);
players[fourthdisplayplayer].skincolor = skins[players[fourthdisplayplayer].skin].prefcolor;
CV_StealthSetValue(&cv_playercolor4, skins[players[displayplayers[3]].skin].prefcolor);
players[displayplayers[3]].skincolor = skins[players[displayplayers[3]].skin].prefcolor;
}
}
}
@ -2727,7 +2751,7 @@ static boolean P_CanSave(void)
if ((cursaveslot < 0) // Playing without saving
|| (modifiedgame && !savemoddata) // Game is modified
|| (netgame || multiplayer) // Not in single-player
|| (demoplayback || demorecording || metalrecording) // Currently in demo
|| (demo.playback || demo.recording || metalrecording) // Currently in demo
|| (players[consoleplayer].lives <= 0) // Completely dead
|| (modeattacking || ultimatemode || G_IsSpecialStage(gamemap))) // Specialized instances
return false;
@ -2791,7 +2815,8 @@ boolean P_SetupLevel(boolean skipprecip)
P_LevelInitStuff();
postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none;
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'
&& atoi(mapheaderinfo[gamemap-1]->forcecharacter) != 255)
@ -2827,7 +2852,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Encore mode fade to pink to white
// This is handled BEFORE sounds are stopped.
if (rendermode != render_none && encoremode && !prevencoremode)
if (rendermode != render_none && encoremode && !prevencoremode && !demo.rewinding)
{
tic_t locstarttime, endtime, nowtime;
@ -2879,7 +2904,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Let's fade to white here
// But only if we didn't do the encore startup wipe
if (rendermode != render_none && !ranspecialwipe)
if (rendermode != render_none && !ranspecialwipe && !demo.rewinding)
{
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
@ -3111,9 +3136,9 @@ boolean P_SetupLevel(boolean skipprecip)
}
}
if (modeattacking == ATTACKING_RECORD && !demoplayback)
if (modeattacking == ATTACKING_RECORD && !demo.playback)
P_LoadRecordGhosts();
/*else if (modeattacking == ATTACKING_NIGHTS && !demoplayback)
/*else if (modeattacking == ATTACKING_NIGHTS && !demo.playback)
P_LoadNightsGhosts();*/
if (G_TagGametype())
@ -3161,25 +3186,25 @@ boolean P_SetupLevel(boolean skipprecip)
? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps);
// Start recording replay in multiplayer with a temp filename
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
if (!demo.playback && multiplayer && !dedicated) {
static char buf[256];
sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap));
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
G_RecordDemo(buf);
}
// ===========
// landing point for netgames.
netgameskip:
if (!dedicated)
{
P_SetupCamera(displayplayer, &camera);
if (splitscreen)
{
P_SetupCamera(secondarydisplayplayer, &camera2);
if (splitscreen > 1)
{
P_SetupCamera(thirddisplayplayer, &camera3);
if (splitscreen > 2)
{
P_SetupCamera(fourthdisplayplayer, &camera4);
}
}
}
for (i = 0; i <= splitscreen; i++)
P_SetupCamera(displayplayers[i], &camera[i]);
// Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_height.changed)
@ -3220,7 +3245,7 @@ boolean P_SetupLevel(boolean skipprecip)
/*if (rendermode != render_none)
CV_Set(&cv_fov, cv_fov.defaultvalue);*/
displayplayer = consoleplayer; // Start with your OWN view, please!
displayplayers[0] = consoleplayer; // Start with your OWN view, please!
}
/*if (cv_useranalog.value)
@ -3299,7 +3324,10 @@ boolean P_SetupLevel(boolean skipprecip)
savedata.lives = 0;
}
skyVisible = skyVisible1 = skyVisible2 = skyVisible3 = skyVisible4 = true; // assume the skybox is visible on level load.
// assume the skybox is visible on level load.
skyVisible = true;
memset(skyVisiblePerPlayer, true, sizeof(skyVisiblePerPlayer));
if (loadprecip) // uglier hack
{ // to make a newly loaded level start on the second frame.
INT32 buf = gametic % BACKUPTICS;

View file

@ -264,7 +264,7 @@ void P_SpawnSlope_Line(int linenum)
if(!line->frontsector || !line->backsector)
{
CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
CONS_Debug(DBG_SETUP, "P_SpawnSlope_Line used on a line without two sides. (line number %i)\n", linenum);
return;
}

View file

@ -2243,7 +2243,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid!
if (mo && mo->player && botingame)
bot = players[secondarydisplayplayer].mo;
bot = players[displayplayers[1]].mo;
// note: only commands with linedef types >= 400 && < 500 can be used
switch (line->special)
@ -2381,35 +2381,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (mo->player)
{
UINT8 i;
if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3
P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z);
if (splitscreen > 2 && mo->player == &players[fourthdisplayplayer] && camera4.chase)
for (i = 0; i <= splitscreen; i++)
{
camera4.x += x;
camera4.y += y;
camera4.z += z;
camera4.subsector = R_PointInSubsector(camera4.x, camera4.y);
}
else if (splitscreen > 1 && mo->player == &players[thirddisplayplayer] && camera3.chase)
{
camera3.x += x;
camera3.y += y;
camera3.z += z;
camera3.subsector = R_PointInSubsector(camera3.x, camera3.y);
}
else if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase)
{
camera2.x += x;
camera2.y += y;
camera2.z += z;
camera2.subsector = R_PointInSubsector(camera2.x, camera2.y);
}
else if (camera.chase && mo->player == &players[displayplayer])
{
camera.x += x;
camera.y += y;
camera.z += z;
camera.subsector = R_PointInSubsector(camera.x, camera.y);
if (mo->player == &players[displayplayers[i]] && camera[i].chase)
{
camera[i].x += x;
camera[i].y += y;
camera[i].z += z;
camera[i].subsector = R_PointInSubsector(camera[i].x, camera[i].y);
break;
}
}
}
}
@ -2440,18 +2426,71 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// console player only unless NOCLIMB is set
if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)))
{
UINT16 tracknum = (UINT16)sides[line->sidenum[0]].bottomtexture;
boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7));
UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0);
INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0);
UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0);
UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0);
UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0);
INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1);
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
mapmusname[6] = 0;
// Seek offset from current song position
if (line->flags & ML_EFFECT1)
{
// adjust for loop point if subtracting
if (position < 0 && S_GetMusicLength() &&
S_GetMusicPosition() > S_GetMusicLoopPoint() &&
S_GetMusicPosition() + position < S_GetMusicLoopPoint())
position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0);
else
position = max(S_GetMusicPosition() + position, 0);
}
mapmusflags = tracknum & MUSIC_TRACKMASK;
if (!(line->flags & ML_BLOCKMONSTERS))
mapmusflags |= MUSIC_RELOADRESET;
// Fade current music to target volume (if music won't be changed)
if ((line->flags & ML_EFFECT2) && fadetarget && musicsame)
{
// 0 fadesource means fade from current volume.
// meaning that we can't specify volume 0 as the source volume -- this starts at 1.
if (!fadesource)
fadesource = -1;
S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
if (!(line->flags & ML_EFFECT3))
S_ShowMusicCredit();
if (!postfadems)
S_SetInternalMusicVolume(fadetarget);
else
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
if (!(line->flags & ML_EFFECT3))
S_ShowMusicCredit();
if (position)
S_SetMusicPosition(position);
}
// Change the music and apply position/fade operations
else
{
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
mapmusname[6] = 0;
mapmusflags = tracknum & MUSIC_TRACKMASK;
if (!(line->flags & ML_BLOCKMONSTERS))
mapmusflags |= MUSIC_RELOADRESET;
if (line->flags & ML_BOUNCY)
mapmusflags |= MUSIC_FORCERESET;
mapmusposition = position;
S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position,
!(line->flags & ML_EFFECT2) ? prefadems : 0,
!(line->flags & ML_EFFECT2) ? postfadems : 0);
if ((line->flags & ML_EFFECT2) && fadetarget)
{
if (!postfadems)
S_SetInternalMusicVolume(fadetarget);
else
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
}
}
// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
@ -2515,8 +2554,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (line->flags & ML_NOCLIMB)
{
// play the sound from nowhere, but only if display player triggered it
if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer]
|| mo->player == &players[thirddisplayplayer] || mo->player == &players[fourthdisplayplayer]))
if (mo && mo->player && P_IsDisplayPlayer(mo->player))
S_StartSound(NULL, sfxnum);
}
else if (line->flags & ML_EFFECT4)
@ -3834,16 +3872,16 @@ DoneSection2:
if (player->mo->scale > mapobjectscale)
linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale));
if (!demoplayback || P_AnalogMove(player))
if (!demo.playback || P_AnalogMove(player))
{
if (player == &players[consoleplayer])
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
localangle[0] = player->mo->angle;
else if (player == &players[displayplayers[1]])
localangle[1] = player->mo->angle;
else if (player == &players[displayplayers[2]])
localangle[2] = player->mo->angle;
else if (player == &players[displayplayers[3]])
localangle[3] = player->mo->angle;
}
if (!(lines[i].flags & ML_EFFECT4))
@ -7841,44 +7879,44 @@ void T_Pusher(pusher_t *p)
thing->player->pflags |= PF_SLIDING;
thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR));
if (!demoplayback || P_AnalogMove(thing->player))
if (!demo.playback || P_AnalogMove(thing->player))
{
if (thing->player == &players[consoleplayer])
{
if (thing->angle - localangle > ANGLE_180)
localangle -= (localangle - thing->angle) / 8;
if (thing->angle - localangle[0] > ANGLE_180)
localangle[0] -= (localangle[0] - thing->angle) / 8;
else
localangle += (thing->angle - localangle) / 8;
localangle[0] += (thing->angle - localangle[0]) / 8;
}
else if (thing->player == &players[secondarydisplayplayer])
else if (thing->player == &players[displayplayers[1]])
{
if (thing->angle - localangle2 > ANGLE_180)
localangle2 -= (localangle2 - thing->angle) / 8;
if (thing->angle - localangle[1] > ANGLE_180)
localangle[1] -= (localangle[1] - thing->angle) / 8;
else
localangle2 += (thing->angle - localangle2) / 8;
localangle[1] += (thing->angle - localangle[1]) / 8;
}
else if (thing->player == &players[thirddisplayplayer])
else if (thing->player == &players[displayplayers[2]])
{
if (thing->angle - localangle3 > ANGLE_180)
localangle3 -= (localangle3 - thing->angle) / 8;
if (thing->angle - localangle[2] > ANGLE_180)
localangle[2] -= (localangle[2] - thing->angle) / 8;
else
localangle3 += (thing->angle - localangle3) / 8;
localangle[2] += (thing->angle - localangle[2]) / 8;
}
else if (thing->player == &players[fourthdisplayplayer])
else if (thing->player == &players[displayplayers[3]])
{
if (thing->angle - localangle4 > ANGLE_180)
localangle4 -= (localangle4 - thing->angle) / 8;
if (thing->angle - localangle[3] > ANGLE_180)
localangle[3] -= (localangle[3] - thing->angle) / 8;
else
localangle4 += (thing->angle - localangle4) / 8;
localangle[3] += (thing->angle - localangle[3]) / 8;
}
/*if (thing->player == &players[consoleplayer])
localangle = thing->angle;
else if (thing->player == &players[secondarydisplayplayer])
localangle2 = thing->angle;
else if (thing->player == &players[thirddisplayplayer])
localangle3 = thing->angle;
else if (thing->player == &players[fourthdisplayplayer])
localangle4 = thing->angle;*/
localangle[0] = thing->angle;
else if (thing->player == &players[displayplayers[1]])
localangle[1] = thing->angle;
else if (thing->player == &players[displayplayers[2]])
localangle[2] = thing->angle;
else if (thing->player == &players[displayplayers[3]])
localangle[3] = thing->angle;*/
}
}

View file

@ -36,6 +36,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
INT32 flags2)
{
const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
UINT8 i;
// the move is ok,
// so link the thing into its new position
@ -64,23 +65,25 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
// absolute angle position
if (thing == players[consoleplayer].mo)
localangle = angle;
if (thing == players[secondarydisplayplayer].mo)
localangle2 = angle;
if (thing == players[thirddisplayplayer].mo)
localangle3 = angle;
if (thing == players[fourthdisplayplayer].mo)
localangle4 = angle;
localangle[0] = angle;
else if (splitscreen)
{
for (i = 1; i <= splitscreen; i++)
{
if (thing == players[displayplayers[i]].mo)
{
localangle[i] = angle;
break;
}
}
}
// move chasecam at new player location
if (splitscreen > 2 && camera4.chase && thing->player == &players[fourthdisplayplayer])
P_ResetCamera(thing->player, &camera4);
else if (splitscreen > 1 && camera3.chase && thing->player == &players[thirddisplayplayer])
P_ResetCamera(thing->player, &camera3);
else if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])
P_ResetCamera(thing->player, &camera2);
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
for (i = 0; i <= splitscreen; i++)
{
if (thing->player == &players[displayplayers[i]] && camera[i].chase)
P_ResetCamera(thing->player, &camera[i]);
}
// don't run in place after a teleport
thing->player->cmomx = thing->player->cmomy = 0;
@ -123,6 +126,8 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
*/
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove)
{
UINT8 i;
if (!P_TeleportMove(thing, x, y, z))
return false;
@ -144,24 +149,26 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
thing->reactiontime = TICRATE/2; // don't move for about half a second
// absolute angle position
if (thing->player == &players[consoleplayer])
localangle = angle;
if (thing->player == &players[secondarydisplayplayer])
localangle2 = angle;
if (thing->player == &players[thirddisplayplayer])
localangle3 = angle;
if (thing->player == &players[fourthdisplayplayer])
localangle4 = angle;
if (thing == players[consoleplayer].mo)
localangle[0] = angle;
else if (splitscreen)
{
for (i = 1; i <= splitscreen; i++)
{
if (thing == players[displayplayers[i]].mo)
{
localangle[i] = angle;
break;
}
}
}
// move chasecam at new player location
if (splitscreen > 2 && camera4.chase && thing->player == &players[fourthdisplayplayer])
P_ResetCamera(thing->player, &camera4);
else if (splitscreen > 1 && camera3.chase && thing->player == &players[thirddisplayplayer])
P_ResetCamera(thing->player, &camera3);
else if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])
P_ResetCamera(thing->player, &camera2);
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
for (i = 0; i <= splitscreen; i++)
{
if (thing->player == &players[displayplayers[i]] && camera[i].chase)
P_ResetCamera(thing->player, &camera[i]);
}
// don't run in place after a teleport
if (!dontstopmove)

View file

@ -13,6 +13,7 @@
#include "doomstat.h"
#include "g_game.h"
#include "g_input.h"
#include "p_local.h"
#include "z_zone.h"
#include "s_sound.h"
@ -582,7 +583,7 @@ void P_Ticker(boolean run)
{
P_MapStart();
OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera, false);
P_MoveChaseCamera(&players[0], &camera[0], false);
P_MapEnd();
return;
}
@ -590,18 +591,60 @@ void P_Ticker(boolean run)
// Check for pause or menu up in single player
if (paused || P_AutoPause())
return;
{
if (demo.rewinding && leveltime > 0)
{
leveltime = (leveltime-1) & ~3;
G_PreviewRewind(leveltime);
}
postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none;
return;
}
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
P_MapStart();
if (run)
{
if (demorecording)
G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0);
if (demoplayback)
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
if (demo.recording)
{
G_WriteDemoExtraData();
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
G_WriteDemoTiccmd(&players[i].cmd, i);
}
if (demo.playback)
{
#ifdef DEMO_COMPAT_100
if (demo.version == 0x0001)
{
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
}
else
{
#endif
G_ReadDemoExtraData();
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
//@TODO all this throwdir stuff shouldn't be here! But it's added to maintain 1.0.4 compat for now...
// Remove for 1.1!
if (players[i].cmd.buttons & BT_FORWARD)
players[i].kartstuff[k_throwdir] = 1;
else if (players[i].cmd.buttons & BT_BACKWARD)
players[i].kartstuff[k_throwdir] = -1;
else
players[i].kartstuff[k_throwdir] = 0;
G_ReadDemoTiccmd(&players[i].cmd, i);
}
#ifdef DEMO_COMPAT_100
}
#endif
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
@ -609,7 +652,7 @@ void P_Ticker(boolean run)
}
// Keep track of how long they've been playing!
if (!demoplayback) // Don't increment if a demo is playing.
if (!demo.playback) // Don't increment if a demo is playing.
totalplaytime++;
/*if (!useNightsSS && G_IsSpecialStage(gamemap))
@ -705,10 +748,25 @@ void P_Ticker(boolean run)
G_ReadMetalTic(metalplayback);
if (metalrecording)
G_WriteMetalTic(players[consoleplayer].mo);
if (demorecording)
G_WriteGhostTic(players[consoleplayer].mo);
if (demoplayback) // Use Ghost data for consistency checks.
G_ConsGhostTic();
if (demo.recording)
{
G_WriteAllGhostTics();
if (cv_recordmultiplayerdemos.value && (demo.savemode == DSM_NOTSAVING || demo.savemode == DSM_WILLAUTOSAVE))
if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1))
demo.savemode = DSM_TITLEENTRY;
}
else if (demo.playback) // Use Ghost data for consistency checks.
{
#ifdef DEMO_COMPAT_100
if (demo.version == 0x0001)
G_ConsGhostTic(0);
else
#endif
G_ConsAllGhostTics();
}
if (modeattacking)
G_GhostTicker();
@ -719,17 +777,17 @@ void P_Ticker(boolean run)
}
// Always move the camera.
if (camera.chase)
P_MoveChaseCamera(&players[displayplayer], &camera, false);
if (splitscreen && camera2.chase)
P_MoveChaseCamera(&players[secondarydisplayplayer], &camera2, false);
if (splitscreen > 1 && camera3.chase)
P_MoveChaseCamera(&players[thirddisplayplayer], &camera3, false);
if (splitscreen > 2 && camera4.chase)
P_MoveChaseCamera(&players[fourthdisplayplayer], &camera4, false);
for (i = 0; i <= splitscreen; i++)
{
if (camera[i].chase)
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
}
P_MapEnd();
if (demo.playback)
G_StoreRewindInfo();
// Z_CheckMemCleanup();
}
@ -739,7 +797,8 @@ void P_PreTicker(INT32 frames)
INT32 i,framecnt;
ticcmd_t temptic;
postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none;
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
for (framecnt = 0; framecnt < frames; ++framecnt)
{

File diff suppressed because it is too large Load diff

View file

@ -252,20 +252,23 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
mobj_t *viewmobj = viewplayer->mo;
INT32 heightsec;
boolean underwater;
UINT8 i;
if (splitscreen > 2 && viewplayer == &players[fourthdisplayplayer] && camera4.chase)
heightsec = R_PointInSubsector(camera4.x, camera4.y)->sector->heightsec;
else if (splitscreen > 1 && viewplayer == &players[thirddisplayplayer] && camera3.chase)
heightsec = R_PointInSubsector(camera3.x, camera3.y)->sector->heightsec;
else if (splitscreen && viewplayer == &players[secondarydisplayplayer] && camera2.chase)
heightsec = R_PointInSubsector(camera2.x, camera2.y)->sector->heightsec;
else if (camera.chase && viewplayer == &players[displayplayer])
heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec;
else if (viewmobj)
for (i = 0; i <= splitscreen; i++)
{
if (viewplayer == &players[displayplayers[i]] && camera[i].chase)
{
heightsec = R_PointInSubsector(camera[i].x, camera[i].y)->sector->heightsec;
break;
}
}
if (i > splitscreen && viewmobj)
heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec;
else
return sec;
underwater = heightsec != -1 && viewz <= sectors[heightsec].floorheight;
underwater = (heightsec != -1 && viewz <= sectors[heightsec].floorheight);
// Replace sector being drawn, with a copy to be hacked
*tempsec = *sec;
@ -827,7 +830,7 @@ static void R_AddPolyObjects(subsector_t *sub)
drawseg_t *firstseg;
static void R_Subsector(size_t num, UINT8 viewnumber)
static void R_Subsector(size_t num)
{
INT32 count, floorlightlevel, ceilinglightlevel, light;
seg_t *line;
@ -1149,7 +1152,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber)
// Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way,
// like passing it as an argument.
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2, viewnumber);
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2);
firstseg = NULL;
@ -1355,7 +1358,7 @@ INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside)
//
// killough 5/2/98: reformatted, removed tail recursion
void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber)
void R_RenderBSPNode(INT32 bspnum)
{
node_t *bsp;
INT32 side;
@ -1366,7 +1369,7 @@ void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber)
// Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp);
// Recursively divide front space.
R_RenderBSPNode(bsp->children[side], viewnumber);
R_RenderBSPNode(bsp->children[side]);
// Possibly divide back space.
@ -1384,5 +1387,5 @@ void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber)
portalcullsector = NULL;
}
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR, viewnumber);
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}

View file

@ -37,7 +37,7 @@ extern INT32 doorclosed;
void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber);
void R_RenderBSPNode(INT32 bspnum);
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2);
#ifdef POLYOBJECTS

View file

@ -1600,7 +1600,7 @@ void R_PrecacheLevel(void)
thinker_t *th;
spriteframe_t *sf;
if (demoplayback)
if (demo.playback)
return;
// do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap()

View file

@ -30,6 +30,7 @@
#include "p_spec.h" // skyboxmo
#include "z_zone.h"
#include "m_random.h" // quake camera shake
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -65,9 +66,10 @@ size_t loopcount;
fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle;
UINT8 viewssnum;
fixed_t viewcos, viewsin;
boolean viewsky, skyVisible;
boolean skyVisible1, skyVisible2, skyVisible3, skyVisible4; // saved values of skyVisible for P1/P2/P3/P4, for splitscreen
boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player
sector_t *viewsector;
player_t *viewplayer;
@ -193,19 +195,12 @@ void SplitScreen_OnChange(void)
// recompute screen size
R_ExecuteSetViewSize();
if (!demoplayback && !botingame)
if (!demo.playback && !botingame)
{
for (i = 1; i < 3; i++)
for (i = 1; i < MAXSPLITSCREENPLAYERS; i++)
{
if (i > splitscreen)
{
if (i == 1)
CL_RemoveSplitscreenPlayer(secondarydisplayplayer);
else if (i == 2)
CL_RemoveSplitscreenPlayer(thirddisplayplayer);
else if (i == 3)
CL_RemoveSplitscreenPlayer(fourthdisplayplayer);
}
CL_RemoveSplitscreenPlayer(displayplayers[i]);
else
CL_AddSplitscreenPlayer();
}
@ -215,21 +210,27 @@ void SplitScreen_OnChange(void)
}
else
{
secondarydisplayplayer = consoleplayer;
thirddisplayplayer = consoleplayer;
fourthdisplayplayer = consoleplayer;
for (i = 1; i < MAXSPLITSCREENPLAYERS; i++)
displayplayers[i] = consoleplayer;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && i != consoleplayer)
{
if (secondarydisplayplayer == consoleplayer)
secondarydisplayplayer = i;
else if (thirddisplayplayer == consoleplayer)
thirddisplayplayer = i;
else if (fourthdisplayplayer == consoleplayer)
fourthdisplayplayer = i;
else
UINT8 j;
for (j = 1; j < MAXSPLITSCREENPLAYERS; j++)
{
if (displayplayers[j] == consoleplayer)
{
displayplayers[j] = i;
break;
}
}
if (j == MAXSPLITSCREENPLAYERS)
break;
}
}
}
}
static void Fov_OnChange(void)
@ -844,16 +845,20 @@ static void R_SetupFreelook(void)
void R_SkyboxFrame(player_t *player)
{
camera_t *thiscam;
camera_t *thiscam = &camera[0];
UINT8 i;
if (splitscreen > 2 && player == &players[fourthdisplayplayer])
thiscam = &camera4;
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
thiscam = &camera3;
else if (splitscreen && player == &players[secondarydisplayplayer])
thiscam = &camera2;
else
thiscam = &camera;
if (splitscreen)
{
for (i = 1; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
thiscam = &camera[i];
break;
}
}
}
// cut-away view stuff
viewsky = true;
@ -879,27 +884,24 @@ void R_SkyboxFrame(player_t *player)
{
aimingangle = player->aiming;
viewangle = player->mo->angle;
if (/*!demoplayback && */player->playerstate != PST_DEAD)
if (/*!demo.playback && */player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{
viewangle = localangle; // WARNING: camera uses this
aimingangle = localaiming;
viewangle = localangle[0]; // WARNING: camera uses this
aimingangle = localaiming[0];
}
else if (player == &players[secondarydisplayplayer])
else if (splitscreen)
{
viewangle = localangle2;
aimingangle = localaiming2;
}
else if (player == &players[thirddisplayplayer])
{
viewangle = localangle3;
aimingangle = localaiming3;
}
else if (player == &players[fourthdisplayplayer])
{
viewangle = localangle4;
aimingangle = localaiming4;
for (i = 1; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
viewangle = localangle[i];
aimingangle = localaiming[i];
break;
}
}
}
}
}
@ -1078,24 +1080,24 @@ void R_SetupFrame(player_t *player, boolean skybox)
camera_t *thiscam;
boolean chasecam = false;
if (splitscreen > 2 && player == &players[fourthdisplayplayer])
if (splitscreen > 2 && player == &players[displayplayers[3]])
{
thiscam = &camera4;
thiscam = &camera[3];
chasecam = (cv_chasecam4.value != 0);
}
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
else if (splitscreen > 1 && player == &players[displayplayers[2]])
{
thiscam = &camera3;
thiscam = &camera[2];
chasecam = (cv_chasecam3.value != 0);
}
else if (splitscreen && player == &players[secondarydisplayplayer])
else if (splitscreen && player == &players[displayplayers[1]])
{
thiscam = &camera2;
thiscam = &camera[1];
chasecam = (cv_chasecam2.value != 0);
}
else
{
thiscam = &camera;
thiscam = &camera[0];
chasecam = (cv_chasecam.value != 0);
}
@ -1141,27 +1143,25 @@ void R_SetupFrame(player_t *player, boolean skybox)
aimingangle = player->aiming;
viewangle = viewmobj->angle;
if (/*!demoplayback && */player->playerstate != PST_DEAD)
if (/*!demo.playback && */player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{
viewangle = localangle; // WARNING: camera uses this
aimingangle = localaiming;
viewangle = localangle[0]; // WARNING: camera uses this
aimingangle = localaiming[0];
}
else if (player == &players[secondarydisplayplayer])
else if (splitscreen)
{
viewangle = localangle2;
aimingangle = localaiming2;
}
else if (player == &players[thirddisplayplayer])
{
viewangle = localangle3;
aimingangle = localaiming3;
}
else if (player == &players[fourthdisplayplayer])
{
viewangle = localangle4;
aimingangle = localaiming4;
UINT8 i;
for (i = 1; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
viewangle = localangle[i];
aimingangle = localaiming[i];
break;
}
}
}
}
}
@ -1323,19 +1323,10 @@ void R_RenderPlayerView(player_t *player)
{
portal_pair *portal;
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
UINT8 viewnumber;
if (player == &players[secondarydisplayplayer] && splitscreen)
viewnumber = 1;
else if (player == &players[thirddisplayplayer] && splitscreen > 1)
viewnumber = 2;
else if (player == &players[fourthdisplayplayer] && splitscreen > 2)
viewnumber = 3;
else
viewnumber = 0;
UINT8 i;
// if this is display player 1
if (cv_homremoval.value && player == &players[displayplayer])
if (cv_homremoval.value && player == &players[displayplayers[0]])
{
if (cv_homremoval.value == 1)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
@ -1343,7 +1334,7 @@ void R_RenderPlayerView(player_t *player)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15));
}
// Draw over the fourth screen so you don't have to stare at a HOM :V
else if (splitscreen == 2 && player == &players[thirddisplayplayer])
else if (splitscreen == 2 && player == &players[displayplayers[2]])
#if 1
{
// V_DrawPatchFill, but for the fourth screen only
@ -1362,14 +1353,14 @@ void R_RenderPlayerView(player_t *player)
#endif
// load previous saved value of skyVisible for the player
if (splitscreen > 2 && player == &players[fourthdisplayplayer])
skyVisible = skyVisible4;
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
skyVisible = skyVisible3;
else if (splitscreen && player == &players[secondarydisplayplayer])
skyVisible = skyVisible2;
else
skyVisible = skyVisible1;
for (i = 0; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
skyVisible = skyVisiblePerPlayer[i];
break;
}
}
portalrender = 0;
portal_base = portal_cap = NULL;
@ -1386,7 +1377,7 @@ void R_RenderPlayerView(player_t *player)
R_ClearVisibleFloorSplats();
#endif
R_RenderBSPNode((INT32)numnodes - 1, viewnumber);
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
R_DrawPlanes();
#ifdef FLOORSPLATS
@ -1419,7 +1410,7 @@ void R_RenderPlayerView(player_t *player)
mytotal = 0;
ProfZeroTimer();
#endif
R_RenderBSPNode((INT32)numnodes - 1, viewnumber);
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
#ifdef TIMING
RDMSR(0x10, &mycount);
@ -1444,7 +1435,7 @@ void R_RenderPlayerView(player_t *player)
validcount++;
R_RenderBSPNode((INT32)numnodes - 1, viewnumber);
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
//R_DrawPlanes();
//R_DrawMasked();
@ -1470,16 +1461,16 @@ void R_RenderPlayerView(player_t *player)
// Check for new console commands.
NetUpdate();
// save value to skyVisible1 or skyVisible2
// save value to skyVisiblePerPlayer
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
if (splitscreen > 2 && player == &players[fourthdisplayplayer])
skyVisible4 = skyVisible;
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
skyVisible3 = skyVisible;
else if (splitscreen && player == &players[secondarydisplayplayer])
skyVisible2 = skyVisible;
else
skyVisible1 = skyVisible;
for (i = 0; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
skyVisiblePerPlayer[i] = skyVisible;
break;
}
}
}
// =========================================================================
@ -1561,7 +1552,6 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grgammared);
CV_RegisterVar(&cv_grfovchange);
CV_RegisterVar(&cv_grfog);
CV_RegisterVar(&cv_voodoocompatibility);
CV_RegisterVar(&cv_grfogcolor);
CV_RegisterVar(&cv_grsoftwarefog);
#ifdef ALAM_LIGHTING
@ -1570,7 +1560,9 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grcoronas);
CV_RegisterVar(&cv_grcoronasize);
#endif
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grmdls);
CV_RegisterVar(&cv_grfallbackplayermodel);
CV_RegisterVar(&cv_grspritebillboarding);
#endif
#ifdef HWRENDER

View file

@ -883,12 +883,12 @@ void R_DrawSinglePlane(visplane_t *pl)
if (bottom > vid.height)
bottom = vid.height;
if (splitscreen > 2 && viewplayer == &players[fourthdisplayplayer]) // Only copy the part of the screen we need
if (splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need
scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth);
else if ((splitscreen == 1 && viewplayer == &players[secondarydisplayplayer])
|| (splitscreen > 1 && viewplayer == &players[thirddisplayplayer]))
else if ((splitscreen == 1 && viewplayer == &players[displayplayers[1]])
|| (splitscreen > 1 && viewplayer == &players[displayplayers[2]]))
scr = (screens[0] + (top+(viewheight))*vid.width);
else if (splitscreen > 1 && viewplayer == &players[secondarydisplayplayer])
else if (splitscreen > 1 && viewplayer == &players[displayplayers[1]])
scr = (screens[0] + ((top)*vid.width) + viewwidth);
else
scr = (screens[0] + ((top)*vid.width));

View file

@ -862,8 +862,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
{
lightlist_t *nextlight = &frontsector->lightlist[i+1];
if (nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height > pfloorleft
&& nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height > pfloorright)
if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft
&& (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright)
continue;
}

View file

@ -17,6 +17,7 @@
// Need data structure definitions.
#include "d_player.h"
#include "r_data.h"
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#ifdef __GNUG__
#pragma interface
@ -88,8 +89,9 @@ extern side_t *sides;
//
extern fixed_t viewx, viewy, viewz;
extern angle_t viewangle, aimingangle;
extern UINT8 viewssnum; // splitscreen view number
extern boolean viewsky, skyVisible;
extern boolean skyVisible1, skyVisible2, skyVisible3, skyVisible4; // saved values of skyVisible for P1 and P2, for splitscreen
extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player
extern sector_t *viewsector;
extern player_t *viewplayer;
extern UINT8 portalrender;

View file

@ -40,6 +40,8 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
#endif
CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2];
static void R_InitSkins(void);
#define MINZ (FRACUNIT*4)
@ -925,6 +927,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (vis->x2 >= vid.width)
vis->x2 = vid.width-1;
#if 1
// Something is occasionally setting 1px-wide sprites whose frac is exactly the width of the sprite, causing crashes due to
// accessing invalid column info. Until the cause is found, let's try to correct those manually...
while (frac + vis->xiscale*(vis->x2-vis->x1) > SHORT(patch->width)<<FRACBITS && vis->x2 >= vis->x1)
vis->x2--;
#endif
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
{
if (vis->scalestep) // currently papersprites only
@ -1695,7 +1704,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// R_AddSprites
// During BSP traversal, this adds sprites by sector.
//
void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
void R_AddSprites(sector_t *sec, INT32 lightlevel)
{
mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002
@ -1741,19 +1750,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
if (splitscreen)
{
if (thing->eflags & MFE_DRAWONLYFORP1)
if (viewnumber != 0)
if (viewssnum != 0)
continue;
if (thing->eflags & MFE_DRAWONLYFORP2)
if (viewnumber != 1)
if (viewssnum != 1)
continue;
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
if (viewnumber != 2)
if (viewssnum != 2)
continue;
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
if (viewnumber != 3)
if (viewssnum != 3)
continue;
}
@ -1776,19 +1785,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
if (splitscreen)
{
if (thing->eflags & MFE_DRAWONLYFORP1)
if (viewnumber != 0)
if (viewssnum != 0)
continue;
if (thing->eflags & MFE_DRAWONLYFORP2)
if (viewnumber != 1)
if (viewssnum != 1)
continue;
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
if (viewnumber != 2)
if (viewssnum != 2)
continue;
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
if (viewnumber != 3)
if (viewssnum != 3)
continue;
}
@ -2581,6 +2590,10 @@ void R_InitSkins(void)
skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes;
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0);
// Set values for Sonic skin
Forceskin_cons_t[1].value = 0;
Forceskin_cons_t[1].strvalue = skin->name;
//MD2 for sonic doesn't want to load in Linux.
#ifdef HWRENDER
if (rendermode == render_opengl)
@ -2646,15 +2659,15 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
player->kartspeed = skin->kartspeed;
player->kartweight = skin->kartweight;
/*if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking))
/*if (!(cv_debug || devparm) && !(netgame || multiplayer || demo.playback || modeattacking))
{
if (playernum == consoleplayer)
CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
else if (playernum == secondarydisplayplayer)
else if (playernum == displayplayers[1])
CV_StealthSetValue(&cv_playercolor2, skin->prefcolor);
else if (playernum == thirddisplayplayer)
else if (playernum == displayplayers[2])
CV_StealthSetValue(&cv_playercolor3, skin->prefcolor);
else if (playernum == fourthdisplayplayer)
else if (playernum == displayplayers[3])
CV_StealthSetValue(&cv_playercolor4, skin->prefcolor);
player->skincolor = skin->prefcolor;
if (player->mo)
@ -2663,6 +2676,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
if (player->mo)
P_SetScale(player->mo, player->mo->scale);
demo_extradata[playernum] |= DXD_SKIN;
return;
}
@ -2964,6 +2980,10 @@ next_token:
skin_cons_t[numskins].strvalue = skin->name;
#endif
// Update the forceskin possiblevalues
Forceskin_cons_t[numskins+1].value = numskins;
Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name;
// add face graphics
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins);

View file

@ -55,7 +55,7 @@ void R_DelSpriteDefs(UINT16 wadnum);
#endif
//SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber);
void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_InitSprites(void);
void R_ClearSprites(void);
void R_ClipSprites(void);
@ -97,6 +97,8 @@ typedef struct
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
} skin_t;
extern CV_PossibleValue_t Forceskin_cons_t[];
// -----------
// NOT SKINS STUFF !
// -----------

View file

@ -38,6 +38,10 @@ extern INT32 msg_id;
#include "p_local.h" // camera info
#include "m_misc.h" // for tunes command
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
#include "lua_hook.h" // MusicChange hook
#endif
#ifdef HW3SOUND
// 3D Sound Interface
#include "hardware/hw3sound.h"
@ -438,7 +442,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
listener_t listener3 = {0,0,0,0};
listener_t listener4 = {0,0,0,0};
mobj_t *listenmobj = players[displayplayer].mo;
mobj_t *listenmobj = players[displayplayers[0]].mo;
mobj_t *listenmobj2 = NULL;
mobj_t *listenmobj3 = NULL;
mobj_t *listenmobj4 = NULL;
@ -450,26 +454,26 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (sfx_id == sfx_None)
return;
if (players[displayplayer].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj;
if (players[displayplayers[0]].awayviewtics)
listenmobj = players[displayplayers[0]].awayviewmobj;
if (splitscreen)
{
listenmobj2 = players[secondarydisplayplayer].mo;
if (players[secondarydisplayplayer].awayviewtics)
listenmobj2 = players[secondarydisplayplayer].awayviewmobj;
listenmobj2 = players[displayplayers[1]].mo;
if (players[displayplayers[1]].awayviewtics)
listenmobj2 = players[displayplayers[1]].awayviewmobj;
if (splitscreen > 1)
{
listenmobj3 = players[thirddisplayplayer].mo;
if (players[thirddisplayplayer].awayviewtics)
listenmobj3 = players[thirddisplayplayer].awayviewmobj;
listenmobj3 = players[displayplayers[2]].mo;
if (players[displayplayers[2]].awayviewtics)
listenmobj3 = players[displayplayers[2]].awayviewmobj;
if (splitscreen > 2)
{
listenmobj4 = players[fourthdisplayplayer].mo;
if (players[fourthdisplayplayer].awayviewtics)
listenmobj4 = players[fourthdisplayplayer].awayviewmobj;
listenmobj4 = players[displayplayers[3]].mo;
if (players[displayplayers[3]].awayviewtics)
listenmobj4 = players[displayplayers[3]].awayviewmobj;
}
}
}
@ -482,12 +486,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
};
#endif
if (camera.chase && !players[displayplayer].awayviewtics)
if (camera[0].chase && !players[displayplayers[0]].awayviewtics)
{
listener.x = camera.x;
listener.y = camera.y;
listener.z = camera.z;
listener.angle = camera.angle;
listener.x = camera[0].x;
listener.y = camera[0].y;
listener.z = camera[0].z;
listener.angle = camera[0].angle;
}
else if (listenmobj)
{
@ -501,12 +505,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (listenmobj2)
{
if (camera2.chase && !players[secondarydisplayplayer].awayviewtics)
if (camera[1].chase && !players[displayplayers[1]].awayviewtics)
{
listener2.x = camera2.x;
listener2.y = camera2.y;
listener2.z = camera2.z;
listener2.angle = camera2.angle;
listener2.x = camera[1].x;
listener2.y = camera[1].y;
listener2.z = camera[1].z;
listener2.angle = camera[1].angle;
}
else
{
@ -519,12 +523,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (listenmobj3)
{
if (camera3.chase && !players[thirddisplayplayer].awayviewtics)
if (camera[2].chase && !players[displayplayers[2]].awayviewtics)
{
listener3.x = camera3.x;
listener3.y = camera3.y;
listener3.z = camera3.z;
listener3.angle = camera3.angle;
listener3.x = camera[2].x;
listener3.y = camera[2].y;
listener3.z = camera[2].z;
listener3.angle = camera[2].angle;
}
else
{
@ -537,12 +541,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (listenmobj4)
{
if (camera4.chase && !players[fourthdisplayplayer].awayviewtics)
if (camera[3].chase && !players[displayplayers[3]].awayviewtics)
{
listener4.x = camera4.x;
listener4.y = camera4.y;
listener4.z = camera4.z;
listener4.angle = camera4.angle;
listener4.x = camera[3].x;
listener4.y = camera[3].y;
listener4.z = camera[3].z;
listener4.angle = camera[3].angle;
}
else
{
@ -899,7 +903,7 @@ void S_UpdateSounds(void)
listener_t listener3;
listener_t listener4;
mobj_t *listenmobj = players[displayplayer].mo;
mobj_t *listenmobj = players[displayplayers[0]].mo;
mobj_t *listenmobj2 = NULL;
mobj_t *listenmobj3 = NULL;
mobj_t *listenmobj4 = NULL;
@ -935,36 +939,36 @@ void S_UpdateSounds(void)
if (dedicated || sound_disabled)
return;
if (players[displayplayer].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj;
if (players[displayplayers[0]].awayviewtics)
listenmobj = players[displayplayers[0]].awayviewmobj;
if (splitscreen)
{
listenmobj2 = players[secondarydisplayplayer].mo;
if (players[secondarydisplayplayer].awayviewtics)
listenmobj2 = players[secondarydisplayplayer].awayviewmobj;
listenmobj2 = players[displayplayers[1]].mo;
if (players[displayplayers[1]].awayviewtics)
listenmobj2 = players[displayplayers[1]].awayviewmobj;
if (splitscreen > 1)
{
listenmobj3 = players[thirddisplayplayer].mo;
if (players[thirddisplayplayer].awayviewtics)
listenmobj3 = players[thirddisplayplayer].awayviewmobj;
listenmobj3 = players[displayplayers[2]].mo;
if (players[displayplayers[2]].awayviewtics)
listenmobj3 = players[displayplayers[2]].awayviewmobj;
if (splitscreen > 2)
{
listenmobj4 = players[fourthdisplayplayer].mo;
if (players[fourthdisplayplayer].awayviewtics)
listenmobj4 = players[fourthdisplayplayer].awayviewmobj;
listenmobj4 = players[displayplayers[3]].mo;
if (players[displayplayers[3]].awayviewtics)
listenmobj4 = players[displayplayers[3]].awayviewmobj;
}
}
}
if (camera.chase && !players[displayplayer].awayviewtics)
if (camera[0].chase && !players[displayplayers[0]].awayviewtics)
{
listener.x = camera.x;
listener.y = camera.y;
listener.z = camera.z;
listener.angle = camera.angle;
listener.x = camera[0].x;
listener.y = camera[0].y;
listener.z = camera[0].z;
listener.angle = camera[0].angle;
}
else if (listenmobj)
{
@ -989,12 +993,12 @@ void S_UpdateSounds(void)
if (listenmobj2)
{
if (camera2.chase && !players[secondarydisplayplayer].awayviewtics)
if (camera[1].chase && !players[displayplayers[1]].awayviewtics)
{
listener2.x = camera2.x;
listener2.y = camera2.y;
listener2.z = camera2.z;
listener2.angle = camera2.angle;
listener2.x = camera[1].x;
listener2.y = camera[1].y;
listener2.z = camera[1].z;
listener2.angle = camera[1].angle;
}
else
{
@ -1007,12 +1011,12 @@ void S_UpdateSounds(void)
if (listenmobj3)
{
if (camera3.chase && !players[thirddisplayplayer].awayviewtics)
if (camera[2].chase && !players[displayplayers[2]].awayviewtics)
{
listener3.x = camera3.x;
listener3.y = camera3.y;
listener3.z = camera3.z;
listener3.angle = camera3.angle;
listener3.x = camera[2].x;
listener3.y = camera[2].y;
listener3.z = camera[2].z;
listener3.angle = camera[2].angle;
}
else
{
@ -1025,12 +1029,12 @@ void S_UpdateSounds(void)
if (listenmobj4)
{
if (camera4.chase && !players[fourthdisplayplayer].awayviewtics)
if (camera[3].chase && !players[displayplayers[3]].awayviewtics)
{
listener4.x = camera4.x;
listener4.y = camera4.y;
listener4.z = camera4.z;
listener4.angle = camera4.angle;
listener4.x = camera[3].x;
listener4.y = camera[3].y;
listener4.z = camera[3].z;
listener4.angle = camera[3].angle;
}
else
{
@ -1060,9 +1064,9 @@ void S_UpdateSounds(void)
// check non-local sounds for distance clipping
// or modify their params
if (c->origin && ((c->origin != players[consoleplayer].mo)
|| (splitscreen && c->origin != players[secondarydisplayplayer].mo)
|| (splitscreen > 1 && c->origin != players[thirddisplayplayer].mo)
|| (splitscreen > 2 && c->origin != players[fourthdisplayplayer].mo)))
|| (splitscreen && c->origin != players[displayplayers[1]].mo)
|| (splitscreen > 1 && c->origin != players[displayplayers[2]].mo)
|| (splitscreen > 2 && c->origin != players[displayplayers[3]].mo)))
{
// Whomever is closer gets the sound, but only in splitscreen.
if (splitscreen)
@ -1071,13 +1075,10 @@ void S_UpdateSounds(void)
fixed_t recdist = -1;
INT32 i, p = -1;
for (i = 0; i < 4; i++)
for (i = 0; i <= splitscreen; i++)
{
fixed_t thisdist = -1;
if (i > splitscreen)
break;
if (i == 0 && listenmobj)
thisdist = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y);
else if (i == 1 && listenmobj2)
@ -1250,33 +1251,33 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v
if (!listener)
return false;
if (listener == players[displayplayer].mo && camera.chase)
if (listener == players[displayplayers[0]].mo && camera[0].chase)
{
listensource.x = camera.x;
listensource.y = camera.y;
listensource.z = camera.z;
listensource.angle = camera.angle;
listensource.x = camera[0].x;
listensource.y = camera[0].y;
listensource.z = camera[0].z;
listensource.angle = camera[0].angle;
}
else if (splitscreen && listener == players[secondarydisplayplayer].mo && camera2.chase)
else if (splitscreen && listener == players[displayplayers[1]].mo && camera[1].chase)
{
listensource.x = camera2.x;
listensource.y = camera2.y;
listensource.z = camera2.z;
listensource.angle = camera2.angle;
listensource.x = camera[1].x;
listensource.y = camera[1].y;
listensource.z = camera[1].z;
listensource.angle = camera[1].angle;
}
else if (splitscreen > 1 && listener == players[thirddisplayplayer].mo && camera3.chase)
else if (splitscreen > 1 && listener == players[displayplayers[2]].mo && camera[2].chase)
{
listensource.x = camera3.x;
listensource.y = camera3.y;
listensource.z = camera3.z;
listensource.angle = camera3.angle;
listensource.x = camera[2].x;
listensource.y = camera[2].y;
listensource.z = camera[2].z;
listensource.angle = camera[2].angle;
}
else if (splitscreen > 2 && listener == players[fourthdisplayplayer].mo && camera4.chase)
else if (splitscreen > 2 && listener == players[displayplayers[3]].mo && camera[3].chase)
{
listensource.x = camera4.x;
listensource.y = camera4.y;
listensource.z = camera4.z;
listensource.angle = camera4.angle;
listensource.x = camera[3].x;
listensource.y = camera[3].y;
listensource.z = camera[3].z;
listensource.angle = camera[3].angle;
}
else
{
@ -1550,6 +1551,12 @@ static void *music_data;
static UINT16 music_flags;
static boolean music_looping;
static char queue_name[7];
static UINT16 queue_flags;
static boolean queue_looping;
static UINT32 queue_position;
static UINT32 queue_fadeinms;
/// ------------------------
/// Music Definitions
/// ------------------------
@ -1733,7 +1740,7 @@ void S_ShowMusicCredit(void)
{
musicdef_t *def = musicdefstart;
if (!cv_songcredits.value)
if (!cv_songcredits.value || demo.rewinding)
return;
if (!def) // No definitions
@ -1788,6 +1795,11 @@ musictype_t S_MusicType(void)
return I_SongType();
}
const char *S_MusicName(void)
{
return music_name;
}
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping)
{
if (!I_SongPlaying())
@ -1818,6 +1830,35 @@ boolean S_SpeedMusic(float speed)
return I_SetSongSpeed(speed);
}
/// ------------------------
/// Music Seeking
/// ------------------------
UINT32 S_GetMusicLength(void)
{
return I_GetSongLength();
}
boolean S_SetMusicLoopPoint(UINT32 looppoint)
{
return I_SetSongLoopPoint(looppoint);
}
UINT32 S_GetMusicLoopPoint(void)
{
return I_GetSongLoopPoint();
}
boolean S_SetMusicPosition(UINT32 position)
{
return I_SetSongPosition(position);
}
UINT32 S_GetMusicPosition(void)
{
return I_GetSongPosition();
}
/// ------------------------
/// Music Playback
/// ------------------------
@ -1894,12 +1935,13 @@ static void S_UnloadMusic(void)
music_looping = false;
}
static boolean S_PlayMusic(boolean looping)
static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
{
if (S_MusicDisabled())
return false;
if (!I_PlaySong(looping))
if ((!fadeinms && !I_PlaySong(looping)) ||
(fadeinms && !I_FadeInPlaySong(fadeinms, looping)))
{
S_UnloadMusic();
return false;
@ -1913,49 +1955,106 @@ static boolean S_PlayMusic(boolean looping)
return true;
}
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 fadeinms)
{
strncpy(queue_name, mmusic, 7);
queue_flags = mflags;
queue_looping = looping;
queue_position = position;
queue_fadeinms = fadeinms;
}
static void S_ClearQueue(void)
{
queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0;
}
static void S_ChangeMusicToQueue(void)
{
S_ChangeMusicEx(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms);
S_ClearQueue();
}
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
{
char newmusic[7];
#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X)
S_ClearSfx();
#endif
if (S_MusicDisabled()
|| titledemo) // SRB2Kart: Demos don't interrupt title screen music
|| demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return;
// No Music (empty string)
if (mmusic[0] == 0)
{
S_StopMusic();
strncpy(newmusic, mmusic, 7);
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
return;
#endif
newmusic[6] = 0;
// No Music (empty string)
if (newmusic[0] == 0)
{
if (prefadems)
I_FadeSong(0, prefadems, &S_StopMusic);
else
S_StopMusic();
return;
}
if (strnicmp(music_name, mmusic, 6))
if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same
{
S_StopMusic(); // shutdown old music
CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name);
S_QueueMusic(newmusic, mflags, looping, position, fadeinms);
I_FadeSong(0, prefadems, S_ChangeMusicToQueue);
return;
}
else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET))
{
CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic);
if (!S_LoadMusic(mmusic))
S_StopMusic();
if (!S_LoadMusic(newmusic))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", mmusic);
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic);
return;
}
music_flags = mflags;
music_looping = looping;
if (!S_PlayMusic(looping))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", mmusic);
if (!S_PlayMusic(looping, fadeinms))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic);
return;
}
if (position)
I_SetSongPosition(position);
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
}
else if (fadeinms) // let fades happen with same music
{
I_SetSongPosition(position);
I_FadeSong(100, fadeinms, NULL);
}
else // reset volume to 100 with same music
{
I_StopFadingSong();
I_FadeSong(100, 500, NULL);
}
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
}
void S_StopMusic(void)
{
if (!I_SongPlaying()
|| titledemo) // SRB2Kart: Demos don't interrupt title screen music
|| demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return;
if (I_SongPaused())
@ -2055,6 +2154,32 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
}
}
/// ------------------------
/// Music Fading
/// ------------------------
void S_SetInternalMusicVolume(INT32 volume)
{
I_SetInternalMusicVolume(min(max(volume, 0), 100));
}
void S_StopFadingMusic(void)
{
I_StopFadingSong();
}
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms)
{
if (source_volume < 0)
return I_FadeSong(target_volume, ms, NULL);
else
return I_FadeSongFromVolume(target_volume, source_volume, ms, NULL);
}
boolean S_FadeOutStopMusic(UINT32 ms)
{
return I_FadeSong(0, ms, &S_StopMusic);
}
/// ------------------------
/// Init & Others
@ -2072,26 +2197,28 @@ void S_Start(void)
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
}
//if (cv_resetmusic.value) // Starting ambience should always be restarted
S_StopMusic();
if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart
S_ChangeMusic((encoremode ? "estart" : "kstart"), 0, false);
S_ChangeMusicEx((encoremode ? "estart" : "kstart"), 0, false, mapmusposition, 0, 0);
else
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
static void Command_Tunes_f(void)
{
const char *tunearg;
UINT16 tunenum, track = 0;
UINT32 position = 0;
const size_t argc = COM_Argc();
if (argc < 2) //tunes slot ...
{
CONS_Printf("tunes <name/num> [track] [speed] / <-show> / <-default> / <-none>:\n");
CONS_Printf("tunes <name/num> [track] [speed] [position] / <-show> / <-default> / <-none>:\n");
CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n"));
CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n"));
CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n"));
@ -2138,10 +2265,15 @@ static void Command_Tunes_f(void)
snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum));
else
strncpy(mapmusname, tunearg, 7);
if (argc > 4)
position = (UINT32)atoi(COM_Argv(4));
mapmusname[6] = 0;
mapmusflags = (track & MUSIC_TRACKMASK);
mapmusposition = position;
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
if (argc > 3)
{
@ -2182,7 +2314,7 @@ static void Command_RestartAudio_f(void)
void GameSounds_OnChange(void)
{
if (M_CheckParm("-nosound"))
if (M_CheckParm("-nosound") || M_CheckParm("-noaudio"))
return;
if (sound_disabled)
@ -2196,7 +2328,7 @@ void GameSounds_OnChange(void)
void GameDigiMusic_OnChange(void)
{
if (M_CheckParm("-nomusic"))
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
return;
else if (M_CheckParm("-nodigmusic"))
return;
@ -2239,7 +2371,7 @@ void GameDigiMusic_OnChange(void)
#ifndef NO_MIDI
void GameMIDIMusic_OnChange(void)
{
if (M_CheckParm("-nomusic"))
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
return;
else if (M_CheckParm("-nomidimusic"))
return;

Some files were not shown because too many files have changed in this diff Show more