From 358a47967bfd2376e1e9692122290c3f295e2c00 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 11 Jun 2018 19:36:47 +0100 Subject: [PATCH 001/382] backport fix to L/R sprite loading code from internal basically we don't want L/R sprites to always be flipped, for obvious reasons --- src/r_things.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 1352209d7..fa0316bf7 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -148,7 +148,11 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].lumppat[r + rightfactor] = lumppat; sprtemp[frame].lumpid[r + rightfactor] = lumpid; } - sprtemp[frame].flip |= (flipped ? (0x0F << rightfactor) : 0); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R + if (flipped) + sprtemp[frame].flip |= (0x0F< Date: Tue, 18 Sep 2018 10:22:17 -0400 Subject: [PATCH 002/382] MusicPlus Core (positioning and fading) 2.2 -> 2.1 backport --- src/android/i_sound.c | 72 ++++++ src/d_netcmd.c | 10 +- src/dehacked.c | 11 + src/djgppdos/i_sound.c | 72 ++++++ src/doomdef.h | 2 + src/doomstat.h | 4 + src/dummy/i_sound.c | 74 +++++- src/f_finale.c | 10 +- src/g_game.c | 12 +- src/i_sound.h | 23 ++ src/lua_baselib.c | 44 ++-- src/lua_hook.h | 1 + src/lua_hooklib.c | 1 + src/lua_maplib.c | 2 + src/p_setup.c | 2 + src/p_spec.c | 2 + src/p_user.c | 4 +- src/s_sound.c | 153 +++++++++-- src/s_sound.h | 41 ++- src/sdl/mixer_sound.c | 559 +++++++++++++++++++++++++++++++++++++++-- src/sdl/sdl_sound.c | 72 ++++++ src/win32/win_snd.c | 95 +++++++ 22 files changed, 1175 insertions(+), 91 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 1d16e4df3..d7a7973d4 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -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 /// ------------------------ @@ -139,3 +170,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; +} diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a58aff3fe..5211b31e9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3885,11 +3885,12 @@ 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 [track] [speed] / <-show> / <-default> / <-none>:\n"); + CONS_Printf("tunes [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")); @@ -3936,10 +3937,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) { diff --git a/src/dehacked.c b/src/dehacked.c index b7e874b16..e2df11142 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1192,6 +1192,8 @@ 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, "FORCECHARACTER")) { strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1); @@ -1483,6 +1485,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); @@ -6977,6 +6984,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. @@ -8264,6 +8272,9 @@ 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]) return 0; diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 5403aef17..00e0f8c90 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -436,6 +436,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 /// ------------------------ @@ -543,3 +574,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; +} diff --git a/src/doomdef.h b/src/doomdef.h index 7f641558f..9cde20f9a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -288,6 +288,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 512*FRACUNIT // how close you need to be to a ring to attract it #define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items. diff --git a/src/doomstat.h b/src/doomstat.h index 27bd3fa19..d6fd046b4 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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; @@ -145,6 +147,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 @@ -215,6 +218,7 @@ typedef struct INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. 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. diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 4bace7a41..89c400631 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -94,6 +94,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 /// ------------------------ @@ -141,4 +172,45 @@ boolean I_SetSongTrack(int track) { (void)track; return false; -} \ No newline at end of file +} + +/// ------------------------ +// 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; +} diff --git a/src/f_finale.c b/src/f_finale.c index a8b27bb80..2499931ab 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1714,9 +1714,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; @@ -1788,9 +1789,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(); } diff --git a/src/g_game.c b/src/g_game.c index 4f1c49b42..6be4cf96e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -71,6 +71,7 @@ static void G_DoWorldDone(void); char mapmusname[7]; // Music name UINT16 mapmusflags; // Track and reset bit +UINT32 mapmusposition; // Position to jump to INT16 gamemap = 1; INT16 maptol; @@ -2187,17 +2188,6 @@ void G_PlayerReborn(INT32 player) if ((netgame || multiplayer) && !p->spectator) p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent - if (p-players == consoleplayer) - { - if (mapmusflags & MUSIC_RELOADRESET) - { - strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); - mapmusname[6] = 0; - mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK; - } - S_ChangeMusic(mapmusname, mapmusflags, true); - } - if (gametype == GT_COOP) P_FindEmerald(); // scan for emeralds to hunt for diff --git a/src/i_sound.h b/src/i_sound.h index 1be970d2e..3c2608093 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -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 /// ------------------------ diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e8e8fd020..f7a0a5995 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -719,8 +719,14 @@ static int lib_pRestoreMusic(lua_State *L) NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - P_RestoreMusic(player); - return 0; + else if (P_IsLocalPlayer(player)) + { + P_RestoreMusic(player); + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; } static int lib_pSpawnShieldOrb(lua_State *L) @@ -1717,7 +1723,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; @@ -1745,7 +1751,6 @@ static int lib_sChangeMusic(lua_State *L) music_name = luaL_checkstring(L, 1); } - looping = (boolean)lua_opttrueboolean(L, 2); #else @@ -1770,9 +1775,18 @@ 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); - return 0; + { + S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms); + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; } static int lib_sSpeedMusic(lua_State *L) @@ -1790,25 +1804,10 @@ static int lib_sSpeedMusic(lua_State *L) if (!player || P_IsLocalPlayer(player)) lua_pushboolean(L, S_SpeedMusic(speed)); else - lua_pushboolean(L, false); + lua_pushnil(L); return 1; } -static int lib_sStopMusic(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_StopMusic(); - return 0; -} - static int lib_sOriginPlaying(lua_State *L) { void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2131,7 +2130,6 @@ static luaL_Reg lib[] = { {"S_StopSound",lib_sStopSound}, {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, - {"S_StopMusic",lib_sStopMusic}, {"S_OriginPlaying",lib_sOriginPlaying}, {"S_IdPlaying",lib_sIdPlaying}, {"S_SoundPlaying",lib_sSoundPlaying}, diff --git a/src/lua_hook.h b/src/lua_hook.h index 53e0a7d8e..74a6b5e75 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -43,6 +43,7 @@ enum hook { hook_PlayerMsg, hook_HurtMsg, hook_PlayerSpawn, + hook_MusicChange, hook_MAX // last hook }; diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index eadd01537..dff2b8f46 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -54,6 +54,7 @@ const char *const hookNames[hook_MAX+1] = { "PlayerMsg", "HurtMsg", "PlayerSpawn", + "MusicChange", NULL }; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 208aebe37..a1d7994bf 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1192,6 +1192,8 @@ 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,"forcecharacter")) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) diff --git a/src/p_setup.c b/src/p_setup.c index 17a6797f4..6c6b9153d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -185,6 +185,8 @@ 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]->mustrack), UNDO_NONE); + mapheaderinfo[num]->muspos = 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); diff --git a/src/p_spec.c b/src/p_spec.c index c62c3b209..afc3c0533 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2428,6 +2428,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!(line->flags & ML_BLOCKMONSTERS)) mapmusflags |= MUSIC_RELOADRESET; + mapmusposition = 0; + S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4)); // Except, you can use the ML_BLOCKMONSTERS flag to change this behavior. diff --git a/src/p_user.c b/src/p_user.c index 7abf85347..03b037fed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1124,13 +1124,13 @@ void P_RestoreMusic(player_t *player) if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC) { S_SpeedMusic(1.4f); - S_ChangeMusic(mapmusname, mapmusflags, true); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } else S_ChangeMusicInternal("shoes", true); } else - S_ChangeMusic(mapmusname, mapmusflags, true); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } // diff --git a/src/s_sound.c b/src/s_sound.c index ea129a109..3da594fe1 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -37,6 +37,10 @@ extern INT32 msg_id; #include "r_sky.h" // skyflatnum #include "p_local.h" // camera info +#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) +#include "lua_hook.h" // MusicChange hook +#endif + #ifdef HW3SOUND // 3D Sound Interface #include "hardware/hw3sound.h" @@ -1219,6 +1223,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 Status /// ------------------------ @@ -1253,6 +1263,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()) @@ -1283,6 +1298,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 /// ------------------------ @@ -1355,12 +1399,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; @@ -1370,7 +1415,27 @@ 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) { #if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X) S_ClearSfx(); @@ -1379,33 +1444,62 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) if (S_MusicDisabled()) return; - // No Music (empty string) - if (mmusic[0] == 0) - { - S_StopMusic(); + char newmusic[7]; + 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); } - I_SetSongTrack(mflags & MUSIC_TRACKMASK); + else if (fadeinms) // let fades happen with same music + { + I_SetSongPosition(position); + I_FadeSong(100, fadeinms, NULL); + } } void S_StopMusic(void) @@ -1480,6 +1574,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, false); +} + +boolean S_FadeOutStopMusic(UINT32 ms) +{ + return I_FadeSong(0, ms, &S_StopMusic); +} /// ------------------------ /// Init & Others @@ -1497,9 +1617,10 @@ 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) S_StopMusic(); - S_ChangeMusic(mapmusname, mapmusflags, true); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } diff --git a/src/s_sound.h b/src/s_sound.h index a2d51a59b..538707ffb 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -108,29 +108,49 @@ boolean S_MusicDisabled(void); boolean S_MusicPlaying(void); boolean S_MusicPaused(void); musictype_t S_MusicType(void); +const char *S_MusicName(void); boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping); boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); #define S_DigExists(a) S_MusicExists(a, false, true) #define S_MIDIExists(a) S_MusicExists(a, true, false) - // -// Music Properties +// Music Effects // // Set Speed of Music boolean S_SpeedMusic(float speed); // -// Music Routines +// Music Seeking +// + +// Get Length of Music +UINT32 S_GetMusicLength(void); + +// Set LoopPoint of Music +boolean S_SetMusicLoopPoint(UINT32 looppoint); + +// Get LoopPoint of Music +UINT32 S_GetMusicLoopPoint(void); + +// Set Position of Music +boolean S_SetMusicPosition(UINT32 position); + +// Get Position of Music +UINT32 S_GetMusicPosition(void); + +// +// Music Playback // // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet // and the last bit we ignore (internal game flag for resetting music on reload) -#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b) -void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping); +void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms); +#define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0) +#define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0) // Stops the music. void S_StopMusic(void); @@ -139,6 +159,17 @@ void S_StopMusic(void); void S_PauseAudio(void); void S_ResumeAudio(void); +// +// Music Fading +// + +void S_SetInternalMusicVolume(INT32 volume); +void S_StopFadingMusic(void); +boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms); +#define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b) +#define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicEx(a,b,c,0,0,d) +boolean S_FadeOutStopMusic(UINT32 ms); + // // Updates music & sounds // diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 87f8fd671..9b09ffe80 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -69,15 +69,41 @@ UINT8 sound_started = false; static Mix_Music *music; -static UINT8 music_volume, sfx_volume; +static UINT8 music_volume, sfx_volume, internal_volume; static float loop_point; +static float song_length; // length in seconds static boolean songpaused; +static UINT32 music_bytes; +static boolean is_looping; + +// fading +static boolean is_fading; +static UINT8 fading_source; +static UINT8 fading_target; +static UINT32 fading_timer; +static UINT32 fading_duration; +static INT32 fading_id; +static void (*fading_callback)(void); #ifdef HAVE_LIBGME static Music_Emu *gme; static INT32 current_track; #endif +static void var_cleanup(void) +{ + loop_point = song_length =\ + music_bytes = fading_source = fading_target =\ + fading_timer = fading_duration = 0; + + songpaused = is_looping =\ + is_fading = false; + + fading_callback = NULL; + + internal_volume = 100; +} + /// ------------------------ /// Audio System /// ------------------------ @@ -99,6 +125,8 @@ void I_StartupSound(void) return; } + var_cleanup(); + music = NULL; music_volume = sfx_volume = 0; @@ -323,6 +351,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = malloc(len); gme_play(emu, len >> 1, mem); + gme_free_info(info); gme_delete(emu); return Mix_QuickLoad_RAW((Uint8 *)mem, len); @@ -395,6 +424,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = malloc(len); gme_play(emu, len >> 1, mem); + gme_free_info(info); gme_delete(emu); return Mix_QuickLoad_RAW((Uint8 *)mem, len); @@ -447,14 +477,96 @@ void I_SetSfxVolume(UINT8 volume) sfx_volume = volume; } +/// ------------------------ +/// Music Utilities +/// ------------------------ + +static UINT32 get_real_volume(UINT8 volume) +{ +#ifdef _WIN32 + if (I_SongType() == MU_MID) + // HACK: Until we stop using native MIDI, + // disable volume changes + return ((UINT32)31*128/31); // volume = 31 + else +#endif + // convert volume to mixer's 128 scale + // then apply internal_volume as a percentage + return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100; +} + +static UINT32 get_adjusted_position(UINT32 position) +{ + // all in milliseconds + UINT32 length = I_GetSongLength(); + UINT32 looppoint = I_GetSongLoopPoint(); + if (length) + return position >= length ? (position % (length-looppoint)) : position; + else + return position; +} + +static void do_fading_callback() +{ + if (fading_callback) + (*fading_callback)(); + fading_callback = NULL; +} + /// ------------------------ /// Music Hooks /// ------------------------ +static void count_music_bytes(int chan, void *stream, int len, void *udata) +{ + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID) + return; + music_bytes += len; +} + static void music_loop(void) { - Mix_PlayMusic(music, 0); - Mix_SetMusicPosition(loop_point); + if (is_looping) + { + Mix_PlayMusic(music, 0); + Mix_SetMusicPosition(loop_point); + music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + } + else + I_StopSong(); +} + +static UINT32 music_fade(UINT32 interval, void *param) +{ + if (!is_fading || + internal_volume == fading_target || + fading_duration == 0) + { + I_StopFadingSong(); + do_fading_callback(); + return 0; + } + else if (songpaused) // don't decrement timer + return interval; + else if ((fading_timer -= 10) <= 0) + { + internal_volume = fading_target; + Mix_VolumeMusic(get_real_volume(music_volume)); + I_StopFadingSong(); + do_fading_callback(); + return 0; + } + else + { + UINT8 delta = abs(fading_target - fading_source); + double factor = (double)(fading_duration - fading_timer) / (double)fading_duration; + if (fading_target < fading_source) + internal_volume = max(min(internal_volume, fading_source - (UINT8)round(delta * factor)), fading_target); + else if (fading_target > fading_source) + internal_volume = min(max(internal_volume, fading_source + (UINT8)round(delta * factor)), fading_target); + Mix_VolumeMusic(get_real_volume(music_volume)); + return interval; + } } #ifdef HAVE_LIBGME @@ -474,7 +586,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len) // apply volume to stream for (i = 0, p = (short *)stream; i < len/2; i++, p++) - *p = ((INT32)*p) * music_volume*2 / 42; + *p = ((INT32)*p) * (music_volume*internal_volume/100)*2 / 42; } #endif @@ -552,6 +664,194 @@ boolean I_SetSongSpeed(float speed) return false; } +/// ------------------------ +/// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + INT32 length; + +#ifdef HAVE_LIBGME + if (gme) + { + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + length = 0; + } + else + { + // reconstruct info->play_length, from GME source + // we only want intro + 1 loop, not 2 + length = info->length; + if (length <= 0) + { + length = info->intro_length + info->loop_length; // intro + 1 loop + if (length <= 0) + length = 150 * 1000; // 2.5 minutes + } + } + + gme_free_info(info); + return max(length, 0); + } + else +#endif + if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + return 0; + else + { + // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! + // SDL mixer can't read music length itself. + length = (UINT32)(song_length*1000); + if (!length) + CONS_Debug(DBG_DETAILED, "Getting music length: music is missing LENGTHMS= tag. Needed for seeking.\n"); + return length; + } +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping) + return false; + else + { + UINT32 length = I_GetSongLength(); + + if (length > 0) + looppoint %= length; + + loop_point = max((float)(looppoint / 1000.0L), 0); + return true; + } +} + +UINT32 I_GetSongLoopPoint(void) +{ +#ifdef HAVE_LIBGME + if (gme) + { + INT32 looppoint; + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + looppoint = 0; + } + else + looppoint = info->intro_length > 0 ? info->intro_length : 0; + + gme_free_info(info); + return max(looppoint, 0); + } + else +#endif + if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + return 0; + else + return (UINT32)(loop_point * 1000); +} + +boolean I_SetSongPosition(UINT32 position) +{ + UINT32 length; +#ifdef HAVE_LIBGME + if (gme) + { + // this is unstable, so fail silently + return true; + // this isn't required technically, but GME thread-locks for a second + // if you seek too high from the counter + // length = I_GetSongLength(); + // if (length) + // position = get_adjusted_position(position); + + // SDL_LockAudio(); + // gme_err_t gme_e = gme_seek(gme, position); + // SDL_UnlockAudio(); + + // if (gme_e != NULL) + // { + // CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + // return false; + // } + // else + // return true; + } + else +#endif + if (!music || I_SongType() == MU_MID) + return false; + else if (I_SongType() == MU_MOD) + return Mix_SetMusicPosition(position); // Goes by channels + else + { + // Because SDL mixer can't identify song length, if you have + // a position input greater than the real length, then + // music_bytes becomes inaccurate. + + length = I_GetSongLength(); // get it in MS + if (length) + position = get_adjusted_position(position); + + Mix_RewindMusic(); // needed for mp3 + if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) + music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + else + // NOTE: This block fires on incorrect song format, + // NOT if position input is greater than song length. + music_bytes = 0; + + return true; + } +} + +UINT32 I_GetSongPosition(void) +{ +#ifdef HAVE_LIBGME + if (gme) + { + INT32 position = gme_tell(gme); + + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + return position; + } + else + { + // adjust position, since GME's counter keeps going past loop + if (info->length > 0) + position %= info->length; + else if (info->intro_length + info->loop_length > 0) + position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position; + else + position %= 150 * 1000; // 2.5 minutes + } + + gme_free_info(info); + return max(position, 0); + } + else +#endif + if (!music || I_SongType() == MU_MID) + return 0; + else + return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz + // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) + // This is hardcoded in I_StartupSound. Other formats for factor: + // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 +} + /// ------------------------ /// Music Playback /// ------------------------ @@ -561,9 +861,21 @@ boolean I_LoadSong(char *data, size_t len) const char *key1 = "LOOP"; const char *key2 = "POINT="; const char *key3 = "MS="; + const char *key4 = "LENGTHMS="; const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); + const size_t key4len = strlen(key4); + + // for mp3 wide chars + const char *key1w = "L\0O\0O\0P\0"; + const char *key2w = "P\0O\0I\0N\0T\0\0\0\xFF\xFE"; + const char *key3w = "M\0S\0\0\0\xFF\xFE"; + const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0\0\0\xFF\xFE"; + const char *wterm = "\0\0"; + char wval[10]; + + size_t wstart, wp; char *p = data; if (music @@ -573,6 +885,8 @@ boolean I_LoadSong(char *data, size_t len) ) I_UnloadSong(); + var_cleanup(); + #ifdef HAVE_LIBGME if ((UINT8)data[0] == 0x1F && (UINT8)data[1] == 0x8B) @@ -675,32 +989,96 @@ boolean I_LoadSong(char *data, size_t len) return false; } + if (I_SongType() == MU_MP3) + { + CONS_Debug(DBG_BASIC, "MP3 songs are unsupported and may crash! Use OGG instead.\n"); + CONS_Debug(DBG_DETAILED, "MP3 songs are unsupported and may crash! Use OGG instead.\n"); + } + // Find the OGG loop point. loop_point = 0.0f; + song_length = 0.0f; while ((UINT32)(p - data) < len) { - if (strncmp(p++, key1, key1len)) - continue; - p += key1len-1; // skip OOP (the L was skipped in strncmp) - if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? + if (!loop_point && !strncmp(p, key1, key1len)) { - p += key2len; // skip POINT= - loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. - // because SDL_Mixer is USELESS and can't even tell us - // something simple like the frequency of the streaming music, - // we are unfortunately forced to assume that ALL MUSIC is 44100hz. - // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. + p += key1len; // skip LOOP + if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? + { + p += key2len; // skip POINT= + loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. + // because SDL_Mixer is USELESS and can't even tell us + // something simple like the frequency of the streaming music, + // we are unfortunately forced to assume that ALL MUSIC is 44100hz. + // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. + } + else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? + { + p += key3len; // skip MS= + loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. + // Everything that uses LOOPMS will work perfectly with SDL_Mixer. + } } - else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? + else if (!song_length && !strncmp(p, key4, key4len)) // is it LENGTHMS=? { - p += key3len; // skip MS= - loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. - // Everything that uses LOOPMS will work perfectly with SDL_Mixer. + p += key4len; // skip LENGTHMS + song_length = (float)(atoi(p) / 1000.0L); + } + // below: search MP3 or other tags that use wide char encoding + else if (!loop_point && !memcmp(p, key1w, key1len*2)) // LOOP wide char + { + p += key1len*2; + if (!memcmp(p, key2w, (key2len+1)*2)) // POINT= wide char + { + p += (key2len+1)*2; + wstart = (size_t)p; + wp = 0; + while (wp < 9 && memcmp(p, wterm, 2)) + { + wval[wp] = *p; + p += 2; + wp = ((size_t)(p-wstart))/2; + } + wval[min(wp, 9)] = 0; + loop_point = (float)((44.1L+atoi(wval) / 44100.0L)); + } + else if (!memcmp(p, key3w, (key3len+1)*2)) // MS= wide char + { + p += (key3len+1)*2; + wstart = (size_t)p; + wp = 0; + while (wp < 9 && memcmp(p, wterm, 2)) + { + wval[wp] = *p; + p += 2; + wp = ((size_t)(p-wstart))/2; + } + wval[min(wp, 9)] = 0; + loop_point = (float)(atoi(wval) / 1000.0L); + } + } + else if (!song_length && !memcmp(p, key4w, (key4len+1)*2)) // LENGTHMS= wide char + { + p += (key4len+1)*2; + wstart = (size_t)p; + wp = 0; + while (wp < 9 && memcmp(p, wterm, 2)) + { + wval[wp] = *p; + p += 2; + wp = ((size_t)(p-wstart))/2; + } + wval[min(wp, 9)] = 0; + song_length = (float)(atoi(wval) / 1000.0L); } - // Neither?! Continue searching. - } + if (loop_point && song_length && song_length > loop_point) // Got what we needed + // the last case is a sanity check, in case the wide char searches were false matches. + break; + else // continue searching + p++; + } return true; } @@ -737,15 +1115,30 @@ boolean I_PlaySong(boolean looping) if (!music) return false; - if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1) + if (!song_length && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) + CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n"); + + if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1) + { + CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); + return false; + } + else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return false; } - Mix_VolumeMusic((UINT32)music_volume*128/31); - if (loop_point != 0.0f) - Mix_HookMusicFinished(music_loop); + is_looping = looping; + + I_SetMusicVolume(music_volume); + + if (I_SongType() != MU_MOD && I_SongType() != MU_MID) + Mix_HookMusicFinished(music_loop); // don't bother counting if MOD + + if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); + return true; } @@ -760,19 +1153,40 @@ void I_StopSong(void) #endif if (music) { + var_cleanup(); + I_StopFadingSong(); + Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); Mix_HaltMusic(); } } -void I_PauseSong(void) +void I_PauseSong() { + if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? + return; + + if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); + Mix_PauseMusic(); songpaused = true; } -void I_ResumeSong(void) +void I_ResumeSong() { + if (I_SongType() == MU_MID) + return; + + if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + { + while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } + // HACK: fixes issue of multiple effect callbacks being registered + + if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); + } + Mix_ResumeMusic(); songpaused = false; } @@ -791,7 +1205,7 @@ void I_SetMusicVolume(UINT8 volume) #endif music_volume = volume; - Mix_VolumeMusic((UINT32)music_volume*128/31); + Mix_VolumeMusic(get_real_volume(music_volume)); } boolean I_SetSongTrack(int track) @@ -820,9 +1234,100 @@ boolean I_SetSongTrack(int track) SDL_UnlockAudio(); return false; } + else #endif + if (I_SongType() == MU_MOD) + return !Mix_SetMusicPosition(track); (void)track; return false; } +/// ------------------------ +/// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + internal_volume = volume; + if (!I_SongPlaying()) + return; + Mix_VolumeMusic(get_real_volume(music_volume)); +} + +void I_StopFadingSong(void) +{ + if (fading_id) + SDL_RemoveTimer(fading_id); + is_fading = false; + fading_source = fading_target = fading_timer = fading_duration = fading_id = 0; +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) +{ + INT16 volume_delta; + + source_volume = min(source_volume, 100); + volume_delta = (INT16)(target_volume - source_volume); + + I_StopFadingSong(); + + if (!ms && volume_delta) + { + I_SetInternalMusicVolume(target_volume); + if (callback) + (*callback)(); + return true; + + } + else if (!volume_delta) + { + if (callback) + (*callback)(); + return true; + } + + // Round MS to nearest 10 + // If n - lower > higher - n, then round up + ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ? + (((ms / 10) * 10) + 10) // higher + : ((ms / 10) * 10); // lower + + if (!ms) + I_SetInternalMusicVolume(target_volume); + else if (source_volume != target_volume) + { + fading_id = SDL_AddTimer(10, music_fade, NULL); + if (fading_id) + { + is_fading = true; + fading_timer = fading_duration = ms; + fading_source = source_volume; + fading_target = target_volume; + fading_callback = callback; + + if (internal_volume != source_volume) + I_SetInternalMusicVolume(source_volume); + } + } + + return is_fading; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) +{ + return I_FadeSongFromVolume(target_volume, internal_volume, ms, callback); +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + return I_FadeSongFromVolume(0, internal_volume, ms, &I_StopSong); +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + if (I_PlaySong(looping)) + return I_FadeSongFromVolume(100, 0, ms, NULL); + else + return false; +} #endif \ No newline at end of file diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index e29ac080b..25c21a07a 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1368,6 +1368,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 /// ------------------------ @@ -1436,6 +1467,47 @@ boolean I_SetSongTrack(int 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; +} + /// ------------------------ // MUSIC LOADING AND CLEANUP // \todo Split logic between loading and playing, diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 36a5904a5..85cae2ed1 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -810,6 +810,60 @@ void I_SetMusicVolume(UINT8 volume) FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); } +UINT32 I_GetSongLength() +{ + if (midimode) + return 0; + UINT32 length; + e = FMOD_Sound_GetLength(music_stream, length, FMOD_TIMEUNIT_MS); + return length; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + if(midimode) + // Dummy out; this works for some MIDI, but not others. + // SDL does not support this for any MIDI. + return false; + FMOD_RESULT e; + e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS); + if (e == FMOD_OK) + return true; + else if (e == FMOD_ERR_UNSUPPORTED // Only music modules, numbnuts! + || e == FMOD_ERR_INVALID_POSITION) // Out-of-bounds! + return false; + else // Congrats, you horribly broke it somehow + { + FMR_MUSIC(e); + return false; + } +} + +UINT32 I_GetSongPosition(void) +{ + if(midimode) + // Dummy out because unsupported, even though FMOD does this correctly. + return 0; + FMOD_RESULT e; + unsigned int fmposition = 0; + e = FMOD_Channel_GetPosition(music_channel, &fmposition, FMOD_TIMEUNIT_MS); + if (e == FMOD_OK) + return (UINT32)fmposition; + else + return 0; +} + boolean I_SetSongTrack(INT32 track) { if (track != current_track) // If the track's already playing, then why bother? @@ -854,3 +908,44 @@ boolean I_SetSongTrack(INT32 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; +} From 9c89bf3fefbbf2c641fba08e3cec30a7ef1ad430 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 10:32:38 -0400 Subject: [PATCH 003/382] MusicPlus core: Lua separation fixes --- src/lua_baselib.c | 36 ++++++++++++++++++++---------------- src/lua_hook.h | 1 - src/lua_hooklib.c | 1 - 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f7a0a5995..6a8784259 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -720,13 +720,8 @@ static int lib_pRestoreMusic(lua_State *L) if (!player) return LUA_ErrInvalid(L, "player_t"); else if (P_IsLocalPlayer(player)) - { P_RestoreMusic(player); - lua_pushboolean(L, true); - } - else - lua_pushnil(L); - return 1; + return 0; } static int lib_pSpawnShieldOrb(lua_State *L) @@ -1780,13 +1775,8 @@ static int lib_sChangeMusic(lua_State *L) fadeinms = (UINT32)luaL_optinteger(L, 7, 0); if (!player || P_IsLocalPlayer(player)) - { S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms); - lua_pushboolean(L, true); - } - else - lua_pushnil(L); - return 1; + return 0; } static int lib_sSpeedMusic(lua_State *L) @@ -1802,10 +1792,23 @@ 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_pushnil(L); - return 1; + S_SpeedMusic(speed); + return 0; +} + +static int lib_sStopMusic(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_StopMusic(); + return 0; } static int lib_sOriginPlaying(lua_State *L) @@ -2130,6 +2133,7 @@ static luaL_Reg lib[] = { {"S_StopSound",lib_sStopSound}, {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, + {"S_StopMusic",lib_sStopMusic}, {"S_OriginPlaying",lib_sOriginPlaying}, {"S_IdPlaying",lib_sIdPlaying}, {"S_SoundPlaying",lib_sSoundPlaying}, diff --git a/src/lua_hook.h b/src/lua_hook.h index 74a6b5e75..53e0a7d8e 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -43,7 +43,6 @@ enum hook { hook_PlayerMsg, hook_HurtMsg, hook_PlayerSpawn, - hook_MusicChange, hook_MAX // last hook }; diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index dff2b8f46..eadd01537 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -54,7 +54,6 @@ const char *const hookNames[hook_MAX+1] = { "PlayerMsg", "HurtMsg", "PlayerSpawn", - "MusicChange", NULL }; From 80ce366b3f22c90362bcbddaf498da58b135f853 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 12:51:42 -0400 Subject: [PATCH 004/382] Mixer I_StopSong: StopFadingSong and var_cleanup call fix --- src/sdl/mixer_sound.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 9b09ffe80..fbd587322 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1144,6 +1144,8 @@ boolean I_PlaySong(boolean looping) void I_StopSong(void) { + I_StopFadingSong(); + #ifdef HAVE_LIBGME if (gme) { @@ -1153,12 +1155,12 @@ void I_StopSong(void) #endif if (music) { - var_cleanup(); - I_StopFadingSong(); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); Mix_HaltMusic(); } + + var_cleanup(); } void I_PauseSong() From d65967908da2a41220734dca97931e7070fa2342 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 13:23:08 -0400 Subject: [PATCH 005/382] MusicPlus core: NOMIXER=1 compile fix --- src/sdl/sdl_sound.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 25c21a07a..d3b51b15e 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1480,7 +1480,7 @@ void I_StopFadingSong(void) { } -boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)source_volume; @@ -1488,7 +1488,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms return false; } -boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)ms; From 4ce05ceadfbd6c115b3f07d7349d3a3628245715 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 14:08:31 -0400 Subject: [PATCH 006/382] MusicPlus core: Win32 DD compile fixes --- src/win32/win_snd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 85cae2ed1..543de3231 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -812,10 +812,10 @@ void I_SetMusicVolume(UINT8 volume) UINT32 I_GetSongLength() { - if (midimode) + if (I_SongType() == MU_MID) return 0; UINT32 length; - e = FMOD_Sound_GetLength(music_stream, length, FMOD_TIMEUNIT_MS); + FMR_MUSIC(FMOD_Sound_GetLength(music_stream, &length, FMOD_TIMEUNIT_MS)); return length; } @@ -832,7 +832,7 @@ UINT32 I_GetSongLoopPoint(void) boolean I_SetSongPosition(UINT32 position) { - if(midimode) + if(I_SongType() == MU_MID) // Dummy out; this works for some MIDI, but not others. // SDL does not support this for any MIDI. return false; @@ -852,7 +852,7 @@ boolean I_SetSongPosition(UINT32 position) UINT32 I_GetSongPosition(void) { - if(midimode) + if(I_SongType() == MU_MID) // Dummy out because unsupported, even though FMOD does this correctly. return 0; FMOD_RESULT e; @@ -922,7 +922,7 @@ void I_StopFadingSong(void) { } -boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)source_volume; @@ -930,7 +930,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms return false; } -boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)ms; From a3664c3083b6d9819aa93de378cd4d2c29ba23cc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 15:10:42 -0400 Subject: [PATCH 007/382] Lua P_RestoreMusic else if fix --- src/lua_baselib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6a8784259..093683660 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -719,7 +719,7 @@ static int lib_pRestoreMusic(lua_State *L) NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - else if (P_IsLocalPlayer(player)) + if (P_IsLocalPlayer(player)) P_RestoreMusic(player); return 0; } From 4fa7a4ca3772e6d8c543c22df7e7a27726ba55f5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 15:28:57 -0400 Subject: [PATCH 008/382] musicplus-le-changemusic 2.2 -> 2.1 backport --- src/p_setup.c | 36 ++++++++++++++++++++++---------- src/p_spec.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6c6b9153d..f504ffb57 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1514,19 +1514,33 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) { 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; } case 414: // Play SFX diff --git a/src/p_spec.c b/src/p_spec.c index afc3c0533..7832ff038 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2419,18 +2419,60 @@ 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 : 0, -1); - strncpy(mapmusname, sides[line->sidenum[0]].text, 7); - mapmusname[6] = 0; + 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; + if ((line->flags & ML_EFFECT2) && fadetarget && musicsame) + { + if (!postfadems) + S_SetInternalMusicVolume(fadetarget); + else + S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); - mapmusposition = 0; + if (position) + S_SetMusicPosition(position); + } + else + { + strncpy(mapmusname, sides[line->sidenum[0]].text, 7); + mapmusname[6] = 0; - S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4)); + 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. From 9d40bf57fe05c247a329fa638f4cb12968b2d47a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 22:15:53 -0400 Subject: [PATCH 009/382] Mixer: Add back var_cleanup in I_LoadSong Because musicplus-libopenmpt deleted it, I added a cautionary note to ALWAYS clean up your vars! --- src/sdl/mixer_sound.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index fbd587322..f966f531a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -885,6 +885,7 @@ boolean I_LoadSong(char *data, size_t len) ) I_UnloadSong(); + // always do this whether or not a music already exists var_cleanup(); #ifdef HAVE_LIBGME From ec611647655ec9e6d4f3130248b12240660874b6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 23:29:18 -0400 Subject: [PATCH 010/382] MP Core: 2.1 dehacked typo --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6c6b9153d..4ca6c97c6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -185,7 +185,7 @@ 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]->mustrack), UNDO_NONE); + DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE); mapheaderinfo[num]->muspos = 0; DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE); mapheaderinfo[num]->forcecharacter[0] = '\0'; From fae377b8963ab76beb1621cbcfd4ec5bbfea04cf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 18:26:33 -0400 Subject: [PATCH 011/382] MP Core Mixer: Unused param fixes (buildbots) --- src/sdl/mixer_sound.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index f966f531a..644a667b3 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -519,6 +519,10 @@ static void do_fading_callback() static void count_music_bytes(int chan, void *stream, int len, void *udata) { + (void)chan; + (void)stream; + (void)udata; + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID) return; music_bytes += len; @@ -538,6 +542,8 @@ static void music_loop(void) static UINT32 music_fade(UINT32 interval, void *param) { + (void)param; + if (!is_fading || internal_volume == fading_target || fading_duration == 0) From 8eb2171fcd32c13a8a0128c45bd8f51116c11473 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:06:24 -0400 Subject: [PATCH 012/382] MP Core Mixer: Old-style function dec fixes (buildbots) --- src/sdl/mixer_sound.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 644a667b3..e5552b0a6 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -506,7 +506,7 @@ static UINT32 get_adjusted_position(UINT32 position) return position; } -static void do_fading_callback() +static void do_fading_callback(void) { if (fading_callback) (*fading_callback)(); @@ -1170,7 +1170,7 @@ void I_StopSong(void) var_cleanup(); } -void I_PauseSong() +void I_PauseSong(void) { if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? return; @@ -1182,7 +1182,7 @@ void I_PauseSong() songpaused = true; } -void I_ResumeSong() +void I_ResumeSong(void) { if (I_SongType() == MU_MID) return; From 43f6038d986621cf809abd4b4e652c428a651d4a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:18:35 -0400 Subject: [PATCH 013/382] MP Core Mixer fade: Use fixed instead of double calc (fixes buildbots) --- src/sdl/mixer_sound.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index e5552b0a6..fc6ccf50c 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -565,11 +565,11 @@ static UINT32 music_fade(UINT32 interval, void *param) else { UINT8 delta = abs(fading_target - fading_source); - double factor = (double)(fading_duration - fading_timer) / (double)fading_duration; + fixed_t factor = FixedDiv(fading_duration - fading_timer, fading_duration); if (fading_target < fading_source) - internal_volume = max(min(internal_volume, fading_source - (UINT8)round(delta * factor)), fading_target); + internal_volume = max(min(internal_volume, fading_source - FixedMul(delta, factor)), fading_target); else if (fading_target > fading_source) - internal_volume = min(max(internal_volume, fading_source + (UINT8)round(delta * factor)), fading_target); + internal_volume = min(max(internal_volume, fading_source + FixedMul(delta, factor)), fading_target); Mix_VolumeMusic(get_real_volume(music_volume)); return interval; } From 85e028c1bf427973aff6cd8f03223d6fd9a13f1f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:19:18 -0400 Subject: [PATCH 014/382] MP Core s_sound: Mixed D+C fix (buildbots) --- src/s_sound.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 3da594fe1..4a9500e71 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1437,6 +1437,8 @@ static void S_ChangeMusicToQueue(void) 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 @@ -1444,7 +1446,6 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 if (S_MusicDisabled()) return; - char newmusic[7]; strncpy(newmusic, mmusic, 7); #if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) From 67e89f9425b971b48e7d9b4ff4f8b9b3f2b94ef0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:46:57 -0400 Subject: [PATCH 015/382] MP Core s_sound: I_FadeSongFromVolume call fix (buildbots) --- src/s_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 4a9500e71..4a52ead52 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1594,7 +1594,7 @@ boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 m if (source_volume < 0) return I_FadeSong(target_volume, ms, NULL); else - return I_FadeSongFromVolume(target_volume, source_volume, ms, false); + return I_FadeSongFromVolume(target_volume, source_volume, ms, NULL); } boolean S_FadeOutStopMusic(UINT32 ms) From 9fd7fac3aee987c461f73194b97511a1d60e871b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Sep 2018 08:41:40 -0400 Subject: [PATCH 016/382] MP Core Win32: Fix FadeSong unused callback param (buildbots) --- src/win32/win_snd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 543de3231..6fed59a93 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -927,6 +927,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms (void)target_volume; (void)source_volume; (void)ms; + (void)callback; return false; } @@ -934,6 +935,7 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)ms; + (void)callback; return false; } From 8dc37a850b025959e85c52eb4b1db2763896ebdb Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 1 Jan 2019 10:47:16 -0500 Subject: [PATCH 017/382] Fix loop_point and song_length floating point comparisons --- src/sdl/mixer_sound.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 4a87712fa..04e82ea34 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1049,7 +1049,7 @@ boolean I_LoadSong(char *data, size_t len) while ((UINT32)(p - data) < len) { - if (!loop_point && !strncmp(p, key1, key1len)) + if (fpclassify(loop_point) == FP_ZERO && !strncmp(p, key1, key1len)) { p += key1len; // skip LOOP if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? @@ -1068,13 +1068,13 @@ boolean I_LoadSong(char *data, size_t len) // Everything that uses LOOPMS will work perfectly with SDL_Mixer. } } - else if (!song_length && !strncmp(p, key4, key4len)) // is it LENGTHMS=? + else if (fpclassify(song_length) == FP_ZERO && !strncmp(p, key4, key4len)) // is it LENGTHMS=? { p += key4len; // skip LENGTHMS song_length = (float)(atoi(p) / 1000.0L); } // below: search MP3 or other tags that use wide char encoding - else if (!loop_point && !memcmp(p, key1w, key1len*2)) // LOOP wide char + else if (fpclassify(loop_point) == FP_ZERO && !memcmp(p, key1w, key1len*2)) // LOOP wide char { p += key1len*2; if (!memcmp(p, key2w, (key2len+1)*2)) // POINT= wide char @@ -1106,7 +1106,7 @@ boolean I_LoadSong(char *data, size_t len) loop_point = (float)(atoi(wval) / 1000.0L); } } - else if (!song_length && !memcmp(p, key4w, (key4len+1)*2)) // LENGTHMS= wide char + else if (fpclassify(song_length) == FP_ZERO && !memcmp(p, key4w, (key4len+1)*2)) // LENGTHMS= wide char { p += (key4len+1)*2; wstart = (size_t)p; @@ -1121,7 +1121,7 @@ boolean I_LoadSong(char *data, size_t len) song_length = (float)(atoi(wval) / 1000.0L); } - if (loop_point && song_length && song_length > loop_point) // Got what we needed + if (fpclassify(loop_point) != FP_ZERO && fpclassify(song_length) != FP_ZERO && song_length > loop_point) // Got what we needed // the last case is a sanity check, in case the wide char searches were false matches. break; else // continue searching @@ -1150,7 +1150,6 @@ void I_UnloadSong(void) boolean I_PlaySong(boolean looping) { - boolean lpz = fpclassify(loop_point) == FP_ZERO; #ifdef HAVE_LIBGME if (gme) { @@ -1164,7 +1163,7 @@ boolean I_PlaySong(boolean looping) if (!music) return false; - if (!song_length && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) + if (fpclassify(song_length) == FP_ZERO && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n"); if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1) From 0724d042bc83ea622bf0d13038e354666ab14a84 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 04:58:03 -0500 Subject: [PATCH 018/382] Add safe lua music functions S_MusicExists S_SetInternalMusicVolume S_StopFadingMusic S_FadeMusic S_FadeOutStopMusic --- src/lua_baselib.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 00b309025..f5f3aeb76 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1899,6 +1899,42 @@ static int lib_sSpeedMusic(lua_State *L) return 0; } +static int lib_sMusicExists(lua_State *L) +{ + boolean checkMIDI = lua_opttrueboolean(L, 2); + boolean checkDigi = lua_opttrueboolean(L, 3); +#ifdef MUSICSLOT_COMPATIBILITY + const char *music_name; + UINT32 music_num; + char music_compat_name[7]; + UINT16 music_flags = 0; + NOHUD + if (lua_isnumber(L, 1)) + { + music_num = (UINT32)luaL_checkinteger(L, 1); + music_flags = (UINT16)(music_num & 0x0000FFFF); + if (music_flags && music_flags <= 1035) + snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags)); + else if (music_flags && music_flags <= 1050) + strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7); + else + music_compat_name[0] = 0; // becomes empty string + music_compat_name[6] = 0; + music_name = (const char *)&music_compat_name; + } + else + { + music_num = 0; + music_name = luaL_checkstring(L, 1); + } +#else + const char *music_name = luaL_checkstring(L, 1); +#endif + NOHUD + lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi)); + return 1; +} + static int lib_sStopMusic(lua_State *L) { player_t *player = NULL; @@ -1914,6 +1950,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)); @@ -2265,7 +2405,12 @@ static luaL_Reg lib[] = { {"S_StopSound",lib_sStopSound}, {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, + {"S_MusicExists",lib_sMusicExists}, {"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}, From 2ba11a6d693d1074f7fdef73cc8d9529c4bd7f55 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 21 Oct 2018 14:51:49 -0400 Subject: [PATCH 019/382] Support for per-map intermission music --- src/dehacked.c | 3 +++ src/doomstat.h | 3 +++ src/lua_maplib.c | 2 ++ src/p_setup.c | 2 ++ src/y_inter.c | 12 ++++++++++-- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 871fa0a44..011936688 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1198,6 +1198,9 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1); else if (fastcmp(word, "MUSICPOS")) mapheaderinfo[num-1]->muspos = (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); diff --git a/src/doomstat.h b/src/doomstat.h index ad989f365..716c4d654 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -247,6 +247,9 @@ typedef struct UINT8 numGradedMares; ///< Internal. For grade support. nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. + // Music stuff. + 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. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index e63ea34d8..d77e636b3 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1470,6 +1470,8 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->mustrack); else if (fastcmp(field,"muspos")) lua_pushinteger(L, header->muspos); + 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")) diff --git a/src/p_setup.c b/src/p_setup.c index db7379fbb..4409ec356 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -189,6 +189,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->mustrack = 0; DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE); mapheaderinfo[num]->muspos = 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); diff --git a/src/y_inter.c b/src/y_inter.c index 4b340cabd..e6e5a1d22 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -696,7 +696,12 @@ void Y_Ticker(void) boolean anybonuses = false; if (!intertic) // first time only - S_ChangeMusicInternal("lclear", false); // don't loop it + { + if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) + S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it + else + S_ChangeMusicInternal("lclear", false); // don't loop it + } if (intertic < TICRATE) // one second pause before tally begins return; @@ -757,7 +762,10 @@ void Y_Ticker(void) if (!intertic) // first time only { - S_ChangeMusicInternal("lclear", false); // don't loop it + if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) + S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it + else + S_ChangeMusicInternal("lclear", false); // don't loop it tallydonetic = 0; } From 5807384dbd7fe2a15facdecd80a5994bc6e4316a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 06:26:18 -0500 Subject: [PATCH 020/382] Remove S_MusicExists lua --- src/lua_baselib.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f5f3aeb76..d3443312a 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1899,42 +1899,6 @@ static int lib_sSpeedMusic(lua_State *L) return 0; } -static int lib_sMusicExists(lua_State *L) -{ - boolean checkMIDI = lua_opttrueboolean(L, 2); - boolean checkDigi = lua_opttrueboolean(L, 3); -#ifdef MUSICSLOT_COMPATIBILITY - const char *music_name; - UINT32 music_num; - char music_compat_name[7]; - UINT16 music_flags = 0; - NOHUD - if (lua_isnumber(L, 1)) - { - music_num = (UINT32)luaL_checkinteger(L, 1); - music_flags = (UINT16)(music_num & 0x0000FFFF); - if (music_flags && music_flags <= 1035) - snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags)); - else if (music_flags && music_flags <= 1050) - strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7); - else - music_compat_name[0] = 0; // becomes empty string - music_compat_name[6] = 0; - music_name = (const char *)&music_compat_name; - } - else - { - music_num = 0; - music_name = luaL_checkstring(L, 1); - } -#else - const char *music_name = luaL_checkstring(L, 1); -#endif - NOHUD - lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi)); - return 1; -} - static int lib_sStopMusic(lua_State *L) { player_t *player = NULL; @@ -2405,7 +2369,6 @@ static luaL_Reg lib[] = { {"S_StopSound",lib_sStopSound}, {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, - {"S_MusicExists",lib_sMusicExists}, {"S_StopMusic",lib_sStopMusic}, {"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume}, {"S_StopFadingMusic",lib_sStopFadingMusic}, From c5e9d6c97f8eb8260f34980a1a9aa98d45ceac6b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 06:48:06 -0500 Subject: [PATCH 021/382] DD Compile fixes --- src/win32/win_snd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 4507c27ff..f3e3bbed4 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -815,11 +815,11 @@ void I_SetMusicVolume(UINT8 volume) FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); } -UINT32 I_GetSongLength() +UINT32 I_GetSongLength(void) { + UINT32 length; if (I_SongType() == MU_MID) return 0; - UINT32 length; FMR_MUSIC(FMOD_Sound_GetLength(music_stream, &length, FMOD_TIMEUNIT_MS)); return length; } @@ -837,11 +837,11 @@ UINT32 I_GetSongLoopPoint(void) boolean I_SetSongPosition(UINT32 position) { + FMOD_RESULT e; if(I_SongType() == MU_MID) // Dummy out; this works for some MIDI, but not others. // SDL does not support this for any MIDI. return false; - FMOD_RESULT e; e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS); if (e == FMOD_OK) return true; @@ -857,11 +857,11 @@ boolean I_SetSongPosition(UINT32 position) UINT32 I_GetSongPosition(void) { + FMOD_RESULT e; + unsigned int fmposition = 0; if(I_SongType() == MU_MID) // Dummy out because unsupported, even though FMOD does this correctly. return 0; - FMOD_RESULT e; - unsigned int fmposition = 0; e = FMOD_Channel_GetPosition(music_channel, &fmposition, FMOD_TIMEUNIT_MS); if (e == FMOD_OK) return (UINT32)fmposition; From e45c54dc600c544173e52f8467dffeb903f99613 Mon Sep 17 00:00:00 2001 From: Digiku Date: Mon, 7 Jan 2019 03:41:25 -0500 Subject: [PATCH 022/382] Update f_finale.c - Remove Torgo's real name by request --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 64e371211..b177212c1 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1055,12 +1055,12 @@ static const char *credits[] = { "Dan \"Blitzzo\" Hagerstrand", "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", - "Erik \"Torgo\" Nielsen", "\"Kaito Sinclaire\"", "Wessel \"sphere\" Smit", "\"Spazzo\"", "\"SSNTails\"", "Rob Tisdell", + "\"Torgo\"", "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", "Marco \"mazmazz\" Zafra", From e5375e1d64dbb964c3f195c47eb6fd72783d09cb Mon Sep 17 00:00:00 2001 From: Arthur Date: Sat, 15 Dec 2018 08:46:08 -0500 Subject: [PATCH 023/382] New fixed math functions - ClosestPointOnVector, and Strength. Normal also returns length now, since it is free. --- src/m_fixed.c | 239 +++++++++++++++++++++++++++++--------------------- src/m_fixed.h | 4 +- 2 files changed, 140 insertions(+), 103 deletions(-) diff --git a/src/m_fixed.c b/src/m_fixed.c index d45bb70bf..5e7896739 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -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("); diff --git a/src/m_fixed.h b/src/m_fixed.h index 4609913b7..8145a6917 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -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); From e67c1bee5d1549e4838138e7ae6b8435639b143e Mon Sep 17 00:00:00 2001 From: Arthur Date: Sat, 15 Dec 2018 20:57:11 -0500 Subject: [PATCH 024/382] Common model format, with MD2/MD3 loading --- src/hardware/hw_drv.h | 6 +- src/hardware/hw_md2.c | 361 +------------ src/hardware/hw_md2.h | 94 +--- src/hardware/hw_md2load.c | 520 ++++++++++++++++++ src/hardware/hw_md2load.h | 19 + src/hardware/hw_md3load.c | 489 +++++++++++++++++ src/hardware/hw_md3load.h | 19 + src/hardware/hw_model.c | 706 +++++++++++++++++++++++++ src/hardware/hw_model.h | 104 ++++ src/hardware/r_opengl/r_opengl.c | 178 ++++--- src/hardware/u_list.c | 230 ++++++++ src/hardware/u_list.h | 29 + src/sdl/Srb2SDL-vc10.vcxproj | 10 +- src/sdl/Srb2SDL-vc10.vcxproj.filters | 24 + src/sdl/hwsym_sdl.c | 3 +- src/sdl/i_video.c | 3 +- src/win32/Srb2win-vc10.vcxproj | 10 +- src/win32/Srb2win-vc10.vcxproj.filters | 24 + src/win32/win_dll.c | 6 +- 19 files changed, 2319 insertions(+), 516 deletions(-) create mode 100644 src/hardware/hw_md2load.c create mode 100644 src/hardware/hw_md2load.h create mode 100644 src/hardware/hw_md3load.c create mode 100644 src/hardware/hw_md3load.h create mode 100644 src/hardware/hw_model.c create mode 100644 src/hardware/hw_model.h create mode 100644 src/hardware/u_list.c create mode 100644 src/hardware/u_list.h diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index e2fa90eb0..0afd6d272 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -58,8 +58,7 @@ 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, mdlframe_t *frame, INT32 duration, INT32 tics, mdlframe_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT INT32 HWRAPI(GetRenderVersion) (void); @@ -96,8 +95,7 @@ struct hwdriver_s GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility - DrawMD2 pfnDrawMD2; - DrawMD2i pfnDrawMD2i; + DrawModel pfnDrawModel; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; GetRenderVersion pfnGetRenderVersion; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 2856cada3..5d865c5ae 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -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,36 +83,9 @@ md2_t md2_playermodels[MAXSKINS]; /* * free model */ -static void md2_freeModel (md2_model_t *model) +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); } @@ -285,157 +93,13 @@ static void md2_freeModel (md2_model_t *model) // 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) - { - 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; + return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC); } -static inline void md2_printModelInfo (md2_model_t *model) +static inline void md2_printModelInfo (model_t *model) { #if 0 INT32 i; @@ -936,7 +600,7 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu 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) @@ -1216,10 +880,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 *curr, *next = NULL; const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); spritedef_t *sprdef; spriteframe_t *sprframe; @@ -1332,9 +995,8 @@ 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]; + frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; + curr = &md2->model->meshes[0].frames[frame]; #if 0 if (cv_grmd2.value == 1 && tics <= durs) { @@ -1401,7 +1063,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.anglex = FIXED_TO_FLOAT(tempangle); } - color[0] = Surf.FlatColor.s.red; color[1] = Surf.FlatColor.s.green; color[2] = Surf.FlatColor.s.blue; @@ -1413,7 +1074,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.flip = atransform.flip; p.mirror = atransform.mirror; - HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color); + HWD.pfnDrawModel(md2->model, curr, durs, tics, next, &p, finalscale, flip, color); } } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index ca43c7b4f..57d8026b9 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -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; diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c new file mode 100644 index 000000000..3b083fee4 --- /dev/null +++ b/src/hardware/hw_md2load.c @@ -0,0 +1,520 @@ +/* + 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 +#include +#include +#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) +{ + useFloat = true; // Right now we always useFloat = true, because the GL subsystem needs some work for the other option to work. + + model_t *retModel = NULL; + md2header_t *header; + + FILE *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; + const char *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 + char *buffer = malloc(fileLen); + fread(buffer, fileLen, 1, f); + 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 + md2triangle_t *tris = (md2triangle_t*)&buffer[header->offsetTris]; + md2texcoord_t *texcoords = (md2texcoord_t*)&buffer[header->offsetST]; + md2frame_t *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 + { + 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); + + byte *ptr = (byte*)frames; + for (i = 0; i < header->numFrames; i++, ptr += header->framesize) + { + 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); + + short *vertptr = retModel->meshes[0].tinyframes[i].vertices; + char *normptr = retModel->meshes[0].tinyframes[i].normals; + +// char *tanptr = retModel->meshes[0].tinyframes[i].tangents; + retModel->meshes[0].tinyframes[i].material = &retModel->materials[0]; + + framePtr++; // Advance to vertex list + md2vertex_t *vertex = (md2vertex_t*)framePtr; + framePtr--; + for (j = 0; j < header->numXYZ; j++, vertex++) + { + *vertptr = (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale); + vertptr++; + *vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale); + vertptr++; + *vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale); + vertptr++; + + // Normal + *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][1] * 127); + *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][2] * 127); + *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][0] * 127); + } + } + + // This doesn't need to be done every frame! + md2triangle_t *trisPtr = tris; + unsigned short *indexptr = retModel->meshes[0].indices; + float *uvptr = (float*)retModel->meshes[0].uvs; + for (j = 0; j < header->numTris; j++, trisPtr++) + { + *indexptr = trisPtr->meshIndex[0]; + indexptr++; + *indexptr = trisPtr->meshIndex[2]; + indexptr++; + *indexptr = trisPtr->meshIndex[1]; + indexptr++; + + 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); + 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); + } + } + else // Full float loading method + { + 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); + + md2triangle_t *trisPtr = tris; + float *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); + } + + byte *ptr = (byte*)frames; + for (i = 0; i < header->numFrames; i++, ptr += header->framesize) + { + 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 + md2vertex_t *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][1]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2]; + + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2]; + + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2]; + } + /* + // Rotate MD2 by 90 degrees in code BLAAHH + vector_t *normVecptr = (vector_t*)retModel->meshes[0].frames[i].normals; + vector_t *vertVecptr = (vector_t*)retModel->meshes[0].frames[i].vertices; + for (j = 0; j < header->numTris * 3; j++, normVecptr++, vertVecptr++) + { + VectorRotate(normVecptr, &vectorYaxis, -90.0f); + VectorRotate(vertVecptr, &vectorYaxis, -90.0f); + }*/ + } + } + + free(buffer); + return retModel; +} diff --git a/src/hardware/hw_md2load.h b/src/hardware/hw_md2load.h new file mode 100644 index 000000000..1662d6471 --- /dev/null +++ b/src/hardware/hw_md2load.h @@ -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 diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c new file mode 100644 index 000000000..bac799cdb --- /dev/null +++ b/src/hardware/hw_md3load.c @@ -0,0 +1,489 @@ +/* + 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 +#include +#include +#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++; +} + +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; + } +} + +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 bool latlnginit = false; + +model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) +{ + useFloat = true; // Right now we always useFloat = true, because the GL subsystem needs some work for the other option to work. + + if (!latlnginit) + { + LatLngInit(); + latlnginit = true; + } + + const float WUNITS = 1.0f; + model_t *retModel = NULL; + + FILE *f = fopen(fileName, "rb"); + + if (!f) + return NULL; + + retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); + + md3modelHeader *mdh; + + // find length of file + fseek(f, 0, SEEK_END); + long fileLen = ftell(f); + fseek(f, 0, SEEK_SET); + + // read in file + char *buffer = malloc(fileLen); + fread(buffer, fileLen, 1, f); + fclose(f); + + // get pointer to file header + mdh = (md3modelHeader*)buffer; + + retModel->numMeshes = mdh->numSurfaces; + + retModel->numMaterials = 0; + int surfEnd = 0; + int i; + 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); + + int t; + 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); + + int matCount = 0; + for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++) + { + md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd]; + surfEnd += mdS->offsetEnd; + + md3Shader *mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders); + int j; + 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]; + 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++) + { + 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); + short *vertptr = retModel->meshes[i].tinyframes[j].vertices; + char *normptr = retModel->meshes[i].tinyframes[j].normals; + +// char *tanptr = retModel->meshes[i].tinyframes[j].tangents; + retModel->meshes[i].tinyframes[j].material = &retModel->materials[i]; + + int k; + for (k = 0; k < mdS->numVerts; k++) + { + // Vertex + *vertptr = mdV[k].y; + vertptr++; + *vertptr = mdV[k].z; + vertptr++; + *vertptr = mdV[k].x; + vertptr++; + + // Normal + GetNormalFromLatLong(mdV[k].n, tempNormal); + *normptr = (byte)(tempNormal[1] * 127); + normptr++; + *normptr = (byte)(tempNormal[2] * 127); + normptr++; + *normptr = (byte)(tempNormal[0] * 127); + normptr++; + } + } + + float *uvptr = (float*)retModel->meshes[i].uvs; + md3TexCoord *mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); + for (j = 0; j < mdS->numVerts; j++) + { + *uvptr = mdST[j].st[0]; + uvptr++; + *uvptr = 1.0f - mdST[j].st[1]; + uvptr++; + } + + unsigned short *indexptr = retModel->meshes[i].indices; + md3Triangle *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[2]; + indexptr++; + *indexptr = (unsigned short)mdT->index[1]; + indexptr++; + } + } + else // Traditional full-float loading method + { + retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts; + float dataScale = 0.015624f * WUNITS; + float tempNormal[3]; + 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++) + { + 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); + float *vertptr = retModel->meshes[i].frames[j].vertices; + float *normptr = retModel->meshes[i].frames[j].normals; + retModel->meshes[i].frames[j].material = &retModel->materials[i]; + + int k; + md3Triangle *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 = mdV[mdT->index[0]].y * dataScale; + vertptr++; + + GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal); + *normptr = tempNormal[1]; + normptr++; + *normptr = tempNormal[2]; + normptr++; + *normptr = tempNormal[0]; + normptr++; + + // Vertex 2 + *vertptr = mdV[mdT->index[2]].x * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[2]].z * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[2]].y * dataScale; + vertptr++; + + GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal); + *normptr = tempNormal[1]; + normptr++; + *normptr = tempNormal[2]; + normptr++; + *normptr = tempNormal[0]; + normptr++; + + // Vertex 3 + *vertptr = mdV[mdT->index[1]].x * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[1]].z * dataScale; + vertptr++; + *vertptr = mdV[mdT->index[1]].y * dataScale; + vertptr++; + + GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal); + *normptr = tempNormal[1]; + normptr++; + *normptr = tempNormal[2]; + normptr++; + *normptr = tempNormal[0]; + normptr++; + + mdT++; // Advance to next triangle + } + } + + md3TexCoord *mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); + float *uvptr = (float*)retModel->meshes[i].uvs; + int k; + md3Triangle *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[2]].st[0]; + uvptr++; + *uvptr = mdST[mdT->index[2]].st[1]; + uvptr++; + + *uvptr = mdST[mdT->index[1]].st[0]; + uvptr++; + *uvptr = mdST[mdT->index[1]].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; +} diff --git a/src/hardware/hw_md3load.h b/src/hardware/hw_md3load.h new file mode 100644 index 000000000..c0e0522ff --- /dev/null +++ b/src/hardware/hw_md3load.h @@ -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 diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c new file mode 100644 index 000000000..73b2b484b --- /dev/null +++ b/src/hardware/hw_model.c @@ -0,0 +1,706 @@ +/* + 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 + +static float PI = (3.1415926535897932384626433832795f); +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) +{ + angle = U_Deg2Rad(angle); + + // Rotate the point (x,y,z) around the vector (u,v,w) + float ux = axisVec->x * rotVec->x; + float uy = axisVec->x * rotVec->y; + float uz = axisVec->x * rotVec->z; + float vx = axisVec->y * rotVec->x; + float vy = axisVec->y * rotVec->y; + float vz = axisVec->y * rotVec->z; + float wx = axisVec->z * rotVec->x; + float wy = axisVec->z * rotVec->y; + float wz = axisVec->z * rotVec->z; + float sa = sinf(angle); + float 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 CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame) +{ + return; +/* int bufferSize = sizeof(VBO::vbotiny_t)*mesh->numTriangles*3; + VBO::vbotiny_t *buffer = (VBO::vbotiny_t*)Z_Malloc(bufferSize, PU_STATIC, 0); + VBO::vbotiny_t *bufPtr = buffer; + + short *vertPtr = frame->vertices; + char *normPtr = frame->normals; + float *uvPtr = mesh->uvs; + char *tanPtr = frame->tangents; + + int i; + for (i = 0; i < mesh->numTriangles*3; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = (*normPtr++) * 127; + bufPtr->ny = (*normPtr++) * 127; + bufPtr->nz = (*normPtr++) * 127; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr) + { + bufPtr->tanx = *tanPtr++; + bufPtr->tany = *tanPtr++; + bufPtr->tanz = *tanPtr++; + } + + bufPtr++; + } + + bglGenBuffers(1, &frame->vboID); + bglBindBuffer(BGL_ARRAY_BUFFER, frame->vboID); + bglBufferData(BGL_ARRAY_BUFFER, bufferSize, buffer, BGL_STATIC_DRAW); + Z_Free(buffer);*/ +} + +void CreateVBO(mesh_t *mesh, mdlframe_t *frame) +{ + return; +/* int bufferSize = sizeof(VBO::vbo64_t)*mesh->numTriangles*3; + VBO::vbo64_t *buffer = (VBO::vbo64_t*)Z_Malloc(bufferSize, PU_STATIC, 0); + VBO::vbo64_t *bufPtr = buffer; + + float *vertPtr = frame->vertices; + float *normPtr = frame->normals; + float *tanPtr = frame->tangents; + float *uvPtr = mesh->uvs; + float *lightPtr = mesh->lightuvs; + byte *colorPtr = frame->colors; + + int i; + for (i = 0; i < mesh->numTriangles*3; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr != NULL) + { + bufPtr->tan0 = *tanPtr++; + bufPtr->tan1 = *tanPtr++; + bufPtr->tan2 = *tanPtr++; + } + + if (lightPtr != NULL) + { + bufPtr->s1 = *lightPtr++; + bufPtr->t1 = *lightPtr++; + } + + if (colorPtr) + { + bufPtr->r = *colorPtr++; + bufPtr->g = *colorPtr++; + bufPtr->b = *colorPtr++; + bufPtr->a = *colorPtr++; + } + else + { + bufPtr->r = 255; + bufPtr->g = 255; + bufPtr->b = 255; + bufPtr->a = 255; + } + + bufPtr++; + } + + bglGenBuffers(1, &frame->vboID); + bglBindBuffer(BGL_ARRAY_BUFFER, frame->vboID); + bglBufferData(BGL_ARRAY_BUFFER, bufferSize, buffer, BGL_STATIC_DRAW); + Z_Free(buffer);*/ +} + +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; + } + + CONS_Printf("Generating VBOs for %s\n", filename); + for (i = 0; i < model->numMeshes; i++) + { + mesh_t *mesh = &model->meshes[i]; + + if (mesh->frames) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + frame->vboID = 0; + CreateVBO(mesh, frame); + } + } + else if (mesh->tinyframes) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + tinyframe_t *frame = &mesh->tinyframes[j]; + frame->vboID = 0; + CreateVBOTiny(mesh, frame); + } + } + } + + 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++) + { + mesh_t *mesh = &model->meshes[i]; + + if (!mesh->frames) + continue; + + int j; + 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); + 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); + }*/ + + int k; + float *vertPtr = frame->vertices; + for (k = 0; k < mesh->numVertices; k++) + { + float x, y, z; + x = *vertPtr++; + y = *vertPtr++; + z = *vertPtr++; + + int vCount = 0; + vector_t normal; + normal.x = normal.y = normal.z = 0; + int l; + float *testPtr = frame->vertices; + for (l = 0; l < mesh->numVertices; l++) + { + float testX, testY, testZ; + testX = *testPtr++; + testY = *testPtr++; + testZ = *testPtr++; + + if (x != testX || y != testY || z != testZ) + 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; + }*/ + } + } + + float *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 bool AddMaterialToList(materiallist_t **head, material_t *material) +{ + materiallist_t *node; + for (node = *head; node; node = node->next) + { + if (node->material == material) + return false; + } + + // Didn't find it, so add to the list + materiallist_t *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) +{ + if (model->numMeshes <= 1) + return; // No need + + int numMeshes = 0; + int i; + materiallist_t *matListHead = NULL; + 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++; + } + + int memTag = PU_STATIC; + mesh_t *newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0); + + i = 0; + materiallist_t *node; + for (node = matListHead; node; node = node->next) + { + material_t *curMat = node->material; + mesh_t *newMesh = &newMeshes[i]; + + // 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); + mdlframe_t *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 = (byte*)Z_Malloc(sizeof(byte)*4*numTriangles*3, memTag, 0); + + // Now traverse the meshes of the model, adding in + // vertices/normals/uvs that match the current material + int uvCount = 0; + int vertCount = 0; + int 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; + + 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; + + byte *destByte; + byte *srcByte; + destByte = (byte*)newMesh->frames[0].colors; + srcByte = (byte*)curMesh->frames[0].colors; + + if (srcByte) + { + M_Memcpy(&destByte[colorCount], + srcByte, + sizeof(byte)*4*curMesh->numTriangles*3); + } + else + { + memset(&destByte[colorCount], + 255, + sizeof(byte)*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++) + { + mesh_t *mesh = &model->meshes[i]; + + if (!mesh->frames) + continue; + + int j; + for (j = 0; j < mesh->numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + + frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0); + + const float *vertices = frame->vertices; + vector_t *polyNormals = frame->polyNormals; + int k; + for (k = 0; k < mesh->numTriangles; k++) + { +// Vector::Normal(vertices, polyNormals); + vertices += 3 * 3; + polyNormals++; + } + } + } +} + +// +// Reload +// +// Reload VBOs +// +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]); + } + } + }*/ +} + +void DeleteVBOs(model_t *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; + } + } + }*/ +} diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h new file mode 100644 index 000000000..ed7e41a55 --- /dev/null +++ b/src/hardware/hw_model.h @@ -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; + bool 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; + byte *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 diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 91578e7f4..f8b324ed0 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -245,6 +245,12 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglColor4f glColor4f #define pglColor4fv glColor4fv #define pglTexCoord2f glTexCoord2f +#define pglVertexPointer glVertexPointer +#define pglNormalPointer glNormalPointer +#define pglTexCoordPointer glTexCoordPointer +#define pglDrawArrays glDrawArrays +#define pglEnableClientState glEnableClientState +#define pglDisableClientState pglDisableClientState /* Lighting */ #define pglShadeModel glShadeModel @@ -357,6 +363,18 @@ typedef void (APIENTRY * PFNglColor4fv) (const GLfloat *v); static PFNglColor4fv pglColor4fv; typedef void (APIENTRY * PFNglTexCoord2f) (GLfloat s, GLfloat t); static PFNglTexCoord2f pglTexCoord2f; +typedef void (APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglVertexPointer pglVertexPointer; +typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglNormalPointer pglNormalPointer; +typedef void (APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglTexCoordPointer pglTexCoordPointer; +typedef void (APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count); +static PFNglDrawArrays pglDrawArrays; +typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); +static PFNglEnableClientState pglEnableClientState; +typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap); +static PFNglDisableClientState pglDisableClientState; /* Lighting */ typedef void (APIENTRY * PFNglShadeModel) (GLenum mode); @@ -495,6 +513,12 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglColor4f , glColor4f) GETOPENGLFUNC(pglColor4fv , glColor4fv) GETOPENGLFUNC(pglTexCoord2f , glTexCoord2f) + GETOPENGLFUNC(pglVertexPointer, glVertexPointer) + GETOPENGLFUNC(pglNormalPointer, glNormalPointer) + GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) + GETOPENGLFUNC(pglDrawArrays, glDrawArrays) + GETOPENGLFUNC(pglEnableClientState, glEnableClientState) + GETOPENGLFUNC(pglDisableClientState, glDisableClientState) GETOPENGLFUNC(pglShadeModel , glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) @@ -1878,14 +1902,15 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } } -static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) -{ +static void DrawModelEx(model_t *model, mdlframe_t *frame, INT32 duration, INT32 tics, mdlframe_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +{ INT32 val, count, pindex; GLfloat s, t; GLfloat ambient[4]; GLfloat diffuse[4]; float pol = 0.0f; + scale *= 0.5f; float scalex = scale, scaley = scale, scalez = scale; // Because Otherwise, scaling the screen negatively vertically breaks the lighting @@ -1966,68 +1991,107 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); - val = *gl_cmd_buffer++; + pglScalef(scalex, scaley, scalez); - while (val != 0) + mesh_t *mesh = &model->meshes[0]; + + if (!nextframe || pol == 0.0f) { - if (val < 0) + // Zoom! Take advantage of just shoving the entire arrays to the GPU. + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglEnableClientState(GL_NORMAL_ARRAY); + pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); + pglNormalPointer(GL_FLOAT, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + pglDisableClientState(GL_NORMAL_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + /* + pglBegin(GL_TRIANGLES); + + int i = 0; + float *uvPtr = mesh->uvs; + float *frameVert = frame->vertices; + float *frameNormal = frame->normals; + for (i = 0; i < mesh->numTriangles; i++) { - pglBegin(GL_TRIANGLE_FAN); - count = -val; - } - else - { - pglBegin(GL_TRIANGLE_STRIP); - count = val; + float uvx = *uvPtr++; + float uvy = *uvPtr++; + + // Interpolate + float px1 = *frameVert++; + float py1 = *frameVert++; + float pz1 = *frameVert++; + float nx1 = *frameNormal++; + float ny1 = *frameNormal++; + float nz1 = *frameNormal++; + + pglTexCoord2f(uvx, uvy); + pglNormal3f(nx1, ny1, nz1); + pglVertex3f(px1, py1, pz1); } - while (count--) + pglEnd();*/ + } + else + { + // Dangit, I soooo want to do this in a GLSL shader... + pglBegin(GL_TRIANGLES); + + int i = 0; + float *uvPtr = mesh->uvs; + float *frameVert = frame->vertices; + float *frameNormal = frame->normals; + float *nextFrameVert = nextframe->vertices; + float *nextFrameNormal = frame->normals; + for (i = 0; i < mesh->numTriangles; i++) { - s = *(float *) gl_cmd_buffer++; - t = *(float *) gl_cmd_buffer++; - pindex = *gl_cmd_buffer++; + float uvx = *uvPtr++; + float uvy = *uvPtr++; - pglTexCoord2f(s, t); + // Interpolate + float px1 = *frameVert++; + float px2 = *nextFrameVert++; + float py1 = *frameVert++; + float py2 = *nextFrameVert++; + float pz1 = *frameVert++; + float pz2 = *nextFrameVert++; + float nx1 = *frameNormal++; + float nx2 = *nextFrameNormal++; + float ny1 = *frameNormal++; + float ny2 = *nextFrameNormal++; + float nz1 = *frameNormal++; + float nz2 = *nextFrameNormal++; - if (!nextframe || pol == 0.0f) - { - pglNormal3f(frame->vertices[pindex].normal[0], - frame->vertices[pindex].normal[1], - frame->vertices[pindex].normal[2]); - - pglVertex3f(frame->vertices[pindex].vertex[0]*scalex/2.0f, - frame->vertices[pindex].vertex[1]*scaley/2.0f, - frame->vertices[pindex].vertex[2]*scalez/2.0f); - } - else - { - // Interpolate - float px1 = frame->vertices[pindex].vertex[0]*scalex/2.0f; - float px2 = nextframe->vertices[pindex].vertex[0]*scalex/2.0f; - float py1 = frame->vertices[pindex].vertex[1]*scaley/2.0f; - float py2 = nextframe->vertices[pindex].vertex[1]*scaley/2.0f; - float pz1 = frame->vertices[pindex].vertex[2]*scalez/2.0f; - float pz2 = nextframe->vertices[pindex].vertex[2]*scalez/2.0f; - float nx1 = frame->vertices[pindex].normal[0]; - float nx2 = nextframe->vertices[pindex].normal[0]; - float ny1 = frame->vertices[pindex].normal[1]; - float ny2 = nextframe->vertices[pindex].normal[1]; - float nz1 = frame->vertices[pindex].normal[2]; - float nz2 = nextframe->vertices[pindex].normal[2]; - - pglNormal3f((nx1 + pol * (nx2 - nx1)), - (ny1 + pol * (ny2 - ny1)), - (nz1 + pol * (nz2 - nz1))); - pglVertex3f((px1 + pol * (px2 - px1)), - (py1 + pol * (py2 - py1)), - (pz1 + pol * (pz2 - pz1))); - } + pglTexCoord2f(uvx, uvy); + pglNormal3f((nx1 + pol * (nx2 - nx1)), + (ny1 + pol * (ny2 - ny1)), + (nz1 + pol * (nz2 - nz1))); + pglVertex3f((px1 + pol * (px2 - px1)), + (py1 + pol * (py2 - py1)), + (pz1 + pol * (pz2 - pz1))); } pglEnd(); - - val = *gl_cmd_buffer++; } + +/* if (lightType != LIGHT_NONE) + { + glVertexAttribPointer(program->slots[Shaders::A_NORMAL_SLOT], 3, BGL_FLOAT, BGL_FALSE, 0, frame->normals); + // if (normalmapped) + // bglVertexAttribPointer(program->slots[Shaders::A_TANGENT_SLOT], 3, BGL_FLOAT, BGL_FALSE, 0, frame->tangents); + } + + if (frame->colors) + glVertexAttribPointer(program->slots[Shaders::A_COLOR_SLOT], 4, GL_UNSIGNED_BYTE, BGL_TRUE, 0, frame->colors); + else + { + SetGlobalWhiteColorArray(mesh->numTriangles * 3); + glVertexAttribPointer(program->slots[Shaders::A_COLOR_SLOT], 3, BGL_UNSIGNED_BYTE, BGL_TRUE, 0, globalWhiteColorArray); + } + */ pglPopMatrix(); // should be the same as glLoadIdentity if (color) pglDisable(GL_LIGHTING); @@ -2038,17 +2102,11 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, // -----------------+ // HWRAPI DrawMD2 : Draw an MD2 model with glcommands // -----------------+ -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, mdlframe_t *frame, INT32 duration, INT32 tics, mdlframe_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { - DrawMD2Ex(gl_cmd_buffer, frame, duration, tics, nextframe, pos, scale, flipped, color); + DrawModelEx(model, frame, duration, tics, nextframe, pos, scale, flipped, color); } -EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale) -{ - DrawMD2Ex(gl_cmd_buffer, frame, 0, 0, NULL, pos, scale, false, NULL); -} - - // -----------------+ // SetTransform : // -----------------+ diff --git a/src/hardware/u_list.c b/src/hardware/u_list.c new file mode 100644 index 000000000..dc49a74e7 --- /dev/null +++ b/src/hardware/u_list.c @@ -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; +} diff --git a/src/hardware/u_list.h b/src/hardware/u_list.h new file mode 100644 index 000000000..7e9a3cabd --- /dev/null +++ b/src/hardware/u_list.h @@ -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 diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index df582865c..a51661380 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -156,6 +156,10 @@ + + + + @@ -294,8 +298,12 @@ + + + + @@ -304,7 +312,7 @@ - + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 09287436d..d789a61fe 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -246,6 +246,18 @@ Hw_Hardware + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + I_Interface @@ -624,9 +636,21 @@ Hw_Hardware + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + Hw_Hardware + + Hw_Hardware + I_Interface diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 05ac6450e..7962e01b1 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -87,8 +87,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); GETFUNC(GetTextureUsed); - GETFUNC(DrawMD2); - GETFUNC(DrawMD2i); + GETFUNC(DrawModel); GETFUNC(SetTransform); GETFUNC(GetRenderVersion); #ifdef SHUFFLE diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 78dfc820c..336a709df 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1546,8 +1546,7 @@ void I_StartupGraphics(void) HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); HWD.pfnSetPalette = hwSym("SetPalette",NULL); HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); - HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL); - HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL); + HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); #ifdef SHUFFLE diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index 5bfa29b8c..3056b975a 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -124,7 +124,11 @@ + + + + @@ -132,7 +136,7 @@ - + @@ -287,6 +291,10 @@ + + + + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index d20dd672b..1a2a7f80d 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -108,9 +108,21 @@ Hw_Hardware + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + Hw_Hardware + + Hw_Hardware + Hw_Hardware @@ -506,6 +518,15 @@ Hw_Hardware + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + Hw_Hardware @@ -515,6 +536,9 @@ Hw_Hardware + + Hw_Hardware + BLUA diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 71eda0437..bc67f04a5 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -109,8 +109,7 @@ static loadfunc_t hwdFuncTable[] = { {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, {"SetSpecialState@8", &hwdriver.pfnSetSpecialState}, - {"DrawMD2@16", &hwdriver.pfnDrawMD2}, - {"DrawMD2i@36", &hwdriver.pfnDrawMD2i}, + {"DrawModel@16", &hwdriver.pfnDrawModel}, {"SetTransform@4", &hwdriver.pfnSetTransform}, {"GetTextureUsed@0", &hwdriver.pfnGetTextureUsed}, {"GetRenderVersion@0", &hwdriver.pfnGetRenderVersion}, @@ -140,8 +139,7 @@ static loadfunc_t hwdFuncTable[] = { {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, {"SetSpecialState", &hwdriver.pfnSetSpecialState}, - {"DrawMD2", &hwdriver.pfnDrawMD2}, - {"DrawMD2i", &hwdriver.pfnDrawMD2i}, + {"DrawModel", &hwdriver.pfnDrawModel}, {"SetTransform", &hwdriver.pfnSetTransform}, {"GetTextureUsed", &hwdriver.pfnGetTextureUsed}, {"GetRenderVersion", &hwdriver.pfnGetRenderVersion}, From 797023102bfc4a467e8139a33dffeb7783717f05 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 16 Dec 2018 12:04:10 -0500 Subject: [PATCH 025/382] Support for 'tinyframes', and lots more optimization --- src/hardware/hw_drv.h | 2 +- src/hardware/hw_md2.c | 5 +- src/hardware/hw_md2load.c | 16 +-- src/hardware/hw_md3load.c | 68 +++++---- src/hardware/r_opengl/r_opengl.c | 228 +++++++++++++++++++------------ 5 files changed, 183 insertions(+), 136 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 0afd6d272..7b45b0974 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -58,7 +58,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, mdlframe_t *frame, INT32 duration, INT32 tics, mdlframe_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(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT INT32 HWRAPI(GetRenderVersion) (void); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5d865c5ae..10517b7e0 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -832,7 +832,8 @@ 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]; @@ -1074,7 +1075,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.flip = atransform.flip; p.mirror = atransform.mirror; - HWD.pfnDrawModel(md2->model, curr, durs, tics, next, &p, finalscale, flip, color); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); } } diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 3b083fee4..998dc70b6 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -233,8 +233,6 @@ typedef struct // Load the model model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) { - useFloat = true; // Right now we always useFloat = true, because the GL subsystem needs some work for the other option to work. - model_t *retModel = NULL; md2header_t *header; @@ -397,17 +395,17 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) framePtr--; for (j = 0; j < header->numXYZ; j++, vertex++) { - *vertptr = (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale); + *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 = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale); + *vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale); vertptr++; // Normal + *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][0] * 127); *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][1] * 127); *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][2] * 127); - *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][0] * 127); } } @@ -419,17 +417,17 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) { *indexptr = trisPtr->meshIndex[0]; indexptr++; - *indexptr = trisPtr->meshIndex[2]; - 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); - 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); } } else // Full float loading method diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index bac799cdb..87a2f6ed1 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -144,8 +144,6 @@ static bool latlnginit = false; model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) { - useFloat = true; // Right now we always useFloat = true, because the GL subsystem needs some work for the other option to work. - if (!latlnginit) { LatLngInit(); @@ -307,20 +305,20 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) for (k = 0; k < mdS->numVerts; k++) { // Vertex - *vertptr = mdV[k].y; + *vertptr = mdV[k].x; vertptr++; *vertptr = mdV[k].z; vertptr++; - *vertptr = mdV[k].x; + *vertptr = 1.0f - mdV[k].y; vertptr++; // Normal GetNormalFromLatLong(mdV[k].n, tempNormal); - *normptr = (byte)(tempNormal[1] * 127); + *normptr = (byte)(tempNormal[0] * 127); normptr++; *normptr = (byte)(tempNormal[2] * 127); normptr++; - *normptr = (byte)(tempNormal[0] * 127); + *normptr = (byte)(tempNormal[1] * 127); normptr++; } } @@ -331,7 +329,7 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) { *uvptr = mdST[j].st[0]; uvptr++; - *uvptr = 1.0f - mdST[j].st[1]; + *uvptr = mdST[j].st[1]; uvptr++; } @@ -342,10 +340,10 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) // Indices *indexptr = (unsigned short)mdT->index[0]; indexptr++; - *indexptr = (unsigned short)mdT->index[2]; - indexptr++; *indexptr = (unsigned short)mdT->index[1]; indexptr++; + *indexptr = (unsigned short)mdT->index[2]; + indexptr++; } } else // Traditional full-float loading method @@ -377,48 +375,48 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) vertptr++; *vertptr = mdV[mdT->index[0]].z * dataScale; vertptr++; - *vertptr = mdV[mdT->index[0]].y * dataScale; + *vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale; vertptr++; GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal); - *normptr = tempNormal[1]; + *normptr = tempNormal[0]; normptr++; *normptr = tempNormal[2]; normptr++; - *normptr = tempNormal[0]; + *normptr = tempNormal[1]; normptr++; // Vertex 2 - *vertptr = mdV[mdT->index[2]].x * dataScale; - vertptr++; - *vertptr = mdV[mdT->index[2]].z * dataScale; - vertptr++; - *vertptr = mdV[mdT->index[2]].y * dataScale; - vertptr++; - - GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal); - *normptr = tempNormal[1]; - normptr++; - *normptr = tempNormal[2]; - normptr++; - *normptr = tempNormal[0]; - normptr++; - - // Vertex 3 *vertptr = mdV[mdT->index[1]].x * dataScale; vertptr++; *vertptr = mdV[mdT->index[1]].z * dataScale; vertptr++; - *vertptr = mdV[mdT->index[1]].y * dataScale; + *vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale; vertptr++; GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal); - *normptr = tempNormal[1]; + *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 } @@ -436,16 +434,16 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) *uvptr = mdST[mdT->index[0]].st[1]; uvptr++; - *uvptr = mdST[mdT->index[2]].st[0]; - uvptr++; - *uvptr = mdST[mdT->index[2]].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 } } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index f8b324ed0..dbf9649d4 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -241,14 +241,18 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglBegin glBegin #define pglEnd glEnd #define pglVertex3f glVertex3f +#define pglVertex3sv glVertex3sv #define pglNormal3f glNormal3f +#define pglNormal3bv glNormal3bv #define pglColor4f glColor4f #define pglColor4fv glColor4fv #define pglTexCoord2f glTexCoord2f +#define pglTexCoord2fv glTexCoord2fv #define pglVertexPointer glVertexPointer #define pglNormalPointer glNormalPointer #define pglTexCoordPointer glTexCoordPointer #define pglDrawArrays glDrawArrays +#define pglDrawElements glDrawElements #define pglEnableClientState glEnableClientState #define pglDisableClientState pglDisableClientState @@ -355,14 +359,20 @@ typedef void (APIENTRY * PFNglEnd) (void); static PFNglEnd pglEnd; typedef void (APIENTRY * PFNglVertex3f) (GLfloat x, GLfloat y, GLfloat z); static PFNglVertex3f pglVertex3f; +typedef void (APIENTRY * PFNglVertex3sv) (const GLshort *v); +static PFNglVertex3sv pglVertex3sv; typedef void (APIENTRY * PFNglNormal3f) (GLfloat x, GLfloat y, GLfloat z); static PFNglNormal3f pglNormal3f; +typedef void (APIENTRY * PFNglNormal3bv)(const GLbyte *v); +static PFNglNormal3bv pglNormal3bv; typedef void (APIENTRY * PFNglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); static PFNglColor4f pglColor4f; typedef void (APIENTRY * PFNglColor4fv) (const GLfloat *v); static PFNglColor4fv pglColor4fv; typedef void (APIENTRY * PFNglTexCoord2f) (GLfloat s, GLfloat t); static PFNglTexCoord2f pglTexCoord2f; +typedef void (APIENTRY * PFNglTexCoord2fv) (const GLfloat *v); +static PFNglTexCoord2fv pglTexCoord2fv; typedef void (APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); static PFNglVertexPointer pglVertexPointer; typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); @@ -371,6 +381,8 @@ typedef void (APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei static PFNglTexCoordPointer pglTexCoordPointer; typedef void (APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count); static PFNglDrawArrays pglDrawArrays; +typedef void (APIENTRY * PFNglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +static PFNglDrawElements pglDrawElements; typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); static PFNglEnableClientState pglEnableClientState; typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap); @@ -509,14 +521,18 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglBegin , glBegin) GETOPENGLFUNC(pglEnd , glEnd) GETOPENGLFUNC(pglVertex3f , glVertex3f) + GETOPENGLFUNC(pglVertex3sv, glVertex3sv) GETOPENGLFUNC(pglNormal3f , glNormal3f) + GETOPENGLFUNC(pglNormal3bv, glNomral3bv) GETOPENGLFUNC(pglColor4f , glColor4f) GETOPENGLFUNC(pglColor4fv , glColor4fv) GETOPENGLFUNC(pglTexCoord2f , glTexCoord2f) + GETOPENGLFUNC(pglTexCoord2fv, glTexCoord2fv) GETOPENGLFUNC(pglVertexPointer, glVertexPointer) GETOPENGLFUNC(pglNormalPointer, glNormalPointer) GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) GETOPENGLFUNC(pglDrawArrays, glDrawArrays) + GETOPENGLFUNC(pglDrawElements, glDrawElements) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) GETOPENGLFUNC(pglDisableClientState, glDisableClientState) @@ -1902,7 +1918,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } } -static void DrawModelEx(model_t *model, mdlframe_t *frame, INT32 duration, INT32 tics, mdlframe_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { INT32 val, count, pindex; GLfloat s, t; @@ -1993,105 +2009,139 @@ static void DrawModelEx(model_t *model, mdlframe_t *frame, INT32 duration, INT32 pglScalef(scalex, scaley, scalez); - mesh_t *mesh = &model->meshes[0]; + boolean useTinyFrames = model->meshes[0].tinyframes != NULL; - if (!nextframe || pol == 0.0f) + if (useTinyFrames) + pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); + + for (int i = 0; i < model->numMeshes; i++) { - // Zoom! Take advantage of just shoving the entire arrays to the GPU. - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - pglEnableClientState(GL_NORMAL_ARRAY); - pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); - pglNormalPointer(GL_FLOAT, 0, frame->normals); - pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); - pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); - pglDisableClientState(GL_NORMAL_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - /* - pglBegin(GL_TRIANGLES); + mesh_t *mesh = &model->meshes[i]; - int i = 0; - float *uvPtr = mesh->uvs; - float *frameVert = frame->vertices; - float *frameNormal = frame->normals; - for (i = 0; i < mesh->numTriangles; i++) + if (useTinyFrames) { - float uvx = *uvPtr++; - float uvy = *uvPtr++; + tinyframe_t *frame = &mesh->tinyframes[frameIndex % mesh->numFrames]; + tinyframe_t *nextframe = NULL; - // Interpolate - float px1 = *frameVert++; - float py1 = *frameVert++; - float pz1 = *frameVert++; - float nx1 = *frameNormal++; - float ny1 = *frameNormal++; - float nz1 = *frameNormal++; + if (nextFrameIndex != -1) + nextframe = &mesh->tinyframes[nextFrameIndex % mesh->numFrames]; - pglTexCoord2f(uvx, uvy); - pglNormal3f(nx1, ny1, nz1); - pglVertex3f(px1, py1, pz1); + if (!nextframe || pol == 0.0f) + { + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglEnableClientState(GL_NORMAL_ARRAY); + pglVertexPointer(3, GL_SHORT, 0, frame->vertices); + pglNormalPointer(GL_BYTE, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglDisableClientState(GL_NORMAL_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + // Dangit, I soooo want to do this in a GLSL shader... + pglBegin(GL_TRIANGLES); + + short *buffer = malloc(mesh->numVertices * sizeof(short)); + short *vertPtr = buffer; + char *normBuffer = malloc(mesh->numVertices * sizeof(char)); + char *normPtr = normBuffer; + + int j = 0; + for (j = 0; j < mesh->numVertices; j++) + { + // Interpolate + *vertPtr++ = (short)(frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j]))); + *normPtr++ = (short)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); + } + + float *uvPtr = mesh->uvs; + vertPtr = buffer; + normPtr = normBuffer; + for (j = 0; j < mesh->numTriangles; j++) + { + pglTexCoord2fv(uvPtr); + pglNormal3bv(normPtr); + pglVertex3sv(vertPtr); + + uvPtr += 2; + normPtr += 3; + vertPtr += 3; + } + + free(buffer); + free(normBuffer); + + pglEnd(); + } } - - pglEnd();*/ - } - else - { - // Dangit, I soooo want to do this in a GLSL shader... - pglBegin(GL_TRIANGLES); - - int i = 0; - float *uvPtr = mesh->uvs; - float *frameVert = frame->vertices; - float *frameNormal = frame->normals; - float *nextFrameVert = nextframe->vertices; - float *nextFrameNormal = frame->normals; - for (i = 0; i < mesh->numTriangles; i++) + else { - float uvx = *uvPtr++; - float uvy = *uvPtr++; + mdlframe_t *frame = &mesh->frames[frameIndex % mesh->numFrames]; + mdlframe_t *nextframe = NULL; - // Interpolate - float px1 = *frameVert++; - float px2 = *nextFrameVert++; - float py1 = *frameVert++; - float py2 = *nextFrameVert++; - float pz1 = *frameVert++; - float pz2 = *nextFrameVert++; - float nx1 = *frameNormal++; - float nx2 = *nextFrameNormal++; - float ny1 = *frameNormal++; - float ny2 = *nextFrameNormal++; - float nz1 = *frameNormal++; - float nz2 = *nextFrameNormal++; + if (nextFrameIndex != -1) + nextframe = &mesh->frames[nextFrameIndex % mesh->numFrames]; - pglTexCoord2f(uvx, uvy); - pglNormal3f((nx1 + pol * (nx2 - nx1)), - (ny1 + pol * (ny2 - ny1)), - (nz1 + pol * (nz2 - nz1))); - pglVertex3f((px1 + pol * (px2 - px1)), - (py1 + pol * (py2 - py1)), - (pz1 + pol * (pz2 - pz1))); + if (!nextframe || pol == 0.0f) + { + // Zoom! Take advantage of just shoving the entire arrays to the GPU. + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglEnableClientState(GL_NORMAL_ARRAY); + pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); + pglNormalPointer(GL_FLOAT, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + pglDisableClientState(GL_NORMAL_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + // Dangit, I soooo want to do this in a GLSL shader... + pglBegin(GL_TRIANGLES); + + int j = 0; + float *uvPtr = mesh->uvs; + float *frameVert = frame->vertices; + float *frameNormal = frame->normals; + float *nextFrameVert = nextframe->vertices; + float *nextFrameNormal = frame->normals; + for (j = 0; j < mesh->numTriangles; j++) + { + // Interpolate + float px1 = *frameVert++; + float px2 = *nextFrameVert++; + float py1 = *frameVert++; + float py2 = *nextFrameVert++; + float pz1 = *frameVert++; + float pz2 = *nextFrameVert++; + float nx1 = *frameNormal++; + float nx2 = *nextFrameNormal++; + float ny1 = *frameNormal++; + float ny2 = *nextFrameNormal++; + float nz1 = *frameNormal++; + float nz2 = *nextFrameNormal++; + + pglTexCoord2fv(uvPtr); + pglNormal3f((nx1 + pol * (nx2 - nx1)), + (ny1 + pol * (ny2 - ny1)), + (nz1 + pol * (nz2 - nz1))); + pglVertex3f((px1 + pol * (px2 - px1)), + (py1 + pol * (py2 - py1)), + (pz1 + pol * (pz2 - pz1))); + + uvPtr++; + } + + pglEnd(); + } } - - pglEnd(); } -/* if (lightType != LIGHT_NONE) - { - glVertexAttribPointer(program->slots[Shaders::A_NORMAL_SLOT], 3, BGL_FLOAT, BGL_FALSE, 0, frame->normals); - // if (normalmapped) - // bglVertexAttribPointer(program->slots[Shaders::A_TANGENT_SLOT], 3, BGL_FLOAT, BGL_FALSE, 0, frame->tangents); - } - - if (frame->colors) - glVertexAttribPointer(program->slots[Shaders::A_COLOR_SLOT], 4, GL_UNSIGNED_BYTE, BGL_TRUE, 0, frame->colors); - else - { - SetGlobalWhiteColorArray(mesh->numTriangles * 3); - glVertexAttribPointer(program->slots[Shaders::A_COLOR_SLOT], 3, BGL_UNSIGNED_BYTE, BGL_TRUE, 0, globalWhiteColorArray); - } - */ pglPopMatrix(); // should be the same as glLoadIdentity if (color) pglDisable(GL_LIGHTING); @@ -2102,9 +2152,9 @@ static void DrawModelEx(model_t *model, mdlframe_t *frame, INT32 duration, INT32 // -----------------+ // HWRAPI DrawMD2 : Draw an MD2 model with glcommands // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, mdlframe_t *frame, INT32 duration, INT32 tics, mdlframe_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) { - DrawModelEx(model, frame, duration, tics, nextframe, pos, scale, flipped, color); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, color); } // -----------------+ From ee2d105308e7e33213cd840934c9a8cebf528dcc Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 16 Dec 2018 15:24:17 -0500 Subject: [PATCH 026/382] Remove CONS_Printf message that isn't even doing what it says it is! --- src/hardware/hw_model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 73b2b484b..495c8c109 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -320,7 +320,7 @@ model_t *LoadModel(const char *filename, int ztag) material->shininess = 25.0f; } - CONS_Printf("Generating VBOs for %s\n", filename); +// CONS_Printf("Generating VBOs for %s\n", filename); for (i = 0; i < model->numMeshes; i++) { mesh_t *mesh = &model->meshes[i]; From 3f2208bda2095f7a6d9f5a7482ff533b3ae2b458 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 17:57:39 -0500 Subject: [PATCH 027/382] Add MD2/MD3 files to makefile --- src/Makefile | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Makefile b/src/Makefile index a2279a94d..753bfab46 100644 --- a/src/Makefile +++ b/src/Makefile @@ -277,7 +277,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 @@ -728,16 +729,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 @@ -889,24 +892,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 From 43089535d558447150b2eba0b58f28e535478b51 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 19:17:33 -0500 Subject: [PATCH 028/382] GCC compile fixes --- src/hardware/hw_md2.c | 107 +------------------------------ src/hardware/hw_md3load.c | 8 ++- src/hardware/hw_model.c | 19 ++++-- src/hardware/hw_model.h | 2 +- src/hardware/r_opengl/r_opengl.c | 10 ++- 5 files changed, 25 insertions(+), 121 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 10517b7e0..b9ff29578 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -83,10 +83,12 @@ md2_t md2_playermodels[MAXSKINS]; /* * free model */ +#if 0 static void md2_freeModel (model_t *model) { UnloadModel(model); } +#endif // @@ -832,11 +834,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) FSurfaceInfo Surf; char filename[64]; - INT32 frame = 0; - INT32 nextFrame = -1; - FTransform p; md2_t *md2; - UINT8 color[4]; if (!cv_grmd2.value) return; @@ -881,17 +879,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr) // Look at HWR_ProjectSprite for more { GLPatch_t *gpatch; - INT32 durs = spr->mobj->state->tics; - INT32 tics = spr->mobj->tics; - mdlframe_t *curr, *next = NULL; - const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); - spritedef_t *sprdef; - spriteframe_t *sprframe; - float finalscale; - - // Apparently people don't like jump frames like that, so back it goes - //if (tics > durs) - //durs = tics; if (spr->mobj->flags2 & MF2_SHADOW) Surf.FlatColor.s.alpha = 0x40; @@ -933,7 +920,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr) } } //HWD.pfnSetBlend(blend); // This seems to actually break translucency? - finalscale = md2->scale; //Hurdler: arf, I don't like that implementation at all... too much crappy gpatch = md2->grpatch; if (!gpatch || !gpatch->mipmap.grInfo.format || !gpatch->mipmap.downloaded) @@ -987,95 +973,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr) gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); HWR_GetMappedPatch(gpatch, spr->colormap); } - - if (spr->mobj->frame & FF_ANIMATE) - { - // set duration and tics to be the correct values for FF_ANIMATE states - durs = spr->mobj->state->var2; - tics = spr->mobj->anim_duration; - } - - //FIXME: this is not yet correct - frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; - curr = &md2->model->meshes[0].frames[frame]; -#if 0 - if (cv_grmd2.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]; - } - else - { - if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL) - { - const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; - next = &md2->model->frames[nextframe]; - } - } - } -#endif - - //Hurdler: it seems there is still a small problem with mobj angle - p.x = FIXED_TO_FLOAT(spr->mobj->x); - p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset; - - if (spr->mobj->eflags & MFE_VERTICALFLIP) - p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); - else - p.z = FIXED_TO_FLOAT(spr->mobj->z); - - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - sprdef = &((skin_t *)spr->mobj->skin)->spritedef; - else - sprdef = &sprites[spr->mobj->sprite]; - - sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK]; - - if (sprframe->rotate) - { - fixed_t anglef; - if (spr->mobj->player) - anglef = AngleFixed(spr->mobj->player->frameangle); - else - anglef = AngleFixed(spr->mobj->angle); - p.angley = FIXED_TO_FLOAT(anglef); - } - else - { - const fixed_t anglef = AngleFixed((R_PointToAngle(spr->mobj->x, spr->mobj->y))-ANGLE_180); - p.angley = FIXED_TO_FLOAT(anglef); - } - p.anglex = 0.0f; - p.anglez = 0.0f; - if (spr->mobj->standingslope) - { - fixed_t tempz = spr->mobj->standingslope->normal.z; - fixed_t tempy = spr->mobj->standingslope->normal.y; - fixed_t tempx = spr->mobj->standingslope->normal.x; - fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); - p.anglez = FIXED_TO_FLOAT(tempangle); - tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); - p.anglex = FIXED_TO_FLOAT(tempangle); - } - - color[0] = Surf.FlatColor.s.red; - color[1] = Surf.FlatColor.s.green; - color[2] = Surf.FlatColor.s.blue; - color[3] = Surf.FlatColor.s.alpha; - - // SRB2CBTODO: MD2 scaling support - finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); - - p.flip = atransform.flip; - p.mirror = atransform.mirror; - - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); } } diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index 87a2f6ed1..1f1763ebd 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -95,6 +95,7 @@ static void GetNormalFromLatLong(short latlng, float *out) out[2] = *lookup++; } +#if 0 static void NormalToLatLng(float *n, short *out) { // Special cases @@ -115,6 +116,7 @@ static void NormalToLatLng(float *n, short *out) *out = (x << 8) + y; } } +#endif static inline void LatLngToNormal(short n, float *out) { @@ -140,7 +142,7 @@ static void LatLngInit(void) } } -static bool latlnginit = false; +static boolean latlnginit = false; model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) { @@ -218,7 +220,7 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) } retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0); - + int matCount = 0; for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++) { @@ -236,7 +238,7 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) // Load material /* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE); - + if (!systemSucks) { // Check for a normal map...?? diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 495c8c109..f0c6f283b 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -16,7 +16,7 @@ #include static float PI = (3.1415926535897932384626433832795f); -float U_Deg2Rad(float deg) +static float U_Deg2Rad(float deg) { return deg * ((float)PI / 180.0f); } @@ -49,11 +49,13 @@ void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle) void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame) { + (void)mesh; + (void)frame; return; /* int bufferSize = sizeof(VBO::vbotiny_t)*mesh->numTriangles*3; VBO::vbotiny_t *buffer = (VBO::vbotiny_t*)Z_Malloc(bufferSize, PU_STATIC, 0); VBO::vbotiny_t *bufPtr = buffer; - + short *vertPtr = frame->vertices; char *normPtr = frame->normals; float *uvPtr = mesh->uvs; @@ -91,6 +93,8 @@ void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame) void CreateVBO(mesh_t *mesh, mdlframe_t *frame) { + (void)mesh; + (void)frame; return; /* int bufferSize = sizeof(VBO::vbo64_t)*mesh->numTriangles*3; VBO::vbo64_t *buffer = (VBO::vbo64_t*)Z_Malloc(bufferSize, PU_STATIC, 0); @@ -161,7 +165,7 @@ void UnloadModel(model_t *model) for (i = 0; i < model->numMeshes; i++) { mesh_t *mesh = &model->meshes[i]; - + if (mesh->frames) { int j; @@ -450,7 +454,7 @@ typedef struct materiallist_s material_t *material; } materiallist_t; -static bool AddMaterialToList(materiallist_t **head, material_t *material) +static boolean AddMaterialToList(materiallist_t **head, material_t *material) { materiallist_t *node; for (node = *head; node; node = node->next) @@ -619,7 +623,7 @@ void GeneratePolygonNormals(model_t *model, int ztag) for (i = 0; i < model->numMeshes; i++) { mesh_t *mesh = &model->meshes[i]; - + if (!mesh->frames) continue; @@ -648,7 +652,8 @@ void GeneratePolygonNormals(model_t *model, int ztag) // // Reload VBOs // -void Reload(void) +#if 0 +static void Reload(void) { /* model_t *node; for (node = modelHead; node; node = node->next) @@ -673,9 +678,11 @@ void Reload(void) } }*/ } +#endif void DeleteVBOs(model_t *model) { + (void)model; /* for (int i = 0; i < model->numMeshes; i++) { mesh_t *mesh = &model->meshes[i]; diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index ed7e41a55..34e83731f 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -27,7 +27,7 @@ typedef struct { float ambient[4], diffuse[4], specular[4], emissive[4]; float shininess; - bool spheremap; + boolean spheremap; // Texture::texture_t *texture; // Texture::texture_t *lightmap; } material_t; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index dbf9649d4..a36563ef7 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1919,9 +1919,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) -{ - INT32 val, count, pindex; - GLfloat s, t; +{ GLfloat ambient[4]; GLfloat diffuse[4]; @@ -2062,9 +2060,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 normPtr = normBuffer; for (j = 0; j < mesh->numTriangles; j++) { - pglTexCoord2fv(uvPtr); - pglNormal3bv(normPtr); - pglVertex3sv(vertPtr); + pglTexCoord2fv((const GLfloat*) uvPtr); + pglNormal3bv((const GLbyte*) normPtr); + pglVertex3sv((const GLshort*) vertPtr); uvPtr += 2; normPtr += 3; From 6b9ddf47fb8b48a5ac4db839db26f73ef775700a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 19:31:30 -0500 Subject: [PATCH 029/382] Buildbot fixes (changed byte types to char; mixed d&c) --- src/hardware/hw_md2load.c | 89 ++++++++++++++++----------- src/hardware/hw_md3load.c | 86 +++++++++++++++----------- src/hardware/hw_model.c | 102 ++++++++++++++++++------------- src/hardware/hw_model.h | 2 +- src/hardware/r_opengl/r_opengl.c | 45 +++++++++----- 5 files changed, 197 insertions(+), 127 deletions(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 998dc70b6..1fdfefb97 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -17,7 +17,7 @@ #define NUMVERTEXNORMALS 162 -// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and +// 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}, @@ -195,9 +195,9 @@ typedef struct 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 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 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 @@ -236,6 +236,20 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) model_t *retModel = NULL; md2header_t *header; + size_t fileLen; + int i, j, t; + + size_t namelen; + char *texturefilename, *buffer; + const char *texPos; + + const float WUNITS = 1.0f; + float dataScale; + + md2triangle_t *tris; + md2texcoord_t *texcoords; + md2frame_t *frames; + FILE *f = fopen(fileName, "rb"); if (!f) @@ -243,12 +257,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); - size_t fileLen; - int i, j; - - size_t namelen; - char *texturefilename; - const char *texPos = strchr(fileName, '/'); + texPos = strchr(fileName, '/'); if (texPos) { @@ -274,7 +283,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) fseek(f, 0, SEEK_SET); // read in file - char *buffer = malloc(fileLen); + buffer = malloc(fileLen); fread(buffer, fileLen, 1, f); fclose(f); @@ -284,13 +293,13 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) 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; + + dataScale = WUNITS; // Tris and ST are simple structures that can be straight-copied - md2triangle_t *tris = (md2triangle_t*)&buffer[header->offsetTris]; - md2texcoord_t *texcoords = (md2texcoord_t*)&buffer[header->offsetST]; - md2frame_t *frames = (md2frame_t*)&buffer[header->offsetFrames]; + 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; @@ -300,7 +309,6 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) 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; @@ -327,6 +335,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) if (!systemSucks) { // Check for a normal map...?? + Resource::resource_t *res char openfilename[1024]; char normalMapName[1024]; strcpy(normalMapName, texturefilename); @@ -355,7 +364,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) openfilename[k] = '/'; } - Resource::resource_t *res = Resource::Open(openfilename); + res = Resource::Open(openfilename); if (res) { Resource::Close(res); @@ -368,15 +377,24 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) if (!useFloat) // Decompress to MD3 'tinyframe' space { + char *ptr = (char*)frames; + 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); - byte *ptr = (byte*)frames; for (i = 0; i < header->numFrames; i++, ptr += header->framesize) { + short *vertptr; + char *normptr; + //char *tanptr; md2frame_t *framePtr = (md2frame_t*)ptr; + md2vertex_t *vertex; + 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); @@ -384,14 +402,14 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) // 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); - short *vertptr = retModel->meshes[0].tinyframes[i].vertices; - char *normptr = retModel->meshes[0].tinyframes[i].normals; + vertptr = retModel->meshes[0].tinyframes[i].vertices; + normptr = retModel->meshes[0].tinyframes[i].normals; -// char *tanptr = retModel->meshes[0].tinyframes[i].tangents; +// tanptr = retModel->meshes[0].tinyframes[i].tangents; retModel->meshes[0].tinyframes[i].material = &retModel->materials[0]; framePtr++; // Advance to vertex list - md2vertex_t *vertex = (md2vertex_t*)framePtr; + vertex = (md2vertex_t*)framePtr; framePtr--; for (j = 0; j < header->numXYZ; j++, vertex++) { @@ -403,16 +421,16 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) vertptr++; // Normal - *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][0] * 127); - *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][1] * 127); - *normptr++ = (byte)(avertexnormals[vertex->lightNormalIndex][2] * 127); + *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127); + *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127); + *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127); } } // This doesn't need to be done every frame! - md2triangle_t *trisPtr = tris; - unsigned short *indexptr = retModel->meshes[0].indices; - float *uvptr = (float*)retModel->meshes[0].uvs; + 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]; @@ -432,12 +450,14 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) } else // Full float loading method { + md2triangle_t *trisPtr = tris; + float *uvptr = retModel->meshes[0].uvs; + char *ptr = (char*)frames; + 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); - md2triangle_t *trisPtr = tris; - float *uvptr = retModel->meshes[0].uvs; for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++) { *uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth; @@ -448,23 +468,24 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) *uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight); } - byte *ptr = (byte*)frames; for (i = 0; i < header->numFrames; i++, ptr += header->framesize) { + md2vertex_t *vertex; md2frame_t *framePtr = (md2frame_t*)ptr; + float *vertptr, *normptr; 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 - md2vertex_t *vertex = (md2vertex_t*)framePtr; + vertex = (md2vertex_t*)framePtr; framePtr--; for (j = 0; j < header->numTris; j++, trisPtr++) { diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index 1f1763ebd..35c6abf29 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -146,31 +146,36 @@ 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; + char *buffer; + int surfEnd; + int i, t; + int matCount; + FILE *f; + if (!latlnginit) { LatLngInit(); latlnginit = true; } - const float WUNITS = 1.0f; - model_t *retModel = NULL; - - FILE *f = fopen(fileName, "rb"); + f = fopen(fileName, "rb"); if (!f) return NULL; retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); - md3modelHeader *mdh; - // find length of file fseek(f, 0, SEEK_END); - long fileLen = ftell(f); + fileLen = ftell(f); fseek(f, 0, SEEK_SET); // read in file - char *buffer = malloc(fileLen); + buffer = malloc(fileLen); fread(buffer, fileLen, 1, f); fclose(f); @@ -180,8 +185,7 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->numMeshes = mdh->numSurfaces; retModel->numMaterials = 0; - int surfEnd = 0; - int i; + surfEnd = 0; for (i = 0; i < mdh->numSurfaces; i++) { md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces]; @@ -196,7 +200,6 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) 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.3686f; @@ -221,14 +224,16 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0); - int matCount = 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; - md3Shader *mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders); - int j; + mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders); + for (j = 0; j < mdS->numShaders; j++, matCount++) { size_t len = strlen(mdShader[j].name); @@ -285,11 +290,20 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) 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); @@ -297,13 +311,12 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) // 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); - short *vertptr = retModel->meshes[i].tinyframes[j].vertices; - char *normptr = retModel->meshes[i].tinyframes[j].normals; + vertptr = retModel->meshes[i].tinyframes[j].vertices; + normptr = retModel->meshes[i].tinyframes[j].normals; -// char *tanptr = retModel->meshes[i].tinyframes[j].tangents; +// tanptr = retModel->meshes[i].tinyframes[j].tangents; retModel->meshes[i].tinyframes[j].material = &retModel->materials[i]; - int k; for (k = 0; k < mdS->numVerts; k++) { // Vertex @@ -316,17 +329,17 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) // Normal GetNormalFromLatLong(mdV[k].n, tempNormal); - *normptr = (byte)(tempNormal[0] * 127); + *normptr = (char)(tempNormal[0] * 127); normptr++; - *normptr = (byte)(tempNormal[2] * 127); + *normptr = (char)(tempNormal[2] * 127); normptr++; - *normptr = (byte)(tempNormal[1] * 127); + *normptr = (char)(tempNormal[1] * 127); normptr++; } } - float *uvptr = (float*)retModel->meshes[i].uvs; - md3TexCoord *mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); + uvptr = (float*)retModel->meshes[i].uvs; + mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); for (j = 0; j < mdS->numVerts; j++) { *uvptr = mdST[j].st[0]; @@ -335,8 +348,8 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) uvptr++; } - unsigned short *indexptr = retModel->meshes[i].indices; - md3Triangle *mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); + indexptr = retModel->meshes[i].indices; + mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); for (j = 0; j < mdS->numTriangles; j++, mdT++) { // Indices @@ -350,25 +363,31 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) } else // Traditional full-float loading method { - retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts; 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); - float *vertptr = retModel->meshes[i].frames[j].vertices; - float *normptr = retModel->meshes[i].frames[j].normals; + vertptr = retModel->meshes[i].frames[j].vertices; + normptr = retModel->meshes[i].frames[j].normals; retModel->meshes[i].frames[j].material = &retModel->materials[i]; - int k; - md3Triangle *mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); + mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); for (k = 0; k < mdS->numTriangles; k++) { @@ -424,10 +443,9 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) } } - md3TexCoord *mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST); - float *uvptr = (float*)retModel->meshes[i].uvs; - int k; - md3Triangle *mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles); + 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++) { diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index f0c6f283b..828339563 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -27,20 +27,22 @@ 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) - float ux = axisVec->x * rotVec->x; - float uy = axisVec->x * rotVec->y; - float uz = axisVec->x * rotVec->z; - float vx = axisVec->y * rotVec->x; - float vy = axisVec->y * rotVec->y; - float vz = axisVec->y * rotVec->z; - float wx = axisVec->z * rotVec->x; - float wy = axisVec->z * rotVec->y; - float wz = axisVec->z * rotVec->z; - float sa = sinf(angle); - float ca = cosf(angle); + 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; @@ -105,7 +107,7 @@ void CreateVBO(mesh_t *mesh, mdlframe_t *frame) float *tanPtr = frame->tangents; float *uvPtr = mesh->uvs; float *lightPtr = mesh->lightuvs; - byte *colorPtr = frame->colors; + char *colorPtr = frame->colors; int i; for (i = 0; i < mesh->numTriangles*3; i++) @@ -364,17 +366,22 @@ 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; - int j; 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) @@ -384,20 +391,20 @@ void GenerateVertexNormals(model_t *model) M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3); }*/ - int k; - float *vertPtr = frame->vertices; 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++; - int vCount = 0; - vector_t normal; normal.x = normal.y = normal.z = 0; - int l; - float *testPtr = frame->vertices; + for (l = 0; l < mesh->numVertices; l++) { float testX, testY, testZ; @@ -433,7 +440,7 @@ void GenerateVertexNormals(model_t *model) } } - float *oldNormals = frame->normals; + oldNormals = frame->normals; frame->normals = newNormals; Z_Free(oldNormals); @@ -456,7 +463,7 @@ typedef struct materiallist_s static boolean AddMaterialToList(materiallist_t **head, material_t *material) { - materiallist_t *node; + materiallist_t *node, *newMatNode; for (node = *head; node; node = node->next) { if (node->material == material) @@ -464,7 +471,7 @@ static boolean AddMaterialToList(materiallist_t **head, material_t *material) } // Didn't find it, so add to the list - materiallist_t *newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0); + newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0); newMatNode->material = material; ListAdd(newMatNode, (listitem_t**)head); return true; @@ -478,12 +485,16 @@ static boolean AddMaterialToList(materiallist_t **head, material_t *material) // void Optimize(model_t *model) { - if (model->numMeshes <= 1) - return; // No need - 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]; @@ -501,15 +512,18 @@ void Optimize(model_t *model) numMeshes++; } - int memTag = PU_STATIC; - mesh_t *newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0); + memTag = PU_STATIC; + newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0); i = 0; - materiallist_t *node; 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; @@ -529,20 +543,20 @@ void Optimize(model_t *model) // 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); - mdlframe_t *curFrame = &newMesh->frames[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 = (byte*)Z_Malloc(sizeof(byte)*4*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 - int uvCount = 0; - int vertCount = 0; - int colorCount = 0; + uvCount = 0; + vertCount = 0; + colorCount = 0; for (j = 0; j < model->numMeshes; j++) { mesh_t *curMesh = &model->meshes[j]; @@ -551,6 +565,8 @@ void Optimize(model_t *model) { float *dest; float *src; + char *destByte; + char *srcByte; M_Memcpy(&newMesh->uvs[uvCount], curMesh->uvs, @@ -587,22 +603,20 @@ void Optimize(model_t *model) vertCount += 3 * curMesh->numTriangles * 3; - byte *destByte; - byte *srcByte; - destByte = (byte*)newMesh->frames[0].colors; - srcByte = (byte*)curMesh->frames[0].colors; + destByte = (char*)newMesh->frames[0].colors; + srcByte = (char*)curMesh->frames[0].colors; if (srcByte) { M_Memcpy(&destByte[colorCount], srcByte, - sizeof(byte)*4*curMesh->numTriangles*3); + sizeof(char)*4*curMesh->numTriangles*3); } else { memset(&destByte[colorCount], 255, - sizeof(byte)*4*curMesh->numTriangles*3); + sizeof(char)*4*curMesh->numTriangles*3); } colorCount += 4 * curMesh->numTriangles * 3; @@ -622,21 +636,23 @@ 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; - int j; 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); - const float *vertices = frame->vertices; - vector_t *polyNormals = frame->polyNormals; - int k; + polyNormals = frame->polyNormals; + for (k = 0; k < mesh->numTriangles; k++) { // Vector::Normal(vertices, polyNormals); diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index 34e83731f..1803f4c5c 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -38,7 +38,7 @@ typedef struct float *vertices; float *normals; float *tangents; - byte *colors; + char *colors; unsigned int vboID; vector_t *polyNormals; } mdlframe_t; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index a36563ef7..e29c6a383 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1924,14 +1924,19 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 GLfloat diffuse[4]; float pol = 0.0f; - scale *= 0.5f; float scalex = scale, scaley = scale, scalez = scale; + boolean useTinyFrames; + + int i; + // Because Otherwise, scaling the screen negatively vertically breaks the lighting #ifndef KOS_GL_COMPATIBILITY GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; #endif + scale *= 0.5f; + if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { UINT32 newtime = (duration - tics); // + 1; @@ -2007,12 +2012,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglScalef(scalex, scaley, scalez); - boolean useTinyFrames = model->meshes[0].tinyframes != NULL; + useTinyFrames = model->meshes[0].tinyframes != NULL; if (useTinyFrames) pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); - for (int i = 0; i < model->numMeshes; i++) + for (i = 0; i < model->numMeshes; i++) { mesh_t *mesh = &model->meshes[i]; @@ -2039,15 +2044,19 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } else { + short *buffer, *vertPtr; + char *normBuffer, *normPtr; + float *uvPtr; + int j = 0; + // Dangit, I soooo want to do this in a GLSL shader... pglBegin(GL_TRIANGLES); - short *buffer = malloc(mesh->numVertices * sizeof(short)); - short *vertPtr = buffer; - char *normBuffer = malloc(mesh->numVertices * sizeof(char)); - char *normPtr = normBuffer; + buffer = malloc(mesh->numVertices * sizeof(short)); + vertPtr = buffer; + normBuffer = malloc(mesh->numVertices * sizeof(char)); + normPtr = normBuffer; - int j = 0; for (j = 0; j < mesh->numVertices; j++) { // Interpolate @@ -2055,7 +2064,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 *normPtr++ = (short)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); } - float *uvPtr = mesh->uvs; + uvPtr = mesh->uvs; vertPtr = buffer; normPtr = normBuffer; for (j = 0; j < mesh->numTriangles; j++) @@ -2099,15 +2108,21 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } else { + int j = 0; + float *uvPtr; + float *frameVert; + float *frameNormal; + float *nextFrameVert; + float *nextFrameNormal; + // Dangit, I soooo want to do this in a GLSL shader... pglBegin(GL_TRIANGLES); - int j = 0; - float *uvPtr = mesh->uvs; - float *frameVert = frame->vertices; - float *frameNormal = frame->normals; - float *nextFrameVert = nextframe->vertices; - float *nextFrameNormal = frame->normals; + uvPtr = mesh->uvs; + frameVert = frame->vertices; + frameNormal = frame->normals; + nextFrameVert = nextframe->vertices; + nextFrameNormal = frame->normals; for (j = 0; j < mesh->numTriangles; j++) { // Interpolate From 3c496db7f540fc7931bc47ee6e27764f8c4c82e7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 20:36:39 -0500 Subject: [PATCH 030/382] Add new model files to CMake --- src/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index faa860d44..97360b4f4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -395,7 +395,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 @@ -409,6 +413,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 From b9b99cc6be5ee05a43028b8342add46157cf46fe Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 20:41:08 -0500 Subject: [PATCH 031/382] Ignore fread return value (buildbot error) --- src/hardware/hw_md2load.c | 5 ++++- src/hardware/hw_md3load.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 1fdfefb97..ff195dda5 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -237,6 +237,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) md2header_t *header; size_t fileLen; + size_t fileReadLen; int i, j, t; size_t namelen; @@ -284,9 +285,11 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) // read in file buffer = malloc(fileLen); - fread(buffer, fileLen, 1, f); + fileReadLen = fread(buffer, fileLen, 1, f); fclose(f); + (void)fileReadLen; // intentionally ignore return value, per buildbot + // get pointer to file header header = (md2header_t*)buffer; diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index 35c6abf29..53f6034c0 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -150,6 +150,7 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) model_t *retModel = NULL; md3modelHeader *mdh; long fileLen; + long fileReadLen; char *buffer; int surfEnd; int i, t; @@ -176,9 +177,11 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) // read in file buffer = malloc(fileLen); - fread(buffer, fileLen, 1, f); + fileReadLen = fread(buffer, fileLen, 1, f); fclose(f); + (void)fileReadLen; // intentionally ignore return value, per buildbot + // get pointer to file header mdh = (md3modelHeader*)buffer; From 1b2124b99b6394c82c37179842184daccf008549 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 21:53:30 -0500 Subject: [PATCH 032/382] Add model sources to sdl1.2 VC project --- src/sdl12/Srb2SDL-vc10.vcxproj | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/sdl12/Srb2SDL-vc10.vcxproj b/src/sdl12/Srb2SDL-vc10.vcxproj index 958cd7d02..9c550a092 100644 --- a/src/sdl12/Srb2SDL-vc10.vcxproj +++ b/src/sdl12/Srb2SDL-vc10.vcxproj @@ -755,6 +755,36 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -765,6 +795,16 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -1329,7 +1369,11 @@ + + + + From a140fe92316422fbafa907749bfae69978f28f4b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 22:50:00 -0500 Subject: [PATCH 033/382] hw_md2 merge errors --- src/hardware/hw_md2.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index b9ff29578..c29bfe172 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -765,6 +765,8 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT // mostly copied from HWR_GetMappedPatch, hence the similarities and comment GLMipmap_t *grmip, *newmip; + (void)skinnum; + if (colormap == colormaps || colormap == NULL) { // Don't do any blending @@ -834,7 +836,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) FSurfaceInfo Surf; char filename[64]; + INT32 frame = 0; + INT32 nextFrame = -1; + FTransform p; md2_t *md2; + UINT8 color[4]; if (!cv_grmd2.value) return; @@ -879,6 +885,16 @@ void HWR_DrawMD2(gr_vissprite_t *spr) // Look at HWR_ProjectSprite for more { GLPatch_t *gpatch; + INT32 durs = spr->mobj->state->tics; + INT32 tics = spr->mobj->tics; + const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); + spritedef_t *sprdef; + spriteframe_t *sprframe; + float finalscale; + + // Apparently people don't like jump frames like that, so back it goes + //if (tics > durs) + //durs = tics; if (spr->mobj->flags2 & MF2_SHADOW) Surf.FlatColor.s.alpha = 0x40; @@ -920,6 +936,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) } } //HWD.pfnSetBlend(blend); // This seems to actually break translucency? + finalscale = md2->scale; //Hurdler: arf, I don't like that implementation at all... too much crappy gpatch = md2->grpatch; if (!gpatch || !gpatch->mipmap.grInfo.format || !gpatch->mipmap.downloaded) @@ -973,6 +990,90 @@ void HWR_DrawMD2(gr_vissprite_t *spr) gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); HWR_GetMappedPatch(gpatch, spr->colormap); } + + if (spr->mobj->frame & FF_ANIMATE) + { + // set duration and tics to be the correct values for FF_ANIMATE states + durs = spr->mobj->state->var2; + tics = spr->mobj->anim_duration; + } + + //FIXME: this is not yet correct + frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; +#if 0 + if (cv_grmd2.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]; + } + else + { + if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL) + { + const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; + next = &md2->model->frames[nextframe]; + } + } + } +#endif + + //Hurdler: it seems there is still a small problem with mobj angle + p.x = FIXED_TO_FLOAT(spr->mobj->x); + p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset; + + if (spr->mobj->eflags & MFE_VERTICALFLIP) + p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); + else + p.z = FIXED_TO_FLOAT(spr->mobj->z); + + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + sprdef = &((skin_t *)spr->mobj->skin)->spritedef; + else + sprdef = &sprites[spr->mobj->sprite]; + + sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK]; + + if (sprframe->rotate) + { + const fixed_t anglef = AngleFixed(spr->mobj->angle); + p.angley = FIXED_TO_FLOAT(anglef); + } + else + { + const fixed_t anglef = AngleFixed((R_PointToAngle(spr->mobj->x, spr->mobj->y))-ANGLE_180); + p.angley = FIXED_TO_FLOAT(anglef); + } + p.anglex = 0.0f; + p.anglez = 0.0f; + if (spr->mobj->standingslope) + { + fixed_t tempz = spr->mobj->standingslope->normal.z; + fixed_t tempy = spr->mobj->standingslope->normal.y; + fixed_t tempx = spr->mobj->standingslope->normal.x; + fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); + p.anglez = FIXED_TO_FLOAT(tempangle); + tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); + p.anglex = FIXED_TO_FLOAT(tempangle); + } + + color[0] = Surf.FlatColor.s.red; + color[1] = Surf.FlatColor.s.green; + color[2] = Surf.FlatColor.s.blue; + color[3] = Surf.FlatColor.s.alpha; + + // SRB2CBTODO: MD2 scaling support + finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); + + p.flip = atransform.flip; + p.mirror = atransform.mirror; + + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); } } From 4116ffb5e996fa8cfa4d0ecb18b64d08ea1008e4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 23:44:38 -0500 Subject: [PATCH 034/382] More hw_md2 merge errors; re-enable interpolation code block --- src/hardware/hw_md2.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index c29bfe172..6cba468e9 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -765,8 +765,6 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT // mostly copied from HWR_GetMappedPatch, hence the similarities and comment GLMipmap_t *grmip, *newmip; - (void)skinnum; - if (colormap == colormaps || colormap == NULL) { // Don't do any blending @@ -1000,7 +998,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) //FIXME: this is not yet correct frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; -#if 0 + if (cv_grmd2.value == 1 && tics <= durs) { // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation @@ -1014,14 +1012,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr) } 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]; } } } -#endif //Hurdler: it seems there is still a small problem with mobj angle p.x = FIXED_TO_FLOAT(spr->mobj->x); From 2685af7331f9092f421bc65f60b8fa8afb32dca9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 00:17:51 -0500 Subject: [PATCH 035/382] Hide/add Kart FTransform mirror and anglez behind ifdef --- src/hardware/hw_defs.h | 11 +++++++++++ src/hardware/hw_md2.c | 7 ++++++- src/hardware/r_opengl/r_opengl.c | 22 ++++++++++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index ece627d3c..fc6ae348e 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -101,15 +101,26 @@ 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 + 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 diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 6cba468e9..10e2847f9 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1048,6 +1048,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) { @@ -1059,6 +1061,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; @@ -1069,7 +1072,9 @@ 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.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index e29c6a383..5f21ec7ed 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1971,6 +1971,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglEnable(GL_CULL_FACE); +#ifdef USE_FTRANSFORM_MIRROR // flipped is if the object is flipped // pos->flip is if the screen is flipped vertically // pos->mirror is if the screen is flipped horizontally @@ -1982,6 +1983,17 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 else pglCullFace(GL_BACK); } +#else + // pos->flip is if the screen is flipped too + if (flipped != pos->flip) // If either are active, but not both, invert the model's culling + { + pglCullFace(GL_FRONT); + } + else + { + pglCullFace(GL_BACK); + } +#endif #ifndef KOS_GL_COMPATIBILITY pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); @@ -2006,7 +2018,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglTranslatef(pos->x, pos->z, pos->y); if (flipped) scaley = -scaley; - pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); +#ifdef USE_FTRANSFORM_ANGLEZ + pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart +#endif pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); @@ -2182,9 +2196,13 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) // keep a trace of the transformation for md2 memcpy(&md2_transform, stransform, sizeof (md2_transform)); +#ifdef USE_FTRANSFORM_MIRROR + // mirroring from Kart if (stransform->mirror) pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez); - else if (stransform->flip) + else +#endif + if (stransform->flip) pglScalef(stransform->scalex, -stransform->scaley, -stransform->scalez); else pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez); From 71aa549a15044224db8b3c8e777f791256bc9025 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 00:38:00 -0500 Subject: [PATCH 036/382] Adapt re-enabled DrawMD2 code block for meshes --- src/hardware/hw_md2.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 10e2847f9..f58de224b 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -885,6 +885,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) GLPatch_t *gpatch; INT32 durs = spr->mobj->state->tics; INT32 tics = spr->mobj->tics; + //mdlframe_t *next = NULL; const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); spritedef_t *sprdef; spriteframe_t *sprframe; @@ -1004,19 +1005,19 @@ void HWR_DrawMD2(gr_vissprite_t *spr) // 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 && !(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]; } } } From cb1dba7798a05dd38a1c2e851793c32a8bd48e79 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 01:57:54 -0500 Subject: [PATCH 037/382] Interpolation fix attempt? * Fix pglNormal3bv pointer because typo --- src/hardware/r_opengl/r_opengl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 5f21ec7ed..7bb8442e4 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -523,7 +523,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglVertex3f , glVertex3f) GETOPENGLFUNC(pglVertex3sv, glVertex3sv) GETOPENGLFUNC(pglNormal3f , glNormal3f) - GETOPENGLFUNC(pglNormal3bv, glNomral3bv) + GETOPENGLFUNC(pglNormal3bv, glNormal3bv) GETOPENGLFUNC(pglColor4f , glColor4f) GETOPENGLFUNC(pglColor4fv , glColor4fv) GETOPENGLFUNC(pglTexCoord2f , glTexCoord2f) @@ -2075,7 +2075,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 { // Interpolate *vertPtr++ = (short)(frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j]))); - *normPtr++ = (short)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); + *normPtr++ = (char)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); } uvPtr = mesh->uvs; @@ -2083,9 +2083,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 normPtr = normBuffer; for (j = 0; j < mesh->numTriangles; j++) { - pglTexCoord2fv((const GLfloat*) uvPtr); - pglNormal3bv((const GLbyte*) normPtr); - pglVertex3sv((const GLshort*) vertPtr); + pglTexCoord2fv(uvPtr); + pglNormal3bv((signed char*) normPtr); + pglVertex3sv(vertPtr); uvPtr += 2; normPtr += 3; From c8fd6f01b9069cb081dd06360297c6d3529b26cd Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 10:33:13 -0500 Subject: [PATCH 038/382] Ifdef nextFrame handling under USE_MODEL_NEXTFRAME --- src/hardware/hw_defs.h | 3 +++ src/hardware/hw_md2.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index fc6ae348e..04f63af71 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -106,6 +106,9 @@ typedef struct #define USE_FTRANSFORM_ANGLEZ #define USE_FTRANSFORM_MIRROR +// Vanilla features +#define USE_MODEL_NEXTFRAME + typedef struct { FLOAT x,y,z; // position diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index f58de224b..33cd8b8a3 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1000,6 +1000,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) //FIXME: this is not yet correct frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; +#ifdef USE_MODEL_NEXTFRAME if (cv_grmd2.value == 1 && tics <= durs) { // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation @@ -1021,6 +1022,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) } } } +#endif //Hurdler: it seems there is still a small problem with mobj angle p.x = FIXED_TO_FLOAT(spr->mobj->x); From 0adf6fea1975c84e29532cf082903aa56b2430d7 Mon Sep 17 00:00:00 2001 From: AJ Freda Date: Wed, 19 Dec 2018 20:52:47 -0500 Subject: [PATCH 039/382] Fixed a few unnoticable mistakes [vanilla] --- src/hardware/hw_md2load.c | 3 +- src/hardware/r_opengl/r_opengl.c | 75 ++++++++++++-------------------- 2 files changed, 31 insertions(+), 47 deletions(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index ff195dda5..49fdbf8ab 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -454,12 +454,13 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) else // Full float loading method { md2triangle_t *trisPtr = tris; - float *uvptr = retModel->meshes[0].uvs; + float *uvptr; char *ptr = (char*)frames; 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); + uvptr = retModel->meshes[0].uvs; for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++) { diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 7bb8442e4..c0b6d2a7c 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1924,6 +1924,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 GLfloat diffuse[4]; float pol = 0.0f; + scale *= 0.5f; float scalex = scale, scaley = scale, scalez = scale; boolean useTinyFrames; @@ -1935,8 +1936,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; #endif - scale *= 0.5f; - if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { UINT32 newtime = (duration - tics); // + 1; @@ -2054,22 +2053,16 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); pglDisableClientState(GL_NORMAL_ARRAY); pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_VERTEX_ARRAY); } else { - short *buffer, *vertPtr; - char *normBuffer, *normPtr; - float *uvPtr; - int j = 0; - // Dangit, I soooo want to do this in a GLSL shader... - pglBegin(GL_TRIANGLES); - - buffer = malloc(mesh->numVertices * sizeof(short)); - vertPtr = buffer; - normBuffer = malloc(mesh->numVertices * sizeof(char)); - normPtr = normBuffer; + short *buffer = malloc(mesh->numVertices * sizeof(short) * 3); + short *vertPtr = buffer; + char *normBuffer = malloc(mesh->numVertices * sizeof(char) * 3); + char *normPtr = normBuffer; + int j = 0; for (j = 0; j < mesh->numVertices; j++) { @@ -2078,24 +2071,19 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 *normPtr++ = (char)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); } - uvPtr = mesh->uvs; - vertPtr = buffer; - normPtr = normBuffer; - for (j = 0; j < mesh->numTriangles; j++) - { - pglTexCoord2fv(uvPtr); - pglNormal3bv((signed char*) normPtr); - pglVertex3sv(vertPtr); - - uvPtr += 2; - normPtr += 3; - vertPtr += 3; - } + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglEnableClientState(GL_NORMAL_ARRAY); + pglVertexPointer(3, GL_SHORT, 0, buffer); + pglNormalPointer(GL_BYTE, 0, normBuffer); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglDisableClientState(GL_NORMAL_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_VERTEX_ARRAY); free(buffer); free(normBuffer); - - pglEnd(); } } else @@ -2118,39 +2106,34 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); pglDisableClientState(GL_NORMAL_ARRAY); pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_VERTEX_ARRAY); } else { int j = 0; - float *uvPtr; - float *frameVert; - float *frameNormal; - float *nextFrameVert; - float *nextFrameNormal; + float *uvPtr = mesh->uvs; + float *frameVert = frame->vertices; + float *frameNormal = frame->normals; + float *nextFrameVert = nextframe->vertices; + float *nextFrameNormal = nextframe->normals; // Dangit, I soooo want to do this in a GLSL shader... pglBegin(GL_TRIANGLES); - uvPtr = mesh->uvs; - frameVert = frame->vertices; - frameNormal = frame->normals; - nextFrameVert = nextframe->vertices; - nextFrameNormal = frame->normals; - for (j = 0; j < mesh->numTriangles; j++) + for (j = 0; j < mesh->numTriangles * 3; j++) { // Interpolate float px1 = *frameVert++; - float px2 = *nextFrameVert++; float py1 = *frameVert++; - float py2 = *nextFrameVert++; float pz1 = *frameVert++; + float px2 = *nextFrameVert++; + float py2 = *nextFrameVert++; float pz2 = *nextFrameVert++; float nx1 = *frameNormal++; - float nx2 = *nextFrameNormal++; float ny1 = *frameNormal++; - float ny2 = *nextFrameNormal++; float nz1 = *frameNormal++; + float nx2 = *nextFrameNormal++; + float ny2 = *nextFrameNormal++; float nz2 = *nextFrameNormal++; pglTexCoord2fv(uvPtr); @@ -2161,7 +2144,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 (py1 + pol * (py2 - py1)), (pz1 + pol * (pz2 - pz1))); - uvPtr++; + uvPtr += 2; } pglEnd(); From 8a4066486ec690a52e816955218ffdf1d4d47591 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 20:56:58 -0500 Subject: [PATCH 040/382] Small Mixed D&C fix --- src/hardware/r_opengl/r_opengl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index c0b6d2a7c..fec8c33a3 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1924,8 +1924,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 GLfloat diffuse[4]; float pol = 0.0f; - scale *= 0.5f; - float scalex = scale, scaley = scale, scalez = scale; + + float scalex, scaley, scalez; boolean useTinyFrames; @@ -1936,6 +1936,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; #endif + scale *= 0.5f; + scalex = scaley = scalez = scale; + if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { UINT32 newtime = (duration - tics); // + 1; From 9617e604bbc159158953c718a8618d3c82d672c6 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 23 Dec 2018 17:00:11 -0500 Subject: [PATCH 041/382] Removed all glBegin/glEnd references MD2/MD3 now works, with the exception of WAD textures for some odd reason --- src/hardware/hw_drv.h | 4 - src/hardware/hw_main.c | 2 - src/hardware/hw_md2load.c | 250 +++---- src/hardware/r_opengl/r_opengl.c | 885 ++++++++----------------- src/hardware/r_opengl/r_opengl.h | 2 - src/sdl/hwsym_sdl.c | 2 - src/sdl/i_video.c | 2 - src/win32/Srb2win-vc10.vcxproj.filters | 16 +- 8 files changed, 386 insertions(+), 777 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 7b45b0974..c1ece091a 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -63,10 +63,8 @@ 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); @@ -105,9 +103,7 @@ struct hwdriver_s #ifndef HAVE_SDL Shutdown pfnShutdown; #endif -#ifdef SHUFFLE PostImgRedraw pfnPostImgRedraw; -#endif FlushScreenTextures pfnFlushScreenTextures; StartScreenWipe pfnStartScreenWipe; EndScreenWipe pfnEndScreenWipe; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e4c9e8330..fc70492ca 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6838,7 +6838,6 @@ void HWR_DoPostProcessor(player_t *player) if (splitscreen) // Not supported in splitscreen - someone want to add support? return; -#ifdef SHUFFLE // Drunken vision! WooOOooo~ if (*type == postimg_water || *type == postimg_heat) { @@ -6881,7 +6880,6 @@ void HWR_DoPostProcessor(player_t *player) HWD.pfnMakeScreenTexture(); } // Flipping of the screen isn't done here anymore -#endif // SHUFFLE } void HWR_StartScreenWipe(void) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 49fdbf8ab..d29414b0f 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -17,7 +17,7 @@ #define NUMVERTEXNORMALS 162 -// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and +// 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}, @@ -186,71 +186,57 @@ float avertexnormals[NUMVERTEXNORMALS][3] = { 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) + 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 + 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; + 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 + 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 + 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) { + useFloat = true; model_t *retModel = NULL; md2header_t *header; - size_t fileLen; - size_t fileReadLen; - int i, j, t; - - size_t namelen; - char *texturefilename, *buffer; - const char *texPos; - - const float WUNITS = 1.0f; - float dataScale; - - md2triangle_t *tris; - md2texcoord_t *texcoords; - md2frame_t *frames; - FILE *f = fopen(fileName, "rb"); if (!f) @@ -258,7 +244,13 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); - texPos = strchr(fileName, '/'); + size_t fileLen; + + int i, j; + + size_t namelen; + char *texturefilename; + const char *texPos = strchr(fileName, '/'); if (texPos) { @@ -274,9 +266,9 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) strcpy(texturefilename, fileName); } - texturefilename[namelen-2] = 'z'; - texturefilename[namelen-3] = 'u'; - texturefilename[namelen-4] = 'b'; + texturefilename[namelen - 2] = 'z'; + texturefilename[namelen - 3] = 'u'; + texturefilename[namelen - 4] = 'b'; // find length of file fseek(f, 0, SEEK_END); @@ -284,25 +276,23 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) fseek(f, 0, SEEK_SET); // read in file - buffer = malloc(fileLen); - fileReadLen = fread(buffer, fileLen, 1, f); + char *buffer = malloc(fileLen); + fread(buffer, fileLen, 1, f); fclose(f); - (void)fileReadLen; // intentionally ignore return value, per buildbot - // 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; - - dataScale = WUNITS; + 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]; + md2triangle_t *tris = (md2triangle_t*)&buffer[header->offsetTris]; + md2texcoord_t *texcoords = (md2texcoord_t*)&buffer[header->offsetST]; + md2frame_t *frames = (md2frame_t*)&buffer[header->offsetFrames]; // Read in textures retModel->numMaterials = header->numSkins; @@ -312,6 +302,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) 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; @@ -333,86 +324,76 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->materials[t].shininess = 0.0f; retModel->materials[t].spheremap = false; -/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE); + /* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE); - if (!systemSucks) - { - // Check for a normal map...?? - Resource::resource_t *res - 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'; + 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; + 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] = '/'; - } + if (openfilename[k] == '\\') + openfilename[k] = '/'; + } - res = Resource::Open(openfilename); - if (res) - { - Resource::Close(res); - retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE); - } - }*/ + 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 = (char*)frames; - 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); + retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0); + byte *ptr = (byte*)frames; for (i = 0; i < header->numFrames; i++, ptr += header->framesize) { - short *vertptr; - char *normptr; - //char *tanptr; md2frame_t *framePtr = (md2frame_t*)ptr; - md2vertex_t *vertex; + 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); - 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); + // 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; + short *vertptr = retModel->meshes[0].tinyframes[i].vertices; + char *normptr = retModel->meshes[0].tinyframes[i].normals; -// tanptr = retModel->meshes[0].tinyframes[i].tangents; + // char *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; + md2vertex_t *vertex = (md2vertex_t*)framePtr; framePtr--; for (j = 0; j < header->numXYZ; j++, vertex++) { @@ -425,15 +406,15 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) // Normal *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127); - *normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 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; + md2triangle_t *trisPtr = tris; + unsigned short *indexptr = retModel->meshes[0].indices; + float *uvptr = (float*)retModel->meshes[0].uvs; for (j = 0; j < header->numTris; j++, trisPtr++) { *indexptr = trisPtr->meshIndex[0]; @@ -453,15 +434,12 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) } else // Full float loading method { - md2triangle_t *trisPtr = tris; - float *uvptr; - char *ptr = (char*)frames; - - retModel->meshes[0].numVertices = header->numTris*3; + 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); - uvptr = retModel->meshes[0].uvs; + retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0); + md2triangle_t *trisPtr = tris; + float *uvptr = retModel->meshes[0].uvs; for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++) { *uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth; @@ -472,16 +450,15 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) *uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight); } + byte *ptr = (byte*)frames; for (i = 0; i < header->numFrames; i++, ptr += header->framesize) { - 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; - 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); - normptr = (float*)retModel->meshes[0].frames[i].normals; vertptr = (float*)retModel->meshes[0].frames[i].vertices; trisPtr = tris; @@ -489,7 +466,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->meshes[0].frames[i].material = &retModel->materials[0]; framePtr++; // Advance to vertex list - vertex = (md2vertex_t*)framePtr; + md2vertex_t *vertex = (md2vertex_t*)framePtr; framePtr--; for (j = 0; j < header->numTris; j++, trisPtr++) { @@ -515,26 +492,17 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) vertptr++; *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0]; - *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1]; *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][1]; *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][1]; *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2]; + *normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1]; } - /* - // Rotate MD2 by 90 degrees in code BLAAHH - vector_t *normVecptr = (vector_t*)retModel->meshes[0].frames[i].normals; - vector_t *vertVecptr = (vector_t*)retModel->meshes[0].frames[i].vertices; - for (j = 0; j < header->numTris * 3; j++, normVecptr++, vertVecptr++) - { - VectorRotate(normVecptr, &vectorYaxis, -90.0f); - VectorRotate(vertVecptr, &vectorYaxis, -90.0f); - }*/ } } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index fec8c33a3..4f77680d9 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -29,11 +29,6 @@ #include #include -#ifndef SHUFFLE -#ifndef KOS_GL_COMPATIBILITY -#define SHUFFLE -#endif -#endif #include "r_opengl.h" #if defined (HWRENDER) && !defined (NOROPENGL) @@ -83,9 +78,7 @@ GLint screen_height = 0; GLbyte screen_depth = 0; GLint textureformatGL = 0; GLint maximumAnisotropy = 0; -#ifndef KOS_GL_COMPATIBILITY static GLboolean MipMap = GL_FALSE; -#endif static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; @@ -94,11 +87,9 @@ static FTransform md2_transform; const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) -#ifndef MINI_GL_COMPATIBILITY static GLdouble modelMatrix[16]; static GLdouble projMatrix[16]; static GLint viewport[4]; -#endif #ifdef USE_PALETTED_TEXTURE @@ -167,11 +158,6 @@ float byteasfloat(UINT8 fbyte) static I_Error_t I_Error_GL = NULL; -#ifndef MINI_GL_COMPATIBILITY -static boolean gl13 = false; // whether we can use opengl 1.3 functions -#endif - - // -----------------+ // DBG_Printf : Output error messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing @@ -207,14 +193,10 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglScissor glScissor #define pglEnable glEnable #define pglDisable glDisable -#ifndef MINI_GL_COMPATIBILITY #define pglGetDoublev glGetDoublev -#endif //glGetIntegerv //glGetString -#ifdef KOS_GL_COMPATIBILITY #define pglHint glHint -#endif /* Depth Buffer */ #define pglClearDepth glClearDepth @@ -228,11 +210,8 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglPushMatrix glPushMatrix #define pglPopMatrix glPopMatrix #define pglLoadIdentity glLoadIdentity -#ifdef MINI_GL_COMPATIBILITY #define pglMultMatrixf glMultMatrixf -#else #define pglMultMatrixd glMultMatrixd -#endif #define pglRotatef glRotatef #define pglScalef glScalef #define pglTranslatef glTranslatef @@ -241,6 +220,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglBegin glBegin #define pglEnd glEnd #define pglVertex3f glVertex3f +#define pglVertex3fv glVertex3fv #define pglVertex3sv glVertex3sv #define pglNormal3f glNormal3f #define pglNormal3bv glNormal3bv @@ -254,7 +234,8 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglDrawArrays glDrawArrays #define pglDrawElements glDrawElements #define pglEnableClientState glEnableClientState -#define pglDisableClientState pglDisableClientState +#define pglDisableClientState glDisableClientState +#define pglClientActiveTexture glClientActiveTexture /* Lighting */ #define pglShadeModel glShadeModel @@ -280,10 +261,8 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglDeleteTextures glDeleteTextures #define pglBindTexture glBindTexture /* texture mapping */ //GL_EXT_copy_texture -#ifndef KOS_GL_COMPATIBILITY #define pglCopyTexImage2D glCopyTexImage2D #define pglCopyTexSubImage2D glCopyTexSubImage2D -#endif #else //!STATIC_OPENGL @@ -310,10 +289,8 @@ typedef void (APIENTRY * PFNglEnable) (GLenum cap); static PFNglEnable pglEnable; typedef void (APIENTRY * PFNglDisable) (GLenum cap); static PFNglDisable pglDisable; -#ifndef MINI_GL_COMPATIBILITY typedef void (APIENTRY * PFNglGetDoublev) (GLenum pname, GLdouble *params); static PFNglGetDoublev pglGetDoublev; -#endif //glGetIntegerv //glGetString @@ -338,13 +315,10 @@ typedef void (APIENTRY * PFNglPopMatrix) (void); static PFNglPopMatrix pglPopMatrix; typedef void (APIENTRY * PFNglLoadIdentity) (void); static PFNglLoadIdentity pglLoadIdentity; -#ifdef MINI_GL_COMPATIBILITY typedef void (APIENTRY * PFNglMultMatrixf) (const GLfloat *m); static PFNglMultMatrixf pglMultMatrixf; -#else typedef void (APIENTRY * PFNglMultMatrixd) (const GLdouble *m); static PFNglMultMatrixd pglMultMatrixd; -#endif typedef void (APIENTRY * PFNglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); static PFNglRotatef pglRotatef; typedef void (APIENTRY * PFNglScalef) (GLfloat x, GLfloat y, GLfloat z); @@ -359,6 +333,8 @@ typedef void (APIENTRY * PFNglEnd) (void); static PFNglEnd pglEnd; typedef void (APIENTRY * PFNglVertex3f) (GLfloat x, GLfloat y, GLfloat z); static PFNglVertex3f pglVertex3f; +typedef void (APIENTRY * PFNglVertex3fv)(const GLfloat *v); +static PFNglVertex3fv pglVertex3fv; typedef void (APIENTRY * PFNglVertex3sv) (const GLshort *v); static PFNglVertex3sv pglVertex3sv; typedef void (APIENTRY * PFNglNormal3f) (GLfloat x, GLfloat y, GLfloat z); @@ -434,15 +410,16 @@ static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); static PFNgluBuild2DMipmaps pgluBuild2DMipmaps; -#ifndef MINI_GL_COMPATIBILITY /* 1.3 functions for multitexturing */ typedef void (APIENTRY *PFNglActiveTexture) (GLenum); static PFNglActiveTexture pglActiveTexture; typedef void (APIENTRY *PFNglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); static PFNglMultiTexCoord2f pglMultiTexCoord2f; -#endif +typedef void (APIENTRY *PFNglMultiTexCoord2fv) (GLenum target, const GLfloat *v); +static PFNglMultiTexCoord2fv pglMultiTexCoord2fv; +typedef void (APIENTRY *PFNglClientActiveTexture) (GLenum); +static PFNglClientActiveTexture pglClientActiveTexture; -#ifndef MINI_GL_COMPATIBILITY /* 1.2 Parms */ /* GL_CLAMP_TO_EDGE_EXT */ #ifndef GL_CLAMP_TO_EDGE @@ -463,14 +440,6 @@ static PFNglMultiTexCoord2f pglMultiTexCoord2f; #define GL_TEXTURE1 0x84C1 #endif -#endif - -#ifdef MINI_GL_COMPATIBILITY -#undef GL_CLAMP_TO_EDGE -#undef GL_TEXTURE_MIN_LOD -#undef GL_TEXTURE_MAX_LOD -#endif - boolean SetupGLfunc(void) { #ifndef STATIC_OPENGL @@ -493,9 +462,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglScissor , glScissor) GETOPENGLFUNC(pglEnable , glEnable) GETOPENGLFUNC(pglDisable , glDisable) -#ifndef MINI_GL_COMPATIBILITY GETOPENGLFUNC(pglGetDoublev , glGetDoublev) -#endif GETOPENGLFUNC(pglGetIntegerv , glGetIntegerv) GETOPENGLFUNC(pglGetString , glGetString) @@ -509,11 +476,8 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglPushMatrix , glPushMatrix) GETOPENGLFUNC(pglPopMatrix , glPopMatrix) GETOPENGLFUNC(pglLoadIdentity , glLoadIdentity) -#ifdef MINI_GL_COMPATIBILITY GETOPENGLFUNC(pglMultMatrixf , glMultMatrixf) -#else GETOPENGLFUNC(pglMultMatrixd , glMultMatrixd) -#endif GETOPENGLFUNC(pglRotatef , glRotatef) GETOPENGLFUNC(pglScalef , glScalef) GETOPENGLFUNC(pglTranslatef , glTranslatef) @@ -521,6 +485,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglBegin , glBegin) GETOPENGLFUNC(pglEnd , glEnd) GETOPENGLFUNC(pglVertex3f , glVertex3f) + GETOPENGLFUNC(pglVertex3fv, glVertex3fv) GETOPENGLFUNC(pglVertex3sv, glVertex3sv) GETOPENGLFUNC(pglNormal3f , glNormal3f) GETOPENGLFUNC(pglNormal3bv, glNormal3bv) @@ -535,6 +500,9 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglDrawElements, glDrawElements) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) GETOPENGLFUNC(pglDisableClientState, glDisableClientState) + GETOPENGLFUNC(pglClientActiveTexture, glClientActiveTexture) + if (!pglClientActiveTexture) + GETOPENGLFUNC(pglClientActiveTexture, glClientActiveTextureARB) GETOPENGLFUNC(pglShadeModel , glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) @@ -566,47 +534,15 @@ boolean SetupGLfunc(void) } // This has to be done after the context is created so the version number can be obtained +// This is stupid -- even some of the oldest usable OpenGL hardware today supports 1.3-level featureset. boolean SetupGLFunc13(void) { -#ifdef MINI_GL_COMPATIBILITY - return false; -#else - const GLubyte *version = pglGetString(GL_VERSION); - int glmajor, glminor; - - gl13 = false; - // Parse the GL version - if (version != NULL) - { - if (sscanf((const char*)version, "%d.%d", &glmajor, &glminor) == 2) - { - // Look, we gotta prepare for the inevitable arrival of GL 2.0 code... - if (glmajor == 1 && glminor >= 3) - gl13 = true; - else if (glmajor > 1) - gl13 = true; - } - } - - if (gl13) - { - pglActiveTexture = GetGLFunc("glActiveTexture"); - pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); - } - else if (isExtAvailable("GL_ARB_multitexture", gl_extensions)) - { - // Get the functions - pglActiveTexture = GetGLFunc("glActiveTextureARB"); - pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2fARB"); - - gl13 = true; // This is now true, so the new fade mask stuff can be done, if OpenGL version is less than 1.3, it still uses the old fade stuff. - DBG_Printf("GL_ARB_multitexture support: enabled\n"); - - } - else - DBG_Printf("GL_ARB_multitexture support: disabled\n"); + pglActiveTexture = GetGLFunc("glActiveTexture"); + pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); + pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); + pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv"); + return true; -#endif } // -----------------+ @@ -624,11 +560,7 @@ static void SetNoTexture(void) static void GLPerspective(GLdouble fovy, GLdouble aspect) { -#ifdef MINI_GL_COMPATIBILITY - GLfloat m[4][4] = -#else GLdouble m[4][4] = -#endif { { 1.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f, 0.0f}, @@ -651,14 +583,10 @@ static void GLPerspective(GLdouble fovy, GLdouble aspect) m[1][1] = cotangent; m[2][2] = -(zFar + zNear) / deltaZ; m[3][2] = -2.0f * zNear * zFar / deltaZ; -#ifdef MINI_GL_COMPATIBILITY - pglMultMatrixf(&m[0][0]); -#else + pglMultMatrixd(&m[0][0]); -#endif } -#ifndef MINI_GL_COMPATIBILITY static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ, GLdouble* winX, GLdouble* winY, GLdouble* winZ) { @@ -698,7 +626,6 @@ static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ, *winY=in[1]; *winZ=in[2]; } -#endif // -----------------+ // SetModelView : @@ -729,10 +656,8 @@ void SetModelView(GLint w, GLint h) //pglScalef(1.0f, 320.0f/200.0f, 1.0f); // gr_scalefrustum (ORIGINAL_ASPECT) // added for new coronas' code (without depth buffer) -#ifndef MINI_GL_COMPATIBILITY pglGetIntegerv(GL_VIEWPORT, viewport); pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); -#endif } @@ -757,17 +682,15 @@ void SetStates(void) //pglShadeModel(GL_FLAT); pglEnable(GL_TEXTURE_2D); // two-dimensional texturing -#ifndef KOS_GL_COMPATIBILITY + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); pglAlphaFunc(GL_NOTEQUAL, 0.0f); -#endif + //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) pglEnable(GL_BLEND); // enable color blending -#ifndef KOS_GL_COMPATIBILITY pglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -#endif //pglDisable(GL_DITHER); // faB: ??? (undocumented in OpenGL 1.1) // Hurdler: yes, it is! @@ -792,9 +715,7 @@ void SetStates(void) //tex_downloaded = NOTEXTURE_NUM; //pglTexImage2D(GL_TEXTURE_2D, 0, 4, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data); -#ifndef KOS_GL_COMPATIBILITY pglPolygonOffset(-1.0f, -1.0f); -#endif //pglEnable(GL_CULL_FACE); //pglCullFace(GL_FRONT); @@ -815,9 +736,7 @@ void SetStates(void) // bp : when no t&l :) pglLoadIdentity(); pglScalef(1.0f, 1.0f, -1.0f); -#ifndef MINI_GL_COMPATIBILITY pglGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) -#endif } @@ -921,14 +840,6 @@ EXPORT void HWRAPI(ClearMipMapCache) (void) EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data) { -#ifdef KOS_GL_COMPATIBILITY - (void)x; - (void)y; - (void)width; - (void)height; - (void)dst_stride; - (void)dst_data; -#else INT32 i; // DBG_Printf ("ReadRect()\n"); if (dst_stride == width*3) @@ -970,7 +881,6 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, } free(image); } -#endif } @@ -991,10 +901,8 @@ EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, f pglMatrixMode(GL_MODELVIEW); // added for new coronas' code (without depth buffer) -#ifndef MINI_GL_COMPATIBILITY pglGetIntegerv(GL_VIEWPORT, viewport); pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); -#endif } @@ -1041,12 +949,9 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, GLRGBAFloat c; // DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); -#ifdef MINI_GL_COMPATIBILITY - GLfloat px1, px2, px3, px4; - GLfloat py1, py2, py3, py4; + GLfloat p[12]; GLfloat dx, dy; GLfloat angle; -#endif // BP: we should reflect the new state in our variable //SetBlend(PF_Modulated|PF_NoTexture); @@ -1058,33 +963,24 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, c.blue = byte2float[Color.s.blue]; c.alpha = byte2float[Color.s.alpha]; -#ifndef MINI_GL_COMPATIBILITY - pglColor4fv(&c.red); // is in RGBA float format - pglBegin(GL_LINES); - pglVertex3f(v1->x, -v1->y, 1.0f); - pglVertex3f(v2->x, -v2->y, 1.0f); - pglEnd(); -#else + // This is the preferred, 'modern' way of rendering lines -- creating a polygon. if (v2->x != v1->x) angle = (float)atan((v2->y-v1->y)/(v2->x-v1->x)); else - angle = N_PI_DEMI; + angle = (float)N_PI_DEMI; dx = (float)sin(angle) / (float)screen_width; dy = (float)cos(angle) / (float)screen_height; - px1 = v1->x - dx; py1 = v1->y + dy; - px2 = v2->x - dx; py2 = v2->y + dy; - px3 = v2->x + dx; py3 = v2->y - dy; - px4 = v1->x + dx; py4 = v1->y - dy; + p[0] = v1->x - dx; p[1] = -(v1->y + dy); p[2] = 1; + p[3] = v2->x - dx; p[4] = -(v2->y + dy); p[5] = 1; + p[6] = v2->x + dx; p[7] = -(v2->y - dy); p[8] = 1; + p[9] = v1->x + dx; p[10] = -(v1->y - dy); p[11] = 1; - pglColor4f(c.red, c.green, c.blue, c.alpha); - pglBegin(GL_TRIANGLE_FAN); - pglVertex3f(px1, -py1, 1); - pglVertex3f(px2, -py2, 1); - pglVertex3f(px3, -py3, 1); - pglVertex3f(px4, -py4, 1); - pglEnd(); -#endif + pglColor4fv(&c.red); // is in RGBA float format + pglEnableClientState(GL_VERTEX_ARRAY); + pglVertexPointer(3, GL_FLOAT, 0, p); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglDisableClientState(GL_VERTEX_ARRAY); pglEnable(GL_TEXTURE_2D); } @@ -1114,60 +1010,42 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) switch (PolyFlags & PF_Blending) { case PF_Translucent & PF_Blending: pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_NOTEQUAL, 0.0f); -#endif break; case PF_Masked & PF_Blending: // Hurdler: does that mean lighting is only made by alpha src? // it sounds ok, but not for polygonsmooth pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_GREATER, 0.5f); -#endif break; case PF_Additive & PF_Blending: -#ifdef ATI_RAGE_PRO_COMPATIBILITY - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency -#else pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest -#endif -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_NOTEQUAL, 0.0f); -#endif break; case PF_Environment & PF_Blending: pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_NOTEQUAL, 0.0f); -#endif break; case PF_Substractive & PF_Blending: // good for shadow - // not realy but what else ? + // not really but what else ? pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_NOTEQUAL, 0.0f); -#endif break; case PF_Fog & PF_Fog: // Sryder: Fog // multiplies input colour by input alpha, and destination colour by input colour, then adds them pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_NOTEQUAL, 0.0f); -#endif break; default : // must be 0, otherwise it's an error // No blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending -#ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_GREATER, 0.5f); -#endif break; } } -#ifndef KOS_GL_COMPATIBILITY + if (Xor & PF_NoAlphaTest) { if (PolyFlags & PF_NoAlphaTest) @@ -1183,7 +1061,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) else pglDisable(GL_POLYGON_OFFSET_FILL); } -#endif + if (Xor&PF_NoDepthTest) { if (PolyFlags & PF_NoDepthTest) @@ -1210,10 +1088,6 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } -#ifdef KOS_GL_COMPATIBILITY - if (Xor&PF_Modulated && !(PolyFlags & PF_Modulated)) - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); -#else if (Xor&PF_Modulated) { #if defined (__unix__) || defined (UNIXCOMMON) @@ -1233,7 +1107,6 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } } -#endif if (Xor & PF_Occlude) // depth test but (no) depth write { @@ -1287,11 +1160,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) else { // Download a mipmap -#ifdef KOS_GL_COMPATIBILITY - static GLushort tex[2048*2048]; -#else static RGBA_t tex[2048*2048]; -#endif const GLvoid *ptex = tex; INT32 w, h; @@ -1310,102 +1179,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } else #endif -#ifdef KOS_GL_COMPATIBILITY - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || - (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && - (pTexInfo->flags & TF_CHROMAKEYED)) - { - tex[w*j+i] = 0; - } - else - { - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88 && !(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i] = 0; - else - tex[w*j+i] = (myPaletteData[*pImgData].s.alpha>>4)<<12; - - tex[w*j+i] |= (myPaletteData[*pImgData].s.red >>4)<<8; - tex[w*j+i] |= (myPaletteData[*pImgData].s.green>>4)<<4; - tex[w*j+i] |= (myPaletteData[*pImgData].s.blue >>4); - } - - pImgData++; - - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) - { - if (!(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i] |= ((*pImgData)>>4)<<12; - pImgData++; - } - - } - } - } - else if (pTexInfo->grInfo.format == GR_RGBA) - { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - const RGBA_t *pImgData = (const RGBA_t *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i] = (pImgData->s.alpha>>4)<<12; - tex[w*j+i] |= (pImgData->s.red >>4)<<8; - tex[w*j+i] |= (pImgData->s.green>>4)<<4; - tex[w*j+i] |= (pImgData->s.blue >>4); - pImgData++; - } - } - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - const GLubyte sID = (*pImgData)>>4; - tex[w*j+i] = sID<<8 | sID<<4 | sID; - pImgData++; - tex[w*j+i] |= ((*pImgData)>>4)<<12; - pImgData++; - } - } - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i] = (pImgData>>4)<<12; - tex[w*j+i] |= (255>>4)<<8; - tex[w*j+i] |= (255>>4)<<4; - tex[w*j+i] |= (255>>4); - pImgData++; - } - } - } - else - DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); -#else if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) { @@ -1488,7 +1262,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } else DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); -#endif pTexInfo->downloaded = NextTexAvail++; tex_downloaded = pTexInfo->downloaded; @@ -1497,13 +1270,8 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues if (pTexInfo->flags & TF_TRANSPARENT) { -#ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NONE); -#else pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -#endif } else { @@ -1511,29 +1279,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); } -#ifdef KOS_GL_COMPATIBILITY - pglTexImage2D(GL_TEXTURE_2D, 0, GL_ARGB4444, w, h, 0, GL_ARGB4444, GL_UNSIGNED_BYTE, ptex); -#else -#ifdef MINI_GL_COMPATIBILITY - //if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - //else - if (MipMap) - pgluBuild2DMipmaps(GL_TEXTURE_2D, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - else - pglTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); -#else -#ifdef USE_PALETTED_TEXTURE - //Hurdler: not really supported and not tested recently - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex); - pglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, w, h, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, pTexInfo->grInfo.data); - } - else -#endif if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) { //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); @@ -1593,8 +1338,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) else pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); } -#endif -#endif if (pTexInfo->flags & TF_WRAPX) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); @@ -1618,19 +1361,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) else // initialisation de la liste gr_cachetail = gr_cachehead = pTexInfo; } -#ifdef MINI_GL_COMPATIBILITY - switch (pTexInfo->flags) - { - case 0 : - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - break; - default: - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - break; - } -#endif } @@ -1644,18 +1374,11 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FBITFIELD PolyFlags) { FUINT i; -#ifndef MINI_GL_COMPATIBILITY FUINT j; -#endif GLRGBAFloat c = {0,0,0,0}; -#ifdef MINI_GL_COMPATIBILITY - if (PolyFlags & PF_Corona) - PolyFlags &= ~PF_NoDepthTest; -#else if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) PolyFlags &= ~(PF_NoDepthTest|PF_Corona); -#endif SetBlend(PolyFlags); //TODO: inline (#pragma..) @@ -1677,16 +1400,11 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, c.alpha = byte2float[pSurf->FlatColor.s.alpha]; } -#ifdef MINI_GL_COMPATIBILITY - pglColor4f(c.red, c.green, c.blue, c.alpha); -#else pglColor4fv(&c.red); // is in RGBA float format -#endif } // this test is added for new coronas' code (without depth buffer) // I think I should do a separate function for drawing coronas, so it will be a little faster -#ifndef MINI_GL_COMPATIBILITY if (PolyFlags & PF_Corona) // check to see if we need to draw the corona { //rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value @@ -1733,19 +1451,17 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, c.alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) pglColor4fv(&c.red); } -#endif + if (PolyFlags & PF_MD2) return; - pglBegin(GL_TRIANGLE_FAN); - for (i = 0; i < iNumPts; i++) - { - pglTexCoord2f(pOutVerts[i].sow, pOutVerts[i].tow); - //Hurdler: test code: -pOutVerts[i].z => pOutVerts[i].z - pglVertex3f(pOutVerts[i].x, pOutVerts[i].y, pOutVerts[i].z); - //pglVertex3f(pOutVerts[i].x, pOutVerts[i].y, -pOutVerts[i].z); - } - pglEnd(); + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow); + pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_VERTEX_ARRAY); if (PolyFlags & PF_RemoveYWrap) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -1827,41 +1543,15 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) break; case HWD_SET_POLYGON_SMOOTH: -#ifdef KOS_GL_COMPATIBILITY // GL_POLYGON_SMOOTH_HINT - if (Value) - pglHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST); - else - pglHint(GL_POLYGON_SMOOTH_HINT,GL_FASTEST); -#else if (Value) pglEnable(GL_POLYGON_SMOOTH); else pglDisable(GL_POLYGON_SMOOTH); -#endif break; case HWD_SET_TEXTUREFILTERMODE: switch (Value) { -#ifdef KOS_GL_COMPATIBILITY - case HWD_SET_TEXTUREFILTER_TRILINEAR: - case HWD_SET_TEXTUREFILTER_BILINEAR: - min_filter = mag_filter = GL_FILTER_BILINEAR; - break; - case HWD_SET_TEXTUREFILTER_POINTSAMPLED: - min_filter = mag_filter = GL_FILTER_NONE; - case HWD_SET_TEXTUREFILTER_MIXED1: - min_filter = GL_FILTER_NONE; - mag_filter = GL_LINEAR; - case HWD_SET_TEXTUREFILTER_MIXED2: - min_filter = GL_LINEAR; - mag_filter = GL_FILTER_NONE; - break; - case HWD_SET_TEXTUREFILTER_MIXED3: - min_filter = GL_FILTER_BILINEAR; - mag_filter = GL_FILTER_NONE; - break; -#elif !defined (MINI_GL_COMPATIBILITY) case HWD_SET_TEXTUREFILTER_TRILINEAR: min_filter = GL_LINEAR_MIPMAP_LINEAR; mag_filter = GL_LINEAR; @@ -1890,14 +1580,9 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) mag_filter = GL_NEAREST; MipMap = GL_TRUE; break; -#endif default: -#ifdef KOS_GL_COMPATIBILITY - min_filter = mag_filter = GL_FILTER_NONE; -#else mag_filter = GL_LINEAR; min_filter = GL_NEAREST; -#endif } if (!pgluBuild2DMipmaps) { @@ -1918,26 +1603,64 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } } +static float *vertBuffer = NULL; +static float *normBuffer = NULL; +static size_t lerpBufferSize = 0; +static short *vertTinyBuffer = NULL; +static char *normTinyBuffer = NULL; +static size_t lerpTinyBufferSize = 0; + +// Static temporary buffer for doing frame interpolation +// 'size' is the vertex size +static void AllocLerpBuffer(size_t size) +{ + if (lerpBufferSize >= size) + return; + + if (vertBuffer != NULL) + free(vertBuffer); + + if (normBuffer != NULL) + free(normBuffer); + + lerpBufferSize = size; + vertBuffer = malloc(lerpBufferSize); + normBuffer = malloc(lerpBufferSize); +} + +// Static temporary buffer for doing frame interpolation +// 'size' is the vertex size +static void AllocLerpTinyBuffer(size_t size) +{ + if (lerpTinyBufferSize >= size) + return; + + if (vertTinyBuffer != NULL) + free(vertTinyBuffer); + + if (normTinyBuffer != NULL) + free(normTinyBuffer); + + lerpTinyBufferSize = size; + vertTinyBuffer = malloc(lerpTinyBufferSize); + normTinyBuffer = malloc(lerpTinyBufferSize / 2); +} + static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { GLfloat ambient[4]; GLfloat diffuse[4]; float pol = 0.0f; - - float scalex, scaley, scalez; + scale *= 0.5f; + float scalex = scale, scaley = scale, scalez = scale; boolean useTinyFrames; int i; // Because Otherwise, scaling the screen negatively vertically breaks the lighting -#ifndef KOS_GL_COMPATIBILITY GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; -#endif - - scale *= 0.5f; - scalex = scaley = scalez = scale; if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { @@ -1997,9 +1720,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } #endif -#ifndef KOS_GL_COMPATIBILITY pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); -#endif pglShadeModel(GL_SMOOTH); if (color) @@ -2033,6 +1754,10 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (useTinyFrames) pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglEnableClientState(GL_NORMAL_ARRAY); + for (i = 0; i < model->numMeshes; i++) { mesh_t *mesh = &model->meshes[i]; @@ -2047,46 +1772,30 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || pol == 0.0f) { - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - pglEnableClientState(GL_NORMAL_ARRAY); pglVertexPointer(3, GL_SHORT, 0, frame->vertices); pglNormalPointer(GL_BYTE, 0, frame->normals); pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); - pglDisableClientState(GL_NORMAL_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_VERTEX_ARRAY); } else { // Dangit, I soooo want to do this in a GLSL shader... - short *buffer = malloc(mesh->numVertices * sizeof(short) * 3); - short *vertPtr = buffer; - char *normBuffer = malloc(mesh->numVertices * sizeof(char) * 3); - char *normPtr = normBuffer; + AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); + short *vertPtr = vertTinyBuffer; + char *normPtr = normTinyBuffer; int j = 0; - for (j = 0; j < mesh->numVertices; j++) + for (j = 0; j < mesh->numVertices * 3; j++) { // Interpolate *vertPtr++ = (short)(frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j]))); *normPtr++ = (char)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]))); } - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - pglEnableClientState(GL_NORMAL_ARRAY); - pglVertexPointer(3, GL_SHORT, 0, buffer); - pglNormalPointer(GL_BYTE, 0, normBuffer); + pglVertexPointer(3, GL_SHORT, 0, vertTinyBuffer); + pglNormalPointer(GL_BYTE, 0, normTinyBuffer); pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); - pglDisableClientState(GL_NORMAL_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_VERTEX_ARRAY); - - free(buffer); - free(normBuffer); } } else @@ -2100,61 +1809,38 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || pol == 0.0f) { // Zoom! Take advantage of just shoving the entire arrays to the GPU. - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - pglEnableClientState(GL_NORMAL_ARRAY); pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); pglNormalPointer(GL_FLOAT, 0, frame->normals); pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); - pglDisableClientState(GL_NORMAL_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_VERTEX_ARRAY); } else { - int j = 0; - float *uvPtr = mesh->uvs; - float *frameVert = frame->vertices; - float *frameNormal = frame->normals; - float *nextFrameVert = nextframe->vertices; - float *nextFrameNormal = nextframe->normals; - // Dangit, I soooo want to do this in a GLSL shader... - pglBegin(GL_TRIANGLES); + AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); + float *vertPtr = vertBuffer; + float *normPtr = normBuffer; + int j = 0; - for (j = 0; j < mesh->numTriangles * 3; j++) + for (j = 0; j < mesh->numVertices * 3; j++) { // Interpolate - float px1 = *frameVert++; - float py1 = *frameVert++; - float pz1 = *frameVert++; - float px2 = *nextFrameVert++; - float py2 = *nextFrameVert++; - float pz2 = *nextFrameVert++; - float nx1 = *frameNormal++; - float ny1 = *frameNormal++; - float nz1 = *frameNormal++; - float nx2 = *nextFrameNormal++; - float ny2 = *nextFrameNormal++; - float nz2 = *nextFrameNormal++; - - pglTexCoord2fv(uvPtr); - pglNormal3f((nx1 + pol * (nx2 - nx1)), - (ny1 + pol * (ny2 - ny1)), - (nz1 + pol * (nz2 - nz1))); - pglVertex3f((px1 + pol * (px2 - px1)), - (py1 + pol * (py2 - py1)), - (pz1 + pol * (pz2 - pz1))); - - uvPtr += 2; + *vertPtr++ = frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j])); + *normPtr++ = frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j])); } - pglEnd(); + pglVertexPointer(3, GL_FLOAT, 0, vertBuffer); + pglNormalPointer(GL_FLOAT, 0, normBuffer); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numVertices); } } } + pglDisableClientState(GL_NORMAL_ARRAY); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglDisableClientState(GL_VERTEX_ARRAY); + pglPopMatrix(); // should be the same as glLoadIdentity if (color) pglDisable(GL_LIGHTING); @@ -2204,9 +1890,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) GLPerspective(53.13l, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) else GLPerspective(stransform->fovxangle, ASPECT_RATIO); -#ifndef MINI_GL_COMPATIBILITY pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) -#endif pglMatrixMode(GL_MODELVIEW); } else @@ -2220,15 +1904,11 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) else //Hurdler: is "fov" correct? GLPerspective(fov, ASPECT_RATIO); -#ifndef MINI_GL_COMPATIBILITY pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) -#endif pglMatrixMode(GL_MODELVIEW); } -#ifndef MINI_GL_COMPATIBILITY pglGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) -#endif } EXPORT INT32 HWRAPI(GetTextureUsed) (void) @@ -2249,7 +1929,6 @@ EXPORT INT32 HWRAPI(GetRenderVersion) (void) return VERSION; } -#ifdef SHUFFLE EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) { INT32 x, y; @@ -2269,16 +1948,25 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglDisable(GL_DEPTH_TEST); pglDisable(GL_BLEND); - pglBegin(GL_QUADS); + + const float blackBack[16] = + { + -16.0f, -16.0f, 6.0f, + -16.0f, 16.0f, 6.0f, + 16.0f, 16.0f, 6.0f, + 16.0f, -16.0f, 6.0f + }; + + pglEnableClientState(GL_VERTEX_ARRAY); // Draw a black square behind the screen texture, // so nothing shows through the edges pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); - pglVertex3f(-16.0f, -16.0f, 6.0f); - pglVertex3f(-16.0f, 16.0f, 6.0f); - pglVertex3f(16.0f, 16.0f, 6.0f); - pglVertex3f(16.0f, -16.0f, 6.0f); + + pglVertexPointer(3, GL_FLOAT, 0, blackBack); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); for(x=0;x #include -#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 #endif #endif -#endif #define _CREATE_DLL_ // necessary for Unix AND Windows #include "../../doomdef.h" diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 7962e01b1..9f844c623 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -90,9 +90,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(DrawModel); GETFUNC(SetTransform); GETFUNC(GetRenderVersion); -#ifdef SHUFFLE GETFUNC(PostImgRedraw); -#endif //SHUFFLE GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); GETFUNC(EndScreenWipe); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 336a709df..11ad2be9a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1549,9 +1549,7 @@ void I_StartupGraphics(void) HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); -#ifdef SHUFFLE HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); -#endif HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index 1a2a7f80d..8f6077969 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -108,21 +108,9 @@ Hw_Hardware - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - Hw_Hardware - - Hw_Hardware - Hw_Hardware @@ -465,6 +453,10 @@ M_Misc + + + + From 6f70a07cb68657fef5d1ad28740719935b28b9c2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 26 Dec 2018 23:15:28 -0500 Subject: [PATCH 042/382] Fix floating point comparisons --- src/hardware/hw_model.c | 4 +++- src/hardware/r_opengl/r_opengl.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 828339563..394b0f899 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -412,7 +412,9 @@ void GenerateVertexNormals(model_t *model) testY = *testPtr++; testZ = *testPtr++; - if (x != testX || y != testY || z != testZ) + if (fabsf(x - testX) > FLT_EPSILON + || fabsf(y - testY) > FLT_EPSILON + || fabsf(z - testZ) > FLT_EPSILON) continue; // Found a vertex match! Add it... diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 4f77680d9..22a4d7df8 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -964,7 +964,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, c.alpha = byte2float[Color.s.alpha]; // This is the preferred, 'modern' way of rendering lines -- creating a polygon. - if (v2->x != v1->x) + if (fabsf(v2->x - v1->x) > FLT_EPSILON) angle = (float)atan((v2->y-v1->y)/(v2->x-v1->x)); else angle = (float)N_PI_DEMI; @@ -1770,7 +1770,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (nextFrameIndex != -1) nextframe = &mesh->tinyframes[nextFrameIndex % mesh->numFrames]; - if (!nextframe || pol == 0.0f) + if (!nextframe || fpclassify(pol) == FP_ZERO) { pglVertexPointer(3, GL_SHORT, 0, frame->vertices); pglNormalPointer(GL_BYTE, 0, frame->normals); @@ -2151,6 +2151,8 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) INT32 fademaskdownloaded = tex_downloaded; // the fade mask that has been set + (void)alpha; + // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; From d60b77b0625af01fb32e74511c407b7e06afe348 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 26 Dec 2018 23:31:55 -0500 Subject: [PATCH 043/382] Mixed D&C fixes --- src/hardware/hw_md2load.c | 99 ++++++++++++++++++++------- src/hardware/r_opengl/r_opengl.c | 112 ++++++++++++++++++++----------- 2 files changed, 144 insertions(+), 67 deletions(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index d29414b0f..1d0e4f361 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -17,7 +17,7 @@ #define NUMVERTEXNORMALS 162 -// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and +// 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}, @@ -195,9 +195,9 @@ typedef struct 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 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 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 @@ -233,10 +233,36 @@ typedef struct // Load the model model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) { - useFloat = true; 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; + + int t; + + // MD2 currently does not work with tinyframes, so force useFloat = true + // + // + // 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; + FILE *f = fopen(fileName, "rb"); if (!f) @@ -244,13 +270,13 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0); - size_t fileLen; + //size_t fileLen; - int i, j; + //int i, j; - size_t namelen; - char *texturefilename; - const char *texPos = strchr(fileName, '/'); + //size_t namelen; + //char *texturefilename; + texPos = strchr(fileName, '/'); if (texPos) { @@ -276,7 +302,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) fseek(f, 0, SEEK_SET); // read in file - char *buffer = malloc(fileLen); + buffer = malloc(fileLen); fread(buffer, fileLen, 1, f); fclose(f); @@ -286,8 +312,8 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) 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; + // const float WUNITS = 1.0f; + // float dataScale = WUNITS; // Tris and ST are simple structures that can be straight-copied md2triangle_t *tris = (md2triangle_t*)&buffer[header->offsetTris]; @@ -302,7 +328,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0); - int t; + // int t; for (t = 0; t < retModel->numMaterials; t++) { retModel->materials[t].ambient[0] = 0.8f; @@ -370,14 +396,26 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) if (!useFloat) // Decompress to MD3 'tinyframe' space { + byte *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); - byte *ptr = (byte*)frames; + ptr = (byte*)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); @@ -386,14 +424,14 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) // 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); - short *vertptr = retModel->meshes[0].tinyframes[i].vertices; - char *normptr = retModel->meshes[0].tinyframes[i].normals; + vertptr = retModel->meshes[0].tinyframes[i].vertices; + normptr = retModel->meshes[0].tinyframes[i].normals; - // char *tanptr = retModel->meshes[0].tinyframes[i].tangents; + // tanptr = retModel->meshes[0].tinyframes[i].tangents; retModel->meshes[0].tinyframes[i].material = &retModel->materials[0]; framePtr++; // Advance to vertex list - md2vertex_t *vertex = (md2vertex_t*)framePtr; + vertex = (md2vertex_t*)framePtr; framePtr--; for (j = 0; j < header->numXYZ; j++, vertex++) { @@ -412,9 +450,9 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) } // This doesn't need to be done every frame! - md2triangle_t *trisPtr = tris; - unsigned short *indexptr = retModel->meshes[0].indices; - float *uvptr = (float*)retModel->meshes[0].uvs; + 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]; @@ -434,12 +472,17 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) } else // Full float loading method { + md2triangle_t *trisPtr; + float *uvptr; + + byte *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); - md2triangle_t *trisPtr = tris; - float *uvptr = retModel->meshes[0].uvs; + 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; @@ -450,15 +493,19 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) *uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight); } - byte *ptr = (byte*)frames; + ptr = (byte*)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; + //float *vertptr, *normptr; normptr = (float*)retModel->meshes[0].frames[i].normals; vertptr = (float*)retModel->meshes[0].frames[i].vertices; trisPtr = tris; @@ -466,7 +513,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->meshes[0].frames[i].material = &retModel->materials[0]; framePtr++; // Advance to vertex list - md2vertex_t *vertex = (md2vertex_t*)framePtr; + vertex = (md2vertex_t*)framePtr; framePtr--; for (j = 0; j < header->numTris; j++, trisPtr++) { diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 22a4d7df8..3410ed3ec 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1652,8 +1652,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 GLfloat diffuse[4]; float pol = 0.0f; - scale *= 0.5f; - float scalex = scale, scaley = scale, scalez = scale; + float scalex, scaley, scalez; boolean useTinyFrames; @@ -1662,6 +1661,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 // Because Otherwise, scaling the screen negatively vertically breaks the lighting GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; + // Affect input model scaling + scale *= 0.5f; + scalex = scale; + scaley = scale; + scalez = scale; + if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { UINT32 newtime = (duration - tics); // + 1; @@ -1779,11 +1784,15 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } else { + short *vertPtr; + char *normPtr; + int j; + // Dangit, I soooo want to do this in a GLSL shader... AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); - short *vertPtr = vertTinyBuffer; - char *normPtr = normTinyBuffer; - int j = 0; + vertPtr = vertTinyBuffer; + normPtr = normTinyBuffer; + j = 0; for (j = 0; j < mesh->numVertices * 3; j++) { @@ -1816,10 +1825,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } else { + float *vertPtr; + float *normPtr; + // Dangit, I soooo want to do this in a GLSL shader... AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); - float *vertPtr = vertBuffer; - float *normPtr = normBuffer; + vertPtr = vertBuffer; + normPtr = normBuffer; int j = 0; for (j = 0; j < mesh->numVertices * 3; j++) @@ -1936,6 +1948,14 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) float xfix, yfix; INT32 texsize = 2048; + const float blackBack[16] = + { + -16.0f, -16.0f, 6.0f, + -16.0f, 16.0f, 6.0f, + 16.0f, 16.0f, 6.0f, + 16.0f, -16.0f, 6.0f + }; + // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; @@ -1949,13 +1969,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglDisable(GL_DEPTH_TEST); pglDisable(GL_BLEND); - const float blackBack[16] = - { - -16.0f, -16.0f, 6.0f, - -16.0f, 16.0f, 6.0f, - 16.0f, 16.0f, 6.0f, - 16.0f, -16.0f, 6.0f - }; + // const float blackBack[16] pglEnableClientState(GL_VERTEX_ARRAY); @@ -1971,6 +1985,9 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) { for(y=0;y Date: Wed, 26 Dec 2018 23:40:29 -0500 Subject: [PATCH 044/382] byte -> char --- src/hardware/hw_md2load.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 1d0e4f361..84b1bc531 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -396,7 +396,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) if (!useFloat) // Decompress to MD3 'tinyframe' space { - byte *ptr; + char *ptr; md2triangle_t *trisPtr; unsigned short *indexptr; @@ -407,7 +407,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->meshes[0].numVertices = header->numXYZ; retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0); - ptr = (byte*)frames; + ptr = (char*)frames; for (i = 0; i < header->numFrames; i++, ptr += header->framesize) { short *vertptr; @@ -475,7 +475,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) md2triangle_t *trisPtr; float *uvptr; - byte *ptr; + char *ptr; retModel->meshes[0].numVertices = header->numTris * 3; retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0); @@ -493,7 +493,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) *uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight); } - ptr = (byte*)frames; + ptr = (char*)frames; for (i = 0; i < header->numFrames; i++, ptr += header->framesize) { float *vertptr, *normptr; From c0547d56aa93e1d74663ad7f500c494f226f22ed Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 26 Dec 2018 23:50:35 -0500 Subject: [PATCH 045/382] More mixed d&c fixes --- src/hardware/hw_md2load.c | 14 ++++++++++---- src/hardware/r_opengl/r_opengl.c | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 84b1bc531..ddf89f8db 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -233,6 +233,8 @@ typedef struct // Load the model model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) { + FILE *f; + model_t *retModel = NULL; md2header_t *header; @@ -247,6 +249,10 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) 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 @@ -263,7 +269,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) useFloat = true; - FILE *f = fopen(fileName, "rb"); + f = fopen(fileName, "rb"); if (!f) return NULL; @@ -316,9 +322,9 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) // float dataScale = WUNITS; // Tris and ST are simple structures that can be straight-copied - md2triangle_t *tris = (md2triangle_t*)&buffer[header->offsetTris]; - md2texcoord_t *texcoords = (md2texcoord_t*)&buffer[header->offsetST]; - md2frame_t *frames = (md2frame_t*)&buffer[header->offsetFrames]; + 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; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 3410ed3ec..f7f9dd5bd 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1827,12 +1827,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 { float *vertPtr; float *normPtr; + int j = 0; // Dangit, I soooo want to do this in a GLSL shader... AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); vertPtr = vertBuffer; normPtr = normBuffer; - int j = 0; + //int j = 0; for (j = 0; j < mesh->numVertices * 3; j++) { From dbcdacc8bb97de1a9c472f1c5149332ca145cb39 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 00:01:51 -0500 Subject: [PATCH 046/382] Ignored fread fix --- src/hardware/hw_md2load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index ddf89f8db..3805deffb 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -309,7 +309,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) // read in file buffer = malloc(fileLen); - fread(buffer, fileLen, 1, f); + if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error fclose(f); // get pointer to file header From 191f9454c32f5de4eb739dda6e3bf068fb09f858 Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 24 Dec 2018 12:08:00 -0500 Subject: [PATCH 047/382] boolean fix for VS add GL_NORMALIZE --- src/hardware/r_opengl/r_opengl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index f7f9dd5bd..6813b9564 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1700,6 +1700,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } pglEnable(GL_CULL_FACE); + pglEnable(GL_NORMALIZE); #ifdef USE_FTRANSFORM_MIRROR // flipped is if the object is flipped @@ -1859,6 +1860,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglDisable(GL_LIGHTING); pglShadeModel(GL_FLAT); pglDisable(GL_CULL_FACE); + pglDisable(GL_NORMALIZE); } // -----------------+ From f5562c47ec6a254edf2f92885326e02dd78107a0 Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 25 Dec 2018 21:28:51 -0500 Subject: [PATCH 048/382] Removed unused PF_Md2 flag More OpenGL performance increase by making assumptions about client state --- src/hardware/hw_defs.h | 2 +- src/hardware/r_opengl/r_opengl.c | 142 ++++++++++++------------------- src/hardware/r_opengl/r_opengl.h | 2 + 3 files changed, 58 insertions(+), 88 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 04f63af71..767eac0b6 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -166,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 diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 6813b9564..fc6c21f13 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -42,6 +42,7 @@ struct GLRGBAFloat GLfloat alpha; }; typedef struct GLRGBAFloat GLRGBAFloat; +static const float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; // ========================================================================== // CONSTANTS @@ -541,7 +542,7 @@ boolean SetupGLFunc13(void) pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv"); - + return true; } @@ -936,6 +937,8 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, SetBlend(DepthMask ? PF_Occlude | CurrentPolyFlags : CurrentPolyFlags&~PF_Occlude); pglClear(ClearMask); + pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too } @@ -976,12 +979,12 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, p[6] = v2->x + dx; p[7] = -(v2->y - dy); p[8] = 1; p[9] = v1->x + dx; p[10] = -(v1->y - dy); p[11] = 1; + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); pglColor4fv(&c.red); // is in RGBA float format - pglEnableClientState(GL_VERTEX_ARRAY); pglVertexPointer(3, GL_FLOAT, 0, p); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - pglDisableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); pglEnable(GL_TEXTURE_2D); } @@ -1094,7 +1097,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) if (oglflags & GLF_NOTEXENV) { if (!(PolyFlags & PF_Modulated)) - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + pglColor4fv(white); } else #endif @@ -1452,16 +1455,9 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, pglColor4fv(&c.red); } - if (PolyFlags & PF_MD2) - return; - - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow); pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_VERTEX_ARRAY); if (PolyFlags & PF_RemoveYWrap) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -1760,8 +1756,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (useTinyFrames) pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); pglEnableClientState(GL_NORMAL_ARRAY); for (i = 0; i < model->numMeshes; i++) @@ -1852,8 +1846,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } pglDisableClientState(GL_NORMAL_ARRAY); - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglDisableClientState(GL_VERTEX_ARRAY); pglPopMatrix(); // should be the same as glLoadIdentity if (color) @@ -1974,65 +1966,59 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) // const float blackBack[16] - pglEnableClientState(GL_VERTEX_ARRAY); + // Draw a black square behind the screen texture, + // so nothing shows through the edges + pglColor4fv(white); - // Draw a black square behind the screen texture, - // so nothing shows through the edges - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - pglVertexPointer(3, GL_FLOAT, 0, blackBack); - pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglVertexPointer(3, GL_FLOAT, 0, blackBack); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - for(x=0;x Date: Wed, 26 Dec 2018 10:58:37 -0500 Subject: [PATCH 049/382] Removed gr_voodoocompatibility as even low-power mobile devices do not have this limitation No longer using byte2float in DrawPolygon -- use the surface color data directly Vertex Buffer Objects for non-interpolated model frames Removed some old unused paletted texture stuff --- src/d_main.c | 3 - src/doomtype.h | 16 +- src/hardware/hw_cache.c | 61 ------- src/hardware/hw_defs.h | 2 - src/hardware/hw_drv.h | 2 + src/hardware/hw_main.c | 5 - src/hardware/hw_main.h | 2 - src/hardware/hw_md2.c | 1 + src/hardware/hw_model.c | 138 ---------------- src/hardware/r_opengl/r_opengl.c | 267 ++++++++++++++++++++++++------- src/hardware/r_opengl/r_vbo.h | 52 ++++++ src/r_main.c | 1 - src/sdl/hwsym_sdl.c | 1 + src/sdl/i_video.c | 1 + src/v_video.c | 1 - src/w_wad.c | 4 +- 16 files changed, 276 insertions(+), 281 deletions(-) create mode 100644 src/hardware/r_opengl/r_vbo.h diff --git a/src/d_main.c b/src/d_main.c index 31781cba2..5352ce6e4 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -634,9 +634,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"); diff --git a/src/doomtype.h b/src/doomtype.h index 5d6434845..67491abb3 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -366,16 +366,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; diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 78fc31afc..d49531bdf 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -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' diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 767eac0b6..a1e4ad19a 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -224,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 diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index c1ece091a..e1d050cf8 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -59,6 +59,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development 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); @@ -94,6 +95,7 @@ struct hwdriver_s ClearMipMapCache pfnClearMipMapCache; SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility DrawModel pfnDrawModel; + CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; GetRenderVersion pfnGetRenderVersion; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index fc70492ca..2f5f6c488 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6783,11 +6783,6 @@ static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIE #endif } -void HWR_SetPaletteColor(INT32 palcolor) -{ - HWD.pfnSetSpecialState(HWD_SET_PALETTECOLOR, palcolor); -} - INT32 HWR_GetTextureUsed(void) { return HWD.pfnGetTextureUsed(); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index f74814f00..b8b3e3edc 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -59,7 +59,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); @@ -93,7 +92,6 @@ 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; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 33cd8b8a3..b70d0d6a3 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -926,6 +926,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (md2->model) { md2_printModelInfo(md2->model); + HWD.pfnCreateModelVBOs(md2->model); } else { diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 394b0f899..2c36f9744 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -49,117 +49,6 @@ void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle) 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 CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame) -{ - (void)mesh; - (void)frame; - return; -/* int bufferSize = sizeof(VBO::vbotiny_t)*mesh->numTriangles*3; - VBO::vbotiny_t *buffer = (VBO::vbotiny_t*)Z_Malloc(bufferSize, PU_STATIC, 0); - VBO::vbotiny_t *bufPtr = buffer; - - short *vertPtr = frame->vertices; - char *normPtr = frame->normals; - float *uvPtr = mesh->uvs; - char *tanPtr = frame->tangents; - - int i; - for (i = 0; i < mesh->numTriangles*3; i++) - { - bufPtr->x = *vertPtr++; - bufPtr->y = *vertPtr++; - bufPtr->z = *vertPtr++; - - bufPtr->nx = (*normPtr++) * 127; - bufPtr->ny = (*normPtr++) * 127; - bufPtr->nz = (*normPtr++) * 127; - - bufPtr->s0 = *uvPtr++; - bufPtr->t0 = *uvPtr++; - - if (tanPtr) - { - bufPtr->tanx = *tanPtr++; - bufPtr->tany = *tanPtr++; - bufPtr->tanz = *tanPtr++; - } - - bufPtr++; - } - - bglGenBuffers(1, &frame->vboID); - bglBindBuffer(BGL_ARRAY_BUFFER, frame->vboID); - bglBufferData(BGL_ARRAY_BUFFER, bufferSize, buffer, BGL_STATIC_DRAW); - Z_Free(buffer);*/ -} - -void CreateVBO(mesh_t *mesh, mdlframe_t *frame) -{ - (void)mesh; - (void)frame; - return; -/* int bufferSize = sizeof(VBO::vbo64_t)*mesh->numTriangles*3; - VBO::vbo64_t *buffer = (VBO::vbo64_t*)Z_Malloc(bufferSize, PU_STATIC, 0); - VBO::vbo64_t *bufPtr = buffer; - - float *vertPtr = frame->vertices; - float *normPtr = frame->normals; - float *tanPtr = frame->tangents; - float *uvPtr = mesh->uvs; - float *lightPtr = mesh->lightuvs; - char *colorPtr = frame->colors; - - int i; - for (i = 0; i < mesh->numTriangles*3; i++) - { - bufPtr->x = *vertPtr++; - bufPtr->y = *vertPtr++; - bufPtr->z = *vertPtr++; - - bufPtr->nx = *normPtr++; - bufPtr->ny = *normPtr++; - bufPtr->nz = *normPtr++; - - bufPtr->s0 = *uvPtr++; - bufPtr->t0 = *uvPtr++; - - if (tanPtr != NULL) - { - bufPtr->tan0 = *tanPtr++; - bufPtr->tan1 = *tanPtr++; - bufPtr->tan2 = *tanPtr++; - } - - if (lightPtr != NULL) - { - bufPtr->s1 = *lightPtr++; - bufPtr->t1 = *lightPtr++; - } - - if (colorPtr) - { - bufPtr->r = *colorPtr++; - bufPtr->g = *colorPtr++; - bufPtr->b = *colorPtr++; - bufPtr->a = *colorPtr++; - } - else - { - bufPtr->r = 255; - bufPtr->g = 255; - bufPtr->b = 255; - bufPtr->a = 255; - } - - bufPtr++; - } - - bglGenBuffers(1, &frame->vboID); - bglBindBuffer(BGL_ARRAY_BUFFER, frame->vboID); - bglBufferData(BGL_ARRAY_BUFFER, bufferSize, buffer, BGL_STATIC_DRAW); - Z_Free(buffer);*/ -} - void UnloadModel(model_t *model) { // Wouldn't it be great if C just had destructors? @@ -326,33 +215,6 @@ model_t *LoadModel(const char *filename, int ztag) material->shininess = 25.0f; } -// CONS_Printf("Generating VBOs for %s\n", filename); - for (i = 0; i < model->numMeshes; i++) - { - mesh_t *mesh = &model->meshes[i]; - - if (mesh->frames) - { - int j; - for (j = 0; j < model->meshes[i].numFrames; j++) - { - mdlframe_t *frame = &mesh->frames[j]; - frame->vboID = 0; - CreateVBO(mesh, frame); - } - } - else if (mesh->tinyframes) - { - int j; - for (j = 0; j < model->meshes[i].numFrames; j++) - { - tinyframe_t *frame = &mesh->tinyframes[j]; - frame->vboID = 0; - CreateVBOTiny(mesh, frame); - } - } - } - return model; } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index fc6c21f13..ce1491979 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -30,6 +30,7 @@ #include #include #include "r_opengl.h" +#include "r_vbo.h" #if defined (HWRENDER) && !defined (NOROPENGL) // for KOS: GL_TEXTURE_ENV, glAlphaFunc, glColorMask, glPolygonOffset, glReadPixels, GL_ALPHA_TEST, GL_POLYGON_OFFSET_FILL @@ -42,7 +43,7 @@ struct GLRGBAFloat GLfloat alpha; }; typedef struct GLRGBAFloat GLRGBAFloat; -static const float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +static const GLubyte white[4] = { 255, 255, 255, 255 }; // ========================================================================== // CONSTANTS @@ -227,6 +228,8 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglNormal3bv glNormal3bv #define pglColor4f glColor4f #define pglColor4fv glColor4fv +#define pglColor4ub glColor4ub +#define pglColor4ubv glColor4ubv #define pglTexCoord2f glTexCoord2f #define pglTexCoord2fv glTexCoord2fv #define pglVertexPointer glVertexPointer @@ -237,6 +240,10 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglEnableClientState glEnableClientState #define pglDisableClientState glDisableClientState #define pglClientActiveTexture glClientActiveTexture +#define pglGenBuffers glGenBuffers +#define pglBindBuffer glBindBuffer +#define pglBufferData glBufferData +#define pglDeleteBuffers glDeleteBuffers /* Lighting */ #define pglShadeModel glShadeModel @@ -346,6 +353,10 @@ typedef void (APIENTRY * PFNglColor4f) (GLfloat red, GLfloat green, GLfloat blue static PFNglColor4f pglColor4f; typedef void (APIENTRY * PFNglColor4fv) (const GLfloat *v); static PFNglColor4fv pglColor4fv; +typedef void (APIENTRY * PFNglColor4ub) (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +static PFNglColor4ub pglColor4ub; +typedef void (APIENTRY * PFNglColor4ubv) (const GLubyte *v); +static PFNglColor4ubv pglColor4ubv; typedef void (APIENTRY * PFNglTexCoord2f) (GLfloat s, GLfloat t); static PFNglTexCoord2f pglTexCoord2f; typedef void (APIENTRY * PFNglTexCoord2fv) (const GLfloat *v); @@ -364,6 +375,15 @@ typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); static PFNglEnableClientState pglEnableClientState; typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap); static PFNglDisableClientState pglDisableClientState; +typedef void (APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers); +static PFNglGenBuffers pglGenBuffers; +typedef void (APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer); +static PFNglBindBuffer pglBindBuffer; +typedef void (APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage); +static PFNglBufferData pglBufferData; +typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); +static PFNglDeleteBuffers pglDeleteBuffers; + /* Lighting */ typedef void (APIENTRY * PFNglShadeModel) (GLenum mode); @@ -492,6 +512,8 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglNormal3bv, glNormal3bv) GETOPENGLFUNC(pglColor4f , glColor4f) GETOPENGLFUNC(pglColor4fv , glColor4fv) + GETOPENGLFUNC(pglColor4ub, glColor4ub) + GETOPENGLFUNC(pglColor4ubv, glColor4ubv) GETOPENGLFUNC(pglTexCoord2f , glTexCoord2f) GETOPENGLFUNC(pglTexCoord2fv, glTexCoord2fv) GETOPENGLFUNC(pglVertexPointer, glVertexPointer) @@ -501,9 +523,6 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglDrawElements, glDrawElements) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) GETOPENGLFUNC(pglDisableClientState, glDisableClientState) - GETOPENGLFUNC(pglClientActiveTexture, glClientActiveTexture) - if (!pglClientActiveTexture) - GETOPENGLFUNC(pglClientActiveTexture, glClientActiveTextureARB) GETOPENGLFUNC(pglShadeModel , glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) @@ -542,6 +561,10 @@ boolean SetupGLFunc13(void) pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv"); + pglGenBuffers = GetGLFunc("glGenBuffers"); + pglBindBuffer = GetGLFunc("glBindBuffer"); + pglBufferData = GetGLFunc("glBufferData"); + pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); return true; } @@ -949,8 +972,6 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, F2DCoord * v2, RGBA_t Color) { - GLRGBAFloat c; - // DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); GLfloat p[12]; GLfloat dx, dy; @@ -961,11 +982,6 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, pglDisable(GL_TEXTURE_2D); - c.red = byte2float[Color.s.red]; - c.green = byte2float[Color.s.green]; - c.blue = byte2float[Color.s.blue]; - c.alpha = byte2float[Color.s.alpha]; - // This is the preferred, 'modern' way of rendering lines -- creating a polygon. if (fabsf(v2->x - v1->x) > FLT_EPSILON) angle = (float)atan((v2->y-v1->y)/(v2->x-v1->x)); @@ -980,7 +996,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, p[9] = v1->x + dx; p[10] = -(v1->y - dy); p[11] = 1; pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglColor4fv(&c.red); // is in RGBA float format + pglColor4ubv((GLbyte*)&Color); pglVertexPointer(3, GL_FLOAT, 0, p); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -1097,7 +1113,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) if (oglflags & GLF_NOTEXENV) { if (!(PolyFlags & PF_Modulated)) - pglColor4fv(white); + pglColor4ubv(white); } else #endif @@ -1378,7 +1394,6 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, { FUINT i; FUINT j; - GLRGBAFloat c = {0,0,0,0}; if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) PolyFlags &= ~(PF_NoDepthTest|PF_Corona); @@ -1387,24 +1402,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, // If Modulated, mix the surface colour to the texture if ((CurrentPolyFlags & PF_Modulated) && pSurf) - { - if (pal_col) - { // hack for non-palettized mode - c.red = (const_pal_col.red +byte2float[pSurf->FlatColor.s.red]) /2.0f; - c.green = (const_pal_col.green+byte2float[pSurf->FlatColor.s.green])/2.0f; - c.blue = (const_pal_col.blue +byte2float[pSurf->FlatColor.s.blue]) /2.0f; - c.alpha = byte2float[pSurf->FlatColor.s.alpha]; - } - else - { - c.red = byte2float[pSurf->FlatColor.s.red]; - c.green = byte2float[pSurf->FlatColor.s.green]; - c.blue = byte2float[pSurf->FlatColor.s.blue]; - c.alpha = byte2float[pSurf->FlatColor.s.alpha]; - } - - pglColor4fv(&c.red); // is in RGBA float format - } + pglColor4ubv(&pSurf->FlatColor.s); // this test is added for new coronas' code (without depth buffer) // I think I should do a separate function for drawing coronas, so it will be a little faster @@ -1451,8 +1449,15 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, if (scalef < 0.05f) return; - c.alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) - pglColor4fv(&c.red); + GLubyte c[4]; + c[0] = pSurf->FlatColor.s.red; + c[1] = pSurf->FlatColor.s.green; + c[2] = pSurf->FlatColor.s.blue; + + float alpha = byte2float[pSurf->FlatColor.s.alpha]; + alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) + c[3] = (unsigned char)(alpha * 255); + pglColor4ubv(c); } pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); @@ -1488,15 +1493,6 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } #endif - case HWD_SET_PALETTECOLOR: - { - pal_col = Value; - const_pal_col.blue = byte2float[((Value>>16)&0xff)]; - const_pal_col.green = byte2float[((Value>>8)&0xff)]; - const_pal_col.red = byte2float[((Value)&0xff)]; - break; - } - case HWD_SET_FOG_COLOR: { GLfloat fogcolor[4]; @@ -1538,13 +1534,6 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) pglDisable(GL_FOG); break; - case HWD_SET_POLYGON_SMOOTH: - if (Value) - pglEnable(GL_POLYGON_SMOOTH); - else - pglDisable(GL_POLYGON_SMOOTH); - break; - case HWD_SET_TEXTUREFILTERMODE: switch (Value) { @@ -1642,6 +1631,155 @@ static void AllocLerpTinyBuffer(size_t size) normTinyBuffer = malloc(lerpTinyBufferSize / 2); } +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif + +static void CreateModelVBO(mesh_t *mesh, mdlframe_t *frame) +{ + int bufferSize = sizeof(vbo64_t)*mesh->numTriangles * 3; + vbo64_t *buffer = (vbo64_t*)malloc(bufferSize); + vbo64_t *bufPtr = buffer; + + float *vertPtr = frame->vertices; + float *normPtr = frame->normals; + float *tanPtr = frame->tangents; + float *uvPtr = mesh->uvs; + float *lightPtr = mesh->lightuvs; + char *colorPtr = frame->colors; + + int i; + for (i = 0; i < mesh->numTriangles * 3; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr != NULL) + { + bufPtr->tan0 = *tanPtr++; + bufPtr->tan1 = *tanPtr++; + bufPtr->tan2 = *tanPtr++; + } + + if (lightPtr != NULL) + { + bufPtr->s1 = *lightPtr++; + bufPtr->t1 = *lightPtr++; + } + + if (colorPtr) + { + bufPtr->r = *colorPtr++; + bufPtr->g = *colorPtr++; + bufPtr->b = *colorPtr++; + bufPtr->a = *colorPtr++; + } + else + { + bufPtr->r = 255; + bufPtr->g = 255; + bufPtr->b = 255; + bufPtr->a = 255; + } + + bufPtr++; + } + + pglGenBuffers(1, &frame->vboID); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); + free(buffer); +} + +static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame) +{ + int bufferSize = sizeof(vbotiny_t)*mesh->numTriangles * 3; + vbotiny_t *buffer = (vbotiny_t*)malloc(bufferSize); + vbotiny_t *bufPtr = buffer; + + short *vertPtr = frame->vertices; + char *normPtr = frame->normals; + float *uvPtr = mesh->uvs; + char *tanPtr = frame->tangents; + + int i; + for (i = 0; i < mesh->numVertices; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr) + { + bufPtr->tanx = *tanPtr++; + bufPtr->tany = *tanPtr++; + bufPtr->tanz = *tanPtr++; + } + + bufPtr++; + } + + pglGenBuffers(1, &frame->vboID); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); + free(buffer); +} + +EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) +{ + int i; + for (i = 0; i < model->numMeshes; i++) + { + mesh_t *mesh = &model->meshes[i]; + + if (mesh->frames) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + if (frame->vboID) + pglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + CreateModelVBO(mesh, frame); + } + } + else if (mesh->tinyframes) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + tinyframe_t *frame = &mesh->tinyframes[j]; + if (frame->vboID) + pglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + CreateModelVBOTiny(mesh, frame); + } + } + } +} + +#define BUFFER_OFFSET(i) ((char*)NULL + (i)) + static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { GLfloat ambient[4]; @@ -1772,10 +1910,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || fpclassify(pol) == FP_ZERO) { - pglVertexPointer(3, GL_SHORT, 0, frame->vertices); - pglNormalPointer(GL_BYTE, 0, frame->normals); - pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(byte) * 6)); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); } else { @@ -1813,10 +1954,18 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || pol == 0.0f) { // Zoom! Take advantage of just shoving the entire arrays to the GPU. - pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); +/* pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); pglNormalPointer(GL_FLOAT, 0, frame->normals); pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); - pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);*/ + + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); + + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); } else { @@ -1968,7 +2117,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) // Draw a black square behind the screen texture, // so nothing shows through the edges - pglColor4fv(white); + pglColor4ubv(white); pglVertexPointer(3, GL_FLOAT, 0, blackBack); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -2140,7 +2289,7 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); pglBindTexture(GL_TEXTURE_2D, screentexture); - pglColor4fv(white); + pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); @@ -2205,7 +2354,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) // Draw the original screen pglBindTexture(GL_TEXTURE_2D, startScreenWipe); - pglColor4fv(white); + pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -2363,7 +2512,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) ClearBuffer(true, false, &clearColour); pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); - pglColor4fv(white); + pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, off); diff --git a/src/hardware/r_opengl/r_vbo.h b/src/hardware/r_opengl/r_vbo.h new file mode 100644 index 000000000..ca1a974da --- /dev/null +++ b/src/hardware/r_opengl/r_vbo.h @@ -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 diff --git a/src/r_main.c b/src/r_main.c index 12e3e03b7..a61324dce 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1543,7 +1543,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 diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 9f844c623..4e083b4c2 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -88,6 +88,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetSpecialState); GETFUNC(GetTextureUsed); GETFUNC(DrawModel); + GETFUNC(CreateModelVBOs); GETFUNC(SetTransform); GETFUNC(GetRenderVersion); GETFUNC(PostImgRedraw); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 11ad2be9a..1db1e27bd 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1547,6 +1547,7 @@ void I_StartupGraphics(void) HWD.pfnSetPalette = hwSym("SetPalette",NULL); HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); HWD.pfnDrawModel = hwSym("DrawModel",NULL); + HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); diff --git a/src/v_video.c b/src/v_video.c index 90411d4ea..dd06d04c1 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -60,7 +60,6 @@ static void CV_Gammaxxx_ONChange(void); static CV_PossibleValue_t grgamma_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; -consvar_t cv_voodoocompatibility = {"gr_voodoocompatibility", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/w_wad.c b/src/w_wad.c index 512320c2a..fb2b84b66 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1609,12 +1609,12 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) { char actualmd5text[2*MD5_LEN+1]; PrintMD5String(wadfiles[wadfilenum]->md5sum, actualmd5text); -#ifdef _DEBUG +/*#ifdef _DEBUG CONS_Printf #else I_Error #endif - (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); + (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);*/ } #endif } From 766fb9d8364700dd086b6d1f5ed5bf9cac321aec Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 00:47:43 -0500 Subject: [PATCH 050/382] Compile fixes -- specify GLubyte for pglColor4ubv --- src/hardware/r_opengl/r_opengl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index ce1491979..b75621713 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -67,8 +67,10 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; static GLuint NextTexAvail = FIRST_TEX_AVAIL; static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; +#if 0 static GLuint pal_col = 0; static FRGBAFloat const_pal_col; +#endif static FBITFIELD CurrentPolyFlags; static FTextureInfo* gr_cachetail = NULL; @@ -996,7 +998,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, p[9] = v1->x + dx; p[10] = -(v1->y - dy); p[11] = 1; pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglColor4ubv((GLbyte*)&Color); + pglColor4ubv((GLubyte*)&Color); pglVertexPointer(3, GL_FLOAT, 0, p); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -1402,7 +1404,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, // If Modulated, mix the surface colour to the texture if ((CurrentPolyFlags & PF_Modulated) && pSurf) - pglColor4ubv(&pSurf->FlatColor.s); + pglColor4ubv((GLubyte*)&pSurf->FlatColor.s); // this test is added for new coronas' code (without depth buffer) // I think I should do a separate function for drawing coronas, so it will be a little faster From 89cdc1cbc2bf9778bffb05aba992b9a9aa599d14 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 00:54:27 -0500 Subject: [PATCH 051/382] Buildbot fixes --- src/hardware/r_opengl/r_opengl.c | 10 +++++++--- src/hardware/r_opengl/r_opengl.h | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index b75621713..d24e4bc66 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1416,6 +1416,10 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, GLdouble px = 0.0f, py = 0.0f, pz = -1.0f; GLfloat scalef = 0.0f; + GLubyte c[4]; + + float alpha; + cx = (pOutVerts[0].x + pOutVerts[2].x) / 2.0f; // we should change the coronas' ... cy = (pOutVerts[0].y + pOutVerts[2].y) / 2.0f; // ... code so its only done once. cz = pOutVerts[0].z; @@ -1451,12 +1455,12 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, if (scalef < 0.05f) return; - GLubyte c[4]; + // GLubyte c[4]; c[0] = pSurf->FlatColor.s.red; c[1] = pSurf->FlatColor.s.green; c[2] = pSurf->FlatColor.s.blue; - float alpha = byte2float[pSurf->FlatColor.s.alpha]; + alpha = byte2float[pSurf->FlatColor.s.alpha]; alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) c[3] = (unsigned char)(alpha * 255); pglColor4ubv(c); @@ -1915,7 +1919,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); - pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(byte) * 6)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6)); pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); pglBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 8741a174f..ce834c12c 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -118,9 +118,11 @@ typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params); extern PFNglGetIntegerv pglGetIntegerv; typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name); extern PFNglGetString pglGetString; -typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); +#if 0 +typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c static PFNglEnableClientState pglEnableClientState; #endif +#endif // ========================================================================== // GLOBAL From d1b448f8d1013917ca9b9af581e0860b535b27fb Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 27 Dec 2018 14:58:07 -0500 Subject: [PATCH 052/382] Fix screen transitions --- src/hardware/r_opengl/r_opengl.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index d24e4bc66..0e7d7a8ce 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -998,7 +998,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, p[9] = v1->x + dx; p[10] = -(v1->y - dy); p[11] = 1; pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - pglColor4ubv((GLubyte*)&Color); + pglColor4ubv((GLubyte*)&Color.s); pglVertexPointer(3, GL_FLOAT, 0, p); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -2369,27 +2369,31 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) // Draw the end screen that fades in pglActiveTexture(GL_TEXTURE0); + pglEnable(GL_TEXTURE_2D); pglBindTexture(GL_TEXTURE_2D, endScreenWipe); pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); pglActiveTexture(GL_TEXTURE1); + pglEnable(GL_TEXTURE_2D); pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // const float defaultST[8] - pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglClientActiveTexture(GL_TEXTURE0); pglTexCoordPointer(2, GL_FLOAT, 0, fix); + pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglClientActiveTexture(GL_TEXTURE1); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); pglTexCoordPointer(2, GL_FLOAT, 0, defaultST); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - pglClientActiveTexture(GL_TEXTURE0); - pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglActiveTexture(GL_TEXTURE0); + pglClientActiveTexture(GL_TEXTURE0); tex_downloaded = endScreenWipe; } From f41951bfb130063c09802f21b6d1a677d247dff5 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 27 Dec 2018 15:23:33 -0500 Subject: [PATCH 053/382] Eliminate some old GL functions so we don't slide back into bad habits! --- src/hardware/hw_clip.c | 8 +- src/hardware/hw_drv.h | 2 +- src/hardware/hw_main.c | 2 +- src/hardware/r_opengl/ogl_win.c | 22 +---- src/hardware/r_opengl/r_opengl.c | 158 ++++++++----------------------- src/hardware/r_opengl/r_opengl.h | 5 - 6 files changed, 49 insertions(+), 148 deletions(-) diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index 6d120efe7..4bdc753ec 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -77,8 +77,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 @@ -380,8 +380,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); diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index e1d050cf8..54bd9e786 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -69,7 +69,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); 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); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 2f5f6c488..133e43c39 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6921,7 +6921,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) HWR_GetFadeMask(lumpnum); - HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing + HWD.pfnDoScreenWipe(); HWRWipeCounter += 0.05f; // increase opacity of end screen diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index eb9a31a7d..562afe998 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -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� de palette, il faut recharger toutes les textures + + // on a palette change, you have to reload all of the textures Flush(); } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 0e7d7a8ce..e17ee32f7 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -33,7 +33,6 @@ #include "r_vbo.h" #if defined (HWRENDER) && !defined (NOROPENGL) -// for KOS: GL_TEXTURE_ENV, glAlphaFunc, glColorMask, glPolygonOffset, glReadPixels, GL_ALPHA_TEST, GL_POLYGON_OFFSET_FILL struct GLRGBAFloat { @@ -91,16 +90,10 @@ static FTransform md2_transform; const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) -static GLdouble modelMatrix[16]; -static GLdouble projMatrix[16]; +static GLfloat modelMatrix[16]; +static GLfloat projMatrix[16]; static GLint viewport[4]; - -#ifdef USE_PALETTED_TEXTURE - PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL; - GLubyte palette_tex[256*3]; -#endif - // Yay for arbitrary numbers! NextTexAvail is buggy for some reason. // Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing // flush all of the stored textures, leaving them unavailable at times such as between levels @@ -192,12 +185,11 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglAlphaFunc glAlphaFunc #define pglBlendFunc glBlendFunc #define pglCullFace glCullFace -#define pglPolygonMode glPolygonMode #define pglPolygonOffset glPolygonOffset #define pglScissor glScissor #define pglEnable glEnable #define pglDisable glDisable -#define pglGetDoublev glGetDoublev +#define pglGetFloatv glGetFloatv //glGetIntegerv //glGetString #define pglHint glHint @@ -215,25 +207,12 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglPopMatrix glPopMatrix #define pglLoadIdentity glLoadIdentity #define pglMultMatrixf glMultMatrixf -#define pglMultMatrixd glMultMatrixd #define pglRotatef glRotatef #define pglScalef glScalef #define pglTranslatef glTranslatef /* Drawing Functions */ -#define pglBegin glBegin -#define pglEnd glEnd -#define pglVertex3f glVertex3f -#define pglVertex3fv glVertex3fv -#define pglVertex3sv glVertex3sv -#define pglNormal3f glNormal3f -#define pglNormal3bv glNormal3bv -#define pglColor4f glColor4f -#define pglColor4fv glColor4fv -#define pglColor4ub glColor4ub #define pglColor4ubv glColor4ubv -#define pglTexCoord2f glTexCoord2f -#define pglTexCoord2fv glTexCoord2fv #define pglVertexPointer glVertexPointer #define pglNormalPointer glNormalPointer #define pglTexCoordPointer glTexCoordPointer @@ -289,8 +268,6 @@ typedef void (APIENTRY * PFNglBlendFunc) (GLenum sfactor, GLenum dfactor); static PFNglBlendFunc pglBlendFunc; typedef void (APIENTRY * PFNglCullFace) (GLenum mode); static PFNglCullFace pglCullFace; -typedef void (APIENTRY * PFNglPolygonMode) (GLenum face, GLenum mode); -static PFNglPolygonMode pglPolygonMode; typedef void (APIENTRY * PFNglPolygonOffset) (GLfloat factor, GLfloat units); static PFNglPolygonOffset pglPolygonOffset; typedef void (APIENTRY * PFNglScissor) (GLint x, GLint y, GLsizei width, GLsizei height); @@ -299,8 +276,8 @@ typedef void (APIENTRY * PFNglEnable) (GLenum cap); static PFNglEnable pglEnable; typedef void (APIENTRY * PFNglDisable) (GLenum cap); static PFNglDisable pglDisable; -typedef void (APIENTRY * PFNglGetDoublev) (GLenum pname, GLdouble *params); -static PFNglGetDoublev pglGetDoublev; +typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); +static PFNglGetFloatv pglGetFloatv; //glGetIntegerv //glGetString @@ -327,8 +304,6 @@ typedef void (APIENTRY * PFNglLoadIdentity) (void); static PFNglLoadIdentity pglLoadIdentity; typedef void (APIENTRY * PFNglMultMatrixf) (const GLfloat *m); static PFNglMultMatrixf pglMultMatrixf; -typedef void (APIENTRY * PFNglMultMatrixd) (const GLdouble *m); -static PFNglMultMatrixd pglMultMatrixd; typedef void (APIENTRY * PFNglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); static PFNglRotatef pglRotatef; typedef void (APIENTRY * PFNglScalef) (GLfloat x, GLfloat y, GLfloat z); @@ -337,32 +312,8 @@ typedef void (APIENTRY * PFNglTranslatef) (GLfloat x, GLfloat y, GLfloat z); static PFNglTranslatef pglTranslatef; /* Drawing Functions */ -typedef void (APIENTRY * PFNglBegin) (GLenum mode); -static PFNglBegin pglBegin; -typedef void (APIENTRY * PFNglEnd) (void); -static PFNglEnd pglEnd; -typedef void (APIENTRY * PFNglVertex3f) (GLfloat x, GLfloat y, GLfloat z); -static PFNglVertex3f pglVertex3f; -typedef void (APIENTRY * PFNglVertex3fv)(const GLfloat *v); -static PFNglVertex3fv pglVertex3fv; -typedef void (APIENTRY * PFNglVertex3sv) (const GLshort *v); -static PFNglVertex3sv pglVertex3sv; -typedef void (APIENTRY * PFNglNormal3f) (GLfloat x, GLfloat y, GLfloat z); -static PFNglNormal3f pglNormal3f; -typedef void (APIENTRY * PFNglNormal3bv)(const GLbyte *v); -static PFNglNormal3bv pglNormal3bv; -typedef void (APIENTRY * PFNglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -static PFNglColor4f pglColor4f; -typedef void (APIENTRY * PFNglColor4fv) (const GLfloat *v); -static PFNglColor4fv pglColor4fv; -typedef void (APIENTRY * PFNglColor4ub) (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -static PFNglColor4ub pglColor4ub; typedef void (APIENTRY * PFNglColor4ubv) (const GLubyte *v); static PFNglColor4ubv pglColor4ubv; -typedef void (APIENTRY * PFNglTexCoord2f) (GLfloat s, GLfloat t); -static PFNglTexCoord2f pglTexCoord2f; -typedef void (APIENTRY * PFNglTexCoord2fv) (const GLfloat *v); -static PFNglTexCoord2fv pglTexCoord2fv; typedef void (APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); static PFNglVertexPointer pglVertexPointer; typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); @@ -475,19 +426,18 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglClearColor, glClearColor) - GETOPENGLFUNC(pglClear , glClear) - GETOPENGLFUNC(pglColorMask , glColorMask) - GETOPENGLFUNC(pglAlphaFunc , glAlphaFunc) - GETOPENGLFUNC(pglBlendFunc , glBlendFunc) - GETOPENGLFUNC(pglCullFace , glCullFace) - GETOPENGLFUNC(pglPolygonMode , glPolygonMode) - GETOPENGLFUNC(pglPolygonOffset , glPolygonOffset) - GETOPENGLFUNC(pglScissor , glScissor) - GETOPENGLFUNC(pglEnable , glEnable) - GETOPENGLFUNC(pglDisable , glDisable) - GETOPENGLFUNC(pglGetDoublev , glGetDoublev) - GETOPENGLFUNC(pglGetIntegerv , glGetIntegerv) - GETOPENGLFUNC(pglGetString , glGetString) + GETOPENGLFUNC(pglClear, glClear) + GETOPENGLFUNC(pglColorMask, glColorMask) + GETOPENGLFUNC(pglAlphaFunc, glAlphaFunc) + GETOPENGLFUNC(pglBlendFunc, glBlendFunc) + GETOPENGLFUNC(pglCullFace, glCullFace) + GETOPENGLFUNC(pglPolygonOffset, glPolygonOffset) + GETOPENGLFUNC(pglScissor, glScissor) + GETOPENGLFUNC(pglEnable, glEnable) + GETOPENGLFUNC(pglDisable, glDisable) + GETOPENGLFUNC(pglGetFloatv, glGetFloatv) + GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv) + GETOPENGLFUNC(pglGetString, glGetString) GETOPENGLFUNC(pglClearDepth , glClearDepth) GETOPENGLFUNC(pglDepthFunc , glDepthFunc) @@ -500,24 +450,11 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglPopMatrix , glPopMatrix) GETOPENGLFUNC(pglLoadIdentity , glLoadIdentity) GETOPENGLFUNC(pglMultMatrixf , glMultMatrixf) - GETOPENGLFUNC(pglMultMatrixd , glMultMatrixd) GETOPENGLFUNC(pglRotatef , glRotatef) GETOPENGLFUNC(pglScalef , glScalef) GETOPENGLFUNC(pglTranslatef , glTranslatef) - GETOPENGLFUNC(pglBegin , glBegin) - GETOPENGLFUNC(pglEnd , glEnd) - GETOPENGLFUNC(pglVertex3f , glVertex3f) - GETOPENGLFUNC(pglVertex3fv, glVertex3fv) - GETOPENGLFUNC(pglVertex3sv, glVertex3sv) - GETOPENGLFUNC(pglNormal3f , glNormal3f) - GETOPENGLFUNC(pglNormal3bv, glNormal3bv) - GETOPENGLFUNC(pglColor4f , glColor4f) - GETOPENGLFUNC(pglColor4fv , glColor4fv) - GETOPENGLFUNC(pglColor4ub, glColor4ub) GETOPENGLFUNC(pglColor4ubv, glColor4ubv) - GETOPENGLFUNC(pglTexCoord2f , glTexCoord2f) - GETOPENGLFUNC(pglTexCoord2fv, glTexCoord2fv) GETOPENGLFUNC(pglVertexPointer, glVertexPointer) GETOPENGLFUNC(pglNormalPointer, glNormalPointer) GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) @@ -584,39 +521,39 @@ static void SetNoTexture(void) } } -static void GLPerspective(GLdouble fovy, GLdouble aspect) +static void GLPerspective(GLfloat fovy, GLfloat aspect) { - GLdouble m[4][4] = + GLfloat m[4][4] = { { 1.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f,-1.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}, }; - const GLdouble zNear = NEAR_CLIPPING_PLANE; - const GLdouble zFar = FAR_CLIPPING_PLANE; - const GLdouble radians = (GLdouble)(fovy / 2.0f * M_PIl / 180.0f); - const GLdouble sine = sin(radians); - const GLdouble deltaZ = zFar - zNear; - GLdouble cotangent; + const GLfloat zNear = NEAR_CLIPPING_PLANE; + const GLfloat zFar = FAR_CLIPPING_PLANE; + const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); + const GLfloat sine = sinf(radians); + const GLfloat deltaZ = zFar - zNear; + GLfloat cotangent; if ((deltaZ == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) { return; } - cotangent = cos(radians) / sine; + cotangent = cosf(radians) / sine; m[0][0] = cotangent / aspect; m[1][1] = cotangent; m[2][2] = -(zFar + zNear) / deltaZ; m[3][2] = -2.0f * zNear * zFar / deltaZ; - pglMultMatrixd(&m[0][0]); + pglMultMatrixf(&m[0][0]); } -static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ, - GLdouble* winX, GLdouble* winY, GLdouble* winZ) +static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ, + GLfloat* winX, GLfloat* winY, GLfloat* winZ) { - GLdouble in[4], out[4]; + GLfloat in[4], out[4]; int i; for (i=0; i<4; i++) @@ -683,7 +620,7 @@ void SetModelView(GLint w, GLint h) // added for new coronas' code (without depth buffer) pglGetIntegerv(GL_VIEWPORT, viewport); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); } @@ -745,8 +682,6 @@ void SetStates(void) //pglEnable(GL_CULL_FACE); //pglCullFace(GL_FRONT); - //pglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - //pglPolygonMode(GL_FRONT, GL_LINE); //glFogi(GL_FOG_MODE, GL_EXP); //pglHint(GL_FOG_HINT, GL_FASTEST); @@ -762,7 +697,7 @@ void SetStates(void) // bp : when no t&l :) pglLoadIdentity(); pglScalef(1.0f, 1.0f, -1.0f); - pglGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) } @@ -928,7 +863,7 @@ EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, f // added for new coronas' code (without depth buffer) pglGetIntegerv(GL_VIEWPORT, viewport); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); } @@ -1190,17 +1125,6 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) w = pTexInfo->width; h = pTexInfo->height; -#ifdef USE_PALETTED_TEXTURE - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - // do nothing here. - // Not a problem with MiniGL since we don't use paletted texture - } - else -#endif - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) { @@ -1412,8 +1336,8 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, { //rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value GLfloat buf[8][8]; - GLdouble cx, cy, cz; - GLdouble px = 0.0f, py = 0.0f, pz = -1.0f; + GLfloat cx, cy, cz; + GLfloat px = 0.0f, py = 0.0f, pz = -1.0f; GLfloat scalef = 0.0f; GLubyte c[4]; @@ -2049,10 +1973,10 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglLoadIdentity(); special_splitscreen = (stransform->splitscreen == 1 && stransform->fovxangle == 90.0f); if (special_splitscreen) - GLPerspective(53.13l, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) + GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) else GLPerspective(stransform->fovxangle, ASPECT_RATIO); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) pglMatrixMode(GL_MODELVIEW); } else @@ -2062,15 +1986,15 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); if (special_splitscreen) - GLPerspective(53.13l, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) + GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) else //Hurdler: is "fov" correct? GLPerspective(fov, ASPECT_RATIO); - pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) pglMatrixMode(GL_MODELVIEW); } - pglGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) } EXPORT INT32 HWRAPI(GetTextureUsed) (void) @@ -2305,7 +2229,7 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) } // Do screen fades! -EXPORT void HWRAPI(DoScreenWipe)(float alpha) +EXPORT void HWRAPI(DoScreenWipe)() { INT32 texsize = 2048; float xfix, yfix; diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index ce834c12c..baf5c7b2a 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -71,7 +71,6 @@ extern FILE *gllogstream; #endif #ifndef DRIVER_STRING -// #define USE_PALETTED_TEXTURE #define DRIVER_STRING "HWRAPI Init(): SRB2Kart OpenGL renderer" // Tails #endif @@ -89,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 From 7f88e134920a9fd1f9da1d25dbe186d3ea88fe4e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 22:25:13 -0500 Subject: [PATCH 054/382] Compile fix -- remove (void)alpha from DoScreenWipe --- src/hardware/r_opengl/r_opengl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index e17ee32f7..4a26aa0eb 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2229,7 +2229,7 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) } // Do screen fades! -EXPORT void HWRAPI(DoScreenWipe)() +EXPORT void HWRAPI(DoScreenWipe)(void) { INT32 texsize = 2048; float xfix, yfix; @@ -2254,8 +2254,6 @@ EXPORT void HWRAPI(DoScreenWipe)() 1.0f, 1.0f }; - (void)alpha; - // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; From afb6bde0612e1321f9828aaa6380ce555d017c8d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 23:31:29 -0500 Subject: [PATCH 055/382] Un-dummy md5 checks --- src/w_wad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index fb2b84b66..512320c2a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1609,12 +1609,12 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) { char actualmd5text[2*MD5_LEN+1]; PrintMD5String(wadfiles[wadfilenum]->md5sum, actualmd5text); -/*#ifdef _DEBUG +#ifdef _DEBUG CONS_Printf #else I_Error #endif - (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);*/ + (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); } #endif } From 157cbe4b233f2892c7a56c34c3cda7ab085e2f9f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 3 Jan 2019 00:57:14 -0500 Subject: [PATCH 056/382] Fix blinking MD2 models MD2 models are forced to load float frames, so mesh->indices is never loaded, so glDrawElements can't be used. Use glDrawArrays instead. --- src/hardware/r_opengl/r_opengl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 4a26aa0eb..91c48ccdb 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1894,7 +1894,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); - pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + // No tinyframes, no mesh indices + //pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); pglBindBuffer(GL_ARRAY_BUFFER, 0); } else From b056842deb04c251e7cec96397d72f0e6511327d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 7 Jan 2019 04:38:17 -0500 Subject: [PATCH 057/382] Dummy out nextframe lerping (unused in Kart) --- src/hardware/hw_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index a1e4ad19a..b37850bb7 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -107,7 +107,7 @@ typedef struct #define USE_FTRANSFORM_MIRROR // Vanilla features -#define USE_MODEL_NEXTFRAME +//#define USE_MODEL_NEXTFRAME typedef struct { From 0c9be9fd4b6a83e23e67258c8ad74ae2a9d12973 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 7 Jan 2019 04:40:19 -0500 Subject: [PATCH 058/382] Add floating point epsilons --- src/doomdef.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/doomdef.h b/src/doomdef.h index a35f3291d..8b3bdee6d 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -453,6 +453,15 @@ INT32 I_GetKey(void); #define max(x, y) (((x) > (y)) ? (x) : (y)) #endif +// Floating point comparison epsilons from float.h +#ifndef FLT_EPSILON +#define FLT_EPSILON 1.1920928955078125e-7f +#endif + +#ifndef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 +#endif + // An assert-type mechanism. #ifdef PARANOIA #define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__)) From 8e862b3c98e9053d6cc6734a112ca23b5fd22bbe Mon Sep 17 00:00:00 2001 From: Digiku Date: Mon, 7 Jan 2019 16:50:59 -0500 Subject: [PATCH 059/382] Update f_finale.c - Small credits update --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index b177212c1..7708642e8 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -996,6 +996,7 @@ static const char *credits[] = { "Andrew \"orospakr\" Clunis", "Gregor \"Oogaland\" Dick", "Louis-Antoine \"LJSonic\" de Moulins", // for fixing 2.1's netcode (de Rochefort doesn't quite fit on the screen sorry lol) + "Victor \"Steel Titanium\" Fuentes", "Julio \"Chaos Zero 64\" Guir", "\"Jimita\"", "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog @@ -1006,7 +1007,6 @@ static const char *credits[] = { "Colin \"Sonict\" Pfaff", "Sean \"Sryder13\" Ryder", "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible - "\"Steel Titanium\"", "Ben \"Cue\" Woodford", // Git contributors with 5+ approved merges of substantive quality, // or contributors with at least one groundbreaking merge, may be named. From 22cf53b8ae72ef3d288386dc33d9c0e69c827ff1 Mon Sep 17 00:00:00 2001 From: Digiku Date: Tue, 8 Jan 2019 11:22:33 -0500 Subject: [PATCH 060/382] Update hw_md2.c -- player->frameangle fix --- src/hardware/hw_md2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index b70d0d6a3..fb5b201fa 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1043,7 +1043,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (sprframe->rotate) { - const fixed_t anglef = AngleFixed(spr->mobj->angle); + fixed_t anglef = AngleFixed(spr->mobj->angle); + if (spr->mobj->player) + anglef = AngleFixed(spr->mobj->player->frameangle); + else + anglef = AngleFixed(spr->mobj->angle); p.angley = FIXED_TO_FLOAT(anglef); } else From bfd6d83a3b004fdf86aeb8a45e59d72c8d752e9b Mon Sep 17 00:00:00 2001 From: Digiku Date: Tue, 8 Jan 2019 11:30:04 -0500 Subject: [PATCH 061/382] Update hw_md2.c -- Redundant AngleFixed operation when modifying anglef --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index fb5b201fa..74301a85a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1043,7 +1043,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (sprframe->rotate) { - fixed_t anglef = AngleFixed(spr->mobj->angle); + fixed_t anglef; if (spr->mobj->player) anglef = AngleFixed(spr->mobj->player->frameangle); else From 123b97c5ed2ce25bcb93cbca60e9e784b6e827d9 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 15 Jan 2019 14:29:43 -0500 Subject: [PATCH 062/382] Fix skins overflow --- src/r_things.c | 4 ++-- src/r_things.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 67a45a76e..0382596f1 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2306,7 +2306,7 @@ void R_DrawMasked(void) // ========================================================================== INT32 numskins = 0; -skin_t skins[MAXSKINS+1]; +skin_t skins[MAXSKINS]; // FIXTHIS: don't work because it must be inistilised before the config load //#define SKINVALUES #ifdef SKINVALUES @@ -2559,7 +2559,7 @@ void R_AddSkins(UINT16 wadnum) // advance by default lastlump = lump + 1; - if (numskins > MAXSKINS) + if (numskins >= MAXSKINS) { CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS); continue; // so we know how many skins couldn't be added diff --git a/src/r_things.h b/src/r_things.h index 6614e0aa4..2823c3894 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -180,7 +180,7 @@ typedef struct drawnode_s } drawnode_t; extern INT32 numskins; -extern skin_t skins[MAXSKINS + 1]; +extern skin_t skins[MAXSKINS]; void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 From bcdfe2eb14ee4d862a5d5088e4eb5f3744578d6b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Jan 2019 20:09:55 -0500 Subject: [PATCH 063/382] Update the SP menu stuff to use MAXSKINS Co-authoered-by: Steel Titanium (steeltitanium1@gmail.com> --- src/dehacked.c | 5 ++- src/m_menu.c | 119 ++++++++++++++++++++----------------------------- src/m_menu.h | 4 +- 3 files changed, 54 insertions(+), 74 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a726ecbc1..5161bf242 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -435,11 +435,12 @@ static void readAnimTex(MYFILE *f, INT32 num) static boolean findFreeSlot(INT32 *num) { // Send the character select entry to a free slot. - while (*num < 32 && PlayerMenu[*num].status != IT_DISABLED) + while (*num < MAXSKINS && PlayerMenu[*num].status != IT_DISABLED) *num = *num+1; + CONS_Printf("%d\n", *num); // No more free slots. :( - if (*num >= 32) + if (*num >= MAXSKINS) return false; // Found one! ^_^ diff --git a/src/m_menu.c b/src/m_menu.c index 266bc2516..c27689506 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -112,41 +112,8 @@ typedef enum const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 -description_t description[32] = -{ - {"\x82Sonic\x80 is the fastest of the three, but also the hardest to control. Beginners beware, but experts will find Sonic very powerful.\n\n\x82""Ability:\x80 Speed Thok\nDouble jump to zoom forward with a huge burst of speed.\n\n\x82Tip:\x80 Simply letting go of forward does not slow down in SRB2. To slow down, hold the opposite direction.", "", "sonic"}, - {"\x82Tails\x80 is the most mobile of the three, but has the slowest speed. Because of his mobility, he's well-\nsuited to beginners.\n\n\x82""Ability:\x80 Fly\nDouble jump to start flying for a limited time. Repetitively hit the jump button to ascend.\n\n\x82Tip:\x80 To quickly descend while flying, hit the spin button.", "", "tails"}, - {"\x82Knuckles\x80 is well-\nrounded and can destroy breakable walls simply by touching them, but he can't jump as high as the other two.\n\n\x82""Ability:\x80 Glide & Climb\nDouble jump to glide in the air as long as jump is held. Glide into a wall to climb it.\n\n\x82Tip:\x80 Press spin while climbing to jump off the wall; press jump instead to jump off\nand face away from\nthe wall.", "", "knuckles"}, - {"\x82Sonic & Tails\x80 team up to take on Dr. Eggman!\nControl Sonic while Tails desperately struggles to keep up.\n\nPlayer 2 can control Tails directly by setting the controls in the options menu.\nTails's directional controls are relative to Player 1's camera.\n\nTails can pick up Sonic while flying and carry him around.", "CHRS&T", "sonic&tails"}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""} -}; +description_t description[MAXSKINS]; + static char *char_notes = NULL; static fixed_t char_scroll = 0; @@ -842,41 +809,7 @@ static menuitem_t SP_LevelStatsMenu[] = // A rare case. // External files modify this menu, so we can't call it static. // And I'm too lazy to go through and rename it everywhere. ARRGH! -menuitem_t PlayerMenu[32] = -{ - {IT_CALL, NULL, NULL, M_ChoosePlayer, 0}, - {IT_CALL, NULL, NULL, M_ChoosePlayer, 0}, - {IT_CALL, NULL, NULL, M_ChoosePlayer, 0}, - {IT_CALL, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0} -}; +menuitem_t PlayerMenu[MAXSKINS]; // ----------------------------------- // Multiplayer and all of its submenus @@ -2809,6 +2742,8 @@ void M_Ticker(void) // void M_Init(void) { + UINT8 i; + CV_RegisterVar(&cv_nextmap); CV_RegisterVar(&cv_newgametype); CV_RegisterVar(&cv_chooseskin); @@ -2850,6 +2785,50 @@ void M_Init(void) quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n......right?\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG6] = M_GetText("Aww, is Egg Rock Zone too\ndifficult for you?\n\n(Press 'Y' to quit)"); + // Setup PlayerMenu table + for (i = 0; i < MAXSKINS; i++) + { + PlayerMenu[i].status = (i < 4 ? IT_CALL : IT_DISABLED); + PlayerMenu[i].patch = PlayerMenu[i].text = NULL; + PlayerMenu[i].itemaction = M_ChoosePlayer; + PlayerMenu[i].alphaKey = 0; + } + + // Setup description table + for (i = 0; i < MAXSKINS; i++) + { + if (i == 0) + { + strcpy(description[i].notes, "\x82Sonic\x80 is the fastest of the three, but also the hardest to control. Beginners beware, but experts will find Sonic very powerful.\n\n\x82""Ability:\x80 Speed Thok\nDouble jump to zoom forward with a huge burst of speed.\n\n\x82Tip:\x80 Simply letting go of forward does not slow down in SRB2. To slow down, hold the opposite direction."); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, "sonic"); + } + else if (i == 1) + { + strcpy(description[i].notes, "\x82Tails\x80 is the most mobile of the three, but has the slowest speed. Because of his mobility, he's well-\nsuited to beginners.\n\n\x82""Ability:\x80 Fly\nDouble jump to start flying for a limited time. Repetitively hit the jump button to ascend.\n\n\x82Tip:\x80 To quickly descend while flying, hit the spin button."); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, "tails"); + } + else if (i == 2) + { + strcpy(description[i].notes, "\x82Knuckles\x80 is well-\nrounded and can destroy breakable walls simply by touching them, but he can't jump as high as the other two.\n\n\x82""Ability:\x80 Glide & Climb\nDouble jump to glide in the air as long as jump is held. Glide into a wall to climb it.\n\n\x82Tip:\x80 Press spin while climbing to jump off the wall; press jump instead to jump off\nand face away from\nthe wall."); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, "knuckles"); + } + else if (i == 3) + { + strcpy(description[i].notes, "\x82Sonic & Tails\x80 team up to take on Dr. Eggman!\nControl Sonic while Tails desperately struggles to keep up.\n\nPlayer 2 can control Tails directly by setting the controls in the options menu.\nTails's directional controls are relative to Player 1's camera.\n\nTails can pick up Sonic while flying and carry him around."); + strcpy(description[i].picname, "CHRS&T"); + strcpy(description[i].skinname, "sonic&tails"); + } + else + { + strcpy(description[i].notes, "???"); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, ""); + } + } + #ifdef HWRENDER // Permanently hide some options based on render mode if (rendermode == render_soft) diff --git a/src/m_menu.h b/src/m_menu.h index eb770c194..7e2cce20d 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -151,7 +151,7 @@ typedef struct menuitem_s UINT8 alphaKey; } menuitem_t; -extern menuitem_t PlayerMenu[32]; +extern menuitem_t PlayerMenu[MAXSKINS]; typedef struct menu_s { @@ -206,7 +206,7 @@ typedef struct UINT8 netgame; } saveinfo_t; -extern description_t description[32]; +extern description_t description[MAXSKINS]; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; extern CV_PossibleValue_t gametype_cons_t[]; From 34920c29512a0d87e0defaeda18c6b596ce790b0 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 26 Jan 2019 23:16:49 -0500 Subject: [PATCH 064/382] Setup the tables even eariler. I really hate that PlayerMenu status hack, but that's really the only way I could think off to show the entires for Tails, Knuckles and the Sonic&Tails pair. --- src/d_main.c | 4 ++++ src/m_menu.c | 33 ++++++++++++++++++--------------- src/m_menu.h | 3 +++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index dd2cfe0e5..1782e94f5 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1130,6 +1130,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)) diff --git a/src/m_menu.c b/src/m_menu.c index c27689506..333cdaa70 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2742,8 +2742,6 @@ void M_Ticker(void) // void M_Init(void) { - UINT8 i; - CV_RegisterVar(&cv_nextmap); CV_RegisterVar(&cv_newgametype); CV_RegisterVar(&cv_chooseskin); @@ -2785,6 +2783,24 @@ void M_Init(void) quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n......right?\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG6] = M_GetText("Aww, is Egg Rock Zone too\ndifficult for you?\n\n(Press 'Y' to quit)"); +#ifdef HWRENDER + // Permanently hide some options based on render mode + if (rendermode == render_soft) + OP_VideoOptionsMenu[1].status = IT_DISABLED; +#endif + +#ifndef NONET + CV_RegisterVar(&cv_serversort); +#endif + + //todo put this somewhere better... + CV_RegisterVar(&cv_allcaps); +} + +void M_InitCharacterTables(void) +{ + UINT8 i; + // Setup PlayerMenu table for (i = 0; i < MAXSKINS; i++) { @@ -2828,19 +2844,6 @@ void M_Init(void) strcpy(description[i].skinname, ""); } } - -#ifdef HWRENDER - // Permanently hide some options based on render mode - if (rendermode == render_soft) - OP_VideoOptionsMenu[1].status = IT_DISABLED; -#endif - -#ifndef NONET - CV_RegisterVar(&cv_serversort); -#endif - - //todo put this somewhere better... - CV_RegisterVar(&cv_allcaps); } // ========================================================================== diff --git a/src/m_menu.h b/src/m_menu.h index 7e2cce20d..fcde5b7db 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -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); From 221ec15af09040d58238ede4091387ce46d51ca8 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 26 Jan 2019 23:22:30 -0500 Subject: [PATCH 065/382] How did I forget about this --- src/dehacked.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5161bf242..82d630a55 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -437,7 +437,6 @@ static boolean findFreeSlot(INT32 *num) // Send the character select entry to a free slot. while (*num < MAXSKINS && PlayerMenu[*num].status != IT_DISABLED) *num = *num+1; - CONS_Printf("%d\n", *num); // No more free slots. :( if (*num >= MAXSKINS) From b0792aed46659d8e55e1893275ca6cc5946b3504 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 14:33:38 -0600 Subject: [PATCH 066/382] Start with some strange multiplayer replay init stuff Mostly just disabling the parts of the replay that assume a single player, right now. # Conflicts: # src/g_game.c --- src/g_game.c | 131 ++++++++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 59 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d8022e089..ba926c57d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4481,6 +4481,7 @@ char *G_BuildMapTitle(INT32 mapnum) #define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares! #define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? #define DF_ATTACKSHIFT 1 +#define DF_MULTIPLAYER 0x80 // This demo contains a dynamic number of players! // For demos #define ZT_FWD 0x01 @@ -5442,7 +5443,7 @@ void G_BeginRecording(void) memset(name,0,sizeof(name)); demo_p = demobuffer; - demoflags = DF_GHOST|(modeattacking<>DF_ATTACKSHIFT; + multiplayer = !!(demoflags & DF_MULTIPLAYER); CON_ToggleOff(); hu_demotime = UINT32_MAX; @@ -5861,33 +5869,35 @@ void G_DoPlayDemo(char *defdemoname) // Random seed randseed = READUINT32(demo_p); - // Player name - M_Memcpy(player_names[0],demo_p,16); - demo_p += 16; + if (!multiplayer) { + // Player name + M_Memcpy(player_names[0],demo_p,16); + demo_p += 16; - // Skin - M_Memcpy(skin,demo_p,16); - demo_p += 16; + // Skin + M_Memcpy(skin,demo_p,16); + demo_p += 16; - // Color - M_Memcpy(color,demo_p,16); - demo_p += 16; + // Color + M_Memcpy(color,demo_p,16); + demo_p += 16; - charability = READUINT8(demo_p); - charability2 = READUINT8(demo_p); - actionspd = (fixed_t)READUINT8(demo_p)<color = players[0].skincolor; + oldghost.x = players[0].mo->x; + oldghost.y = players[0].mo->y; + oldghost.z = players[0].mo->z; } - //CV_StealthSetValue(&cv_playercolor, players[0].skincolor); -- as far as I can tell this is more trouble than it's worth - if (players[0].mo) - { - players[0].mo->color = players[0].skincolor; - oldghost.x = players[0].mo->x; - oldghost.y = players[0].mo->y; - oldghost.z = players[0].mo->z; - } - // Set saved attribute values - // No cheat checking here, because even if they ARE wrong... - // it would only break the replay if we clipped them. - players[0].charability = charability; - players[0].charability2 = charability2; - players[0].actionspd = actionspd; - players[0].mindash = mindash; - players[0].maxdash = maxdash; - // SRB2kart - players[0].kartspeed = kartspeed; - players[0].kartweight = kartweight; - // - players[0].normalspeed = normalspeed; - players[0].runspeed = runspeed; - players[0].thrustfactor = thrustfactor; - players[0].accelstart = accelstart; - players[0].acceleration = acceleration; - players[0].jumpfactor = jumpfactor; + // Set saved attribute values + // No cheat checking here, because even if they ARE wrong... + // it would only break the replay if we clipped them. + players[0].charability = charability; + players[0].charability2 = charability2; + players[0].actionspd = actionspd; + players[0].mindash = mindash; + players[0].maxdash = maxdash; + // SRB2kart + players[0].kartspeed = kartspeed; + players[0].kartweight = kartweight; + // + players[0].normalspeed = normalspeed; + players[0].runspeed = runspeed; + players[0].thrustfactor = thrustfactor; + players[0].accelstart = accelstart; + players[0].acceleration = acceleration; + players[0].jumpfactor = jumpfactor; + } demo_start = true; } From 7d881e7af1d196fb7e3038c3a91e06bb1fe8f0b9 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 01:26:14 -0600 Subject: [PATCH 067/382] Store initial player data in net replay --- src/g_game.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index ba926c57d..20e796923 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5434,7 +5434,7 @@ void G_RecordMetal(void) void G_BeginRecording(void) { - UINT8 i; + UINT8 i, p; char name[16]; player_t *player = &players[consoleplayer]; @@ -5481,8 +5481,41 @@ void G_BeginRecording(void) WRITEUINT32(demo_p,P_GetInitSeed()); if (demoflags & DF_MULTIPLAYER) { - // Net replays don't store player info here! Just skip to the netvars and return out. + // Netvars first :) CV_SaveNetVars(&demo_p); + + // Now store a SIMPLIFIED data struct for each in-game player + for (p = 0; p < MAXPLAYERS; p++) { + if (playeringame[p] && !players[p].spectator) { + player = players[p]; + + WRITEUINT8(demo_p, p); + + // Name + memset(name, 0, 16); + strncpy(name, player_names[p], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Skin + memset(name, 0, 16); + strncpy(name, skins[player->skin].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Color + memset(name, 0, 16); + strncpy(name, COLOR_ENUMS[player->skincolor], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Score, since Kart uses this to determine where you start on the map + WRITEUINT32(demo_p, player->score); + } + } + + WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing + return; } @@ -5738,7 +5771,7 @@ void G_DeferedPlayDemo(const char *name) #define SKIPERRORS void G_DoPlayDemo(char *defdemoname) { - UINT8 i; + UINT8 i, p; lumpnum_t l; char skin[17],color[17],*n,*pdemoname; UINT8 version,subversion,charability,charability2,kartspeed,kartweight,thrustfactor,accelstart,acceleration; @@ -5944,6 +5977,46 @@ void G_DoPlayDemo(char *defdemoname) memset(playeringame,0,sizeof(playeringame)); playeringame[0] = !multiplayer; + if (multiplayer) { + player_t *player; + + // Load players that were in-game when the map started + p = READUINT8(demo_p); + + while (p != 0xFF) + { + player = players[p]; + if (!playeringame[displayplayer]) + displayplayer = consoleplayer = p; + playeringame[p] = true; + + // Name + M_Memcpy(player_names[p],demo_p,16); + demo_p += 16; + + // Skin + M_Memcpy(skin,demo_p,16); + demo_p += 16; + SetPlayerSkin(p, skin); + + // Color + M_Memcpy(color,demo_p,16); + demo_p += 16; + for (i = 0; i < MAXSKINCOLORS; i++) + if (!stricmp(KartColor_Names[i],color)) // SRB2kart + { + players[p].skincolor = i; + break; + } + + // Score, since Kart uses this to determine where you start on the map + player->score = READUINT32(demo_p); + + // Look for the next player + p = READUINT8(demo_p); + } + } + P_SetRandSeed(randseed); G_InitNew(false, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. From 11837576a1d01ef6f2c5f730d1f2d161ad9c5163 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 01:26:43 -0600 Subject: [PATCH 068/382] I don't wanna deal with ghosts right now --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 20e796923..c0e10f23f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5443,7 +5443,7 @@ void G_BeginRecording(void) memset(name,0,sizeof(name)); demo_p = demobuffer; - demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking< Date: Sat, 12 Jan 2019 01:32:07 -0600 Subject: [PATCH 069/382] lol test net replay stuff --- src/d_netcmd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 41f88ab95..b9384eec5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2337,6 +2337,11 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) return; } + //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. + if (multiplayer) { + G_RecordDemo("net_replay_test"); + } + if (chmappending) chmappending--; From 61ba4ac1232be1c98438c36edcc11c72994e4c92 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:06:16 -0600 Subject: [PATCH 070/382] Fix compile errors --- src/g_game.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index c0e10f23f..09c0060bd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5487,7 +5487,7 @@ void G_BeginRecording(void) // Now store a SIMPLIFIED data struct for each in-game player for (p = 0; p < MAXPLAYERS; p++) { if (playeringame[p] && !players[p].spectator) { - player = players[p]; + player = &players[p]; WRITEUINT8(demo_p, p); @@ -5505,7 +5505,7 @@ void G_BeginRecording(void) // Color memset(name, 0, 16); - strncpy(name, COLOR_ENUMS[player->skincolor], 16); + strncpy(name, KartColor_Names[player->skincolor], 16); M_Memcpy(demo_p,name,16); demo_p += 16; @@ -5985,7 +5985,7 @@ void G_DoPlayDemo(char *defdemoname) while (p != 0xFF) { - player = players[p]; + player = &players[p]; if (!playeringame[displayplayer]) displayplayer = consoleplayer = p; playeringame[p] = true; From 2b47af32fb5694776278c11a648cdfd5b7c3d988 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:06:40 -0600 Subject: [PATCH 071/382] Record all players' ticcmds in multiplayer --- src/p_tick.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index b46b248bb..e1262a77a 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -599,9 +599,26 @@ void P_Ticker(boolean run) if (run) { if (demorecording) - G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); + { + if (!multiplayer) { + G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); + } else { + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && !players[i].spectator) + G_WriteDemoTiccmd(&players[i].cmd, i); + } + } if (demoplayback) + { + + if (!multiplayer) { G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); + } else { + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && !players[i].spectator) + G_ReadDemoTiccmd(&players[i].cmd, i); + } + } for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) From 5a6ad744b17646a1cb413e5a11a2d86546bd60a1 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:06:56 -0600 Subject: [PATCH 072/382] Separate oldtic for each player --- src/g_game.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 09c0060bd..abc5857b8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4492,7 +4492,7 @@ char *G_BuildMapTitle(INT32 mapnum) #define ZT_DRIFT 0x20 #define DEMOMARKER 0x80 // demoend -static ticcmd_t oldcmd; +static ticcmd_t oldcmd[MAXPLAYERS]; // For Metal Sonic and time attack ghosts #define GZT_XYZ 0x01 @@ -4556,26 +4556,25 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) { UINT8 ziptic; - (void)playernum; if (!demo_p || !demo_start) return; ziptic = READUINT8(demo_p); if (ziptic & ZT_FWD) - oldcmd.forwardmove = READSINT8(demo_p); + oldcmd[playernum].forwardmove = READSINT8(demo_p); if (ziptic & ZT_SIDE) - oldcmd.sidemove = READSINT8(demo_p); + oldcmd[playernum].sidemove = READSINT8(demo_p); if (ziptic & ZT_ANGLE) - oldcmd.angleturn = READINT16(demo_p); + oldcmd[playernum].angleturn = READINT16(demo_p); if (ziptic & ZT_BUTTONS) - oldcmd.buttons = (oldcmd.buttons & (BT_FORWARD|BT_BACKWARD)) | (READUINT16(demo_p) & ~(BT_FORWARD|BT_BACKWARD)); + oldcmd[playernum].buttons = (oldcmd[playernum].buttons & (BT_FORWARD|BT_BACKWARD)) | (READUINT16(demo_p) & ~(BT_FORWARD|BT_BACKWARD)); if (ziptic & ZT_AIMING) - oldcmd.aiming = READINT16(demo_p); + oldcmd[playernum].aiming = READINT16(demo_p); if (ziptic & ZT_DRIFT) - oldcmd.driftturn = READINT16(demo_p); + oldcmd[playernum].driftturn = READINT16(demo_p); - G_CopyTiccmd(cmd, &oldcmd, 1); + G_CopyTiccmd(cmd, &oldcmd[playernum], 1); // SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam if (((players[displayplayer].mo && players[displayplayer].speed > 0) // Moving @@ -4597,51 +4596,50 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) { char ziptic = 0; UINT8 *ziptic_p; - (void)playernum; if (!demo_p) return; ziptic_p = demo_p++; // the ziptic, written at the end of this function - if (cmd->forwardmove != oldcmd.forwardmove) + if (cmd->forwardmove != oldcmd[playernum].forwardmove) { WRITEUINT8(demo_p,cmd->forwardmove); - oldcmd.forwardmove = cmd->forwardmove; + oldcmd[playernum].forwardmove = cmd->forwardmove; ziptic |= ZT_FWD; } - if (cmd->sidemove != oldcmd.sidemove) + if (cmd->sidemove != oldcmd[playernum].sidemove) { WRITEUINT8(demo_p,cmd->sidemove); - oldcmd.sidemove = cmd->sidemove; + oldcmd[playernum].sidemove = cmd->sidemove; ziptic |= ZT_SIDE; } - if (cmd->angleturn != oldcmd.angleturn) + if (cmd->angleturn != oldcmd[playernum].angleturn) { WRITEINT16(demo_p,cmd->angleturn); - oldcmd.angleturn = cmd->angleturn; + oldcmd[playernum].angleturn = cmd->angleturn; ziptic |= ZT_ANGLE; } - if (cmd->buttons != oldcmd.buttons) + if (cmd->buttons != oldcmd[playernum].buttons) { WRITEUINT16(demo_p,cmd->buttons); - oldcmd.buttons = cmd->buttons; + oldcmd[playernum].buttons = cmd->buttons; ziptic |= ZT_BUTTONS; } - if (cmd->aiming != oldcmd.aiming) + if (cmd->aiming != oldcmd[playernum].aiming) { WRITEINT16(demo_p,cmd->aiming); - oldcmd.aiming = cmd->aiming; + oldcmd[playernum].aiming = cmd->aiming; ziptic |= ZT_AIMING; } - if (cmd->driftturn != oldcmd.driftturn) + if (cmd->driftturn != oldcmd[playernum].driftturn) { WRITEINT16(demo_p,cmd->driftturn); - oldcmd.driftturn = cmd->driftturn; + oldcmd[playernum].driftturn = cmd->driftturn; ziptic |= ZT_DRIFT; } From 2ec0673af9e24746fa1e6f57cb3688e5706f27da Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:48:18 -0600 Subject: [PATCH 073/382] Fix players spawning in the wrong spots when watching replays --- src/g_game.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index abc5857b8..2e8c5b481 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4364,7 +4364,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool players[i].marescore = 0; - if (resetplayer) // SRB2Kart + if (resetplayer && !(multiplayer && demoplayback)) // SRB2Kart { players[i].score = 0; } @@ -5983,7 +5983,6 @@ void G_DoPlayDemo(char *defdemoname) while (p != 0xFF) { - player = &players[p]; if (!playeringame[displayplayer]) displayplayer = consoleplayer = p; playeringame[p] = true; @@ -6008,7 +6007,7 @@ void G_DoPlayDemo(char *defdemoname) } // Score, since Kart uses this to determine where you start on the map - player->score = READUINT32(demo_p); + players[p].score = READUINT32(demo_p); // Look for the next player p = READUINT8(demo_p); From 28da2d2a8526569f19852fbb90ec590b7e798c0d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 15:09:58 -0600 Subject: [PATCH 074/382] Store cmd.latency in replays --- src/g_game.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 2e8c5b481..e548399b3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4490,6 +4490,7 @@ char *G_BuildMapTitle(INT32 mapnum) #define ZT_BUTTONS 0x08 #define ZT_AIMING 0x10 #define ZT_DRIFT 0x20 +#define ZT_LATENCY 0x40 #define DEMOMARKER 0x80 // demoend static ticcmd_t oldcmd[MAXPLAYERS]; @@ -4573,6 +4574,8 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) oldcmd[playernum].aiming = READINT16(demo_p); if (ziptic & ZT_DRIFT) oldcmd[playernum].driftturn = READINT16(demo_p); + if (ziptic & ZT_LATENCY) + oldcmd[playernum].latency = READUINT8(demo_p); G_CopyTiccmd(cmd, &oldcmd[playernum], 1); @@ -4643,6 +4646,13 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) ziptic |= ZT_DRIFT; } + if (cmd->latency != oldcmd[playernum].latency) + { + WRITEUINT8(demo_p,cmd->latency); + oldcmd[playernum].latency = cmd->latency; + ziptic |= ZT_LATENCY; + } + *ziptic_p = ziptic; // attention here for the ticcmd size! @@ -5017,6 +5027,8 @@ void G_GhostTicker(void) g->p += 2; if (ziptic & ZT_DRIFT) g->p += 2; + if (ziptic & ZT_LATENCY) + g->p += 1; // Grab ghost data. ziptic = READUINT8(g->p); @@ -5404,6 +5416,8 @@ void G_RecordDemo(const char *name) { INT32 maxsize; + CONS_Printf("Recording demo %s\n", name); + strcpy(demoname, name); strcat(demoname, ".lmp"); maxsize = 1024*1024; From 5b4b5ec302a437c66fa6cba756218115a6a463cf Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 15:45:08 -0600 Subject: [PATCH 075/382] Move where multiplayer replays are started This particularly allows a server to record the first map after startup as a replay. Players joining mid-map can no longer record replays tho --- src/d_netcmd.c | 5 ----- src/p_setup.c | 7 ++++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b9384eec5..41f88ab95 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2337,11 +2337,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) return; } - //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. - if (multiplayer) { - G_RecordDemo("net_replay_test"); - } - if (chmappending) chmappending--; diff --git a/src/p_setup.c b/src/p_setup.c index 49b22184e..764ad211a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3156,6 +3156,11 @@ boolean P_SetupLevel(boolean skipprecip) ? cv_basenumlaps.value : mapheaderinfo[gamemap - 1]->numlaps); + //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. + if (!demoplayback && multiplayer) { + G_RecordDemo("net_replay_test"); + } + // =========== // landing point for netgames. netgameskip: @@ -3435,7 +3440,7 @@ boolean P_AddWadFile(const char *wadfilename) // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] - // + // // edit music defs // S_LoadMusicDefs(wadnum); From d9f134570174a8e60e3a35f7e5238afb4bc44048 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 15:45:42 -0600 Subject: [PATCH 076/382] [HACK] Save correct lap count on netreplays --- src/command.c | 16 +++++++++++++--- src/command.h | 2 +- src/d_clisrv.c | 2 +- src/g_game.c | 4 ++-- src/p_saveg.c | 2 +- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/command.c b/src/command.c index bb2ea86e6..164b0988d 100644 --- a/src/command.c +++ b/src/command.c @@ -1355,7 +1355,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) Setvalue(cvar, svalue, stealth); } -void CV_SaveNetVars(UINT8 **p) +void CV_SaveNetVars(UINT8 **p, boolean demorecording) { consvar_t *cvar; UINT8 *count_p = *p; @@ -1365,10 +1365,20 @@ 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)) || (demorecording && cvar->netid == cv_numlaps.netid)) { WRITEUINT16(*p, cvar->netid); - WRITESTRING(*p, cvar->string); + + // UGLY HACK: Save proper lap count in net replays + if (demorecording && cvar->netid == cv_numlaps.netid) + { + WRITESTRING(*p, cv_basenumlaps.string); + } + else + { + WRITESTRING(*p, cvar->string); + } + WRITEUINT8(*p, false); ++count; } diff --git a/src/command.h b/src/command.h index 82dfaf8aa..70bf74a93 100644 --- a/src/command.h +++ b/src/command.h @@ -160,7 +160,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 demorecording); void CV_LoadNetVars(UINT8 **p); // reset cheat netvars after cheats is deactivated diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c84faa721..5369ff2cf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1500,7 +1500,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); diff --git a/src/g_game.c b/src/g_game.c index e548399b3..d429ccd8d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5494,7 +5494,7 @@ void G_BeginRecording(void) if (demoflags & DF_MULTIPLAYER) { // Netvars first :) - CV_SaveNetVars(&demo_p); + CV_SaveNetVars(&demo_p, true); // Now store a SIMPLIFIED data struct for each in-game player for (p = 0; p < MAXPLAYERS; p++) { @@ -5576,7 +5576,7 @@ void G_BeginRecording(void) WRITEFIXED(demo_p, player->jumpfactor); // Save netvar data (SONICCD, etc) - CV_SaveNetVars(&demo_p); + CV_SaveNetVars(&demo_p, false); //@TODO can this be true? it's not necessary for now but would be nice for consistency memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); diff --git a/src/p_saveg.c b/src/p_saveg.c index 975a4a5d2..52a35c37c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3447,7 +3447,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 From 30649b05746ddc3cab0d785759b15fceff8b09dc Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 16:23:34 -0600 Subject: [PATCH 077/382] broken spectator stuff? --- src/g_game.c | 16 +++++++++++++--- src/p_tick.c | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d429ccd8d..da21d269d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4483,6 +4483,8 @@ char *G_BuildMapTitle(INT32 mapnum) #define DF_ATTACKSHIFT 1 #define DF_MULTIPLAYER 0x80 // This demo contains a dynamic number of players! +#define DEMO_SPECTATOR 0x40 + // For demos #define ZT_FWD 0x01 #define ZT_SIDE 0x02 @@ -5498,10 +5500,10 @@ void G_BeginRecording(void) // Now store a SIMPLIFIED data struct for each in-game player for (p = 0; p < MAXPLAYERS; p++) { - if (playeringame[p] && !players[p].spectator) { + if (playeringame[p]) { player = &players[p]; - WRITEUINT8(demo_p, p); + WRITEUINT8(demo_p, p | (player->spectator ? DEMO_SPECTATOR : 0)); // Name memset(name, 0, 16); @@ -5991,15 +5993,23 @@ void G_DoPlayDemo(char *defdemoname) if (multiplayer) { player_t *player; + boolean spectator; // Load players that were in-game when the map started p = READUINT8(demo_p); while (p != 0xFF) { - if (!playeringame[displayplayer]) + spectator = false; + if (p & DEMO_SPECTATOR) { + spectator = true; + p &= ~DEMO_SPECTATOR; + } + + if (!playeringame[displayplayer] || players[displayplayer].spectator) displayplayer = consoleplayer = p; playeringame[p] = true; + players[p].spectator = spectator; // Name M_Memcpy(player_names[p],demo_p,16); diff --git a/src/p_tick.c b/src/p_tick.c index e1262a77a..8814d4406 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -604,7 +604,7 @@ void P_Ticker(boolean run) G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); } else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !players[i].spectator) + if (playeringame[i]) G_WriteDemoTiccmd(&players[i].cmd, i); } } @@ -615,7 +615,7 @@ void P_Ticker(boolean run) G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); } else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !players[i].spectator) + if (playeringame[i]) G_ReadDemoTiccmd(&players[i].cmd, i); } } From cc5bcd16768bbcf3e38218d88d4a728a61fb7bb5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 17:09:25 -0600 Subject: [PATCH 078/382] Reset oldcmd when recording netreplays --- src/g_game.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index da21d269d..2866624d3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5530,6 +5530,11 @@ void G_BeginRecording(void) WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing + memset(&oldcmd,0,sizeof(oldcmd)); + // Lower two lines aren't useful until ghost replays for mp are implemented, but eh + memset(&oldghost,0,sizeof(oldghost)); + memset(&ghostext,0,sizeof(ghostext)); + return; } From 08582fa7cc7c6b86a9b90063e98b5f6e99cc42f5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 17:48:39 -0600 Subject: [PATCH 079/382] Fix spectators spawning as players in netreplays --- src/p_mobj.c | 3 ++- src/p_tick.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f71ff2092..3eae4cae0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10889,7 +10889,8 @@ void P_SpawnPlayer(INT32 playernum) } // spawn as spectator determination - if (!G_GametypeHasSpectators()) + if (multiplayer && demoplayback); // 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) { diff --git a/src/p_tick.c b/src/p_tick.c index 8814d4406..471b38ecf 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -612,7 +612,7 @@ void P_Ticker(boolean run) { if (!multiplayer) { - G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); + G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); } else { for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) From c944a524d1e4a9f17e22737e9dc3385c40b5147e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 17:58:13 -0600 Subject: [PATCH 080/382] Fix invalid numlaps value being written when set to map default --- src/command.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 164b0988d..50692c67d 100644 --- a/src/command.c +++ b/src/command.c @@ -1372,7 +1372,19 @@ void CV_SaveNetVars(UINT8 **p, boolean demorecording) // UGLY HACK: Save proper lap count in net replays if (demorecording && cvar->netid == cv_numlaps.netid) { - WRITESTRING(*p, cv_basenumlaps.string); + 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 { From 4116c111525701bb9c2f7c301d7ed17be291ce70 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:07:30 -0600 Subject: [PATCH 081/382] Write skin/color/name changes to replay --- src/d_netcmd.c | 2 + src/g_game.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ src/g_game.h | 13 ++++++ src/p_tick.c | 2 + src/r_things.c | 3 ++ 5 files changed, 135 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 41f88ab95..d6cf49047 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1146,6 +1146,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 @@ -1749,6 +1750,7 @@ 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] diff --git a/src/g_game.c b/src/g_game.c index 2866624d3..ced20e5b2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4495,6 +4495,7 @@ char *G_BuildMapTitle(INT32 mapnum) #define ZT_LATENCY 0x40 #define DEMOMARKER 0x80 // demoend +UINT8 demo_extradata[MAXPLAYERS]; static ticcmd_t oldcmd[MAXPLAYERS]; // For Metal Sonic and time attack ghosts @@ -4556,6 +4557,119 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) return dest; } +void G_ReadDemoExtraData(void) +{ + INT32 p, extradata, i; + char name[17]; + + memset(name, '\0', 17); + + p = READUINT8(demo_p); + + while (p != 0xFF) + { + extradata = READUINT8(demo_p); + + if (extradata & DXD_RESPAWN) + { + if (players[p].mo) + P_DamageMobj(players[p].mo, NULL, NULL, 10000); // Is this how this should work..? + } + if (extradata & DXD_SKIN) + { + CONS_Printf("change skin\n"); + // Skin + M_Memcpy(name, demo_p, 16); + demo_p += 16; + SetPlayerSkin(p, name); + } + if (extradata & DXD_COLOR) + { + CONS_Printf("change color\n"); + // Color + M_Memcpy(name, demo_p, 16); + demo_p += 16; + for (i = 0; i < MAXSKINCOLORS; i++) + if (!stricmp(KartColor_Names[i], name)) // SRB2kart + { + players[p].skincolor = i; + if (players[p].mo) + players[p].mo->color = i; + break; + } + } + if (extradata & DXD_NAME) + { + // Name + M_Memcpy(player_names[p],demo_p,16); + demo_p += 16; + } + if (extradata & DXD_PLAYSTATE) + { + extradata = READUINT8(demo_p); + + // @TODO uhhhhh do something here + } + + + p = READUINT8(demo_p); + } +} + +void G_WriteDemoExtraData(void) +{ + INT32 i; + char name[16]; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (demo_extradata[i]) + { + WRITEUINT8(demo_p, i); + WRITEUINT8(demo_p, demo_extradata[i]); + + //if (demo_extradata[i] & DXD_RESPAWN) has no extra data + if (demo_extradata[i] & DXD_SKIN) + { + // Skin + memset(name, 0, 16); + strncpy(name, skins[players[i].skin].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + } + if (demo_extradata[i] & DXD_COLOR) + { + // Color + memset(name, 0, 16); + strncpy(name, KartColor_Names[players[i].skincolor], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + } + if (demo_extradata[i] & DXD_NAME) + { + // Name + memset(name, 0, 16); + strncpy(name, player_names[i], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + } + if (demo_extradata[i] & DXD_PLAYSTATE) + { + if (!playeringame[i]) + WRITEUINT8(demo_p, DXD_PST_LEFT); + else if (players[i].spectator) + WRITEUINT8(demo_p, DXD_PST_SPECTATING); + else + WRITEUINT8(demo_p, DXD_PST_PLAYING); + } + } + + demo_extradata[i] = 0; + } + + WRITEUINT8(demo_p, 0xFF); +} + void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) { UINT8 ziptic; @@ -5531,6 +5645,7 @@ void G_BeginRecording(void) WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing memset(&oldcmd,0,sizeof(oldcmd)); + memset(&demo_extradata, 0, sizeof(demo_extradata)); // Lower two lines aren't useful until ghost replays for mp are implemented, but eh memset(&oldghost,0,sizeof(oldghost)); memset(&ghostext,0,sizeof(ghostext)); diff --git a/src/g_game.h b/src/g_game.h index 6d11a4a02..f97aecd1c 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -154,7 +154,20 @@ typedef enum GHC_INVINCIBLE } ghostcolor_t; +extern UINT8 demo_extradata[MAXPLAYERS]; +#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); diff --git a/src/p_tick.c b/src/p_tick.c index 471b38ecf..4f8829589 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -606,6 +606,7 @@ void P_Ticker(boolean run) for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) G_WriteDemoTiccmd(&players[i].cmd, i); + G_WriteDemoExtraData(); } } if (demoplayback) @@ -617,6 +618,7 @@ void P_Ticker(boolean run) for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) G_ReadDemoTiccmd(&players[i].cmd, i); + G_ReadDemoExtraData(); } } diff --git a/src/r_things.c b/src/r_things.c index d6234d4b3..0f3bf3a83 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2713,6 +2713,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) P_SetScale(player->mo, player->mo->scale); + + demo_extradata[playernum] |= DXD_SKIN; + return; } From f1048d2b5a4ed76bff1eda6c24ad2e82a893b4df Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:09:29 -0600 Subject: [PATCH 082/382] Fix crashing at the end of netreplays --- src/g_game.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index ced20e5b2..40475c024 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4614,6 +4614,13 @@ void G_ReadDemoExtraData(void) p = READUINT8(demo_p); } + + if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus(); + return; + } } void G_WriteDemoExtraData(void) From 5f0fc3f6816ed1fedf615fd10351233fa39c6b75 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:10:25 -0600 Subject: [PATCH 083/382] Write extra data before cmds This will probably nip a possible issue with player cmds getting read/wrote inconsistently if a player joins or leaves. --- src/p_tick.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index 4f8829589..8b99c5aa6 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -603,10 +603,10 @@ void P_Ticker(boolean run) if (!multiplayer) { G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); } else { + G_WriteDemoExtraData(); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) G_WriteDemoTiccmd(&players[i].cmd, i); - G_WriteDemoExtraData(); } } if (demoplayback) @@ -615,10 +615,10 @@ void P_Ticker(boolean run) if (!multiplayer) { G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); } else { + G_ReadDemoExtraData(); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) G_ReadDemoTiccmd(&players[i].cmd, i); - G_ReadDemoExtraData(); } } From 63dd29564ec477f141071bed89cac594bb7cc21c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:30:20 -0600 Subject: [PATCH 084/382] Write respawn command usage to replays --- src/d_netcmd.c | 1 + src/g_game.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d6cf49047..982b75d4c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2536,6 +2536,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. diff --git a/src/g_game.c b/src/g_game.c index 40475c024..1f43faa35 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4577,7 +4577,6 @@ void G_ReadDemoExtraData(void) } if (extradata & DXD_SKIN) { - CONS_Printf("change skin\n"); // Skin M_Memcpy(name, demo_p, 16); demo_p += 16; @@ -4585,7 +4584,6 @@ void G_ReadDemoExtraData(void) } if (extradata & DXD_COLOR) { - CONS_Printf("change color\n"); // Color M_Memcpy(name, demo_p, 16); demo_p += 16; From 8473194e8a21c5f3eaffd702fe9956be9d8d46e8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 20:36:13 -0600 Subject: [PATCH 085/382] Fix replay viewer discarding aim keys --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 1f43faa35..a082abe15 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4690,7 +4690,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) if (ziptic & ZT_ANGLE) oldcmd[playernum].angleturn = READINT16(demo_p); if (ziptic & ZT_BUTTONS) - oldcmd[playernum].buttons = (oldcmd[playernum].buttons & (BT_FORWARD|BT_BACKWARD)) | (READUINT16(demo_p) & ~(BT_FORWARD|BT_BACKWARD)); + oldcmd[playernum].buttons = READUINT16(demo_p); if (ziptic & ZT_AIMING) oldcmd[playernum].aiming = READINT16(demo_p); if (ziptic & ZT_DRIFT) From 8837fac7609f707652fffa682af0e67c41426083 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 31 Jan 2019 00:00:28 -0600 Subject: [PATCH 086/382] 4p split views test --- src/g_game.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index a082abe15..556462121 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6133,6 +6133,19 @@ void G_DoPlayDemo(char *defdemoname) if (!playeringame[displayplayer] || players[displayplayer].spectator) displayplayer = consoleplayer = p; + else if (!spectator && splitscreen < 3) { + if (splitscreen == 0) { + splitscreen = 1; + secondarydisplayplayer = p; + } else if (splitscreen == 1) { + splitscreen = 2; + thirddisplayplayer = p; + } else { + splitscreen = 3; + fourthdisplayplayer = p; + R_ExecuteSetViewSize(); + } + } playeringame[p] = true; players[p].spectator = spectator; From e1c2bc0fa939198c8311159b9657f5f11d6d796e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 31 Jan 2019 23:03:44 -0600 Subject: [PATCH 087/382] Fix replay split breaking with less than four viewpoints --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 556462121..ab4a6b8e6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6143,7 +6143,6 @@ void G_DoPlayDemo(char *defdemoname) } else { splitscreen = 3; fourthdisplayplayer = p; - R_ExecuteSetViewSize(); } } playeringame[p] = true; @@ -6174,6 +6173,7 @@ void G_DoPlayDemo(char *defdemoname) // Look for the next player p = READUINT8(demo_p); } + R_ExecuteSetViewSize(); } P_SetRandSeed(randseed); From e3e72988d407ed1c7709396192ffe98fec1c8833 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 00:44:35 -0600 Subject: [PATCH 088/382] Make joins/quits/enters/spectates sync in replays I'm not 100% sure on joins. That P_RandomByte() call looks ugly. It'll probably be a source of trouble. --- src/d_clisrv.c | 4 +++- src/d_clisrv.h | 1 + src/d_netcmd.c | 2 ++ src/g_game.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5369ff2cf..3c8865d6f 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2479,13 +2479,15 @@ 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; + demo_extradata[playernum] |= DXD_PLAYSTATE; + if (server && !demoplayback) { INT32 node = playernode[playernum]; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 39cb8c4de..e59e44195 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -549,6 +549,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); // Is there a game running boolean Playing(void); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 982b75d4c..7b3925e92 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3362,6 +3362,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) { diff --git a/src/g_game.c b/src/g_game.c index ab4a6b8e6..25a70b3e1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -14,6 +14,7 @@ #include "doomdef.h" #include "console.h" #include "d_main.h" +#include "d_clisrv.h" #include "d_player.h" #include "f_finale.h" #include "p_setup.h" @@ -3032,6 +3033,8 @@ void G_AddPlayer(INT32 playernum) p->jointime = 0; p->playerstate = PST_REBORN; + + demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN; // Set everything } void G_ExitLevel(void) @@ -3118,7 +3121,7 @@ boolean G_GametypeHasSpectators(void) #if 0 return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); #else - return (netgame); //true + return (netgame || (multiplayer && demoplayback)); //true #endif } @@ -4607,6 +4610,43 @@ void G_ReadDemoExtraData(void) extradata = READUINT8(demo_p); // @TODO uhhhhh do something here + + switch (extradata) { + case DXD_PST_PLAYING: + players[p].pflags |= PF_WANTSTOJOIN; // fuck you + break; + + case DXD_PST_SPECTATING: + if (!playeringame[p]) + { + CL_ClearPlayer(p); + playeringame[p] = true; + G_AddPlayer(p); + players[p].spectator = true; + P_RandomByte(); // I'm pretty sure this ISN'T right, but it syncs my one test replay. + } + else + { + players[p].spectator = true; + if (players[p].mo) + P_DamageMobj(players[p].mo, NULL, NULL, 10000); + else + players[p].playerstate = PST_REBORN; + } + break; + + case DXD_PST_LEFT: + CL_RemovePlayer(p, 0); + break; + } + + // maybe these are necessary? + if (G_BattleGametype()) + K_CheckBumpers(); // SRB2Kart + else if (G_RaceGametype()) + P_CheckRacers(); // also SRB2Kart + + CONS_Printf("Change state @ %d\n", leveltime); } @@ -4662,7 +4702,10 @@ void G_WriteDemoExtraData(void) { if (!playeringame[i]) WRITEUINT8(demo_p, DXD_PST_LEFT); - else if (players[i].spectator) + else if ( + players[i].spectator && + !(players[i].pflags & PF_WANTSTOJOIN) // <= fuck you specifically + ) WRITEUINT8(demo_p, DXD_PST_SPECTATING); else WRITEUINT8(demo_p, DXD_PST_PLAYING); @@ -6173,6 +6216,7 @@ void G_DoPlayDemo(char *defdemoname) // Look for the next player p = READUINT8(demo_p); } + R_ExecuteSetViewSize(); } From 37b500a75d23c89a6c8f881ceed34b18e57e6a83 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 01:01:14 -0600 Subject: [PATCH 089/382] Tack on a timestamp to replay filenames --- src/p_setup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 764ad211a..3b5659c87 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3158,7 +3158,10 @@ boolean P_SetupLevel(boolean skipprecip) //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. if (!demoplayback && multiplayer) { - G_RecordDemo("net_replay_test"); +#include "time.h" + static char buf[256]; + sprintf(buf, "net_replay_test_%d", time(NULL)); + G_RecordDemo(buf); } // =========== From ff8e14b9974e738d75047699760b7d99418c35c4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 01:32:35 -0600 Subject: [PATCH 090/382] wip replay viewpoint stuff heck im tired zzz good night --- src/g_game.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 25a70b3e1..9125a1317 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1227,6 +1227,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) static boolean keyboard_look, keyboard_look2, keyboard_look3, keyboard_look4; // true if lookup/down using keyboard static boolean resetdown, resetdown2, resetdown3, resetdown4; // don't cam reset every frame + if (demoplayback) return; + switch (ssplayer) { case 2: @@ -1802,7 +1804,7 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL && ev->type == ev_keydown && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) { - if (splitscreen || !netgame) + if (!demoplayback && (splitscreen || !netgame)) displayplayer = consoleplayer; else { @@ -1813,9 +1815,12 @@ boolean G_Responder(event_t *ev) if (displayplayer == MAXPLAYERS) displayplayer = 0; - if (displayplayer == consoleplayer) + if (!demoplayback && displayplayer == consoleplayer) break; // End loop + if (displayplayer == secondarydisplayplayer || displayplayer == thirddisplayplayer || displayplayer == fourthdisplayplayer) + continue; + if (!playeringame[displayplayer]) continue; @@ -1874,7 +1879,7 @@ boolean G_Responder(event_t *ev) // any other key pops up menu if in demos if (gameaction == ga_nothing && !singledemo && - ((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN)) + ((demoplayback && !modeattacking && !titledemo && !multiplayer) || gamestate == GS_TITLESCREEN)) { if (ev->type == ev_keydown && ev->data1 != 301) { From e6380ecf3efa056360e3b1ee35cb4fd71a61b3d1 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 07:50:42 -0600 Subject: [PATCH 091/382] Make the join sync hack a little more robust --- src/g_game.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 9125a1317..992a38d25 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4628,7 +4628,10 @@ void G_ReadDemoExtraData(void) playeringame[p] = true; G_AddPlayer(p); players[p].spectator = true; - P_RandomByte(); // I'm pretty sure this ISN'T right, but it syncs my one test replay. + + // There's likely an off-by-one error in timing recording or playback of joins. This hacks around it so I don't have to find out where that is. \o/ + if (oldcmd[p].forwardmove) + P_RandomByte(); } else { From 684ca46d8fef734f055d2e59b3ac2449226d53d4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 19:28:05 -0600 Subject: [PATCH 092/382] Draw player names in netreplays --- src/st_stuff.c | 38 +++++++++++++++++++++++++++++++------- src/v_video.c | 8 +++++++- src/v_video.h | 1 + 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 8ebd21321..c49478916 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1894,15 +1894,39 @@ static void ST_overlayDrawer(void) V_DrawScaledPatch(hudinfo[HUD_GRAVBOOTSICO].x, STRINGY(hudinfo[HUD_GRAVBOOTSICO].y), V_SNAPTORIGHT, gravboots); */ - if(!P_IsLocalPlayer(stplyr)) + if (!(multiplayer && demoplayback)) { - /*char name[MAXPLAYERNAME+1]; - // shorten the name if its more than twelve characters. - strlcpy(name, player_names[stplyr-players], 13);*/ + if(!P_IsLocalPlayer(stplyr)) + { + /*char name[MAXPLAYERNAME+1]; + // shorten the name if its more than twelve characters. + strlcpy(name, player_names[stplyr-players], 13);*/ - // Show name of player being displayed - V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Viewpoint:")); - V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]); + // Show name of player being displayed + V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Viewpoint:")); + V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]); + } + } + else + { + + if (!splitscreen) + { + V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Viewpoint:")); + V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_HUDTRANSHALF|V_ALLOWLOWERCASE, player_names[stplyr-players]); + } + else if (splitscreen == 1) + { + char name[MAXPLAYERNAME+12]; + sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); + + INT32 y = (stplyr == &players[displayplayer]) ? 8 : BASEVIDHEIGHT/2-16; + V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name); + } + else if (splitscreen) + { + V_DrawCenteredThinString(BASEVIDWIDTH/4, 4, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP), player_names[stplyr-players]); + } } // This is where we draw all the fun cheese if you have the chasecam off! diff --git a/src/v_video.c b/src/v_video.c index dd95efe3d..2a16ee474 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1872,6 +1872,12 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) } } +void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string) +{ + x -= V_ThinStringWidth(string, option)/2; + V_DrawThinString(x, y, option, string); +} + void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string) { x -= V_ThinStringWidth(string, option); @@ -2305,7 +2311,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) } } - + return w; } diff --git a/src/v_video.h b/src/v_video.h index 4a904f795..bc2549d9c 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -182,6 +182,7 @@ void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *s // draw a string using the tny_font void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); From 2a7bde236620c3e27755daf033e58221dc53382d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 19:46:58 -0600 Subject: [PATCH 093/382] Refactor view changes a bit --- src/d_clisrv.c | 4 +- src/g_game.c | 158 ++++++++++++++++++++++++++++++------------------- src/g_game.h | 2 + 3 files changed, 103 insertions(+), 61 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3c8865d6f..ff15489af 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2561,8 +2561,10 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) RemoveAdminPlayer(playernum); // don't stay admin after you're gone } - if (playernum == displayplayer) + if (playernum == displayplayer && !demoplayback) displayplayer = consoleplayer; // don't look through someone's view who isn't there + else + G_ResetViews(); #ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[playernum]); diff --git a/src/g_game.c b/src/g_game.c index 992a38d25..9d3b442fc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1808,66 +1808,8 @@ boolean G_Responder(event_t *ev) displayplayer = consoleplayer; else { - UINT8 i = 0; // spy mode - for (i = 0; i < MAXPLAYERS; i++) - { - displayplayer++; - if (displayplayer == MAXPLAYERS) - displayplayer = 0; - - if (!demoplayback && displayplayer == consoleplayer) - break; // End loop - - if (displayplayer == secondarydisplayplayer || displayplayer == thirddisplayplayer || displayplayer == fourthdisplayplayer) - continue; - - if (!playeringame[displayplayer]) - continue; - - if (players[displayplayer].spectator) - continue; - - // SRB2Kart: Only go through players who are actually playing - if (players[displayplayer].exiting) - continue; - - if (players[displayplayer].pflags & PF_TIMEOVER) - continue; - - // I don't know if we want this actually, but I'll humor the suggestion anyway - if (G_BattleGametype()) - { - if (players[displayplayer].kartstuff[k_bumper] <= 0) - continue; - } - - // SRB2Kart: we have no team-based modes, YET... - /*if (G_GametypeHasTeams()) - { - if (players[consoleplayer].ctfteam - && players[displayplayer].ctfteam != players[consoleplayer].ctfteam) - continue; - } - else if (gametype == GT_HIDEANDSEEK) - { - if (players[consoleplayer].pflags & PF_TAGIT) - continue; - } - // Other Tag-based gametypes? - else if (G_TagGametype()) - { - if (!players[consoleplayer].spectator - && (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT)) - continue; - } - else if (G_GametypeHasSpectators() && G_BattleGametype()) - { - if (!players[consoleplayer].spectator) - continue; - }*/ - - break; - } + displayplayer++; + G_ResetViews(); // change statusbar also if playing back demo if (singledemo) @@ -2076,6 +2018,102 @@ boolean G_Responder(event_t *ev) return false; } +static INT32 G_FindView(INT32 startview) +{ + UINT8 i = 0; // spy mode + + startview--; // Ensures view doesn't move if the current view is valid + for (i = 0; i < MAXPLAYERS; i++) + { + startview++; + if (startview == MAXPLAYERS) + startview = 0; + + if (!demoplayback && startview == consoleplayer) + break; // End loop + + if (startview == displayplayer || startview == secondarydisplayplayer || startview == thirddisplayplayer || startview == fourthdisplayplayer) + continue; + + if (!playeringame[startview]) + continue; + + if (players[startview].spectator) + continue; + + // SRB2Kart: Only go through players who are actually playing + if (players[startview].exiting) + continue; + + if (players[startview].pflags & PF_TIMEOVER) + continue; + + // I don't know if we want this actually, but I'll humor the suggestion anyway + if (G_BattleGametype()) + { + if (players[startview].kartstuff[k_bumper] <= 0) + continue; + } + + // SRB2Kart: we have no team-based modes, YET... + /*if (G_GametypeHasTeams()) + { + if (players[consoleplayer].ctfteam + && players[startview].ctfteam != players[consoleplayer].ctfteam) + continue; + } + else if (gametype == GT_HIDEANDSEEK) + { + if (players[consoleplayer].pflags & PF_TAGIT) + continue; + } + // Other Tag-based gametypes? + else if (G_TagGametype()) + { + if (!players[consoleplayer].spectator + && (players[consoleplayer].pflags & PF_TAGIT) != (players[startview].pflags & PF_TAGIT)) + continue; + } + else if (G_GametypeHasSpectators() && G_BattleGametype()) + { + if (!players[consoleplayer].spectator) + continue; + }*/ + + break; + } + + return startview; +} + +// +// G_ResetViews +// Ensures all viewpoints are valid +// +void G_ResetViews(void) +{ + INT32 tempplayer; + + tempplayer = displayplayer; + displayplayer = INT32_MAX; + displayplayer = G_FindView(tempplayer); + + tempplayer = secondarydisplayplayer; + secondarydisplayplayer = INT32_MAX; + secondarydisplayplayer = G_FindView(tempplayer); + + tempplayer = thirddisplayplayer; + thirddisplayplayer = INT32_MAX; + thirddisplayplayer = G_FindView(tempplayer); + + tempplayer = fourthdisplayplayer; + fourthdisplayplayer = INT32_MAX; + fourthdisplayplayer = G_FindView(tempplayer); + + if (demoplayback) + consoleplayer = displayplayer; +} + // // G_Ticker // Make ticcmd_ts for the players. diff --git a/src/g_game.h b/src/g_game.h index f97aecd1c..84ba6c510 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -226,6 +226,8 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); +void G_ResetViews(void); + void G_AddPlayer(INT32 playernum); void G_SetExitGameFlag(void); From 0906e02d99776d62e493c9476f703129d1537be3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 19:53:52 -0600 Subject: [PATCH 094/382] Allow changing all players' viewpoints in replays --- src/g_game.c | 25 +++++++++++++++++++++++++ src/m_menu.c | 8 ++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 9d3b442fc..f17df4f7b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1819,6 +1819,31 @@ boolean G_Responder(event_t *ev) } } + if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demoplayback) + { + if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) + { + secondarydisplayplayer++; + G_ResetViews(); + + return true; + } + else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) + { + thirddisplayplayer++; + G_ResetViews(); + + return true; + } + else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) + { + fourthdisplayplayer++; + G_ResetViews(); + + return true; + } + } + // any other key pops up menu if in demos if (gameaction == ga_nothing && !singledemo && ((demoplayback && !modeattacking && !titledemo && !multiplayer) || gamestate == GS_TITLESCREEN)) diff --git a/src/m_menu.c b/src/m_menu.c index f0831a172..6b357cd63 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8816,7 +8816,7 @@ static void M_Setup1PControlsMenu(INT32 choice) OP_AllControlsMenu[15].status = IT_CONTROL; // Chat //OP_AllControlsMenu[16].status = IT_CONTROL; // Team-chat OP_AllControlsMenu[16].status = IT_CONTROL; // Rankings - OP_AllControlsMenu[17].status = IT_CONTROL; // Viewpoint + //OP_AllControlsMenu[17].status = IT_CONTROL; // Viewpoint // 18 is Reset Camera, 19 is Toggle Chasecam OP_AllControlsMenu[20].status = IT_CONTROL; // Pause OP_AllControlsMenu[21].status = IT_CONTROL; // Screenshot @@ -8848,7 +8848,7 @@ static void M_Setup2PControlsMenu(INT32 choice) OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint + //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint // 18 is Reset Camera, 19 is Toggle Chasecam OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot @@ -8880,7 +8880,7 @@ static void M_Setup3PControlsMenu(INT32 choice) OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint + //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint // 18 is Reset Camera, 19 is Toggle Chasecam OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot @@ -8912,7 +8912,7 @@ static void M_Setup4PControlsMenu(INT32 choice) OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint + //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint // 18 is Reset Camera, 19 is Toggle Chasecam OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot From 7d5649ad978bdffba6f2cb72f710fd3606b8941f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 20:19:52 -0600 Subject: [PATCH 095/382] Make replays single-view by default unless requested --- src/g_game.c | 109 +++++++++++++++++++++++++++++++++++++++++---------- src/g_game.h | 2 +- 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index f17df4f7b..76a799c23 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1809,7 +1809,7 @@ boolean G_Responder(event_t *ev) else { displayplayer++; - G_ResetViews(); + G_ResetViews(1); // change statusbar also if playing back demo if (singledemo) @@ -1823,22 +1823,58 @@ boolean G_Responder(event_t *ev) { if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { + if (!splitscreen) + { + splitscreen = 1; + secondarydisplayplayer = displayplayer; + G_ResetViews(2); + + P_ResetCamera(&players[secondarydisplayplayer], &camera2); + R_ExecuteSetViewSize(); + + return true; + } + secondarydisplayplayer++; - G_ResetViews(); + G_ResetViews(2); return true; } else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) { + if (splitscreen == 1) + { + splitscreen = 2; + thirddisplayplayer = displayplayer; + G_ResetViews(3); + + P_ResetCamera(&players[thirddisplayplayer], &camera3); + R_ExecuteSetViewSize(); + + return true; + } + thirddisplayplayer++; - G_ResetViews(); + G_ResetViews(3); return true; } else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) { + if (splitscreen == 2) + { + splitscreen = 3; + fourthdisplayplayer = displayplayer; + G_ResetViews(4); + + P_ResetCamera(&players[fourthdisplayplayer], &camera4); + R_ExecuteSetViewSize(); + + return true; + } + fourthdisplayplayer++; - G_ResetViews(); + G_ResetViews(4); return true; } @@ -2057,7 +2093,16 @@ static INT32 G_FindView(INT32 startview) if (!demoplayback && startview == consoleplayer) break; // End loop - if (startview == displayplayer || startview == secondarydisplayplayer || startview == thirddisplayplayer || startview == fourthdisplayplayer) + if (startview == displayplayer) + continue; + + if (splitscreen && startview == secondarydisplayplayer) + continue; + + if (splitscreen >= 2 && startview == thirddisplayplayer) + continue; + + if (splitscreen == 3 && startview == fourthdisplayplayer) continue; if (!playeringame[startview]) @@ -2115,26 +2160,47 @@ static INT32 G_FindView(INT32 startview) // G_ResetViews // Ensures all viewpoints are valid // -void G_ResetViews(void) +void G_ResetViews(UINT8 viewnum) { INT32 tempplayer; - tempplayer = displayplayer; - displayplayer = INT32_MAX; - displayplayer = G_FindView(tempplayer); + if (!viewnum || viewnum == 1) + { + tempplayer = displayplayer; + displayplayer = INT32_MAX; + displayplayer = G_FindView(tempplayer); + } - tempplayer = secondarydisplayplayer; - secondarydisplayplayer = INT32_MAX; - secondarydisplayplayer = G_FindView(tempplayer); + if (splitscreen && demoplayback) + { - tempplayer = thirddisplayplayer; - thirddisplayplayer = INT32_MAX; - thirddisplayplayer = G_FindView(tempplayer); + if (!viewnum || viewnum == 2) + { + tempplayer = secondarydisplayplayer; + secondarydisplayplayer = INT32_MAX; + secondarydisplayplayer = G_FindView(tempplayer); + } - tempplayer = fourthdisplayplayer; - fourthdisplayplayer = INT32_MAX; - fourthdisplayplayer = G_FindView(tempplayer); + if (splitscreen >= 2) + { + if (!viewnum || viewnum == 3) + { + tempplayer = thirddisplayplayer; + thirddisplayplayer = INT32_MAX; + thirddisplayplayer = G_FindView(tempplayer); + } + if (splitscreen == 3) + { + if (!viewnum || viewnum == 4) + { + tempplayer = fourthdisplayplayer; + fourthdisplayplayer = INT32_MAX; + fourthdisplayplayer = G_FindView(tempplayer); + } + } + } + } if (demoplayback) consoleplayer = displayplayer; } @@ -6246,8 +6312,8 @@ void G_DoPlayDemo(char *defdemoname) } if (!playeringame[displayplayer] || players[displayplayer].spectator) - displayplayer = consoleplayer = p; - else if (!spectator && splitscreen < 3) { + displayplayer = consoleplayer = secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = p; + /*else if (!spectator && splitscreen < 3) { if (splitscreen == 0) { splitscreen = 1; secondarydisplayplayer = p; @@ -6258,7 +6324,7 @@ void G_DoPlayDemo(char *defdemoname) splitscreen = 3; fourthdisplayplayer = p; } - } + }*/ playeringame[p] = true; players[p].spectator = spectator; @@ -6288,6 +6354,7 @@ void G_DoPlayDemo(char *defdemoname) p = READUINT8(demo_p); } + splitscreen = 0; R_ExecuteSetViewSize(); } diff --git a/src/g_game.h b/src/g_game.h index 84ba6c510..256dd2cff 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -226,7 +226,7 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); -void G_ResetViews(void); +void G_ResetViews(UINT8 viewnum); void G_AddPlayer(INT32 playernum); From 46c5e6f533935f566ef21d571362deec8fe57744 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 20:20:14 -0600 Subject: [PATCH 096/382] Fix P3 getting the wrong split flags in 3p splitscreen --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ee50cfdd2..0ecb60d58 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4670,7 +4670,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_driftend] = 0; } - + // Incease/decrease the drift value to continue drifting in that direction if (player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_jmp] == 1 && onground && player->kartstuff[k_drift] != 0) @@ -6333,9 +6333,9 @@ INT32 K_calcSplitFlags(INT32 snapflags) } else if (splitscreen > 1) { - if (stplyr == &players[thirddisplayplayer] || stplyr == &players[fourthdisplayplayer]) + if (stplyr == &players[thirddisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) splitflags |= V_SPLITSCREEN; - if (stplyr == &players[secondarydisplayplayer] || stplyr == &players[fourthdisplayplayer]) + if (stplyr == &players[secondarydisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) splitflags |= V_HORZSCREEN; } } From c85785f29ca6d722dadd6620a2467813f73df680 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 20:50:33 -0600 Subject: [PATCH 097/382] something --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index ff15489af..2e3648eef 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2564,7 +2564,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) if (playernum == displayplayer && !demoplayback) displayplayer = consoleplayer; // don't look through someone's view who isn't there else - G_ResetViews(); + G_ResetViews(0); #ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[playernum]); From ee35987a31ebb0882f1f595466fdd28d02433e47 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 21:06:52 -0600 Subject: [PATCH 098/382] Play intermission after net replays --- src/d_clisrv.c | 2 +- src/g_game.c | 27 +++++++++++++++++++++------ src/y_inter.c | 13 ++++++++++--- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2e3648eef..7806fdc21 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4919,7 +4919,7 @@ void TryRunTics(tic_t realtics) if (demoplayback) { - 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; diff --git a/src/g_game.c b/src/g_game.c index 76a799c23..a6afbb147 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3589,6 +3589,8 @@ static void G_DoCompleted(void) S_StopSounds(); + if (demoplayback) goto demointermission; + prevmap = (INT16)(gamemap-1); // go to next level @@ -3693,12 +3695,15 @@ static void G_DoCompleted(void) nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, false, NULL); } + // We are committed to this map now. // We may as well allocate its header if it doesn't exist // (That is, if it's a real map) if (nextmap < NUMMAPS && !mapheaderinfo[nextmap]) P_AllocMapHeader(nextmap); +demointermission: + if (skipstats && !modeattacking) // Don't skip stats if we're in record attack G_AfterIntermission(); else @@ -3713,6 +3718,12 @@ void G_AfterIntermission(void) HU_ClearCEcho(); //G_NextLevel(); + if (demoplayback) + { + G_StopDemo(); + D_StartTitle(); + return; + } if (modeattacking) // End the run. { M_EndModeAttackRun(); @@ -4782,8 +4793,6 @@ void G_ReadDemoExtraData(void) K_CheckBumpers(); // SRB2Kart else if (G_RaceGametype()) P_CheckRacers(); // also SRB2Kart - - CONS_Printf("Change state @ %d\n", leveltime); } @@ -6892,12 +6901,18 @@ boolean G_CheckDemoStatus(void) { if (singledemo) I_Quit(); - G_StopDemo(); - if (modeattacking) - M_EndModeAttackRun(); + if (multiplayer) + G_ExitLevel(); else - D_AdvanceDemo(); + { + G_StopDemo(); + + if (modeattacking) + M_EndModeAttackRun(); + else + D_AdvanceDemo(); + } return true; } diff --git a/src/y_inter.c b/src/y_inter.c index 021519e3b..d6f89bdc8 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -360,7 +360,7 @@ void Y_IntermissionDrawer(void) else hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP); - if (sorttic != -1 && intertic > sorttic) + if (sorttic != -1 && intertic > sorttic && !demoplayback) { INT32 count = (intertic - sorttic); @@ -540,9 +540,16 @@ void Y_IntermissionDrawer(void) dotimer: if (timer) { + char *string; INT32 tickdown = (timer+1)/TICRATE; + + if (multiplayer && demoplayback) + string = va("Replay ends in %d", tickdown); + else + string = va("%s starts in %d", cv_advancemap.string, tickdown); + V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol, - va("%s starts in %d", cv_advancemap.string, tickdown)); + string); } // Make it obvious that scrambling is happening next round. @@ -603,7 +610,7 @@ void Y_Ticker(void) { if (sorttic == -1) sorttic = intertic + max((cv_inttime.value/2)-2, 2)*TICRATE; // 8 second pause after match results - else + else if (!(multiplayer && demoplayback)) // Don't advance to rankings in replays { if (!data.match.rankingsmode && (intertic >= sorttic + 8)) Y_CalculateMatchData(1, Y_CompareRank); From 3440c23705885b8a505c0ccf96484fe49ce5c2e4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 2 Feb 2019 00:24:15 -0600 Subject: [PATCH 099/382] Fix map name not showing right on replay intermission --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index a6afbb147..78111f259 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3589,10 +3589,10 @@ static void G_DoCompleted(void) S_StopSounds(); - if (demoplayback) goto demointermission; - prevmap = (INT16)(gamemap-1); + if (demoplayback) goto demointermission; + // go to next level // nextmap is 0-based, unlike gamemap if (nextmapoverride != 0) From 3618de853ee883d98645cdf64ae427d79f3f1d7b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 2 Feb 2019 10:54:24 -0600 Subject: [PATCH 100/382] Play generic intermission music after netreplays Mostly because I kept cycling to other people after the top half finished and always got the lose music as a result lol --- src/g_game.c | 2 +- src/p_user.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 78111f259..205773d74 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3581,7 +3581,7 @@ static void G_DoCompleted(void) } // play some generic music if there's no win/cool/lose music going on (for exitlevel commands) - if (G_RaceGametype() && j == splitscreen+1 && (cv_inttime.value > 0)) + if (G_RaceGametype() && ((multiplayer && demoplayback) || j == splitscreen+1) && (cv_inttime.value > 0)) S_ChangeMusicInternal("racent", true); if (automapactive) diff --git a/src/p_user.c b/src/p_user.c index d7423d803..f20c57b84 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1147,6 +1147,9 @@ boolean P_EndingMusic(player_t *player) if (!P_IsLocalPlayer(player)) // Only applies to a local player return false; + if (multiplayer && demoplayback) // Don't play this in multiplayer replays + return false; + // Event - Level Finish // Check for if this is valid or not if (splitscreen) From a7d78cf273b30056b98eaa272d0c249fa94f9417 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Feb 2019 13:55:29 -0600 Subject: [PATCH 101/382] Add support for encore and battle replays --- src/g_game.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 205773d74..171f0a44a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4629,6 +4629,9 @@ char *G_BuildMapTitle(INT32 mapnum) #define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares! #define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? #define DF_ATTACKSHIFT 1 +#define DF_GAMETYPEMASK 0x30 +#define DF_GAMESHIFT 4 +#define DF_ENCORE 0x40 #define DF_MULTIPLAYER 0x80 // This demo contains a dynamic number of players! #define DEMO_SPECTATOR 0x40 @@ -5767,6 +5770,11 @@ void G_BeginRecording(void) demo_p = demobuffer; demoflags = multiplayer ? DF_MULTIPLAYER : (DF_GHOST|(modeattacking<>DF_ATTACKSHIFT; multiplayer = !!(demoflags & DF_MULTIPLAYER); + gametype = (demoflags & DF_GAMETYPEMASK)>>DF_GAMESHIFT; CON_ToggleOff(); hu_demotime = UINT32_MAX; @@ -6368,7 +6377,7 @@ void G_DoPlayDemo(char *defdemoname) } P_SetRandSeed(randseed); - G_InitNew(false, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. + G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. if (!multiplayer) { // Set skin From 5836b0818a4d41f4e43673bb0019cfd4f95d92be Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Feb 2019 14:29:54 -0600 Subject: [PATCH 102/382] Record net replays to replay/online/ --- src/g_game.c | 2 +- src/p_setup.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 171f0a44a..63e5fb726 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5729,7 +5729,7 @@ void G_RecordDemo(const char *name) { INT32 maxsize; - CONS_Printf("Recording demo %s\n", name); + CONS_Printf("Recording demo %s.lmp\n", name); strcpy(demoname, name); strcat(demoname, ".lmp"); diff --git a/src/p_setup.c b/src/p_setup.c index 3b5659c87..a5e585cfa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3158,9 +3158,13 @@ boolean P_SetupLevel(boolean skipprecip) //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. if (!demoplayback && multiplayer) { +// lol sorry #include "time.h" static char buf[256]; - sprintf(buf, "net_replay_test_%d", time(NULL)); + sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", 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); } From 8a1c6114a7537c329ccd0bf3c9ea910bc333bb66 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 4 Feb 2019 03:09:40 -0800 Subject: [PATCH 103/382] Add support for changing viewpoint via console This isn't just a shameless console-empowerement. More precise "spying" can benefit everybody. But especially in net-replays, this is almost necessary. --- src/d_netcmd.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++ src/g_game.c | 38 +++++++++----- src/g_game.h | 2 + src/p_local.h | 2 + src/p_user.c | 12 +++++ 5 files changed, 181 insertions(+), 12 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7b3925e92..9bbb73ef4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -129,6 +129,8 @@ 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_Addfile(void); static void Command_ListWADS_f(void); #ifdef DELFILE @@ -708,6 +710,11 @@ 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("setcontrol", Command_Setcontrol_f); COM_AddCommand("setcontrol2", Command_Setcontrol2_f); COM_AddCommand("setcontrol3", Command_Setcontrol3_f); @@ -1885,6 +1892,138 @@ static void Command_ResetCamera_f(void) P_ResetCamera(&players[displayplayer], &camera); } +static INT32 +RoundToValidPlayerNum (INT32 playernum) +{ + INT32 playernuml, playernumr; + for (playernuml = playernum; --playernuml > 0; ) + { + if (playeringame[playernuml]) + break; + } + for (playernumr = playernum ;; ) + { + if (++playernumr == MAXPLAYERS) + { + playernum = playernuml; + break; + } + if (playeringame[playernumr]) + { + if (playernum - playernuml < playernumr - playernum) + playernum = playernuml;/* "round" down */ + else + playernum = playernumr; + break; + } + } + return playernum; +} + +static INT32/* Consider replacing nametonum with this */ +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) + { + /* Consider strcasestr? */ + /* Match name (case-insensitively) fully, or partially the start. */ + if (playeringame[playernum]) + if (stricmp(player_names[playernum], s) == 0 || + strstr(player_names[playernum], s) == player_names[playernum] ) + { + return playernum; + } + } + return -1;/* We can't "round" a name! */ +} + +#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; + int viewnum; + INT32 playernum, oldplayernum; + 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; + } + displayplayerp = G_GetDisplayplayerPtr(viewnum); + + if (COM_Argc() > 1)/* switch to player */ + { + if (viewnum > splitscreen+2)/* We must arrange in order. */ + { + CONS_Alert(CONS_WARNING, + "You may not change viewpoints more than " + "once ahead the current number of splits. " + "Use view%d instead.\n", splitscreen+2); + return; + } + + if (( playernum = LookupPlayer(COM_Argv(1)) ) == -1) + { + CONS_Alert(CONS_WARNING, "There is no player by that name!\n"); + return; + } + + oldplayernum = playernum; + + if (!playeringame[playernum]) + { + playernum = RoundToValidPlayerNum(playernum); + } + + if ((*displayplayerp) == playernum) + return; + + (*displayplayerp) = playernum; + G_ResetViews(viewnum); + + if ((*displayplayerp) != oldplayernum)/* differ parameter */ + { + if (playernum == oldplayernum)/* skipped some */ + { + CONS_Alert(CONS_NOTICE, + "Another viewpoint is already set to that player.\n"); + } + else + { + CONS_Alert(CONS_NOTICE, "There is no player using that slot.\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 + // ======================================================================== // play a demo, add .lmp for external demos diff --git a/src/g_game.c b/src/g_game.c index 63e5fb726..c6c091fca 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1825,13 +1825,9 @@ boolean G_Responder(event_t *ev) { if (!splitscreen) { - splitscreen = 1; secondarydisplayplayer = displayplayer; G_ResetViews(2); - P_ResetCamera(&players[secondarydisplayplayer], &camera2); - R_ExecuteSetViewSize(); - return true; } @@ -1844,13 +1840,9 @@ boolean G_Responder(event_t *ev) { if (splitscreen == 1) { - splitscreen = 2; thirddisplayplayer = displayplayer; G_ResetViews(3); - P_ResetCamera(&players[thirddisplayplayer], &camera3); - R_ExecuteSetViewSize(); - return true; } @@ -1863,13 +1855,9 @@ boolean G_Responder(event_t *ev) { if (splitscreen == 2) { - splitscreen = 3; fourthdisplayplayer = displayplayer; G_ResetViews(4); - P_ResetCamera(&players[fourthdisplayplayer], &camera4); - R_ExecuteSetViewSize(); - return true; } @@ -2156,6 +2144,18 @@ static INT32 G_FindView(INT32 startview) return startview; } +INT32 * +G_GetDisplayplayerPtr (UINT8 viewnum) +{ + switch (viewnum) + { + case 2: return &secondarydisplayplayer; + case 3: return &thirddisplayplayer; + case 4: return &fourthdisplayplayer; + } + return &displayplayer; +} + // // G_ResetViews // Ensures all viewpoints are valid @@ -2163,6 +2163,8 @@ static INT32 G_FindView(INT32 startview) void G_ResetViews(UINT8 viewnum) { INT32 tempplayer; + INT32 *displayplayerp; + camera_t *camerap; if (!viewnum || viewnum == 1) { @@ -2171,6 +2173,18 @@ void G_ResetViews(UINT8 viewnum) displayplayer = G_FindView(tempplayer); } + if (viewnum > 1 && multiplayer && demoplayback) + if (viewnum == splitscreen+2) + { + splitscreen = viewnum-1; + + displayplayerp = (G_GetDisplayplayerPtr(viewnum)); + camerap = (P_GetCameraPtr(viewnum)); + + P_ResetCamera(&players[(*displayplayerp)], camerap); + R_ExecuteSetViewSize(); + } + if (splitscreen && demoplayback) { diff --git a/src/g_game.h b/src/g_game.h index 256dd2cff..b64fcabb9 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -226,6 +226,8 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); +INT32 * G_GetDisplayplayerPtr (UINT8 viewnum); + void G_ResetViews(UINT8 viewnum); void G_AddPlayer(INT32 playernum); diff --git a/src/p_local.h b/src/p_local.h index cf1387fee..46afc75ea 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -126,6 +126,8 @@ extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; extern fixed_t t_cam3_dist, t_cam3_height, t_cam3_rotate; extern fixed_t t_cam4_dist, t_cam4_height, t_cam4_rotate; +camera_t * P_GetCameraPtr (UINT8 viewnum); + fixed_t P_GetPlayerHeight(player_t *player); fixed_t P_GetPlayerSpinHeight(player_t *player); void P_AddPlayerScore(player_t *player, UINT32 amount); diff --git a/src/p_user.c b/src/p_user.c index f20c57b84..ce8e3f071 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8124,6 +8124,18 @@ fixed_t t_cam4_rotate = -42; #define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode) +camera_t * +P_GetCameraPtr (UINT8 viewnum) +{ + switch (viewnum) + { + case 2: return &camera2; + case 3: return &camera3; + case 4: return &camera4; + } + return &camera; +} + void P_ResetCamera(player_t *player, camera_t *thiscam) { tic_t tries = 0; From f99a7dc36b415370e0f327eb946abef1977b005d Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 17:54:41 -0800 Subject: [PATCH 104/382] Shut up when our "new" viewpoint is just the same Also actually correct for new splits. --- src/d_netcmd.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9bbb73ef4..5788eb65f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1955,6 +1955,7 @@ static void Command_View_f (void) { INT32 *displayplayerp; + INT32 olddisplayplayer; int viewnum; INT32 playernum, oldplayernum; char c; @@ -1971,15 +1972,6 @@ Command_View_f (void) if (COM_Argc() > 1)/* switch to player */ { - if (viewnum > splitscreen+2)/* We must arrange in order. */ - { - CONS_Alert(CONS_WARNING, - "You may not change viewpoints more than " - "once ahead the current number of splits. " - "Use view%d instead.\n", splitscreen+2); - return; - } - if (( playernum = LookupPlayer(COM_Argv(1)) ) == -1) { CONS_Alert(CONS_WARNING, "There is no player by that name!\n"); @@ -1993,12 +1985,14 @@ Command_View_f (void) playernum = RoundToValidPlayerNum(playernum); } - if ((*displayplayerp) == playernum) - return; - + olddisplayplayer = (*displayplayerp); (*displayplayerp) = playernum; G_ResetViews(viewnum); + /* The player we wanted was corrected to who it already was. */ + if ((*displayplayerp) == olddisplayplayer) + return; + if ((*displayplayerp) != oldplayernum)/* differ parameter */ { if (playernum == oldplayernum)/* skipped some */ From b777ae0ca8abc559fb5318142481dd773253cfbe Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 17:58:55 -0800 Subject: [PATCH 105/382] Automatically load splits up to new viewpoint Basically, you can start viewing your third split and the second one views another! --- src/g_game.c | 124 +++++++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 72 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index c6c091fca..8fbcec0c6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1823,14 +1823,6 @@ boolean G_Responder(event_t *ev) { if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { - if (!splitscreen) - { - secondarydisplayplayer = displayplayer; - G_ResetViews(2); - - return true; - } - secondarydisplayplayer++; G_ResetViews(2); @@ -1838,14 +1830,6 @@ boolean G_Responder(event_t *ev) } else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) { - if (splitscreen == 1) - { - thirddisplayplayer = displayplayer; - G_ResetViews(3); - - return true; - } - thirddisplayplayer++; G_ResetViews(3); @@ -1853,14 +1837,6 @@ boolean G_Responder(event_t *ev) } else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) { - if (splitscreen == 2) - { - fourthdisplayplayer = displayplayer; - G_ResetViews(4); - - return true; - } - fourthdisplayplayer++; G_ResetViews(4); @@ -2156,65 +2132,69 @@ G_GetDisplayplayerPtr (UINT8 viewnum) return &displayplayer; } +/* Reset only one view */ +static void +G_ResetView (UINT8 viewnum) +{ + INT32 *displayplayerp; + camera_t *camerap; + + INT32 newdisplayplayer; + UINT8 viewd, splits; + + splits = splitscreen+1; + + displayplayerp = (G_GetDisplayplayerPtr(viewnum)); + newdisplayplayer = (*displayplayerp); + (*displayplayerp) = INT32_MAX; + (*displayplayerp) = G_FindView(newdisplayplayer); + + if (viewnum > splits) + { + splitscreen = viewnum-1; + + for (viewd = splits+1; viewd < viewnum; ++viewd) + { + (*(G_GetDisplayplayerPtr(viewd))) = INT32_MAX;/* ensure clean */ + } + /* Initialise views up from current splitscreen. */ + for (viewd = splits+1 ;; ) + { + displayplayerp = (G_GetDisplayplayerPtr(viewd)); + camerap = (P_GetCameraPtr(viewd)); + + P_ResetCamera(&players[(*displayplayerp)], camerap); + R_ExecuteSetViewSize(); + + if (++viewd > viewnum) + break; + + /* Correct up to but viewnum */ + (*displayplayerp) = G_FindView((*displayplayerp)); + } + } +} + // // G_ResetViews // Ensures all viewpoints are valid // void G_ResetViews(UINT8 viewnum) { - INT32 tempplayer; - INT32 *displayplayerp; - camera_t *camerap; + UINT8 splits = splitscreen+1; - if (!viewnum || viewnum == 1) + if (viewnum == 0) { - tempplayer = displayplayer; - displayplayer = INT32_MAX; - displayplayer = G_FindView(tempplayer); - } - - if (viewnum > 1 && multiplayer && demoplayback) - if (viewnum == splitscreen+2) - { - splitscreen = viewnum-1; - - displayplayerp = (G_GetDisplayplayerPtr(viewnum)); - camerap = (P_GetCameraPtr(viewnum)); - - P_ResetCamera(&players[(*displayplayerp)], camerap); - R_ExecuteSetViewSize(); - } - - if (splitscreen && demoplayback) - { - - if (!viewnum || viewnum == 2) + while (viewnum++ < splits) { - tempplayer = secondarydisplayplayer; - secondarydisplayplayer = INT32_MAX; - secondarydisplayplayer = G_FindView(tempplayer); - } - - if (splitscreen >= 2) - { - if (!viewnum || viewnum == 3) - { - tempplayer = thirddisplayplayer; - thirddisplayplayer = INT32_MAX; - thirddisplayplayer = G_FindView(tempplayer); - } - - if (splitscreen == 3) - { - if (!viewnum || viewnum == 4) - { - tempplayer = fourthdisplayplayer; - fourthdisplayplayer = INT32_MAX; - fourthdisplayplayer = G_FindView(tempplayer); - } - } + G_ResetView(viewnum); } } + else + { + G_ResetView(viewnum); + } + if (demoplayback) consoleplayer = displayplayer; } From b17607c3c3ae30e178ae44cbe86d6bdafa5ef24f Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:09:36 -0800 Subject: [PATCH 106/382] Expose G_ResetView and amend G_ResetViews (fickle's suggestion.) --- src/d_clisrv.c | 2 +- src/d_netcmd.c | 2 +- src/g_game.c | 35 +++++++++++++++-------------------- src/g_game.h | 3 ++- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7806fdc21..72f0dd2b1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2564,7 +2564,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) if (playernum == displayplayer && !demoplayback) displayplayer = consoleplayer; // don't look through someone's view who isn't there else - G_ResetViews(0); + G_ResetViews(); #ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[playernum]); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5788eb65f..84741c054 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1987,7 +1987,7 @@ Command_View_f (void) olddisplayplayer = (*displayplayerp); (*displayplayerp) = playernum; - G_ResetViews(viewnum); + G_ResetView(viewnum); /* The player we wanted was corrected to who it already was. */ if ((*displayplayerp) == olddisplayplayer) diff --git a/src/g_game.c b/src/g_game.c index 8fbcec0c6..ca003248a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1809,7 +1809,7 @@ boolean G_Responder(event_t *ev) else { displayplayer++; - G_ResetViews(1); + G_ResetView(1); // change statusbar also if playing back demo if (singledemo) @@ -1824,21 +1824,21 @@ boolean G_Responder(event_t *ev) if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { secondarydisplayplayer++; - G_ResetViews(2); + G_ResetView(2); return true; } else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) { thirddisplayplayer++; - G_ResetViews(3); + G_ResetView(3); return true; } else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) { fourthdisplayplayer++; - G_ResetViews(4); + G_ResetView(4); return true; } @@ -2132,8 +2132,10 @@ G_GetDisplayplayerPtr (UINT8 viewnum) return &displayplayer; } -/* Reset only one view */ -static void +/* +Ensure a viewpoint is valid. +*/ +void G_ResetView (UINT8 viewnum) { INT32 *displayplayerp; @@ -2173,30 +2175,23 @@ G_ResetView (UINT8 viewnum) (*displayplayerp) = G_FindView((*displayplayerp)); } } + + if (viewnum == 1 && demoplayback) + consoleplayer = displayplayer; } // // G_ResetViews // Ensures all viewpoints are valid // -void G_ResetViews(UINT8 viewnum) +void G_ResetViews(void) { - UINT8 splits = splitscreen+1; - - if (viewnum == 0) - { - while (viewnum++ < splits) - { - G_ResetView(viewnum); - } - } - else + UINT8 viewnum = splitscreen+1; + do { G_ResetView(viewnum); } - - if (demoplayback) - consoleplayer = displayplayer; + while (--viewnum > 0) ; } // diff --git a/src/g_game.h b/src/g_game.h index b64fcabb9..a28a709e5 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -228,7 +228,8 @@ boolean G_Responder(event_t *ev); INT32 * G_GetDisplayplayerPtr (UINT8 viewnum); -void G_ResetViews(UINT8 viewnum); +void G_ResetViews(void); +void G_ResetView (UINT8 viewnum); void G_AddPlayer(INT32 playernum); From d7db80589106742172a3e885f9e9baec821eedc6 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:16:54 -0800 Subject: [PATCH 107/382] Do not round player numbers in range (fickle's suggestion.) --- src/d_netcmd.c | 50 +++++++------------------------------------------- 1 file changed, 7 insertions(+), 43 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 84741c054..223537012 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1892,34 +1892,6 @@ static void Command_ResetCamera_f(void) P_ResetCamera(&players[displayplayer], &camera); } -static INT32 -RoundToValidPlayerNum (INT32 playernum) -{ - INT32 playernuml, playernumr; - for (playernuml = playernum; --playernuml > 0; ) - { - if (playeringame[playernuml]) - break; - } - for (playernumr = playernum ;; ) - { - if (++playernumr == MAXPLAYERS) - { - playernum = playernuml; - break; - } - if (playeringame[playernumr]) - { - if (playernum - playernuml < playernumr - playernum) - playernum = playernuml;/* "round" down */ - else - playernum = playernumr; - break; - } - } - return playernum; -} - static INT32/* Consider replacing nametonum with this */ LookupPlayer (const char *s) { @@ -1945,7 +1917,7 @@ LookupPlayer (const char *s) return playernum; } } - return -1;/* We can't "round" a name! */ + return -1; } #define PRINTVIEWPOINT( pre,suf ) \ @@ -1957,7 +1929,7 @@ Command_View_f (void) INT32 *displayplayerp; INT32 olddisplayplayer; int viewnum; - INT32 playernum, oldplayernum; + INT32 playernum; char c; /* easy peasy */ c = COM_Argv(0)[strlen(COM_Argv(0))-1];/* may be digit */ @@ -1977,12 +1949,10 @@ Command_View_f (void) CONS_Alert(CONS_WARNING, "There is no player by that name!\n"); return; } - - oldplayernum = playernum; - if (!playeringame[playernum]) { - playernum = RoundToValidPlayerNum(playernum); + CONS_Alert(CONS_WARNING, "There is no player using that slot!\n"); + return; } olddisplayplayer = (*displayplayerp); @@ -1995,15 +1965,9 @@ Command_View_f (void) if ((*displayplayerp) != oldplayernum)/* differ parameter */ { - if (playernum == oldplayernum)/* skipped some */ - { - CONS_Alert(CONS_NOTICE, - "Another viewpoint is already set to that player.\n"); - } - else - { - CONS_Alert(CONS_NOTICE, "There is no player using that slot.\n"); - } + /* skipped some */ + CONS_Alert(CONS_NOTICE, + "Another viewpoint is already set to that player.\n"); PRINTVIEWPOINT ("Now "," instead") } else From cd8cd10dbce50b9453a2e9adc8b59a53589ded87 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:29:52 -0800 Subject: [PATCH 108/382] Bleh old stuff --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 223537012..36275305b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1963,7 +1963,7 @@ Command_View_f (void) if ((*displayplayerp) == olddisplayplayer) return; - if ((*displayplayerp) != oldplayernum)/* differ parameter */ + if ((*displayplayerp) != playernum)/* differ parameter */ { /* skipped some */ CONS_Alert(CONS_NOTICE, From 3821918cb5aa49d4ddfc73489e791d788459089b Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:48:48 -0800 Subject: [PATCH 109/382] Restrict viewn command to netreplays --- src/d_netcmd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 36275305b..ab0f4bf38 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1940,6 +1940,13 @@ Command_View_f (void) case '4': viewnum = 4; break; default: viewnum = 1; } + + if (viewnum > 1 && !( multiplayer && demoplayback )) + { + CONS_Alert(CONS_NOTICE, "You must be viewing a multiplayer replay.\n"); + return; + } + displayplayerp = G_GetDisplayplayerPtr(viewnum); if (COM_Argc() > 1)/* switch to player */ From 460bc3c4ec953b3fd640f6bb2542451313af4e05 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 21:23:48 -0800 Subject: [PATCH 110/382] Show scores but not "Player 1" in netreplays --- src/hu_stuff.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a308dfc2b..2c5bf153c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2109,8 +2109,11 @@ 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]); + } if (modeattacking) { V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:"); @@ -2227,10 +2230,7 @@ void HU_Drawer(void) if (cechotimer) HU_DrawCEcho(); - if (demoplayback && hu_showscores) - HU_DrawDemoInfo(); - - if (!Playing() + if (!( Playing() || demoplayback ) || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND @@ -2250,6 +2250,10 @@ void HU_Drawer(void) LUAh_ScoresHUD(); #endif } + if (demoplayback) + { + HU_DrawDemoInfo(); + } } if (gamestate != GS_LEVEL) From dab16409ce5fc3e11dcc536c49cf2f155d695f0c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 6 Feb 2019 20:25:27 -0600 Subject: [PATCH 111/382] Fix views not setting properly when adding multiple at once --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index ca003248a..a69d76ee2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2166,14 +2166,14 @@ G_ResetView (UINT8 viewnum) camerap = (P_GetCameraPtr(viewd)); P_ResetCamera(&players[(*displayplayerp)], camerap); - R_ExecuteSetViewSize(); if (++viewd > viewnum) break; /* Correct up to but viewnum */ - (*displayplayerp) = G_FindView((*displayplayerp)); + (*displayplayerp) = G_FindView(displayplayer); } + R_ExecuteSetViewSize(); } if (viewnum == 1 && demoplayback) From e5cdf6d84d647d9c8a597260453e590a7c8bb150 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 6 Feb 2019 20:25:45 -0600 Subject: [PATCH 112/382] Format for better consistency with the codebase --- src/d_netcmd.c | 7 +++---- src/g_game.c | 13 ++++++------- src/g_game.h | 4 ++-- src/p_local.h | 2 +- src/p_user.c | 3 +-- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index ab0f4bf38..6fb8aa708 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1892,8 +1892,8 @@ static void Command_ResetCamera_f(void) P_ResetCamera(&players[displayplayer], &camera); } -static INT32/* Consider replacing nametonum with this */ -LookupPlayer (const char *s) +/* Consider replacing nametonum with this */ +static INT32 LookupPlayer(const char *s) { INT32 playernum; @@ -1923,8 +1923,7 @@ LookupPlayer (const char *s) #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) +static void Command_View_f(void) { INT32 *displayplayerp; INT32 olddisplayplayer; diff --git a/src/g_game.c b/src/g_game.c index a69d76ee2..c100ce926 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2120,8 +2120,7 @@ static INT32 G_FindView(INT32 startview) return startview; } -INT32 * -G_GetDisplayplayerPtr (UINT8 viewnum) +INT32 *G_GetDisplayplayerPtr(UINT8 viewnum) { switch (viewnum) { @@ -2132,11 +2131,11 @@ G_GetDisplayplayerPtr (UINT8 viewnum) return &displayplayer; } -/* -Ensure a viewpoint is valid. -*/ -void -G_ResetView (UINT8 viewnum) +// +// G_ResetView +// Ensures a viewpoint is valid. +// +void G_ResetView(UINT8 viewnum) { INT32 *displayplayerp; camera_t *camerap; diff --git a/src/g_game.h b/src/g_game.h index a28a709e5..cf7dda09b 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -226,10 +226,10 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); -INT32 * G_GetDisplayplayerPtr (UINT8 viewnum); +INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); void G_ResetViews(void); -void G_ResetView (UINT8 viewnum); +void G_ResetView(UINT8 viewnum); void G_AddPlayer(INT32 playernum); diff --git a/src/p_local.h b/src/p_local.h index 46afc75ea..12d582aa2 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -126,7 +126,7 @@ extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; extern fixed_t t_cam3_dist, t_cam3_height, t_cam3_rotate; extern fixed_t t_cam4_dist, t_cam4_height, t_cam4_rotate; -camera_t * P_GetCameraPtr (UINT8 viewnum); +camera_t *P_GetCameraPtr(UINT8 viewnum); fixed_t P_GetPlayerHeight(player_t *player); fixed_t P_GetPlayerSpinHeight(player_t *player); diff --git a/src/p_user.c b/src/p_user.c index ce8e3f071..803f1c135 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8124,8 +8124,7 @@ fixed_t t_cam4_rotate = -42; #define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode) -camera_t * -P_GetCameraPtr (UINT8 viewnum) +camera_t *P_GetCameraPtr(UINT8 viewnum) { switch (viewnum) { From 4f8ef7c3aa9fe062a4af2e9e74456d14dc1d68f4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 6 Feb 2019 21:03:05 -0600 Subject: [PATCH 113/382] Fix compile warnings --- src/g_game.c | 3 +-- src/p_setup.c | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 2bdaaf119..8a8b021cc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6113,7 +6113,7 @@ void G_DoPlayDemo(char *defdemoname) UINT8 i, p; lumpnum_t l; char skin[17],color[17],*n,*pdemoname; - UINT8 version,subversion,kartspeed,kartweight; + UINT8 version,subversion,kartspeed=5,kartweight=5; UINT32 randseed; char msg[1024]; #if defined(SKIPERRORS) && !defined(DEVELOP) @@ -6342,7 +6342,6 @@ void G_DoPlayDemo(char *defdemoname) playeringame[0] = !multiplayer; if (multiplayer) { - player_t *player; boolean spectator; // Load players that were in-game when the map started diff --git a/src/p_setup.c b/src/p_setup.c index ce162af61..08bcfd2f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -65,6 +65,10 @@ #include "lua_script.h" #include "lua_hook.h" +#if !defined (UNDER_CE) +#include +#endif + #if defined (_WIN32) || defined (_WIN32_WCE) #include #include @@ -3161,10 +3165,8 @@ boolean P_SetupLevel(boolean skipprecip) //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. if (!demoplayback && multiplayer) { -// lol sorry -#include "time.h" static char buf[256]; - sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", time(NULL), G_BuildMapName(gamemap)); + 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); From e3e8465a2daf5b80e96e51e7bf961ef5491968b6 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Feb 2019 07:50:26 +0000 Subject: [PATCH 114/382] Open a new connection before we check socket errors And somehow this applies if you use `addfile` after having added the server. Some claim that there are other cases too. --- src/mserv.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index f5c4fa889..064f8d41c 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -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 == 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)); From 93bed5f40d1c3f341f04739c8b5fc2d50b06d57a Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 11 Feb 2019 16:39:58 -0500 Subject: [PATCH 115/382] Show line number on error, also hide under devmode --- src/p_slopes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 68767b50c..4e12b104f 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -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; } From 011a498f4b0d6f932446c698625d2304c3755a6b Mon Sep 17 00:00:00 2001 From: james Date: Tue, 12 Feb 2019 19:16:36 -0800 Subject: [PATCH 116/382] view command: match names case-insensitively --- src/d_netcmd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 802037899..c1a92f5b9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1912,11 +1912,10 @@ static INT32 LookupPlayer(const char *s) for (playernum = 0; playernum < MAXPLAYERS; ++playernum) { - /* Consider strcasestr? */ - /* Match name (case-insensitively) fully, or partially the start. */ + /* Match name case-insensitively: fully, or partially the start. */ if (playeringame[playernum]) if (stricmp(player_names[playernum], s) == 0 || - strstr(player_names[playernum], s) == player_names[playernum] ) + strnicmp(player_names[playernum], s, strlen(s)) == 0) { return playernum; } From 0c5cc4872f499888a6cfd3e2797717c682dc4058 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 16:17:48 -0800 Subject: [PATCH 117/382] Support splitscreen views in netreplays with less than four players The first view is also not changed if there are no players to view. --- src/d_netcmd.c | 2 +- src/g_game.c | 302 ++++++++++++++++++++++++++++++++----------------- src/g_game.h | 9 +- 3 files changed, 208 insertions(+), 105 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c1a92f5b9..54267d998 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1966,7 +1966,7 @@ static void Command_View_f(void) olddisplayplayer = (*displayplayerp); (*displayplayerp) = playernum; - G_ResetView(viewnum); + G_ResetView(viewnum, playernum); /* The player we wanted was corrected to who it already was. */ if ((*displayplayerp) == olddisplayplayer) diff --git a/src/g_game.c b/src/g_game.c index 8a8b021cc..bd1f3df9c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1831,8 +1831,7 @@ boolean G_Responder(event_t *ev) displayplayer = consoleplayer; else { - displayplayer++; - G_ResetView(1); + G_AdjustView(1, 1); // change statusbar also if playing back demo if (singledemo) @@ -1846,22 +1845,19 @@ boolean G_Responder(event_t *ev) { if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { - secondarydisplayplayer++; - G_ResetView(2); + G_AdjustView(2, 1); return true; } else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) { - thirddisplayplayer++; - G_ResetView(3); + G_AdjustView(3, 1); return true; } else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) { - fourthdisplayplayer++; - G_ResetView(4); + G_AdjustView(4, 1); return true; } @@ -2066,81 +2062,131 @@ boolean G_Responder(event_t *ev) return false; } -static INT32 G_FindView(INT32 startview) +// +// G_CouldView +// Return whether a player could be viewed by any means. +// +boolean G_CouldView(INT32 playernum) { - UINT8 i = 0; // spy mode + player_t *player; - startview--; // Ensures view doesn't move if the current view is valid - for (i = 0; i < MAXPLAYERS; i++) + if (playernum < 0 || playernum > MAXPLAYERS-1) + return false; + + if (!playeringame[playernum]) + return false; + + player = &players[playernum]; + + if (player->spectator) + return false; + + // SRB2Kart: Only go through players who are actually playing + if (player->exiting) + return false; + if (( player->pflags & PF_TIMEOVER )) + return false; + + // I don't know if we want this actually, but I'll humor the suggestion anyway + if (G_BattleGametype()) { - startview++; - if (startview == MAXPLAYERS) - startview = 0; - - if (!demoplayback && startview == consoleplayer) - break; // End loop - - if (startview == displayplayer) - continue; - - if (splitscreen && startview == secondarydisplayplayer) - continue; - - if (splitscreen >= 2 && startview == thirddisplayplayer) - continue; - - if (splitscreen == 3 && startview == fourthdisplayplayer) - continue; - - if (!playeringame[startview]) - continue; - - if (players[startview].spectator) - continue; - - // SRB2Kart: Only go through players who are actually playing - if (players[startview].exiting) - continue; - - if (players[startview].pflags & PF_TIMEOVER) - continue; - - // I don't know if we want this actually, but I'll humor the suggestion anyway - if (G_BattleGametype()) - { - if (players[startview].kartstuff[k_bumper] <= 0) - continue; - } - - // SRB2Kart: we have no team-based modes, YET... - /*if (G_GametypeHasTeams()) - { - if (players[consoleplayer].ctfteam - && players[startview].ctfteam != players[consoleplayer].ctfteam) - continue; - } - else if (gametype == GT_HIDEANDSEEK) - { - if (players[consoleplayer].pflags & PF_TAGIT) - continue; - } - // Other Tag-based gametypes? - else if (G_TagGametype()) - { - if (!players[consoleplayer].spectator - && (players[consoleplayer].pflags & PF_TAGIT) != (players[startview].pflags & PF_TAGIT)) - continue; - } - else if (G_GametypeHasSpectators() && G_BattleGametype()) - { - if (!players[consoleplayer].spectator) - continue; - }*/ - - break; + if (player->kartstuff[k_bumper] <= 0) + return false; } - return startview; + // SRB2Kart: we have no team-based modes, YET... + /*if (G_GametypeHasTeams()) + { + if (players[consoleplayer].ctfteam + && player->ctfteam != players[consoleplayer].ctfteam) + return false; + } + else if (gametype == GT_HIDEANDSEEK) + { + if (players[consoleplayer].pflags & PF_TAGIT) + return false; + } + // Other Tag-based gametypes? + else if (G_TagGametype()) + { + if (!players[consoleplayer].spectator + && (players[consoleplayer].pflags & PF_TAGIT) != (player->pflags & PF_TAGIT)) + return false; + } + else if (G_GametypeHasSpectators() && G_BattleGametype()) + { + if (!players[consoleplayer].spectator) + return false; + }*/ + + return true; +} + +// +// G_CanView +// Return whether a player can be viewed on a particular view (splitscreen). +// +boolean G_CanView(INT32 playernum, UINT8 viewnum) +{ + UINT8 splits; + UINT8 viewd; + INT32 *displayplayerp; + + if (!G_CouldView(playernum)) + return false; + + splits = splitscreen+1; + if (viewnum > splits) + viewnum = splits; + + for (viewd = 1; viewd < viewnum; ++viewd) + { + displayplayerp = (G_GetDisplayplayerPtr(viewd)); + if ((*displayplayerp) == playernum) + return false; + } + for (viewd = viewnum + 1; viewd <= splits; ++viewd) + { + displayplayerp = (G_GetDisplayplayerPtr(viewd)); + if ((*displayplayerp) == playernum) + return false; + } + + return true; +} + +// +// G_FindView +// Return the next player that can be viewed on a view, wraps forward. +// An out of range startview is corrected. +// +INT32 G_FindView(INT32 startview, UINT8 viewnum) +{ + INT32 i; + startview = min(max(startview, 0), MAXPLAYERS); + for (i = startview; i < MAXPLAYERS; ++i) + { + if (G_CanView(i, viewnum)) + return i; + } + for (i = 0; i < startview; ++i) + { + if (G_CanView(i, viewnum)) + return i; + } + return -1; +} + +INT32 G_CountPlayersPotentiallyViewable(void) +{ + INT32 total = 0; + INT32 i; + for (i = 0; i < MAXPLAYERS; ++i) + { + if (G_CouldView(i)) + total++; + } + return total; } INT32 *G_GetDisplayplayerPtr(UINT8 viewnum) @@ -2156,64 +2202,114 @@ INT32 *G_GetDisplayplayerPtr(UINT8 viewnum) // // G_ResetView -// Ensures a viewpoint is valid. +// Correct a viewpoint to playernum or the next available, wraps forward. +// Also promotes splitscreen up to available viewable players. +// An out of range playernum is corrected. // -void G_ResetView(UINT8 viewnum) +void G_ResetView(UINT8 viewnum, INT32 playernum) { + UINT8 splits; + UINT8 viewd; + INT32 *displayplayerp; camera_t *camerap; - INT32 newdisplayplayer; - UINT8 viewd, splits; + INT32 olddisplayplayer; + INT32 playersviewable; splits = splitscreen+1; + /* Promote splits */ + if (viewnum > splits) + { + playersviewable = G_CountPlayersPotentiallyViewable(); + if (playersviewable < splits)/* do not demote */ + return; + + if (viewnum > playersviewable) + viewnum = playersviewable; + splitscreen = viewnum-1; + + /* Prepare extra views for G_FindView to pass. */ + for (viewd = splits+1; viewd < viewnum; ++viewd) + { + displayplayerp = (G_GetDisplayplayerPtr(viewd)); + (*displayplayerp) = INT32_MAX; + } + + R_ExecuteSetViewSize(); + } + + /* Focus our target view first so that we don't take its player. */ displayplayerp = (G_GetDisplayplayerPtr(viewnum)); - newdisplayplayer = (*displayplayerp); - (*displayplayerp) = INT32_MAX; - (*displayplayerp) = G_FindView(newdisplayplayer); + olddisplayplayer = (*displayplayerp); + (*displayplayerp) = G_FindView(playernum, viewnum); + if ((*displayplayerp) != olddisplayplayer) + { + camerap = (P_GetCameraPtr(viewnum)); + P_ResetCamera(&players[(*displayplayerp)], camerap); + } if (viewnum > splits) { - splitscreen = viewnum-1; - for (viewd = splits+1; viewd < viewnum; ++viewd) - { - (*(G_GetDisplayplayerPtr(viewd))) = INT32_MAX;/* ensure clean */ - } - /* Initialise views up from current splitscreen. */ - for (viewd = splits+1 ;; ) { displayplayerp = (G_GetDisplayplayerPtr(viewd)); camerap = (P_GetCameraPtr(viewd)); + (*displayplayerp) = G_FindView(0, viewd); + P_ResetCamera(&players[(*displayplayerp)], camerap); - - if (++viewd > viewnum) - break; - - /* Correct up to but viewnum */ - (*displayplayerp) = G_FindView(displayplayer); } - R_ExecuteSetViewSize(); } if (viewnum == 1 && demoplayback) consoleplayer = displayplayer; } +// +// G_AdjustView +// Increment a viewpoint by offset from the current player. A negative value +// decrements. +// +void G_AdjustView(UINT8 viewnum, INT32 offset) +{ + INT32 *displayplayerp; + displayplayerp = G_GetDisplayplayerPtr(viewnum); + G_ResetView(viewnum, ( (*displayplayerp) + offset )); +} + // // G_ResetViews // Ensures all viewpoints are valid +// Also demotes splitscreen down to one player. // void G_ResetViews(void) { - UINT8 viewnum = splitscreen+1; - do + UINT8 splits; + UINT8 viewd; + + INT32 playersviewable; + + splits = splitscreen+1; + + playersviewable = G_CountPlayersPotentiallyViewable(); + /* Demote splits */ + if (playersviewable < splits) { - G_ResetView(viewnum); + splits = playersviewable; + splitscreen = max(splits-1, 0); + R_ExecuteSetViewSize(); + } + + /* + Consider installing a method to focus the last + view elsewhere if all players spectate? + */ + for (viewd = 1; viewd <= splits; ++viewd) + { + G_AdjustView(viewd, 0); } - while (--viewnum > 0) ; } // diff --git a/src/g_game.h b/src/g_game.h index 9d9a47552..9a485ffec 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -228,8 +228,15 @@ boolean G_Responder(event_t *ev); INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); +boolean G_CouldView(INT32 playernum); +boolean G_CanView(INT32 playernum, UINT8 viewnum); + +INT32 G_FindView(INT32 startview, UINT8 viewnum); +INT32 G_CountPlayersPotentiallyViewable(void); + void G_ResetViews(void); -void G_ResetView(UINT8 viewnum); +void G_ResetView(UINT8 viewnum, INT32 playernum); +void G_AdjustView(UINT8 viewnum, INT32 offset); void G_AddPlayer(INT32 playernum); From 06bda79b1b8ec2d3eb67be65c8d230d1ce88956b Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 20:20:31 -0800 Subject: [PATCH 118/382] Fix "Return to title" doing NOTHING during recording --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5e86a092f..93e7a0f3c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7113,7 +7113,7 @@ static void M_ExitGameResponse(INT32 ch) static void M_EndGame(INT32 choice) { (void)choice; - if (demoplayback || demorecording) + if (demoplayback || ( demorecording && !multiplayer ))/* hack for now */ return; if (!Playing()) From 8a0129253f8e59991336f4ff43ccf9f692ab9cec Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 20:21:09 -0800 Subject: [PATCH 119/382] Wait for HU_Responder and friends to finish eating before viewpoint control --- src/g_game.c | 88 ++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 8a8b021cc..fabb66574 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1823,50 +1823,6 @@ static INT32 spectatedelay, spectatedelay2, spectatedelay3, spectatedelay4 = 0; // boolean G_Responder(event_t *ev) { - // allow spy mode changes even during the demo - if (gamestate == GS_LEVEL && ev->type == ev_keydown - && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) - { - if (!demoplayback && (splitscreen || !netgame)) - displayplayer = consoleplayer; - else - { - displayplayer++; - G_ResetView(1); - - // change statusbar also if playing back demo - if (singledemo) - ST_changeDemoView(); - - return true; - } - } - - if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demoplayback) - { - if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) - { - secondarydisplayplayer++; - G_ResetView(2); - - return true; - } - else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) - { - thirddisplayplayer++; - G_ResetView(3); - - return true; - } - else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) - { - fourthdisplayplayer++; - G_ResetView(4); - - return true; - } - } - // any other key pops up menu if in demos if (gameaction == ga_nothing && !singledemo && ((demoplayback && !modeattacking && !titledemo && !multiplayer) || gamestate == GS_TITLESCREEN)) @@ -1944,6 +1900,50 @@ boolean G_Responder(event_t *ev) if (HU_Responder(ev)) return true; // chat ate the event + // allow spy mode changes even during the demo + if (gamestate == GS_LEVEL && ev->type == ev_keydown + && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) + { + if (!demoplayback && (splitscreen || !netgame)) + displayplayer = consoleplayer; + else + { + displayplayer++; + G_ResetView(1); + + // change statusbar also if playing back demo + if (singledemo) + ST_changeDemoView(); + + return true; + } + } + + if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demoplayback) + { + if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) + { + secondarydisplayplayer++; + G_ResetView(2); + + return true; + } + else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) + { + thirddisplayplayer++; + G_ResetView(3); + + return true; + } + else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) + { + fourthdisplayplayer++; + G_ResetView(4); + + return true; + } + } + // update keys current state G_MapEventsToControls(ev); From da428a7150b8038c3c9fbf2b5e3d561dc10e3467 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 14 Feb 2019 00:17:29 -0800 Subject: [PATCH 120/382] Add support for an optional file list embeded in demos Ghosts are also supported. The playback function can read demos without this file list--it is a flag. --- src/g_game.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 8a8b021cc..731354af6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4634,6 +4634,7 @@ char *G_BuildMapTitle(INT32 mapnum) #define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares! #define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? #define DF_ATTACKSHIFT 1 +#define DF_FILELIST 0x08 // This demo contains an extra files list #define DF_GAMETYPEMASK 0x30 #define DF_GAMESHIFT 4 #define DF_ENCORE 0x40 @@ -5766,6 +5767,10 @@ void G_BeginRecording(void) char name[16]; player_t *player = &players[consoleplayer]; + char *filename; + UINT8 totalfiles; + UINT8 *m; + if (demo_p) return; memset(name,0,sizeof(name)); @@ -5775,6 +5780,8 @@ void G_BeginRecording(void) demoflags |= gametype<filename)) + { + nameonly(( filename = va("%s", wadfiles[i]->filename) )); + /* FIXME: maximum size? */ + WRITESTRING(demo_p, filename); + WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); + + totalfiles++; + } + + WRITEUINT8(m, totalfiles); + switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 @@ -5970,6 +5996,81 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap) }*/ } +static void G_LoadDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles; + char filename[MAX_WADPATH]; + UINT8 md5sum[16]; + filestatus_t ncs; + boolean toomany = false; + boolean alreadyloaded; + UINT8 i, j; + + totalfiles = READUINT8((*pp)); + for (i = 0; i < totalfiles; ++i) + { + if (toomany) + SKIPSTRING((*pp)); + else + { + strlcpy(filename, (char *)(*pp), sizeof filename); + SKIPSTRING((*pp)); + } + READMEM((*pp), md5sum, 16); + + if (!toomany) + { + alreadyloaded = false; + + for (j = 0; j < numwadfiles; ++j) + { + if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) + { + alreadyloaded = true; + break; + } + } + + if (alreadyloaded) + continue; + + if (numwadfiles >= MAX_WADFILES) + toomany = true; + else + ncs = findfile(filename, md5sum, false); + + if (toomany || ncs != FS_FOUND) + { + if (toomany) + CONS_Printf("Too many files loaded\n"); + else if (ncs == FS_NOTFOUND) + CONS_Printf("You do not have a copy of %s\n", filename); + else if (ncs == FS_MD5SUMBAD) + CONS_Printf("Checksum mismatch on %s\n", filename); + else + CONS_Printf("Unknown error finding file (%s)\n", filename); + } + else + { + P_AddWadFile(filename); + } + } + } +} + +static void G_SkipDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles; + UINT8 i; + + totalfiles = READUINT8((*pp)); + for (i = 0; i < totalfiles; ++i) + { + SKIPSTRING((*pp));// file name + (*pp) += 16;// md5 + } +} + // Returns bitfield: // 1 == new demo has lower time // 2 == new demo has higher score @@ -6006,6 +6107,10 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 2; // gamemap p += 16; // map md5 flags = READUINT8(p); // demoflags + if (flags & DF_FILELIST) // file list + { + G_SkipDemoExtraFiles(&p); + } aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK); I_Assert(aflags); @@ -6063,6 +6168,10 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 2; // gamemap p += 16; // mapmd5 flags = READUINT8(p); + if (flags & DF_FILELIST) // file list + { + G_SkipDemoExtraFiles(&p); + } if (!(flags & aflags)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); @@ -6213,6 +6322,11 @@ void G_DoPlayDemo(char *defdemoname) demo_p += 16; // mapmd5 demoflags = READUINT8(demo_p); + if (demoflags & DF_FILELIST) + { + G_LoadDemoExtraFiles(&demo_p); + } + modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; multiplayer = !!(demoflags & DF_MULTIPLAYER); gametype = (demoflags & DF_GAMETYPEMASK)>>DF_GAMESHIFT; @@ -6513,6 +6627,10 @@ void G_AddGhost(char *defdemoname) p += 2; // gamemap p += 16; // mapmd5 (possibly check for consistency?) flags = READUINT8(p); + if (flags & DF_FILELIST) + { + G_LoadDemoExtraFiles(&p); + } if (!(flags & DF_GHOST)) { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); @@ -6665,6 +6783,9 @@ void G_UpdateStaffGhostName(lumpnum_t l) UINT16 ghostversion; UINT8 flags; + UINT8 totalfiles; + UINT8 md5sum[16]; + buffer = p = W_CacheLumpNum(l, PU_CACHE); // read demo header @@ -6691,6 +6812,15 @@ void G_UpdateStaffGhostName(lumpnum_t l) p += 2; // gamemap p += 16; // mapmd5 (possibly check for consistency?) flags = READUINT8(p); + if (flags & DF_FILELIST) // file list + { + totalfiles = READUINT8(p); + for (; totalfiles > 0; --totalfiles) + { + SKIPSTRING(p); + READMEM(p, md5sum, 16); + } + } if (!(flags & DF_GHOST)) { goto fail; // we don't NEED to do it here, but whatever From e32db47d42b3ffedde85647fc3105e5d5bfd7696 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 15 Feb 2019 17:30:27 -0800 Subject: [PATCH 121/382] I shouldn't be surprised --- src/d_net.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_net.h b/src/d_net.h index 9cc1bbd2a..e58aa8b2a 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -19,7 +19,7 @@ #define __D_NET__ // Max computers in a game -#define MAXNETNODES 16 +#define MAXNETNODES 16 // THIS is a fucking signed eight bit integer #define BROADCASTADDR MAXNETNODES #define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer #define NETSPLITSCREEN // Kart's splitscreen netgame feature From b0ea03af2a5716e2ccdf96fd5e29bd0f4bed7cfb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 11:52:35 -0600 Subject: [PATCH 122/382] Improve replay resyncing code Notably, it should no longer cause immediate desync warnings if a track starts on a slope. --- src/g_game.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 8a8b021cc..47bb8ac9c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5073,7 +5073,8 @@ void G_WriteGhostTic(mobj_t *ghost) // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. if (abs(ghost->x-oldghost.x) > MAXMOM || abs(ghost->y-oldghost.y) > MAXMOM - || abs(ghost->z-oldghost.z) > MAXMOM) + || abs(ghost->z-oldghost.z) > MAXMOM + || leveltime & 255 == 1) // Hack to enable slightly nicer resyncing { oldghost.x = ghost->x; oldghost.y = ghost->y; @@ -5087,8 +5088,8 @@ void G_WriteGhostTic(mobj_t *ghost) { // For moving normally: // Store one full byte of movement, plus one byte of fractional movement. - INT16 momx = (INT16)((ghost->x-oldghost.x)>>8); - INT16 momy = (INT16)((ghost->y-oldghost.y)>>8); + INT16 momx = (INT16)((ghost->x-oldghost.x + (1<<4))>>8); + INT16 momy = (INT16)((ghost->y-oldghost.y + (1<<4))>>8); if (momx != oldghost.momx || momy != oldghost.momy) { @@ -5098,7 +5099,7 @@ void G_WriteGhostTic(mobj_t *ghost) WRITEINT16(demo_p,momx); WRITEINT16(demo_p,momy); } - momx = (INT16)((ghost->z-oldghost.z)>>8); + momx = (INT16)((ghost->z-oldghost.z + (1<<4))>>8); if (momx != oldghost.momz) { oldghost.momz = momx; @@ -5202,8 +5203,9 @@ void G_WriteGhostTic(mobj_t *ghost) void G_ConsGhostTic(void) { UINT8 ziptic; - UINT16 px,py,pz,gx,gy,gz; + UINT32 px,py,pz,gx,gy,gz; mobj_t *testmo; + UINT32 syncleeway; boolean nightsfail = false; if (!demo_p || !demo_start) @@ -5220,6 +5222,7 @@ void G_ConsGhostTic(void) oldghost.x = READFIXED(demo_p); oldghost.y = READFIXED(demo_p); oldghost.z = READFIXED(demo_p); + syncleeway = 0; } else { @@ -5233,6 +5236,7 @@ void G_ConsGhostTic(void) oldghost.x += oldghost.momx; oldghost.y += oldghost.momy; oldghost.z += oldghost.momz; + syncleeway = FRACUNIT; } if (ziptic & GZT_ANGLE) demo_p++; @@ -5298,14 +5302,14 @@ void G_ConsGhostTic(void) } // Re-synchronise - px = testmo->x>>FRACBITS; - py = testmo->y>>FRACBITS; - pz = testmo->z>>FRACBITS; - gx = oldghost.x>>FRACBITS; - gy = oldghost.y>>FRACBITS; - gz = oldghost.z>>FRACBITS; + px = testmo->x; + py = testmo->y; + pz = testmo->z; + gx = oldghost.x; + gy = oldghost.y; + gz = oldghost.z; - if (nightsfail || px != gx || py != gy || pz != gz) + if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) { if (demosynced) CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); From 0bbff7f6d42addc546d892645106e7f3eb547bb7 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 12:42:24 -0600 Subject: [PATCH 123/382] [WIP, CRASHES] Save ghost data in netreplays --- src/g_game.c | 249 +++++++++++++++++++++++++------------------------- src/g_game.h | 18 ++-- src/p_enemy.c | 2 +- src/p_inter.c | 6 +- src/p_mobj.c | 4 +- src/p_user.c | 20 ++-- 6 files changed, 152 insertions(+), 147 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 47bb8ac9c..0f5c832f7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -320,7 +320,7 @@ static struct { // EZT_HIT UINT16 hits; mobj_t **hitlist; -} ghostext; +} ghostext[MAXPLAYERS]; // Your naming conventions are stupid and useless. // There is no conflict here. @@ -4675,7 +4675,7 @@ static ticcmd_t oldcmd[MAXPLAYERS]; #define EZT_HIT 0x20 // Damaged a mobj #define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) -static mobj_t oldmetal, oldghost; +static mobj_t oldmetal, oldghost[MAXPLAYERS]; void G_SaveMetal(UINT8 **buffer) { @@ -4737,6 +4737,7 @@ void G_ReadDemoExtraData(void) M_Memcpy(name, demo_p, 16); demo_p += 16; SetPlayerSkin(p, name); + CONS_Printf("new skin %d %d\n", players[p].kartspeed, players[p].kartweight); } if (extradata & DXD_COLOR) { @@ -4761,6 +4762,7 @@ void G_ReadDemoExtraData(void) if (extradata & DXD_PLAYSTATE) { extradata = READUINT8(demo_p); + CONS_Printf("player state %d %d\n", p, extradata); // @TODO uhhhhh do something here @@ -4982,71 +4984,71 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) } } -void G_GhostAddThok(void) +void G_GhostAddThok(INT32 playernum) { if (!demorecording || !(demoflags & DF_GHOST)) return; - ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK; + ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_THOK; } -void G_GhostAddSpin(void) +void G_GhostAddSpin(INT32 playernum) { if (!demorecording || !(demoflags & DF_GHOST)) return; - ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN; + ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_SPIN; } -void G_GhostAddRev(void) +void G_GhostAddRev(INT32 playernum) { if (!demorecording || !(demoflags & DF_GHOST)) return; - ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV; + ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_REV; } -void G_GhostAddFlip(void) +void G_GhostAddFlip(INT32 playernum) { if (!demorecording || !(demoflags & DF_GHOST)) return; - ghostext.flags |= EZT_FLIP; + ghostext[playernum].flags |= EZT_FLIP; } -void G_GhostAddColor(ghostcolor_t color) +void G_GhostAddColor(INT32 playernum, ghostcolor_t color) { if (!demorecording || !(demoflags & DF_GHOST)) return; - if (ghostext.lastcolor == (UINT8)color) + if (ghostext[playernum].lastcolor == (UINT8)color) { - ghostext.flags &= ~EZT_COLOR; + ghostext[playernum].flags &= ~EZT_COLOR; return; } - ghostext.flags |= EZT_COLOR; - ghostext.color = (UINT8)color; + ghostext[playernum].flags |= EZT_COLOR; + ghostext[playernum].color = (UINT8)color; } -void G_GhostAddScale(fixed_t scale) +void G_GhostAddScale(INT32 playernum, fixed_t scale) { if (!demorecording || !(demoflags & DF_GHOST)) return; - if (ghostext.lastscale == scale) + if (ghostext[playernum].lastscale == scale) { - ghostext.flags &= ~EZT_SCALE; + ghostext[playernum].flags &= ~EZT_SCALE; return; } - ghostext.flags |= EZT_SCALE; - ghostext.scale = scale; + ghostext[playernum].flags |= EZT_SCALE; + ghostext[playernum].scale = scale; } -void G_GhostAddHit(mobj_t *victim) +void G_GhostAddHit(INT32 playernum, mobj_t *victim) { if (!demorecording || !(demoflags & DF_GHOST)) return; - ghostext.flags |= EZT_HIT; - ghostext.hits++; - ghostext.hitlist = Z_Realloc(ghostext.hitlist, ghostext.hits * sizeof(mobj_t *), PU_LEVEL, NULL); - ghostext.hitlist[ghostext.hits-1] = victim; + ghostext[playernum].flags |= EZT_HIT; + ghostext[playernum].hits++; + ghostext[playernum].hitlist = Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_LEVEL, NULL); + ghostext[playernum].hitlist[ghostext[playernum].hits-1] = victim; } -void G_WriteGhostTic(mobj_t *ghost) +void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) { char ziptic = 0; UINT8 *ziptic_p; @@ -5071,38 +5073,38 @@ void G_WriteGhostTic(mobj_t *ghost) #define MAXMOM (0xFFFF<<8) // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. - if (abs(ghost->x-oldghost.x) > MAXMOM - || abs(ghost->y-oldghost.y) > MAXMOM - || abs(ghost->z-oldghost.z) > MAXMOM - || leveltime & 255 == 1) // Hack to enable slightly nicer resyncing + if (abs(ghost->x-oldghost[playernum].x) > MAXMOM + || abs(ghost->y-oldghost[playernum].y) > MAXMOM + || abs(ghost->z-oldghost[playernum].z) > MAXMOM + || (leveltime & 255) == 1) // Hack to enable slightly nicer resyncing { - oldghost.x = ghost->x; - oldghost.y = ghost->y; - oldghost.z = ghost->z; + oldghost[playernum].x = ghost->x; + oldghost[playernum].y = ghost->y; + oldghost[playernum].z = ghost->z; ziptic |= GZT_XYZ; - WRITEFIXED(demo_p,oldghost.x); - WRITEFIXED(demo_p,oldghost.y); - WRITEFIXED(demo_p,oldghost.z); + WRITEFIXED(demo_p,oldghost[playernum].x); + WRITEFIXED(demo_p,oldghost[playernum].y); + WRITEFIXED(demo_p,oldghost[playernum].z); } else { // For moving normally: // Store one full byte of movement, plus one byte of fractional movement. - INT16 momx = (INT16)((ghost->x-oldghost.x + (1<<4))>>8); - INT16 momy = (INT16)((ghost->y-oldghost.y + (1<<4))>>8); - if (momx != oldghost.momx - || momy != oldghost.momy) + INT16 momx = (INT16)((ghost->x-oldghost[playernum].x + (1<<4))>>8); + INT16 momy = (INT16)((ghost->y-oldghost[playernum].y + (1<<4))>>8); + if (momx != oldghost[playernum].momx + || momy != oldghost[playernum].momy) { - oldghost.momx = momx; - oldghost.momy = momy; + oldghost[playernum].momx = momx; + oldghost[playernum].momy = momy; ziptic |= GZT_MOMXY; WRITEINT16(demo_p,momx); WRITEINT16(demo_p,momy); } - momx = (INT16)((ghost->z-oldghost.z + (1<<4))>>8); - if (momx != oldghost.momz) + momx = (INT16)((ghost->z-oldghost[playernum].z + (1<<4))>>8); + if (momx != oldghost[playernum].momz) { - oldghost.momz = momx; + oldghost[playernum].momz = momx; ziptic |= GZT_MOMZ; WRITEINT16(demo_p,momx); } @@ -5110,9 +5112,9 @@ void G_WriteGhostTic(mobj_t *ghost) // This SHOULD set oldghost.x/y/z to match ghost->x/y/z // but it keeps the fractional loss of one byte, // so it will hopefully be made up for in future tics. - oldghost.x += oldghost.momx<<8; - oldghost.y += oldghost.momy<<8; - oldghost.z += oldghost.momz<<8; + oldghost[playernum].x += oldghost[playernum].momx<<8; + oldghost[playernum].y += oldghost[playernum].momy<<8; + oldghost[playernum].z += oldghost[playernum].momz<<8; } #undef MAXMOM @@ -5120,56 +5122,56 @@ void G_WriteGhostTic(mobj_t *ghost) // Only store the 8 most relevant bits of angle // because exact values aren't too easy to discern to begin with when only 8 angles have different sprites // and it does not affect this mode of movement at all anyway. - if (ghost->angle>>24 != oldghost.angle) + if (ghost->angle>>24 != oldghost[playernum].angle) { - oldghost.angle = ghost->angle>>24; + oldghost[playernum].angle = ghost->angle>>24; ziptic |= GZT_ANGLE; - WRITEUINT8(demo_p,oldghost.angle); + WRITEUINT8(demo_p,oldghost[playernum].angle); } // Store the sprite frame. frame = ghost->frame & 0xFF; - if (frame != oldghost.frame) + if (frame != oldghost[playernum].frame) { - oldghost.frame = frame; + oldghost[playernum].frame = frame; ziptic |= GZT_SPRITE; - WRITEUINT8(demo_p,oldghost.frame); + WRITEUINT8(demo_p,oldghost[playernum].frame); } // Check for sprite set changes sprite = ghost->sprite; - if (sprite != oldghost.sprite) + if (sprite != oldghost[playernum].sprite) { - oldghost.sprite = sprite; - ghostext.flags |= EZT_SPRITE; + oldghost[playernum].sprite = sprite; + ghostext[playernum].flags |= EZT_SPRITE; } - if (ghostext.flags) + if (ghostext[playernum].color == ghostext[playernum].lastcolor) + ghostext[playernum].flags &= ~EZT_COLOR; + if (ghostext[playernum].scale == ghostext[playernum].lastscale) + ghostext[playernum].flags &= ~EZT_SCALE; + + if (ghostext[playernum].flags) { ziptic |= GZT_EXTRA; + WRITEUINT8(demo_p,ghostext[playernum].flags); - if (ghostext.color == ghostext.lastcolor) - ghostext.flags &= ~EZT_COLOR; - if (ghostext.scale == ghostext.lastscale) - ghostext.flags &= ~EZT_SCALE; - - WRITEUINT8(demo_p,ghostext.flags); - if (ghostext.flags & EZT_COLOR) + if (ghostext[playernum].flags & EZT_COLOR) { - WRITEUINT8(demo_p,ghostext.color); - ghostext.lastcolor = ghostext.color; + WRITEUINT8(demo_p,ghostext[playernum].color); + ghostext[playernum].lastcolor = ghostext[playernum].color; } - if (ghostext.flags & EZT_SCALE) + if (ghostext[playernum].flags & EZT_SCALE) { - WRITEFIXED(demo_p,ghostext.scale); - ghostext.lastscale = ghostext.scale; + WRITEFIXED(demo_p,ghostext[playernum].scale); + ghostext[playernum].lastscale = ghostext[playernum].scale; } - if (ghostext.flags & EZT_HIT) + if (ghostext[playernum].flags & EZT_HIT) { - WRITEUINT16(demo_p,ghostext.hits); - for (i = 0; i < ghostext.hits; i++) + WRITEUINT16(demo_p,ghostext[playernum].hits); + for (i = 0; i < ghostext[playernum].hits; i++) { - mobj_t *mo = ghostext.hitlist[i]; + mobj_t *mo = ghostext[playernum].hitlist[i]; WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.) WRITEUINT32(demo_p,mo->type); WRITEUINT16(demo_p,(UINT16)mo->health); @@ -5178,13 +5180,13 @@ void G_WriteGhostTic(mobj_t *ghost) WRITEFIXED(demo_p,mo->z); WRITEANGLE(demo_p,mo->angle); } - Z_Free(ghostext.hitlist); - ghostext.hits = 0; - ghostext.hitlist = NULL; + Z_Free(ghostext[playernum].hitlist); + ghostext[playernum].hits = 0; + ghostext[playernum].hitlist = NULL; } - if (ghostext.flags & EZT_SPRITE) + if (ghostext[playernum].flags & EZT_SPRITE) WRITEUINT8(demo_p,sprite); - ghostext.flags = 0; + ghostext[playernum].flags = 0; } *ziptic_p = ziptic; @@ -5200,7 +5202,7 @@ void G_WriteGhostTic(mobj_t *ghost) // Uses ghost data to do consistency checks on your position. // This fixes desynchronising demos when fighting eggman. -void G_ConsGhostTic(void) +void G_ConsGhostTic(INT32 playernum) { UINT8 ziptic; UINT32 px,py,pz,gx,gy,gz; @@ -5213,29 +5215,29 @@ void G_ConsGhostTic(void) if (!(demoflags & DF_GHOST)) return; // No ghost data to use. - testmo = players[0].mo; + testmo = players[playernum].mo; // Grab ghost data. ziptic = READUINT8(demo_p); if (ziptic & GZT_XYZ) { - oldghost.x = READFIXED(demo_p); - oldghost.y = READFIXED(demo_p); - oldghost.z = READFIXED(demo_p); + oldghost[playernum].x = READFIXED(demo_p); + oldghost[playernum].y = READFIXED(demo_p); + oldghost[playernum].z = READFIXED(demo_p); syncleeway = 0; } else { if (ziptic & GZT_MOMXY) { - oldghost.momx = READINT16(demo_p)<<8; - oldghost.momy = READINT16(demo_p)<<8; + oldghost[playernum].momx = READINT16(demo_p)<<8; + oldghost[playernum].momy = READINT16(demo_p)<<8; } if (ziptic & GZT_MOMZ) - oldghost.momz = READINT16(demo_p)<<8; - oldghost.x += oldghost.momx; - oldghost.y += oldghost.momy; - oldghost.z += oldghost.momz; + oldghost[playernum].momz = READINT16(demo_p)<<8; + oldghost[playernum].x += oldghost[playernum].momx; + oldghost[playernum].y += oldghost[playernum].momy; + oldghost[playernum].z += oldghost[playernum].momz; syncleeway = FRACUNIT; } if (ziptic & GZT_ANGLE) @@ -5305,21 +5307,21 @@ void G_ConsGhostTic(void) px = testmo->x; py = testmo->y; pz = testmo->z; - gx = oldghost.x; - gy = oldghost.y; - gz = oldghost.z; + gx = oldghost[playernum].x; + gy = oldghost[playernum].y; + gz = oldghost[playernum].z; if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) { if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced! %d>%d %d>%d %d>%d\n"), px, gx, py, gy, pz, gz); demosynced = false; P_UnsetThingPosition(testmo); - testmo->x = oldghost.x; - testmo->y = oldghost.y; + testmo->x = oldghost[playernum].x; + testmo->y = oldghost[playernum].y; P_SetThingPosition(testmo); - testmo->z = oldghost.z; + testmo->z = oldghost[playernum].z; } if (*demo_p == DEMOMARKER) @@ -5775,7 +5777,7 @@ void G_BeginRecording(void) memset(name,0,sizeof(name)); demo_p = demobuffer; - demoflags = multiplayer ? DF_MULTIPLAYER : (DF_GHOST|(modeattacking<mo) + for (i = 0; i < MAXPLAYERS; i++) { - oldghost.x = player->mo->x; - oldghost.y = player->mo->y; - oldghost.z = player->mo->z; - oldghost.angle = player->mo->angle; + ghostext[i].lastcolor = ghostext[i].color = GHC_NORMAL; + ghostext[i].lastscale = ghostext[i].scale = FRACUNIT; - // preticker started us gravity flipped - if (player->mo->eflags & MFE_VERTICALFLIP) - ghostext.flags |= EZT_FLIP; + if (players[i].mo) + { + oldghost[i].x = players[i].mo->x; + oldghost[i].y = players[i].mo->y; + oldghost[i].z = players[i].mo->z; + oldghost[i].angle = players[i].mo->angle; + + // preticker started us gravity flipped + if (players[i].mo->eflags & MFE_VERTICALFLIP) + ghostext[i].flags |= EZT_FLIP; + } } } @@ -6409,15 +6410,19 @@ void G_DoPlayDemo(char *defdemoname) P_SetRandSeed(randseed); G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. + for (i = 0; i < MAXPLAYERS; i++) + { + if (players[i].mo) + { + players[i].mo->color = players[i].skincolor; + oldghost[i].x = players[i].mo->x; + oldghost[i].y = players[i].mo->y; + oldghost[i].z = players[i].mo->z; + } + } + if (!multiplayer) { //CV_StealthSetValue(&cv_playercolor, players[0].skincolor); -- as far as I can tell this is more trouble than it's worth - if (players[0].mo) - { - players[0].mo->color = players[0].skincolor; - oldghost.x = players[0].mo->x; - oldghost.y = players[0].mo->y; - oldghost.z = players[0].mo->z; - } // Set saved attribute values // No cheat checking here, because even if they ARE wrong... diff --git a/src/g_game.h b/src/g_game.h index 9d9a47552..6e4f6408e 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -170,15 +170,15 @@ 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_WriteGhostTic(mobj_t *ghost, INT32 playernum); +void G_ConsGhostTic(INT32 playernum); void G_GhostTicker(void); void G_ReadMetalTic(mobj_t *metal); void G_WriteMetalTic(mobj_t *metal); diff --git a/src/p_enemy.c b/src/p_enemy.c index 9d3aa9519..b01f9be67 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -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); } } diff --git a/src/p_inter.c b/src/p_inter.c index dd27858fc..425461d56 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1424,7 +1424,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; // *************** // @@ -3028,7 +3028,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! @@ -3459,7 +3459,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) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 302f50a1e..4be4afd9f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1220,7 +1220,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 @@ -6010,7 +6010,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 } diff --git a/src/p_user.c b/src/p_user.c index 0c1fb11a3..73caa2111 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1708,7 +1708,7 @@ void P_SpawnThokMobj(player_t *player) P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do if (demorecording) - G_GhostAddThok(); + G_GhostAddThok((INT32) (player - players)); } // @@ -2416,12 +2416,12 @@ static void P_CheckInvincibilityTimer(player_t *player) //if (player->powers[pw_shield] & SH_FIREFLOWER) //{ // player->mo->color = SKINCOLOR_WHITE; - // G_GhostAddColor(GHC_FIREFLOWER); + // G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER); //} //else { player->mo->color = player->skincolor; - G_GhostAddColor(GHC_NORMAL); + G_GhostAddColor((INT32) (player - players), GHC_NORMAL); } } @@ -3673,12 +3673,12 @@ static void P_DoSuperStuff(player_t *player) if (player->powers[pw_shield] & SH_FIREFLOWER) { player->mo->color = SKINCOLOR_WHITE; - G_GhostAddColor(GHC_FIREFLOWER); + G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER); } else { player->mo->color = player->skincolor; - G_GhostAddColor(GHC_NORMAL); + G_GhostAddColor((INT32) (player - players), GHC_NORMAL); } if (gametype != GT_COOP) @@ -3714,7 +3714,7 @@ static void P_DoSuperStuff(player_t *player) P_SetScale(spark, player->mo->scale); } - G_GhostAddColor(GHC_SUPER); + G_GhostAddColor((INT32) (player - players), GHC_SUPER); // Ran out of rings while super! if (player->health <= 1 || player->exiting) @@ -3728,12 +3728,12 @@ static void P_DoSuperStuff(player_t *player) if (player->powers[pw_shield] & SH_FIREFLOWER) { player->mo->color = SKINCOLOR_WHITE; - G_GhostAddColor(GHC_FIREFLOWER); + G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER); } else { player->mo->color = player->skincolor; - G_GhostAddColor(GHC_NORMAL); + G_GhostAddColor((INT32) (player - players), GHC_NORMAL); } if (gametype != GT_COOP) @@ -4035,7 +4035,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. // Now spawn the color thok circle. P_SpawnSpinMobj(player, player->revitem); if (demorecording) - G_GhostAddRev(); + G_GhostAddRev((INT32) (player - players)); } } // If not moving up or down, and travelling faster than a speed of four while not holding @@ -7017,7 +7017,7 @@ static void P_MovePlayer(player_t *player) { P_SpawnSpinMobj(player, player->spinitem); if (demorecording) - G_GhostAddSpin(); + G_GhostAddSpin((INT32) (player - players)); } */ From 73639b650408a56db2d248b8f7783e65a091fba1 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:10:58 -0600 Subject: [PATCH 124/382] ??? --- src/p_tick.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index 8b99c5aa6..7e048af59 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -722,10 +722,43 @@ 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 (multiplayer) + { + if (demorecording) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + G_WriteGhostTic(players[i].mo, i); + } + } + if (demoplayback) // Use Ghost data for consistency checks. + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + G_ConsGhostTic(i); + } + } + } + else + { + if (demorecording) + G_WriteGhostTic(players[consoleplayer].mo, consoleplayer); + if (demoplayback) // Use Ghost data for consistency checks. + G_ConsGhostTic(0); + } if (modeattacking) G_GhostTicker(); From 7c0290795e7f6f6f3648421949c4fc04ac523291 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:42:21 -0600 Subject: [PATCH 125/382] Resync items and bumpers in replays --- src/g_game.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 0f5c832f7..cf40d5685 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -317,6 +317,9 @@ static struct { // EZT_SCALE fixed_t scale, lastscale; + // EZT_KART + INT32 kartitem, kartamount, kartbumpers; + // EZT_HIT UINT16 hits; mobj_t **hitlist; @@ -4674,6 +4677,7 @@ static ticcmd_t oldcmd[MAXPLAYERS]; #define EZT_SCALE 0x10 // Changed size #define EZT_HIT 0x20 // Damaged a mobj #define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) +#define EZT_KART 0x80 // SRB2Kart: Changed current held item/quantity and bumpers for battle static mobj_t oldmetal, oldghost[MAXPLAYERS]; @@ -5146,6 +5150,22 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) ghostext[playernum].flags |= EZT_SPRITE; } + if (ghost->player) + { + if ( + ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || + ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || + ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] + ) + { + ghostext[playernum].flags |= EZT_KART; + ghostext[playernum].kartitem = ghost->player->kartstuff[k_itemtype]; + ghostext[playernum].kartamount = ghost->player->kartstuff[k_itemamount]; + ghostext[playernum].kartbumpers = ghost->player->kartstuff[k_bumper]; + + } + } + if (ghostext[playernum].color == ghostext[playernum].lastcolor) ghostext[playernum].flags &= ~EZT_COLOR; if (ghostext[playernum].scale == ghostext[playernum].lastscale) @@ -5186,6 +5206,12 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) } if (ghostext[playernum].flags & EZT_SPRITE) WRITEUINT8(demo_p,sprite); + if (ghostext[playernum].flags & EZT_KART) + { + WRITEINT32(demo_p, ghostext[playernum].kartitem); + WRITEINT32(demo_p, ghostext[playernum].kartamount); + WRITEINT32(demo_p, ghostext[playernum].kartbumpers); + } ghostext[playernum].flags = 0; } @@ -5301,6 +5327,12 @@ void G_ConsGhostTic(INT32 playernum) } if (ziptic & EZT_SPRITE) demo_p++; + if (ziptic & EZT_KART) + { + ghostext[playernum].kartitem = READINT32(demo_p); + ghostext[playernum].kartamount = READINT32(demo_p); + ghostext[playernum].kartbumpers = READINT32(demo_p); + } } // Re-synchronise @@ -5314,7 +5346,7 @@ void G_ConsGhostTic(INT32 playernum) if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) { if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced! %d>%d %d>%d %d>%d\n"), px, gx, py, gy, pz, gz); + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); demosynced = false; P_UnsetThingPosition(testmo); @@ -5324,6 +5356,21 @@ void G_ConsGhostTic(INT32 playernum) testmo->z = oldghost[playernum].z; } + if ( + players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem || + players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount || + players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers + ) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + + players[playernum].kartstuff[k_itemtype] = ghostext[playernum].kartitem; + players[playernum].kartstuff[k_itemamount] = ghostext[playernum].kartamount; + players[playernum].kartstuff[k_bumper] = ghostext[playernum].kartbumpers; + } + if (*demo_p == DEMOMARKER) { // end of demo data stream @@ -5493,6 +5540,8 @@ void G_GhostTicker(void) } if (ziptic & EZT_SPRITE) g->mo->sprite = READUINT8(g->p); + if (ziptic & EZT_KART) + g->p += 12; // kartitem, kartamount, kartbumpers } // Tick ghost colors (Super and Mario Invincibility flashing) @@ -6321,6 +6370,7 @@ void G_DoPlayDemo(char *defdemoname) memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); + memset(&ghostext,0,sizeof(ghostext)); #if defined(SKIPERRORS) && !defined(DEVELOP) if ((VERSION != version || SUBVERSION != subversion) && !skiperrors) From 82b8590fbc1b3ee084d3d13146144c6684c69b01 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:49:31 -0600 Subject: [PATCH 126/382] Backwards compat for old replays --- src/g_game.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index cf40d5685..e0f9e7fb4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -319,6 +319,7 @@ static struct { // EZT_KART INT32 kartitem, kartamount, kartbumpers; + boolean kartresync; //@TODO backwards compat with old replays. remove eventually // EZT_HIT UINT16 hits; @@ -5332,6 +5333,7 @@ void G_ConsGhostTic(INT32 playernum) ghostext[playernum].kartitem = READINT32(demo_p); ghostext[playernum].kartamount = READINT32(demo_p); ghostext[playernum].kartbumpers = READINT32(demo_p); + ghostext[playernum].kartresync = true; } } @@ -5357,9 +5359,10 @@ void G_ConsGhostTic(INT32 playernum) } if ( + ghostext[playernum].kartresync && ( players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem || players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount || - players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers + players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers) ) { if (demosynced) From bceebf7e3ea2818d1a9129722afd3fe9ec97ba21 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:58:32 -0600 Subject: [PATCH 127/382] Remove debug-related code --- src/g_game.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e0f9e7fb4..063e9a60d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4742,7 +4742,6 @@ void G_ReadDemoExtraData(void) M_Memcpy(name, demo_p, 16); demo_p += 16; SetPlayerSkin(p, name); - CONS_Printf("new skin %d %d\n", players[p].kartspeed, players[p].kartweight); } if (extradata & DXD_COLOR) { @@ -4767,9 +4766,6 @@ void G_ReadDemoExtraData(void) if (extradata & DXD_PLAYSTATE) { extradata = READUINT8(demo_p); - CONS_Printf("player state %d %d\n", p, extradata); - - // @TODO uhhhhh do something here switch (extradata) { case DXD_PST_PLAYING: From 7c6226ee9189f2c00e3de1521b141593fd151b63 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 14:24:00 -0600 Subject: [PATCH 128/382] Try to keep the RNG seed in sync --- src/g_game.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- src/g_game.h | 1 + src/lua_baselib.c | 7 +++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 063e9a60d..c455b3c97 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4656,8 +4656,14 @@ char *G_BuildMapTitle(INT32 mapnum) #define DEMOMARKER 0x80 // demoend UINT8 demo_extradata[MAXPLAYERS]; +UINT8 demo_writerng; // 0=no, 1=yes, 2=yes but on a timeout static ticcmd_t oldcmd[MAXPLAYERS]; +#define DW_END 0xFF // End of extradata block +#define DW_RNG 0xFE // Check RNG seed! + +#define DW_EXTRASTUFF 0xFE // Numbers below this are reserved for writing player slot data + // For Metal Sonic and time attack ghosts #define GZT_XYZ 0x01 #define GZT_MOMXY 0x02 @@ -4727,7 +4733,7 @@ void G_ReadDemoExtraData(void) p = READUINT8(demo_p); - while (p != 0xFF) + while (p < DW_EXTRASTUFF) { extradata = READUINT8(demo_p); @@ -4810,6 +4816,24 @@ void G_ReadDemoExtraData(void) p = READUINT8(demo_p); } + while (p != DW_END) + { + INT32 rng; + + switch (p) + { + case DW_RNG: + rng = READUINT32(demo_p); + if (P_GetRandSeed() != rng) + { + P_SetRandSeed(rng); + CONS_Alert(CONS_WARNING, "Random seed has desynced!\n"); + } + } + + p = READUINT8(demo_p); + } + if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) { // end of demo data stream @@ -4857,6 +4881,7 @@ void G_WriteDemoExtraData(void) } if (demo_extradata[i] & DXD_PLAYSTATE) { + demo_writerng = 1; if (!playeringame[i]) WRITEUINT8(demo_p, DXD_PST_LEFT); else if ( @@ -4872,7 +4897,25 @@ void G_WriteDemoExtraData(void) demo_extradata[i] = 0; } - WRITEUINT8(demo_p, 0xFF); + // May not be necessary, but might as well play it safe... + if ((leveltime & 255) == 128) + demo_writerng = 1; + + { + static UINT8 timeout = 0; + + if (timeout) timeout--; + + if (demo_writerng == 1 || (demo_writerng == 2 && timeout == 0)) + { + demo_writerng = 0; + timeout = 16; + WRITEUINT8(demo_p, DW_RNG); + WRITEUINT32(demo_p, P_GetRandSeed()); + } + } + + WRITEUINT8(demo_p, DW_END); } void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) diff --git a/src/g_game.h b/src/g_game.h index 6e4f6408e..73dcb1ce0 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -155,6 +155,7 @@ typedef enum } 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 diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 78f972f87..36becc56c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -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; } From 712bdfd4b639898c648f198c2082e6a106362d71 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 15:49:54 -0600 Subject: [PATCH 129/382] Double default replay size --- src/g_game.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index c455b3c97..434be94eb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5833,7 +5833,8 @@ void G_RecordDemo(const char *name) strcpy(demoname, name); strcat(demoname, ".lmp"); - maxsize = 1024*1024; + //@TODO make a maxdemosize cvar + maxsize = 1024*1024*2; if (M_CheckParm("-maxdemo") && M_IsNextParm()) maxsize = atoi(M_GetNextParm()) * 1024; // if (demobuffer) From d7d029eb9e085cb44b4ba31d9df7624e38d026eb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 16:16:35 -0600 Subject: [PATCH 130/382] Don't prevent exiting games while recording at all --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 93e7a0f3c..59274e858 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7113,7 +7113,7 @@ static void M_ExitGameResponse(INT32 ch) static void M_EndGame(INT32 choice) { (void)choice; - if (demoplayback || ( demorecording && !multiplayer ))/* hack for now */ + if (demoplayback) return; if (!Playing()) From d2b34a0e200271b1cc23d8d32c29f8b50f62757d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 18:29:51 -0600 Subject: [PATCH 131/382] Add cvar for netreplay saving options --- src/d_netcmd.c | 4 ++++ src/g_game.c | 62 +++++++++++++++++++++++++++++--------------------- src/g_game.h | 5 +++- src/p_tick.c | 4 ++++ src/p_user.c | 3 +++ src/y_inter.c | 11 +++++++++ 6 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 802037899..71adfdf08 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -793,6 +793,8 @@ void D_RegisterClientCommands(void) COM_AddCommand("displayplayer", Command_Displayplayer_f); + CV_RegisterVar(&cv_recordmultiplayerdemos); + // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_usegamma); @@ -2502,6 +2504,8 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) LUAh_MapChange(mapnumber); #endif*/ + demosaved = demodefersave = false; + demosavebutton = 0; G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene); if (demoplayback && !timingdemo) precache = true; diff --git a/src/g_game.c b/src/g_game.c index 864c7f43b..84b5f1ca6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -288,8 +288,8 @@ UINT32 timesBeatenWithEmeralds; //UINT32 timesBeatenUltimate; static char demoname[64]; -boolean demorecording; -boolean demoplayback; +boolean demorecording, demosaved, demodefersave, demoplayback; +tic_t demosavebutton; boolean titledemo; // Title Screen demo can be cancelled by any key boolean fromtitledemo; // SRB2Kart: Don't stop the music static UINT8 *demobuffer = NULL; @@ -334,6 +334,9 @@ boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; +static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; +consvar_t cv_recordmultiplayerdemos = {"recordmultiplayerdemos", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + static UINT8 *savebuffer; // Analog Control @@ -3206,6 +3209,9 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); + + if (multiplayer && demorecording && cv_recordmultiplayerdemos.value == 2) + G_SaveDemo(); } } @@ -6990,8 +6996,6 @@ void G_StopDemo(void) boolean G_CheckDemoStatus(void) { - boolean saved; - while (ghosts) { demoghost *next = ghosts->next; @@ -7040,35 +7044,41 @@ boolean G_CheckDemoStatus(void) return true; } - if (demorecording) + if (demorecording && (!multiplayer || cv_recordmultiplayerdemos.value == 2)) { - UINT8 *p = demobuffer+16; // checksum position -#ifdef NOMD5 - UINT8 i; - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - for (i = 0; i < 16; i++, p++) - *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. -#else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. -#endif - saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. - free(demobuffer); - demorecording = false; - - if (modeattacking != ATTACKING_RECORD) - { - if (saved) - CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); - else - CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); - } + G_SaveDemo(); return true; } + demorecording = false; return false; } +void G_SaveDemo(void) +{ + UINT8 *p = demobuffer+16; // checksum position +#ifdef NOMD5 + UINT8 i; + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + for (i = 0; i < 16; i++, p++) + *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. +#else + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. +#endif + demosaved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. + free(demobuffer); + demorecording = false; + + if (modeattacking != ATTACKING_RECORD) + { + if (demosaved) + CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); + else + CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); + } +} + // // G_SetGamestate // diff --git a/src/g_game.h b/src/g_game.h index 73dcb1ce0..458f166b7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -36,7 +36,9 @@ extern boolean playeringame[MAXPLAYERS]; // ====================================== // demoplaying back and demo recording -extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo; +extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo, demosaved, demodefersave; +extern tic_t demosavebutton; +extern consvar_t cv_recordmultiplayerdemos; // Quit after playing a demo from cmdline. extern boolean singledemo; @@ -207,6 +209,7 @@ void G_StopMetalDemo(void); ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); void G_StopDemo(void); boolean G_CheckDemoStatus(void); +void G_SaveDemo(void); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); diff --git a/src/p_tick.c b/src/p_tick.c index 7e048af59..f5d5d5b20 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -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" @@ -737,6 +738,9 @@ void P_Ticker(boolean run) G_WriteGhostTic(players[i].mo, i); } + + if (demosavebutton && demosavebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) + demodefersave = true; } if (demoplayback) // Use Ghost data for consistency checks. { diff --git a/src/p_user.c b/src/p_user.c index 73caa2111..d51c18af1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1835,6 +1835,9 @@ void P_DoPlayerExit(player_t *player) player->powers[pw_spacetime] = 0; player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation + if (player == &players[consoleplayer]) + demosavebutton = leveltime; + /*if (playeringame[player-players] && netgame && !circuitmap) CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/ } diff --git a/src/y_inter.c b/src/y_inter.c index 0ca175078..995cddfe1 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -562,6 +562,11 @@ dotimer: string); } + if (demorecording && cv_recordmultiplayerdemos.value == 1) + V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_ALLOWLOWERCASE|hilicol, "Press Look Backward to save the replay"); + else if (demosaved) + V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_ALLOWLOWERCASE|hilicol, "Replay saved!"); + // Make it obvious that scrambling is happening next round. if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!")); @@ -577,6 +582,12 @@ void Y_Ticker(void) if (intertype == int_none) return; + if (demorecording && cv_recordmultiplayerdemos.value == 1 && (demodefersave || InputDown(gc_lookback, 1))) + { + demodefersave = false; + G_SaveDemo(); + } + // Check for pause or menu up in single player if (paused || P_AutoPause()) return; From 68266a7250cc8ccc22584c9dcb8357e6cf9897ef Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 20:53:15 -0600 Subject: [PATCH 132/382] Fuck you --- src/g_game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_game.c b/src/g_game.c index 5d854beab..bdc149f0b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4881,6 +4881,7 @@ void G_ReadDemoExtraData(void) break; case DXD_PST_SPECTATING: + players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you if (!playeringame[p]) { CL_ClearPlayer(p); From d68e3efc729e64d8ba2e030472e69d4095342597 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 21:07:11 -0600 Subject: [PATCH 133/382] Reset views away from spectators --- src/g_game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_game.c b/src/g_game.c index bdc149f0b..7dccdaf26 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4908,6 +4908,7 @@ void G_ReadDemoExtraData(void) break; } + G_ResetViews(); // maybe these are necessary? if (G_BattleGametype()) K_CheckBumpers(); // SRB2Kart From 5a5264e5dd76b72e0da653d0f4a6dbd4a8bcc558 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 21:55:08 -0600 Subject: [PATCH 134/382] Fix multiplayer ghosts crashing the game sometimes --- src/g_game.c | 95 ++++++++++++++++++++++++++++++++++------------------ src/g_game.h | 2 ++ src/p_tick.c | 22 ++---------- 3 files changed, 67 insertions(+), 52 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 7dccdaf26..d7b2c4d51 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5196,6 +5196,23 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim) ghostext[playernum].hitlist[ghostext[playernum].hits-1] = victim; } +void G_WriteAllGhostTics(void) +{ + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + WRITEUINT8(demo_p, i); + G_WriteGhostTic(players[i].mo, i); + } + WRITEUINT8(demo_p, 0xFF); +} + void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) { char ziptic = 0; @@ -5370,6 +5387,17 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) } } +void G_ConsAllGhostTics(void) +{ + UINT8 p = READUINT8(demo_p); + + while (p != 0xFF) + { + G_ConsGhostTic(p); + p = READUINT8(demo_p); + } +} + // Uses ghost data to do consistency checks on your position. // This fixes desynchronising demos when fighting eggman. void G_ConsGhostTic(INT32 playernum) @@ -5415,7 +5443,7 @@ void G_ConsGhostTic(INT32 playernum) if (ziptic & GZT_SPRITE) demo_p++; if(ziptic & GZT_NIGHTS) { - if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer) + if (!testmo || !testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer) nightsfail = true; else testmo = testmo->tracer; @@ -5480,41 +5508,44 @@ void G_ConsGhostTic(INT32 playernum) } } - // Re-synchronise - px = testmo->x; - py = testmo->y; - pz = testmo->z; - gx = oldghost[playernum].x; - gy = oldghost[playernum].y; - gz = oldghost[playernum].z; - - if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) + if (testmo) { - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; + // Re-synchronise + px = testmo->x; + py = testmo->y; + pz = testmo->z; + gx = oldghost[playernum].x; + gy = oldghost[playernum].y; + gz = oldghost[playernum].z; - P_UnsetThingPosition(testmo); - testmo->x = oldghost[playernum].x; - testmo->y = oldghost[playernum].y; - P_SetThingPosition(testmo); - testmo->z = oldghost[playernum].z; - } + if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; - if ( - ghostext[playernum].kartresync && ( - players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem || - players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount || - players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers) - ) - { - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; + P_UnsetThingPosition(testmo); + testmo->x = oldghost[playernum].x; + testmo->y = oldghost[playernum].y; + P_SetThingPosition(testmo); + testmo->z = oldghost[playernum].z; + } - players[playernum].kartstuff[k_itemtype] = ghostext[playernum].kartitem; - players[playernum].kartstuff[k_itemamount] = ghostext[playernum].kartamount; - players[playernum].kartstuff[k_bumper] = ghostext[playernum].kartbumpers; + if ( + ghostext[playernum].kartresync && ( + players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem || + players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount || + players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers) + ) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + + players[playernum].kartstuff[k_itemtype] = ghostext[playernum].kartitem; + players[playernum].kartstuff[k_itemamount] = ghostext[playernum].kartamount; + players[playernum].kartstuff[k_bumper] = ghostext[playernum].kartbumpers; + } } if (*demo_p == DEMOMARKER) diff --git a/src/g_game.h b/src/g_game.h index 32c314ff5..10a0280bc 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -180,7 +180,9 @@ 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_ReadMetalTic(mobj_t *metal); diff --git a/src/p_tick.c b/src/p_tick.c index f5d5d5b20..b422e9d2c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -728,32 +728,14 @@ void P_Ticker(boolean run) { if (demorecording) { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - G_WriteGhostTic(players[i].mo, i); - } + G_WriteAllGhostTics(); if (demosavebutton && demosavebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) demodefersave = true; } if (demoplayback) // Use Ghost data for consistency checks. { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - G_ConsGhostTic(i); - } + G_ConsAllGhostTics(); } } else From 53fa9299c1193f73b56ca158717d92179eee858c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:06:47 -0600 Subject: [PATCH 135/382] Fix views getting automatically changed in netreplays --- src/g_game.c | 42 ++++++++++++++++++++++++------------------ src/g_game.h | 8 ++++---- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d7b2c4d51..490b55bd0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1915,7 +1915,7 @@ boolean G_Responder(event_t *ev) displayplayer = consoleplayer; else { - G_AdjustView(1, 1); + G_AdjustView(1, 1, true); // change statusbar also if playing back demo if (singledemo) @@ -1929,19 +1929,19 @@ boolean G_Responder(event_t *ev) { if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { - G_AdjustView(2, 1); + G_AdjustView(2, 1, true); return true; } else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) { - G_AdjustView(3, 1); + G_AdjustView(3, 1, true); return true; } else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) { - G_AdjustView(4, 1); + G_AdjustView(4, 1, true); return true; } @@ -2167,30 +2167,30 @@ boolean G_CanView(INT32 playernum, UINT8 viewnum) // Return the next player that can be viewed on a view, wraps forward. // An out of range startview is corrected. // -INT32 G_FindView(INT32 startview, UINT8 viewnum) +INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive) { INT32 i; startview = min(max(startview, 0), MAXPLAYERS); for (i = startview; i < MAXPLAYERS; ++i) { - if (G_CanView(i, viewnum)) + if (onlyactive ? G_CanView(i, viewnum) : (playeringame[i] && !players[i].spectator)) return i; } for (i = 0; i < startview; ++i) { - if (G_CanView(i, viewnum)) + if (onlyactive ? G_CanView(i, viewnum) : (playeringame[i] && !players[i].spectator)) return i; } return -1; } -INT32 G_CountPlayersPotentiallyViewable(void) +INT32 G_CountPlayersPotentiallyViewable(boolean active) { INT32 total = 0; INT32 i; for (i = 0; i < MAXPLAYERS; ++i) { - if (G_CouldView(i)) + if (active ? G_CouldView(i) : (playeringame[i] && !players[i].spectator)) total++; } return total; @@ -2213,7 +2213,7 @@ INT32 *G_GetDisplayplayerPtr(UINT8 viewnum) // Also promotes splitscreen up to available viewable players. // An out of range playernum is corrected. // -void G_ResetView(UINT8 viewnum, INT32 playernum) +void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) { UINT8 splits; UINT8 viewd; @@ -2229,7 +2229,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum) /* Promote splits */ if (viewnum > splits) { - playersviewable = G_CountPlayersPotentiallyViewable(); + playersviewable = G_CountPlayersPotentiallyViewable(onlyactive); if (playersviewable < splits)/* do not demote */ return; @@ -2250,7 +2250,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum) /* Focus our target view first so that we don't take its player. */ displayplayerp = (G_GetDisplayplayerPtr(viewnum)); olddisplayplayer = (*displayplayerp); - (*displayplayerp) = G_FindView(playernum, viewnum); + (*displayplayerp) = G_FindView(playernum, viewnum, onlyactive); if ((*displayplayerp) != olddisplayplayer) { camerap = (P_GetCameraPtr(viewnum)); @@ -2264,7 +2264,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum) displayplayerp = (G_GetDisplayplayerPtr(viewd)); camerap = (P_GetCameraPtr(viewd)); - (*displayplayerp) = G_FindView(0, viewd); + (*displayplayerp) = G_FindView(0, viewd, onlyactive); P_ResetCamera(&players[(*displayplayerp)], camerap); } @@ -2279,11 +2279,16 @@ void G_ResetView(UINT8 viewnum, INT32 playernum) // Increment a viewpoint by offset from the current player. A negative value // decrements. // -void G_AdjustView(UINT8 viewnum, INT32 offset) +void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive) { - INT32 *displayplayerp; + INT32 *displayplayerp, oldview; displayplayerp = G_GetDisplayplayerPtr(viewnum); - G_ResetView(viewnum, ( (*displayplayerp) + offset )); + oldview = (*displayplayerp); + G_ResetView(viewnum, ( (*displayplayerp) + offset ), onlyactive); + + // If no other view could be found, go back to what we had. + if ((*displayplayerp) == -1) + (*displayplayerp) = oldview; } // @@ -2300,7 +2305,7 @@ void G_ResetViews(void) splits = splitscreen+1; - playersviewable = G_CountPlayersPotentiallyViewable(); + playersviewable = G_CountPlayersPotentiallyViewable(false); /* Demote splits */ if (playersviewable < splits) { @@ -2315,7 +2320,7 @@ void G_ResetViews(void) */ for (viewd = 1; viewd <= splits; ++viewd) { - G_AdjustView(viewd, 0); + G_AdjustView(viewd, 0, false); } } @@ -4909,6 +4914,7 @@ void G_ReadDemoExtraData(void) } G_ResetViews(); + // maybe these are necessary? if (G_BattleGametype()) K_CheckBumpers(); // SRB2Kart diff --git a/src/g_game.h b/src/g_game.h index 10a0280bc..20edb3333 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -237,12 +237,12 @@ INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); boolean G_CouldView(INT32 playernum); boolean G_CanView(INT32 playernum, UINT8 viewnum); -INT32 G_FindView(INT32 startview, UINT8 viewnum); -INT32 G_CountPlayersPotentiallyViewable(void); +INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive); +INT32 G_CountPlayersPotentiallyViewable(boolean active); void G_ResetViews(void); -void G_ResetView(UINT8 viewnum, INT32 playernum); -void G_AdjustView(UINT8 viewnum, INT32 offset); +void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive); +void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive); void G_AddPlayer(INT32 playernum); From fb8ca7c7601ac276133a4c19ab5acadf536d1757 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:19:05 -0600 Subject: [PATCH 136/382] Fix replays crashing upon completion --- src/g_game.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 490b55bd0..6dca67fb7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5402,6 +5402,13 @@ void G_ConsAllGhostTics(void) G_ConsGhostTic(p); p = READUINT8(demo_p); } + + if (*demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus(); + return; + } } // Uses ghost data to do consistency checks on your position. From 15f6e3de48c8769f340d2b656da3fb4d71d48b91 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:19:17 -0600 Subject: [PATCH 137/382] Remove unnecessary ResetViews call --- src/d_clisrv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 8ed33d52a..8d8bfca6e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2563,8 +2563,6 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) if (playernum == displayplayer && !demoplayback) displayplayer = consoleplayer; // don't look through someone's view who isn't there - else - G_ResetViews(); #ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[playernum]); From 63d07acc38e74a645ea1827e87beecfa8f819017 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:24:37 -0600 Subject: [PATCH 138/382] Fix duplicated player views from ResetViews --- src/g_game.c | 8 ++++---- src/g_game.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 6dca67fb7..7a81aea59 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2133,13 +2133,13 @@ boolean G_CouldView(INT32 playernum) // G_CanView // Return whether a player can be viewed on a particular view (splitscreen). // -boolean G_CanView(INT32 playernum, UINT8 viewnum) +boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive) { UINT8 splits; UINT8 viewd; INT32 *displayplayerp; - if (!G_CouldView(playernum)) + if (!(onlyactive ? G_CouldView(playernum) : (playeringame[playernum] && !players[playernum].spectator))) return false; splits = splitscreen+1; @@ -2173,12 +2173,12 @@ INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive) startview = min(max(startview, 0), MAXPLAYERS); for (i = startview; i < MAXPLAYERS; ++i) { - if (onlyactive ? G_CanView(i, viewnum) : (playeringame[i] && !players[i].spectator)) + if (G_CanView(i, viewnum, onlyactive)) return i; } for (i = 0; i < startview; ++i) { - if (onlyactive ? G_CanView(i, viewnum) : (playeringame[i] && !players[i].spectator)) + if (G_CanView(i, viewnum, onlyactive)) return i; } return -1; diff --git a/src/g_game.h b/src/g_game.h index 20edb3333..0042e4bf1 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -235,7 +235,7 @@ boolean G_Responder(event_t *ev); INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); boolean G_CouldView(INT32 playernum); -boolean G_CanView(INT32 playernum, UINT8 viewnum); +boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive); INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive); INT32 G_CountPlayersPotentiallyViewable(boolean active); From c00fcfe2ea81e0bdd0b97165d16b1659dac147d5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 10:03:34 -0600 Subject: [PATCH 139/382] Missed a ResetView line --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6d7817240..65e3c0363 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1968,7 +1968,7 @@ static void Command_View_f(void) olddisplayplayer = (*displayplayerp); (*displayplayerp) = playernum; - G_ResetView(viewnum, playernum); + G_ResetView(viewnum, playernum, false); /* The player we wanted was corrected to who it already was. */ if ((*displayplayerp) == olddisplayplayer) From ed16a35795a8913c9581af26bbd6e5220ffc3921 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 10:04:48 -0600 Subject: [PATCH 140/382] Don't force loading files for replays --- src/d_netcmd.c | 5 +- src/f_finale.c | 2 + src/g_game.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++-- src/g_game.h | 2 +- src/m_menu.c | 2 + 5 files changed, 152 insertions(+), 8 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 65e3c0363..7376bc8c8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2003,7 +2003,7 @@ static void Command_Playdemo_f(void) { char name[256]; - if (COM_Argc() != 2) + if (COM_Argc() < 2) { CONS_Printf(M_GetText("playdemo : playback a demo\n")); return; @@ -2027,6 +2027,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)) diff --git a/src/f_finale.c b/src/f_finale.c index b863ea74b..45f9dc1a4 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1080,6 +1080,8 @@ void F_TitleScreenTicker(boolean run) }*/ titledemo = fromtitledemo = true; + demo_ignorefiles = true; + demo_loadfiles = false; G_DoPlayDemo(dname); } } diff --git a/src/g_game.c b/src/g_game.c index c31514aed..4cbf4360e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -287,8 +287,10 @@ UINT32 timesBeaten; UINT32 timesBeatenWithEmeralds; //UINT32 timesBeatenUltimate; +//@TODO put these all in a struct for namespacing purposes? static char demoname[64]; boolean demorecording, demosaved, demodefersave, demoplayback; +boolean demo_loadfiles, demo_ignorefiles; // Demo file loading options tic_t demosavebutton; boolean titledemo; // Title Screen demo can be cancelled by any key boolean fromtitledemo; // SRB2Kart: Don't stop the music @@ -6053,11 +6055,10 @@ void G_BeginRecording(void) totalfiles = 0; for (i = mainwads; ++i < numwadfiles; ) - if (!W_VerifyNMUSlumps(wadfiles[i]->filename)) + if (!wadfiles[i]->important) { nameonly(( filename = va("%s", wadfiles[i]->filename) )); - /* FIXME: maximum size? */ - WRITESTRING(demo_p, filename); + WRITESTRINGN(demo_p, filename, 64); WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); totalfiles++; @@ -6316,6 +6317,87 @@ static void G_SkipDemoExtraFiles(UINT8 **pp) } } +// 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. +static UINT8 G_CheckDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles, filesloaded, nmusfilecount; + char filename[MAX_WADPATH]; + UINT8 md5sum[16]; + boolean toomany = false; + boolean alreadyloaded; + UINT8 i, j; + UINT8 error = 0; + + totalfiles = READUINT8((*pp)); + filesloaded = 0; + for (i = 0; i < totalfiles; ++i) + { + if (toomany) + SKIPSTRING((*pp)); + else + { + strlcpy(filename, (char *)(*pp), sizeof filename); + SKIPSTRING((*pp)); + } + READMEM((*pp), md5sum, 16); + + if (!toomany) + { + alreadyloaded = false; + nmusfilecount = 0; + + for (j = 0; j < numwadfiles; ++j) + { + if (wadfiles[j]->important && j > mainwads) + nmusfilecount++; + else + continue; + + if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) + { + alreadyloaded = true; + + if (i != nmusfilecount-1 && error < DFILE_ERROR_OUTOFORDER) + error |= DFILE_ERROR_OUTOFORDER; + + break; + } + } + + if (alreadyloaded) + { + filesloaded++; + continue; + } + + if (numwadfiles >= MAX_WADFILES) + error = DFILE_ERROR_CANNOTLOAD; + else if (findfile(filename, md5sum, false) != FS_FOUND) + error = DFILE_ERROR_CANNOTLOAD; + else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) + error |= DFILE_ERROR_NOTLOADED; + } else + error = DFILE_ERROR_CANNOTLOAD; + } + + // Get final file count + nmusfilecount = 0; + + for (j = 0; j < numwadfiles; ++j) + if (wadfiles[j]->important && j > mainwads) + nmusfilecount++; + + if (!error && filesloaded < nmusfilecount) + error = DFILE_ERROR_EXTRAFILES; + + return error; +} + // Returns bitfield: // 1 == new demo has lower time // 2 == new demo has higher score @@ -6455,7 +6537,7 @@ void G_DeferedPlayDemo(const char *name) { COM_BufAddText("playdemo \""); COM_BufAddText(name); - COM_BufAddText("\"\n"); + COM_BufAddText("\" -addfiles\n"); } // @@ -6569,7 +6651,61 @@ void G_DoPlayDemo(char *defdemoname) demoflags = READUINT8(demo_p); if (demoflags & DF_FILELIST) { - G_LoadDemoExtraFiles(&demo_p); + if (titledemo) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. + G_SkipDemoExtraFiles(&demo_p); + if (demo_loadfiles) + G_LoadDemoExtraFiles(&demo_p); + else if (demo_ignorefiles) + G_SkipDemoExtraFiles(&demo_p); + else + { + UINT8 error = G_CheckDemoExtraFiles(&demo_p); + + if (error) + { + switch (error) + { + case DFILE_ERROR_NOTLOADED: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), + pdemoname); + break; + + case DFILE_ERROR_OUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), + pdemoname); + break; + + case DFILE_ERROR_CANNOTLOAD: + snprintf(msg, 1024, + M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + + case DFILE_ERROR_EXTRAFILES: + snprintf(msg, 1024, + M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + } + + CONS_Alert(CONS_ERROR, "%s", msg); + if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } + } } modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; @@ -6879,7 +7015,7 @@ void G_AddGhost(char *defdemoname) flags = READUINT8(p); if (flags & DF_FILELIST) { - G_LoadDemoExtraFiles(&p); + G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. } if (!(flags & DF_GHOST)) { @@ -6959,6 +7095,7 @@ void G_AddGhost(char *defdemoname) if (i == numskins) { + //@TODO nah this should fallback CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid character.\n"), pdemoname); Z_Free(pdemoname); Z_Free(buffer); diff --git a/src/g_game.h b/src/g_game.h index 0042e4bf1..4549044b0 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -36,7 +36,7 @@ extern boolean playeringame[MAXPLAYERS]; // ====================================== // demoplaying back and demo recording -extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo, demosaved, demodefersave; +extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo, demosaved, demodefersave, demo_loadfiles, demo_ignorefiles; extern tic_t demosavebutton; extern consvar_t cv_recordmultiplayerdemos; diff --git a/src/m_menu.c b/src/m_menu.c index 59274e858..9776b2f57 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6897,6 +6897,7 @@ static void M_HandleStaffReplay(INT32 choice) break; M_ClearMenus(true); modeattacking = ATTACKING_RECORD; + demo_loadfiles = false; demo_ignorefiles = true; // Just assume that record attack replays have the files needed G_DoPlayDemo(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value)); break; default: @@ -6917,6 +6918,7 @@ static void M_ReplayTimeAttack(INT32 choice) const char *which; M_ClearMenus(true); modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows + demo_loadfiles = false; demo_ignorefiles = true; // Just assume that record attack replays have the files needed if (currentMenu == &SP_ReplayDef) { From 786e8875ae975ce95ff5a0f2a5cb2eb1ffa045be Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 11:52:23 -0600 Subject: [PATCH 141/382] Whoops, saving the wrong file list --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 4cbf4360e..efea06056 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6055,7 +6055,7 @@ void G_BeginRecording(void) totalfiles = 0; for (i = mainwads; ++i < numwadfiles; ) - if (!wadfiles[i]->important) + if (wadfiles[i]->important) { nameonly(( filename = va("%s", wadfiles[i]->filename) )); WRITESTRINGN(demo_p, filename, 64); From 0b927432443c4506548f162f5257757bd2516b98 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 13:13:45 -0600 Subject: [PATCH 142/382] Support netreplays in titledemos TDEMO###, where ### is a number from 1 to 255. --- src/doomdef.h | 4 +-- src/f_finale.c | 18 ++++++++++++++ src/g_game.c | 17 +++++++++++-- src/k_kart.c | 66 +++++++++++++++++++++++++++++--------------------- src/st_stuff.c | 2 +- 5 files changed, 75 insertions(+), 32 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index ab863c6f6..3126a7cae 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -151,8 +151,8 @@ extern FILE *logstream; #else #define VERSION 100 // Game version #define SUBVERSION 3 // more precise version number -#define VERSIONSTRING "v1.0.3" -#define VERSIONSTRINGW L"v1.0.3" +#define VERSIONSTRING "v1.0.3 Netreplays" +#define VERSIONSTRINGW L"v1.0.3 Netreplays" // Hey! If you change this, add 1 to the MODVERSION below! // Otherwise we can't force updates! #endif diff --git a/src/f_finale.c b/src/f_finale.c index 45f9dc1a4..9872fa455 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1024,11 +1024,28 @@ 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; + 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; @@ -1079,6 +1096,7 @@ void F_TitleScreenTicker(boolean run) return; }*/ +loadreplay: titledemo = fromtitledemo = true; demo_ignorefiles = true; demo_loadfiles = false; diff --git a/src/g_game.c b/src/g_game.c index efea06056..fe6df0918 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6653,7 +6653,7 @@ void G_DoPlayDemo(char *defdemoname) { if (titledemo) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. G_SkipDemoExtraFiles(&demo_p); - if (demo_loadfiles) + else if (demo_loadfiles) G_LoadDemoExtraFiles(&demo_p); else if (demo_ignorefiles) G_SkipDemoExtraFiles(&demo_p); @@ -6839,6 +6839,7 @@ void G_DoPlayDemo(char *defdemoname) if (multiplayer) { boolean spectator; + UINT8 slots[MAXPLAYERS], numslots = 0; // Load players that were in-game when the map started p = READUINT8(demo_p); @@ -6850,6 +6851,7 @@ void G_DoPlayDemo(char *defdemoname) spectator = true; p &= ~DEMO_SPECTATOR; } + slots[numslots] = p; numslots++; if (!playeringame[displayplayer] || players[displayplayer].spectator) displayplayer = consoleplayer = secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = p; @@ -6895,6 +6897,17 @@ void G_DoPlayDemo(char *defdemoname) } splitscreen = 0; + + if (titledemo) + { + splitscreen = min(min(3, numslots-1), max(0, M_RandomKey(6)-1)); // Bias toward 1p and 4p views + + for (p = 0; p <= splitscreen; p++) + G_ResetView(p+1, slots[M_RandomKey(numslots)], false); + + CONS_Printf("%d - %d %d %d %d\n", splitscreen, displayplayer, secondarydisplayplayer, thirddisplayplayer, fourthdisplayplayer); + } + R_ExecuteSetViewSize(); } @@ -7438,7 +7451,7 @@ boolean G_CheckDemoStatus(void) if (singledemo) I_Quit(); - if (multiplayer) + if (multiplayer && !titledemo) G_ExitLevel(); else { diff --git a/src/k_kart.c b/src/k_kart.c index e5cbc9c58..5d99d3144 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8107,19 +8107,12 @@ static void K_drawInput(void) if (timeinmap < 113) { INT32 count = ((INT32)(timeinmap) - 105); - offs = (titledemo ? 128 : 64); + offs = 64; while (count-- > 0) offs >>= 1; x += offs; } - if (titledemo) - { - V_DrawTinyScaledPatch(x-54, 128, splitflags, W_CachePatchName("TTKBANNR", PU_CACHE)); - V_DrawTinyScaledPatch(x-54, 128+25, splitflags, W_CachePatchName("TTKART", PU_CACHE)); - return; - } - #define BUTTW 8 #define BUTTH 11 @@ -8413,7 +8406,7 @@ void K_drawKartHUD(void) && comeback && stplyr->playerstate == PST_LIVE))); - if (!battlefullscreen || splitscreen) + if (!titledemo && (!battlefullscreen || splitscreen)) { // Draw the CHECK indicator before the other items, so it's overlapped by everything else if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) @@ -8428,7 +8421,7 @@ void K_drawKartHUD(void) K_drawKartWanted(); } - if (cv_kartminimap.value && !titledemo) + if (cv_kartminimap.value) { #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_minimap)) @@ -8469,26 +8462,45 @@ void K_drawKartHUD(void) } if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode - { - if (G_RaceGametype()) // Race-only elements - { - if (!titledemo) - { - // Draw the lap counter -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_gametypeinfo)) -#endif - K_drawKartLaps(); + { + if (titledemo) // Draw title logo instead in titledemos + { + INT32 x = BASEVIDWIDTH - 32, y = 128, offs; + + if (splitscreen == 3) + { + x = BASEVIDWIDTH/2 + 10; + y = BASEVIDHEIGHT/2 - 30; + } - if (!splitscreen) - { - // Draw the speedometer - // TODO: Make a better speedometer. + if (timeinmap < 113) + { + INT32 count = ((INT32)(timeinmap) - 104); + offs = 256; + while (count-- > 0) + offs >>= 1; + x += offs; + } + + V_DrawTinyScaledPatch(x-54, y, 0, W_CachePatchName("TTKBANNR", PU_CACHE)); + V_DrawTinyScaledPatch(x-54, y+25, 0, W_CachePatchName("TTKART", PU_CACHE)); + } + else if (G_RaceGametype()) // Race-only elements + { + // Draw the lap counter #ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_speedometer)) + if (LUA_HudEnabled(hud_gametypeinfo)) #endif - K_drawKartSpeedometer(); - } + K_drawKartLaps(); + + if (!splitscreen) + { + // Draw the speedometer + // TODO: Make a better speedometer. +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_speedometer)) +#endif + K_drawKartSpeedometer(); } if (isfreeplay) diff --git a/src/st_stuff.c b/src/st_stuff.c index ef40fae23..73700e1a0 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1907,7 +1907,7 @@ static void ST_overlayDrawer(void) V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]); } } - else + else if (!titledemo) { if (!splitscreen) From 9a1296702031a15b5a69ef0c5d8b99729622d8e0 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 17 Feb 2019 23:39:00 +0100 Subject: [PATCH 143/382] Expose battlefullscreen and battlecomebacktimer huds to lua --- src/k_kart.c | 18 +++++++++++++++--- src/lua_hud.h | 2 ++ src/lua_hudlib.c | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b006ae3bb..39da4a229 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7838,6 +7838,11 @@ static void K_drawBattleFullscreen(void) INT32 y = -64+(stplyr->kartstuff[k_cardanimation]); // card animation goes from 0 to 164, 164 is the middle of the screen INT32 splitflags = V_SNAPTOTOP; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead fixed_t scale = FRACUNIT; + boolean drawcomebacktimer = true; // lazy hack because it's cleaner in the long run. +#ifdef HAVE_BLUA + if (!LUA_HudEnabled(hud_battlecomebacktimer)) + drawcomebacktimer = false; +#endif if (splitscreen) { @@ -7889,7 +7894,7 @@ static void K_drawBattleFullscreen(void) else K_drawKartFinish(); } - else if (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback && !stplyr->spectator) + else if (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback && !stplyr->spectator && drawcomebacktimer) { UINT16 t = stplyr->kartstuff[k_comebacktimer]/(10*TICRATE); INT32 txoff, adjust = (splitscreen > 1) ? 4 : 6; // normal string is 8, kart string is 12, half of that for ease @@ -8449,8 +8454,15 @@ void K_drawKartHUD(void) if (battlefullscreen) { - K_drawBattleFullscreen(); - return; +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_battlefullscreen)) + { +#endif + K_drawBattleFullscreen(); + return; +#ifdef HAVE_BLUA + } // yes we legit checked if we had lua to close a single bracket. Not my proudest code edit tbh. +#endif } // Draw the item window diff --git a/src/lua_hud.h b/src/lua_hud.h index 4fbbbace4..88d7fd6bc 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -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, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index cd8e03923..e0a360ade 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -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", From 97a663745ac04d5796305ec46b6f371a79224b08 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:51:02 -0600 Subject: [PATCH 144/382] Use generic resync message for RNG desyncs --- src/g_game.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index fe6df0918..e65b65711 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4940,7 +4940,10 @@ void G_ReadDemoExtraData(void) if (P_GetRandSeed() != rng) { P_SetRandSeed(rng); - CONS_Alert(CONS_WARNING, "Random seed has desynced!\n"); + + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; } } From bca918cdbff88c68e8f1dffa6261a7474d909362 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:51:28 -0600 Subject: [PATCH 145/382] Let titledemos play while game is unfocused --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index d51c18af1..6b23f67f5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -169,7 +169,7 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move) boolean P_AutoPause(void) { // Don't pause even on menu-up or focus-lost in netgames or record attack - if (netgame || modeattacking) + if (netgame || modeattacking || titledemo) return false; return (menuactive || window_notinfocus); From b176ca27b3ba50e66865e41f07da73909cbd9a3c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:52:21 -0600 Subject: [PATCH 146/382] For now, only use netreplays on the title if available --- src/f_finale.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 9872fa455..1426e50d2 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1024,14 +1024,15 @@ void F_TitleScreenTicker(boolean run) // is it time? if (!(--demoIdleLeft)) { - static boolean use_netreplay = false; + //static boolean use_netreplay = false; char dname[9]; lumpnum_t l; const char *mapname; UINT8 numstaff; - if ((use_netreplay = !use_netreplay)) + //@TODO uncomment this when this goes into vanilla + /*if ((use_netreplay = !use_netreplay))*/ { numstaff = 1; while ((l = W_CheckNumForName(va("TDEMO%03u", numstaff))) != LUMPERROR) From b731e63d76c925fa2486f8b438ef68f1ca9f7d55 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:54:37 -0600 Subject: [PATCH 147/382] Remove debug print --- src/g_game.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e65b65711..19c40a19f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6907,8 +6907,6 @@ void G_DoPlayDemo(char *defdemoname) for (p = 0; p <= splitscreen; p++) G_ResetView(p+1, slots[M_RandomKey(numslots)], false); - - CONS_Printf("%d - %d %d %d %d\n", splitscreen, displayplayer, secondarydisplayplayer, thirddisplayplayer, fourthdisplayplayer); } R_ExecuteSetViewSize(); From 35148c48c049a466a6f9708cb0ff8ad23aa62e58 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 21:08:11 -0600 Subject: [PATCH 148/382] Crash fix I think (CHERRY PICK INTO BASE) --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index c1a847a13..84ca4a1a5 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -651,7 +651,7 @@ void R_DrawMaskedColumn(column_t *column) basetexturemid = dc_texturemid; - for (; column->topdelta != 0xff ;) + for (; column && column->topdelta != 0xff ;) { // calculate unclipped screen coordinates // for post From ae3348e24db4e6970d921f26a357c171e75fa87e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 21:23:05 -0600 Subject: [PATCH 149/382] Allow viewing karma bombs during replays --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 19c40a19f..22daab231 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2097,7 +2097,7 @@ boolean G_CouldView(INT32 playernum) return false; // I don't know if we want this actually, but I'll humor the suggestion anyway - if (G_BattleGametype()) + if (G_BattleGametype() && !demoplayback) { if (player->kartstuff[k_bumper] <= 0) return false; From 5e6b3a650c035db73553911f6d93334bf30740e7 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 21:33:15 -0600 Subject: [PATCH 150/382] Force intermission to 10 seconds on replays --- src/y_inter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/y_inter.c b/src/y_inter.c index 995cddfe1..24c4f93e1 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -780,6 +780,8 @@ void Y_StartIntermission(void) { if (cv_inttime.value == 0 && gametype == GT_COOP) timer = 0; + else if (demoplayback) // Override inttime (which is pulled from the replay anyway + timer = 10*TICRATE; else { timer = cv_inttime.value*TICRATE; From a5a98eec2ff1febbc45db27a88dc3a88d7d8eac2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Feb 2019 17:33:02 -0600 Subject: [PATCH 151/382] Fix count limiter not always working right for titledemo netreplays --- src/g_game.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 22daab231..452c55056 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6903,7 +6903,8 @@ void G_DoPlayDemo(char *defdemoname) if (titledemo) { - splitscreen = min(min(3, numslots-1), max(0, M_RandomKey(6)-1)); // Bias toward 1p and 4p views + splitscreen = M_RandomKey(6)-1; + splitscreen = min(min(3, numslots-1), max(0, splitscreen)); // Bias toward 1p and 4p views for (p = 0; p <= splitscreen; p++) G_ResetView(p+1, slots[M_RandomKey(numslots)], false); From 030428fc9e5637730f219e31fc7e37f6526a2d64 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Feb 2019 19:26:32 -0600 Subject: [PATCH 152/382] Maybe this is a better way to work around the DrawMasked crash... --- src/r_things.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 84ca4a1a5..9816ca22f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -651,7 +651,7 @@ void R_DrawMaskedColumn(column_t *column) basetexturemid = dc_texturemid; - for (; column && column->topdelta != 0xff ;) + for (; column->topdelta != 0xff ;) { // calculate unclipped screen coordinates // for post @@ -925,6 +925,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)<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 From a991af5c6ac18af4c2fa38e052d816f75ed1eab6 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 20 Feb 2019 18:58:17 -0800 Subject: [PATCH 153/382] Remove jitters in view command --- src/d_netcmd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7376bc8c8..c18379aa9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1967,7 +1967,6 @@ static void Command_View_f(void) } olddisplayplayer = (*displayplayerp); - (*displayplayerp) = playernum; G_ResetView(viewnum, playernum, false); /* The player we wanted was corrected to who it already was. */ From a3c2c97a7561179baf1d342ac88dd70c9ce8ed02 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 16:33:45 -0800 Subject: [PATCH 154/382] Add setviews command --- src/d_netcmd.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7376bc8c8..bb10afd9f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -130,6 +130,7 @@ 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); @@ -719,6 +720,8 @@ void D_RegisterClientCommands(void) 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); @@ -1993,6 +1996,37 @@ static void Command_View_f(void) } #undef PRINTVIEWPOINT +static void Command_SetViews_f(void) +{ + UINT8 splits; + UINT8 newsplits; + + if (!( demoplayback && multiplayer )) + { + CONS_Alert(CONS_NOTICE, + "You must be viewing a multiplayer replay to use this.\n"); + return; + } + + if (COM_Argc() != 2) + { + CONS_Printf("setviews : 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); + else + { + splitscreen = newsplits-1; + R_ExecuteSetViewSize(); + } +} + // ======================================================================== // play a demo, add .lmp for external demos From 5c041126d6b8b73365ee99a3cff3f08919b7f684 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 16:30:50 -0800 Subject: [PATCH 155/382] Add race placement criteria to view command --- src/d_netcmd.c | 85 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 9 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c18379aa9..cc75822d3 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1925,6 +1925,44 @@ static INT32 LookupPlayer(const char *s) 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)]); @@ -1933,7 +1971,10 @@ 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 */ @@ -1947,7 +1988,8 @@ static void Command_View_f(void) if (viewnum > 1 && !( multiplayer && demoplayback )) { - CONS_Alert(CONS_NOTICE, "You must be viewing a multiplayer replay.\n"); + CONS_Alert(CONS_NOTICE, + "You must be viewing a multiplayer replay to use this.\n"); return; } @@ -1955,15 +1997,41 @@ static void Command_View_f(void) if (COM_Argc() > 1)/* switch to player */ { - if (( playernum = LookupPlayer(COM_Argv(1)) ) == -1) + playerparam = COM_Argv(1); + if (playerparam[0] == '#')/* search by placement */ { - CONS_Alert(CONS_WARNING, "There is no player by that name!\n"); - return; + 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; + } } - if (!playeringame[playernum]) + else { - CONS_Alert(CONS_WARNING, "There is no player using that slot!\n"); - return; + 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); @@ -1976,8 +2044,7 @@ static void Command_View_f(void) if ((*displayplayerp) != playernum)/* differ parameter */ { /* skipped some */ - CONS_Alert(CONS_NOTICE, - "Another viewpoint is already set to that player.\n"); + CONS_Alert(CONS_NOTICE, "That player cannot be viewed currently.\n"); PRINTVIEWPOINT ("Now "," instead") } else From e984c3d86801c38ac1adbe430d3c92a60e2cec67 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 20 Feb 2019 19:25:56 -0800 Subject: [PATCH 156/382] Document the playdemo command --- src/d_netcmd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7376bc8c8..7ec02edaa 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2005,7 +2005,12 @@ static void Command_Playdemo_f(void) if (COM_Argc() < 2) { - CONS_Printf(M_GetText("playdemo : playback a demo\n")); + CONS_Printf("playdemo [-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; } From 4f5d698d80887046800207e693c8108f73828892 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 21 Feb 2019 19:44:18 -0500 Subject: [PATCH 157/382] Add command to ban an IP address. --- src/d_clisrv.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2529b05d0..8ba356b68 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2627,6 +2627,42 @@ static void Command_Ban(void) } +static void Command_BanIP(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("banip : ban an ip address\n")); + return; + } + + if (server) // Only the server can use this, otherwise does nothing. + { + const char *address = (COM_Argv(1)); + const char *reason; + + if (COM_Argc() == 2) + reason = NULL; + else + reason = COM_Argv(2); + + + if (I_SetBanAddress && I_SetBanAddress(address, NULL)) + { + if (reason) + CONS_Printf("Banned IP address %s for: %s\n", address, reason); + else + CONS_Printf("Banned IP address %s\n", address); + + Ban_Add(reason); + D_SaveBan(); + } + else + { + return; + } + } +} + static void Command_Kick(void) { if (COM_Argc() < 2) @@ -2906,6 +2942,7 @@ void D_ClientServerInit(void) COM_AddCommand("getplayernum", Command_GetPlayerNum); COM_AddCommand("kick", Command_Kick); COM_AddCommand("ban", Command_Ban); + COM_AddCommand("banip", Command_BanIP); COM_AddCommand("clearbans", Command_ClearBans); COM_AddCommand("showbanlist", Command_ShowBan); COM_AddCommand("reloadbans", Command_ReloadBan); From deb58b0e68505ae4c75c9eb0374d2a724313fd6b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 18 Feb 2019 01:03:39 -0500 Subject: [PATCH 158/382] Save ban list right after banning. --- src/d_clisrv.c | 3 +++ src/djgppdos/i_system.c | 3 --- src/sdl12/i_system.c | 3 --- src/win32/win_sys.c | 3 --- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 8ba356b68..f3b1451a4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2596,7 +2596,10 @@ static void Command_Ban(void) else { if (server) // only the server is allowed to do this right now + { Ban_Add(COM_Argv(2)); + D_SaveBan(); // save the ban list + } if (COM_Argc() == 2) { diff --git a/src/djgppdos/i_system.c b/src/djgppdos/i_system.c index dae9ed16e..5413bfdb4 100644 --- a/src/djgppdos/i_system.c +++ b/src/djgppdos/i_system.c @@ -615,9 +615,6 @@ void I_Quit (void) //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. M_SaveConfig (NULL); //save game config, cvars.. -#ifndef NONET - D_SaveBan(); // save the ban list -#endif G_SaveGameData(); // Tails 12-08-2002 if (demorecording) G_CheckDemoStatus(); diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index 10fbc50ee..e9b292449 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -2282,9 +2282,6 @@ void I_Quit(void) quiting = SDL_FALSE; I_ShutdownConsole(); M_SaveConfig(NULL); //save game config, cvars.. -#ifndef NONET - D_SaveBan(); // save the ban list -#endif G_SaveGameData(); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 77a21f7f3..8b7adf7c6 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -639,9 +639,6 @@ void I_Error(const char *error, ...) if (!errorcount) { M_SaveConfig(NULL); // save game config, cvars.. -#ifndef NONET - D_SaveBan(); // save the ban list -#endif G_SaveGameData(); } From 512b001aa048fec29ad5c5910a18fbd799cc2612 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 18 Feb 2019 02:04:58 -0500 Subject: [PATCH 159/382] Save when quitting the game. Also use default reason if not custom reason is given. --- src/djgppdos/i_system.c | 3 +++ src/sdl12/i_system.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/djgppdos/i_system.c b/src/djgppdos/i_system.c index 5413bfdb4..dae9ed16e 100644 --- a/src/djgppdos/i_system.c +++ b/src/djgppdos/i_system.c @@ -615,6 +615,9 @@ void I_Quit (void) //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. M_SaveConfig (NULL); //save game config, cvars.. +#ifndef NONET + D_SaveBan(); // save the ban list +#endif G_SaveGameData(); // Tails 12-08-2002 if (demorecording) G_CheckDemoStatus(); diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index e9b292449..10fbc50ee 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -2282,6 +2282,9 @@ void I_Quit(void) quiting = SDL_FALSE; I_ShutdownConsole(); M_SaveConfig(NULL); //save game config, cvars.. +#ifndef NONET + D_SaveBan(); // save the ban list +#endif G_SaveGameData(); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. From a2820e0f51cfef0a26e006767da3d0cbc2c94242 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 19 Feb 2019 21:22:35 -0500 Subject: [PATCH 160/382] Some small changes. From 1124c06220c23f7e469be2fdccd4f815569854ba Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 21 Feb 2019 22:54:09 -0800 Subject: [PATCH 161/382] I am pretty dumb --- src/d_netcmd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7376bc8c8..4bfb6f2e6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1916,8 +1916,7 @@ static INT32 LookupPlayer(const char *s) { /* Match name case-insensitively: fully, or partially the start. */ if (playeringame[playernum]) - if (stricmp(player_names[playernum], s) == 0 || - strnicmp(player_names[playernum], s, strlen(s)) == 0) + if (strnicmp(player_names[playernum], s, strlen(s)) == 0) { return playernum; } From bfcb6cc67ea9cf4367a2dd9d037b0899bf2c59e5 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 24 Feb 2019 17:47:33 -0800 Subject: [PATCH 162/382] Try to fix compiler errors --- src/command.c | 6 +++--- src/command.h | 2 +- src/g_game.c | 2 +- src/st_stuff.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/command.c b/src/command.c index 50692c67d..886fc85f4 100644 --- a/src/command.c +++ b/src/command.c @@ -1355,7 +1355,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) Setvalue(cvar, svalue, stealth); } -void CV_SaveNetVars(UINT8 **p, boolean demorecording) +void CV_SaveNetVars(UINT8 **p, boolean isdemorecording) { consvar_t *cvar; UINT8 *count_p = *p; @@ -1365,12 +1365,12 @@ void CV_SaveNetVars(UINT8 **p, boolean demorecording) // 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)) || (demorecording && cvar->netid == cv_numlaps.netid)) + if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (isdemorecording && cvar->netid == cv_numlaps.netid)) { WRITEUINT16(*p, cvar->netid); // UGLY HACK: Save proper lap count in net replays - if (demorecording && cvar->netid == cv_numlaps.netid) + if (isdemorecording && cvar->netid == cv_numlaps.netid) { if (cv_basenumlaps.value && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) diff --git a/src/command.h b/src/command.h index 70bf74a93..71cef9d94 100644 --- a/src/command.h +++ b/src/command.h @@ -160,7 +160,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, boolean demorecording); +void CV_SaveNetVars(UINT8 **p, boolean isdemorecording); void CV_LoadNetVars(UINT8 **p); // reset cheat netvars after cheats is deactivated diff --git a/src/g_game.c b/src/g_game.c index 47bb8ac9c..24804458d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5074,7 +5074,7 @@ void G_WriteGhostTic(mobj_t *ghost) if (abs(ghost->x-oldghost.x) > MAXMOM || abs(ghost->y-oldghost.y) > MAXMOM || abs(ghost->z-oldghost.z) > MAXMOM - || leveltime & 255 == 1) // Hack to enable slightly nicer resyncing + || ( leveltime & 255 == 1 )) // Hack to enable slightly nicer resyncing { oldghost.x = ghost->x; oldghost.y = ghost->y; diff --git a/src/st_stuff.c b/src/st_stuff.c index 53a1506ec..b9046abda 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1918,9 +1918,9 @@ static void ST_overlayDrawer(void) else if (splitscreen == 1) { char name[MAXPLAYERNAME+12]; - sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); INT32 y = (stplyr == &players[displayplayer]) ? 8 : BASEVIDHEIGHT/2-16; + sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name); } else if (splitscreen) From 64508edabc5c7c2c91dd61f4ac625bdaa01025a3 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 24 Feb 2019 17:59:13 -0800 Subject: [PATCH 163/382] d'oh --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 24804458d..53a48a9b7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5074,7 +5074,7 @@ void G_WriteGhostTic(mobj_t *ghost) if (abs(ghost->x-oldghost.x) > MAXMOM || abs(ghost->y-oldghost.y) > MAXMOM || abs(ghost->z-oldghost.z) > MAXMOM - || ( leveltime & 255 == 1 )) // Hack to enable slightly nicer resyncing + || ( leveltime & 255 ) == 1) // Hack to enable slightly nicer resyncing { oldghost.x = ghost->x; oldghost.y = ghost->y; From e7952e4de709aa23d4377480c3cea6a2efbb51b1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 26 Feb 2019 21:14:22 +0000 Subject: [PATCH 164/382] Make sure that B_CheckRespawn can be called even if Tails is dead --- src/p_user.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index e4cb01f63..285d36ca9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8688,8 +8688,11 @@ void P_PlayerThink(player_t *player) if (player->bot) { - if (player->playerstate == PST_LIVE && B_CheckRespawn(player)) - player->playerstate = PST_REBORN; + if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD) + { + if (B_CheckRespawn(player)) + player->playerstate = PST_REBORN; + } if (player->playerstate == PST_REBORN) return; } From 7fc180604b73a258cebd14be4dd3de48f475d2dc Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 27 Feb 2019 15:55:39 -0500 Subject: [PATCH 165/382] Upped MAXNETNODES --- src/d_net.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_net.h b/src/d_net.h index 61c669dbb..8e8afcffa 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -20,6 +20,7 @@ // Max computers in a game #define MAXNETNODES 32 +#define MAXNETNODES (MAXPLAYERS+4) #define BROADCASTADDR MAXNETNODES #define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer //#define NETSPLITSCREEN // Kart's splitscreen netgame feature From c748882d0430293a2af645f25602bd09ad837edb Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 27 Feb 2019 16:05:43 -0500 Subject: [PATCH 166/382] Remove double define --- src/d_net.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_net.h b/src/d_net.h index 8e8afcffa..3d1058702 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -19,7 +19,6 @@ #define __D_NET__ // Max computers in a game -#define MAXNETNODES 32 #define MAXNETNODES (MAXPLAYERS+4) #define BROADCASTADDR MAXNETNODES #define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer From fcbe62bbe2e70ee47710099b416515b011ad8bbc Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:24:35 -0600 Subject: [PATCH 167/382] Assign a server player in replays for Lua purposes Unfortunately this doesn't seem to help sync much. It at least prevents constant Lua errors I guess.... --- src/dehacked.c | 2 +- src/g_game.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 11aed24d0..4c3b35a3e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9812,7 +9812,7 @@ static inline int lib_getenum(lua_State *L) lua_pushinteger(L, mapmusflags); return 1; } else if (fastcmp(word,"server")) { - if ((!multiplayer || !netgame) && !playeringame[serverplayer]) + if ((!multiplayer || !(netgame || demoplayback)) && !playeringame[serverplayer]) return 0; LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); return 1; diff --git a/src/g_game.c b/src/g_game.c index 452c55056..219bc8157 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6847,6 +6847,8 @@ void G_DoPlayDemo(char *defdemoname) // Load players that were in-game when the map started p = READUINT8(demo_p); + secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = INT32_MAX; + while (p != 0xFF) { spectator = false; @@ -6857,7 +6859,7 @@ void G_DoPlayDemo(char *defdemoname) slots[numslots] = p; numslots++; if (!playeringame[displayplayer] || players[displayplayer].spectator) - displayplayer = consoleplayer = secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = p; + displayplayer = consoleplayer = serverplayer = p; /*else if (!spectator && splitscreen < 3) { if (splitscreen == 0) { splitscreen = 1; From 2cecd2faf390d0e680228adfa443c2865aeda385 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:25:22 -0600 Subject: [PATCH 168/382] Cleanup :3c --- src/g_game.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 219bc8157..d1252d58f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6860,18 +6860,7 @@ void G_DoPlayDemo(char *defdemoname) if (!playeringame[displayplayer] || players[displayplayer].spectator) displayplayer = consoleplayer = serverplayer = p; - /*else if (!spectator && splitscreen < 3) { - if (splitscreen == 0) { - splitscreen = 1; - secondarydisplayplayer = p; - } else if (splitscreen == 1) { - splitscreen = 2; - thirddisplayplayer = p; - } else { - splitscreen = 3; - fourthdisplayplayer = p; - } - }*/ + playeringame[p] = true; players[p].spectator = spectator; From 3918d5e1778b2b95cf23292c3008177dd4a69979 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:33:59 -0600 Subject: [PATCH 169/382] Fix missing argument in G_AdjustView call --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 84f4b5894..80d1fcea4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2084,7 +2084,7 @@ static void Command_SetViews_f(void) newsplits = atoi(COM_Argv(1)); newsplits = min(max(newsplits, 1), 4); if (newsplits > splits) - G_AdjustView(newsplits, 0); + G_AdjustView(newsplits, 0, true); else { splitscreen = newsplits-1; From 8d6c6823f3bf44c8eb8f3199799a413ee713aca4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:41:20 -0600 Subject: [PATCH 170/382] Maintain compat for record attack replays --- src/g_game.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d1252d58f..10774621f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6031,7 +6031,10 @@ void G_BeginRecording(void) demoflags |= gametype<important) + if (demoflags & DF_FILELIST) { - nameonly(( filename = va("%s", wadfiles[i]->filename) )); - WRITESTRINGN(demo_p, filename, 64); - WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); + // file list + m = demo_p;/* file count */ + demo_p += 1; - totalfiles++; + totalfiles = 0; + for (i = mainwads; ++i < numwadfiles; ) + if (wadfiles[i]->important) + { + nameonly(( filename = va("%s", wadfiles[i]->filename) )); + WRITESTRINGN(demo_p, filename, 64); + WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); + + totalfiles++; + } + + WRITEUINT8(m, totalfiles); } - WRITEUINT8(m, totalfiles); - switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 From cb12da81c1ec80df1d2276bdf7a22d20eec94be5 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 3 Mar 2019 20:02:49 -0800 Subject: [PATCH 171/382] Use correct signedness in comparison --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 10774621f..29a598ac6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4931,7 +4931,7 @@ void G_ReadDemoExtraData(void) while (p != DW_END) { - INT32 rng; + UINT32 rng; switch (p) { From 45236434af8916c34981459194b76ccabf4caab6 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 3 Mar 2019 20:08:28 -0800 Subject: [PATCH 172/382] Remove always true expression --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 29a598ac6..048978961 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6901,7 +6901,7 @@ void G_DoPlayDemo(char *defdemoname) if (titledemo) { splitscreen = M_RandomKey(6)-1; - splitscreen = min(min(3, numslots-1), max(0, splitscreen)); // Bias toward 1p and 4p views + splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views for (p = 0; p <= splitscreen; p++) G_ResetView(p+1, slots[M_RandomKey(numslots)], false); From e93a721ca1fd4dc8b860c56823bd5ab17fe9ee7e Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 19:07:34 -0500 Subject: [PATCH 173/382] Fixup unsigned mess --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 10774621f..29a598ac6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4931,7 +4931,7 @@ void G_ReadDemoExtraData(void) while (p != DW_END) { - INT32 rng; + UINT32 rng; switch (p) { From bcebe2fcc2d30972863efbce90681ec38feffa64 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 19:10:43 -0500 Subject: [PATCH 174/382] Fixup max() mess --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 29a598ac6..048978961 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6901,7 +6901,7 @@ void G_DoPlayDemo(char *defdemoname) if (titledemo) { splitscreen = M_RandomKey(6)-1; - splitscreen = min(min(3, numslots-1), max(0, splitscreen)); // Bias toward 1p and 4p views + splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views for (p = 0; p <= splitscreen; p++) G_ResetView(p+1, slots[M_RandomKey(numslots)], false); From 55d07235a496225cc2954c4b1bf0aa9ef6c39a8f Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 19:16:46 -0500 Subject: [PATCH 175/382] do not overshadow demorecording --- src/command.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/command.c b/src/command.c index 50692c67d..886fc85f4 100644 --- a/src/command.c +++ b/src/command.c @@ -1355,7 +1355,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) Setvalue(cvar, svalue, stealth); } -void CV_SaveNetVars(UINT8 **p, boolean demorecording) +void CV_SaveNetVars(UINT8 **p, boolean isdemorecording) { consvar_t *cvar; UINT8 *count_p = *p; @@ -1365,12 +1365,12 @@ void CV_SaveNetVars(UINT8 **p, boolean demorecording) // 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)) || (demorecording && cvar->netid == cv_numlaps.netid)) + if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (isdemorecording && cvar->netid == cv_numlaps.netid)) { WRITEUINT16(*p, cvar->netid); // UGLY HACK: Save proper lap count in net replays - if (demorecording && cvar->netid == cv_numlaps.netid) + if (isdemorecording && cvar->netid == cv_numlaps.netid) { if (cv_basenumlaps.value && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) From c68cfbdda01b64fd50c09815fd65090066ccc8bf Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:09:20 -0500 Subject: [PATCH 176/382] =?UTF-8?q?Avoid=20=E2=80=98ncs=E2=80=99=20being?= =?UTF-8?q?=20used=20uninitialized?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/g_game.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 048978961..e3a1f3cd7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6294,11 +6294,13 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) else ncs = findfile(filename, md5sum, false); - if (toomany || ncs != FS_FOUND) + if (toomany) { - if (toomany) - CONS_Printf("Too many files loaded\n"); - else if (ncs == FS_NOTFOUND) + CONS_Printf("Too many files loaded\n"); + } + else if (ncs != FS_FOUND) + { + if (ncs == FS_NOTFOUND) CONS_Printf("You do not have a copy of %s\n", filename); else if (ncs == FS_MD5SUMBAD) CONS_Printf("Checksum mismatch on %s\n", filename); From c209e211aea3936e949916b2d3264b60c7205feb Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:26:44 -0500 Subject: [PATCH 177/382] Fixed comparing unsigned/signed mess --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index e3a1f3cd7..62bc4d8d3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5422,7 +5422,7 @@ void G_ConsAllGhostTics(void) void G_ConsGhostTic(INT32 playernum) { UINT8 ziptic; - UINT32 px,py,pz,gx,gy,gz; + fixed_t px,py,pz,gx,gy,gz; mobj_t *testmo; UINT32 syncleeway; boolean nightsfail = false; From 8b5f25caa08e5bc5a895f487eb370f484f7f01aa Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:27:01 -0500 Subject: [PATCH 178/382] the READ/WRITE marcos do not need ; --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 62bc4d8d3..4671b4dab 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7218,8 +7218,8 @@ void G_UpdateStaffGhostName(lumpnum_t l) totalfiles = READUINT8(p); for (; totalfiles > 0; --totalfiles) { - SKIPSTRING(p); - READMEM(p, md5sum, 16); + SKIPSTRING(p) + READMEM(p, md5sum, 16) } } if (!(flags & DF_GHOST)) From 95c2967f358a12a0863ada3c46990f06962161f0 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:35:13 -0500 Subject: [PATCH 179/382] more unsigned mess --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 4671b4dab..19b062da0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5424,7 +5424,7 @@ void G_ConsGhostTic(INT32 playernum) UINT8 ziptic; fixed_t px,py,pz,gx,gy,gz; mobj_t *testmo; - UINT32 syncleeway; + fixed_t syncleeway; boolean nightsfail = false; if (!demo_p || !demo_start) From 6949781ca2c5ac722208c9c8b6ccb51cf722f726 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 4 Mar 2019 22:26:05 -0800 Subject: [PATCH 180/382] Do not record replays when dedicated --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index de250b1fa..0c9ea8c7b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3164,7 +3164,7 @@ boolean P_SetupLevel(boolean skipprecip) : mapheaderinfo[gamemap - 1]->numlaps); //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. - if (!demoplayback && multiplayer) { + if (!demoplayback && multiplayer && !dedicated) { static char buf[256]; sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap)); From 03783a589dfcb63ab83495c738030e410a902de0 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Tue, 5 Mar 2019 11:29:00 -0500 Subject: [PATCH 181/382] fix EOL in k_kart.c --- src/k_kart.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 1732f69c9..7a5b77872 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6397,9 +6397,9 @@ INT32 K_calcSplitFlags(INT32 snapflags) splitflags |= V_SPLITSCREEN; } else if (splitscreen > 1) - { - if (stplyr == &players[thirddisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) - splitflags |= V_SPLITSCREEN; + { + if (stplyr == &players[thirddisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) + splitflags |= V_SPLITSCREEN; if (stplyr == &players[secondarydisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) splitflags |= V_HORZSCREEN; } @@ -8468,16 +8468,16 @@ void K_drawKartHUD(void) } if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode - { - if (titledemo) // Draw title logo instead in titledemos - { - INT32 x = BASEVIDWIDTH - 32, y = 128, offs; - - if (splitscreen == 3) - { - x = BASEVIDWIDTH/2 + 10; - y = BASEVIDHEIGHT/2 - 30; - } + { + if (titledemo) // Draw title logo instead in titledemos + { + INT32 x = BASEVIDWIDTH - 32, y = 128, offs; + + if (splitscreen == 3) + { + x = BASEVIDWIDTH/2 + 10; + y = BASEVIDHEIGHT/2 - 30; + } if (timeinmap < 113) { @@ -8487,10 +8487,10 @@ void K_drawKartHUD(void) offs >>= 1; x += offs; } - + V_DrawTinyScaledPatch(x-54, y, 0, W_CachePatchName("TTKBANNR", PU_CACHE)); V_DrawTinyScaledPatch(x-54, y+25, 0, W_CachePatchName("TTKART", PU_CACHE)); - } + } else if (G_RaceGametype()) // Race-only elements { // Draw the lap counter From 5b369ad21ec4d04cd622ef9987eeb24522c73684 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 5 Mar 2019 19:04:15 -0500 Subject: [PATCH 182/382] Allow names to be used with forceskin --- src/d_netcmd.c | 25 +++++++------------------ src/r_things.c | 10 ++++++++++ src/r_things.h | 2 ++ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a8efd3066..d8412d3c7 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -422,7 +422,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}; @@ -513,6 +513,11 @@ const char *netxcmdnames[MAXNETXCMD - 1] = */ void D_RegisterServerCommands(void) { + Forceskin_cons_t[0].value = -1; + Forceskin_cons_t[0].strvalue = "Off"; + Forceskin_cons_t[MAXSKINS].value = 0; + Forceskin_cons_t[MAXSKINS].strvalue = NULL; + RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor); RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref); RegisterNetXCmd(XD_MAP, Got_Mapcmd); @@ -5021,27 +5026,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 */ 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; @@ -5050,7 +5039,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); } } diff --git a/src/r_things.c b/src/r_things.c index 59a904cbd..4b3eee871 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -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+1]; + static void R_InitSkins(void); #define MINZ (FRACUNIT*4) @@ -2614,6 +2616,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) @@ -3038,6 +3044,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); diff --git a/src/r_things.h b/src/r_things.h index 01d8fc071..0a92b3c23 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -115,6 +115,8 @@ typedef struct sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table } skin_t; +extern CV_PossibleValue_t Forceskin_cons_t[]; + // ----------- // NOT SKINS STUFF ! // ----------- From 92d463d4227a5afa74c00190d99f9ffecb11feb4 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 6 Mar 2019 18:06:16 -0800 Subject: [PATCH 183/382] Check that G_FindView actually found a view --- src/g_game.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 19b062da0..828003467 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2249,10 +2249,13 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) R_ExecuteSetViewSize(); } + /* Check if anyone is available to view. */ + if (( playernum = G_FindView(playernum, viewnum, onlyactive) ) == -1) + return; /* Focus our target view first so that we don't take its player. */ displayplayerp = (G_GetDisplayplayerPtr(viewnum)); olddisplayplayer = (*displayplayerp); - (*displayplayerp) = G_FindView(playernum, viewnum, onlyactive); + (*displayplayerp) = playernum; if ((*displayplayerp) != olddisplayplayer) { camerap = (P_GetCameraPtr(viewnum)); From df8a5ffc1e65f5eef48199dbbb4fa1ae5ff4ab3e Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 11 Mar 2019 22:11:36 -0400 Subject: [PATCH 184/382] Change array size from MAXSKINS+1 to MAXSKINS+2 Also Set the values to 0/NULl, it will be overwritten later when a skin is assigned to the slot. --- src/d_netcmd.c | 10 ++++++++-- src/r_things.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 26743b739..98e9c6e5a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -514,10 +514,16 @@ const char *netxcmdnames[MAXNETXCMD - 1] = */ void D_RegisterServerCommands(void) { + int i; Forceskin_cons_t[0].value = -1; Forceskin_cons_t[0].strvalue = "Off"; - Forceskin_cons_t[MAXSKINS].value = 0; - Forceskin_cons_t[MAXSKINS].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); diff --git a/src/r_things.c b/src/r_things.c index f0acaae56..3ea5ebade 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -40,7 +40,7 @@ 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+1]; +CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; static void R_InitSkins(void); From 832a6433c23b05b3ec077067c2e20435834e42a3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 19:42:29 -0400 Subject: [PATCH 185/382] Remove MP3 warning --- src/sdl/mixer_sound.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 04e82ea34..dde62fc7a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1037,12 +1037,6 @@ boolean I_LoadSong(char *data, size_t len) return false; } - if (I_SongType() == MU_MP3) - { - CONS_Debug(DBG_BASIC, "MP3 songs are unsupported and may crash! Use OGG instead.\n"); - CONS_Debug(DBG_DETAILED, "MP3 songs are unsupported and may crash! Use OGG instead.\n"); - } - // Find the OGG loop point. loop_point = 0.0f; song_length = 0.0f; From 06f4f355ffd441d5db627e35f82e83f009669f7c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 19:44:24 -0400 Subject: [PATCH 186/382] Fix custom fade source bug for Change Music linedef --- src/p_spec.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index e8dc80a75..f3be86ee1 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2414,8 +2414,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) 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 : 0, -1); + INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1); + // Seek offset from current song position if (line->flags & ML_EFFECT1) { // adjust for loop point if subtracting @@ -2427,8 +2428,14 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) position = max(S_GetMusicPosition() + position, 0); } + // 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; + if (!postfadems) S_SetInternalMusicVolume(fadetarget); else @@ -2437,6 +2444,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (position) S_SetMusicPosition(position); } + // Change the music and apply position/fade operations else { strncpy(mapmusname, sides[line->sidenum[0]].text, 7); From aa22941d2cec637279705c539351a5cae41782b5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 21:18:23 -0400 Subject: [PATCH 187/382] Restore MUSIC_RELOADRESET if block in g_game --- src/g_game.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 0992d55a7..c0cb469a1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2263,6 +2263,22 @@ void G_PlayerReborn(INT32 player) if ((netgame || multiplayer) && !p->spectator) p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + if (p-players == consoleplayer) + { + if (mapmusflags & MUSIC_RELOADRESET) + { + strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); + mapmusname[6] = 0; + mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); + mapmusposition = mapheaderinfo[gamemap-1]->muspos; + } + + // This is in S_Start, but this was not here previously. + // if (cv_resetmusic.value) + // S_StopMusic(); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); + } + if (gametype == GT_COOP) P_FindEmerald(); // scan for emeralds to hunt for From 2c823703f9a11071a736aad60456fbb5a4f64fa0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 23:17:35 -0400 Subject: [PATCH 188/382] When changing to same music, reset the internal volume --- src/s_sound.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/s_sound.c b/src/s_sound.c index 89eb697cc..f3e330847 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1523,6 +1523,11 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 I_SetSongPosition(position); I_FadeSong(100, fadeinms, NULL); } + else // reset volume to 100 with same music + { + I_StopFadingSong(); + I_SetInternalMusicVolume(100); + } } void S_StopMusic(void) From bdb9e8cfda9a13d3955ce13d77271adb93c82ec6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 23:55:30 -0400 Subject: [PATCH 189/382] When resetting volume on same music, make it fade instead of a hard change --- src/s_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index f3e330847..acb7dcbbe 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1526,7 +1526,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 else // reset volume to 100 with same music { I_StopFadingSong(); - I_SetInternalMusicVolume(100); + I_FadeSong(100, 500, NULL); } } From 1381343a2e4fbcf5fcd2bebe2dd9e265638f4620 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 15 Mar 2019 01:00:50 -0400 Subject: [PATCH 190/382] Implement MUSICINTERFADEOUT level header --- src/dehacked.c | 2 ++ src/doomstat.h | 1 + src/lua_maplib.c | 2 ++ src/p_setup.c | 2 ++ src/y_inter.c | 8 ++++++-- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 6978dd16a..bda0c38f7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1198,6 +1198,8 @@ static void readlevelheader(MYFILE *f, INT32 num) 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)); diff --git a/src/doomstat.h b/src/doomstat.h index 716c4d654..d9132798f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -248,6 +248,7 @@ typedef struct nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. // Music stuff. + UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds char musintername[7]; ///< Intermission screen music. // Lua stuff. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index d77e636b3..35542fdce 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1470,6 +1470,8 @@ static int mapheaderinfo_get(lua_State *L) 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")) diff --git a/src/p_setup.c b/src/p_setup.c index 4409ec356..033e99f10 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -189,6 +189,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) 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); diff --git a/src/y_inter.c b/src/y_inter.c index e6e5a1d22..1b7796efa 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -697,7 +697,9 @@ void Y_Ticker(void) if (!intertic) // first time only { - if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) + if (mapheaderinfo[gamemap-1]->musinterfadeout) + S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout); + else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it else S_ChangeMusicInternal("lclear", false); // don't loop it @@ -762,7 +764,9 @@ void Y_Ticker(void) if (!intertic) // first time only { - if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) + if (mapheaderinfo[gamemap-1]->musinterfadeout) + S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout); + else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it else S_ChangeMusicInternal("lclear", false); // don't loop it From a40c6f01250df03786a3e7812ee258e80396514e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 15 Mar 2019 01:26:13 -0400 Subject: [PATCH 191/382] Intermission: Don't fade out level music when using win32 midi volume hack --- src/y_inter.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 1b7796efa..ed4972d2e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -697,7 +697,12 @@ void Y_Ticker(void) if (!intertic) // first time only { - if (mapheaderinfo[gamemap-1]->musinterfadeout) + if (mapheaderinfo[gamemap-1]->musinterfadeout +#ifdef _WIN32 + // can't fade midi due to win32 volume hack + && S_MusicType() != MU_MID +#endif + ) S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout); else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it @@ -764,7 +769,12 @@ void Y_Ticker(void) if (!intertic) // first time only { - if (mapheaderinfo[gamemap-1]->musinterfadeout) + if (mapheaderinfo[gamemap-1]->musinterfadeout +#ifdef _WIN32 + // can't fade midi due to win32 volume hack + && S_MusicType() != MU_MID +#endif + ) S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout); else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it From 5d059da843915a7de0675cddf22464061bd2772a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 18 Mar 2019 22:00:23 +0000 Subject: [PATCH 192/382] Added the Gametype_Names array and G_GetGametypeByName for ease in converting gametype nums to strings and vice versa gametype_cons_t is now initialised using the Gametype_Names array, like how Color_cons_t is initialised using Color_Names # Conflicts: # src/doomstat.h # src/m_menu.c --- src/d_clisrv.c | 12 ++------ src/d_main.c | 10 ++----- src/d_netcmd.c | 76 +++++++++++++++++++++----------------------------- src/doomstat.h | 5 +++- src/g_game.c | 32 +++++++++++++++++++++ src/g_game.h | 1 + src/hu_stuff.c | 22 +++++++-------- src/m_menu.c | 27 ++++-------------- 8 files changed, 90 insertions(+), 95 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a0f9f40ab..31fec14fa 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2056,17 +2056,11 @@ static void CL_ConnectToServer(boolean viams) if (i != -1) { - INT32 j; + UINT8 num = serverlist[i].info.gametype; const char *gametypestr = NULL; 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, diff --git a/src/d_main.c b/src/d_main.c index 1782e94f5..527031fa8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1362,13 +1362,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) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 11b9413a8..71ec55de2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -409,6 +409,16 @@ const char *netxcmdnames[MAXNETXCMD - 1] = */ void D_RegisterServerCommands(void) { + INT32 i; + + 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; + RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor); RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref); RegisterNetXCmd(XD_MAP, Got_Mapcmd); @@ -1639,7 +1649,7 @@ static void Command_Map_f(void) { const char *mapname; size_t i; - INT32 j, newmapnum; + INT32 newmapnum; boolean newresetplayers; INT32 newgametype = gametype; @@ -1707,27 +1717,13 @@ static void Command_Map_f(void) return; } - for (j = 0; gametype_cons_t[j].strvalue; j++) - if (!strcasecmp(gametype_cons_t[j].strvalue, COM_Argv(i+1))) - { - // Don't do any variable setting here. Wait until you get your - // map packet first to avoid sending the same info twice! - newgametype = gametype_cons_t[j].value; + newgametype = G_GetGametypeByName(COM_Argv(i+1)); - break; - } - - if (!gametype_cons_t[j].strvalue) // reached end of the list with no match + if (newgametype == -1) // reached end of the list with no match { - // assume they gave us a gametype number, which is okay too - for (j = 0; gametype_cons_t[j].strvalue != NULL; j++) - { - if (atoi(COM_Argv(i+1)) == gametype_cons_t[j].value) - { - newgametype = gametype_cons_t[j].value; - break; - } - } + INT32 j = atoi(COM_Argv(i+1)); // assume they gave us a gametype number, which is okay too + if (j >= 0 && j < NUMGAMETYPES) + newgametype = (INT16)j; } } @@ -1742,12 +1738,11 @@ static void Command_Map_f(void) char gametypestring[32] = "Single Player"; if (multiplayer) - for (i = 0; gametype_cons_t[i].strvalue != NULL; i++) - if (gametype_cons_t[i].value == newgametype) - { - strcpy(gametypestring, gametype_cons_t[i].strvalue); - break; - } + { + if (newgametype >= 0 && newgametype < NUMGAMETYPES + && Gametype_Names[newgametype]) + strcpy(gametypestring, Gametype_Names[newgametype]); + } CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname, gametypestring); return; @@ -3486,7 +3481,6 @@ static void Command_ModDetails_f(void) // static void Command_ShowGametype_f(void) { - INT32 j; const char *gametypestr = NULL; if (!(netgame || multiplayer)) // print "Single player" instead of "Co-op" @@ -3494,15 +3488,11 @@ static void Command_ShowGametype_f(void) CONS_Printf(M_GetText("Current gametype is %s\n"), M_GetText("Single player")); return; } - // find name string for current gametype - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == gametype) - { - gametypestr = gametype_cons_t[j].strvalue; - break; - } - } + + // 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) @@ -3644,15 +3634,13 @@ void D_GameTypeChanged(INT32 lastgametype) { if (netgame) { - INT32 j; const char *oldgt = NULL, *newgt = NULL; - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == lastgametype) - oldgt = gametype_cons_t[j].strvalue; - if (gametype_cons_t[j].value == gametype) - newgt = gametype_cons_t[j].strvalue; - } + + 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); } diff --git a/src/doomstat.h b/src/doomstat.h index d9132798f..8050a1beb 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -318,7 +318,10 @@ enum GameType NUMGAMETYPES }; -// 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; diff --git a/src/g_game.c b/src/g_game.c index c0cb469a1..f9477f91e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2698,6 +2698,38 @@ void G_ExitLevel(void) } } +// See also the enum GameType in doomstat.h +const char *Gametype_Names[NUMGAMETYPES] = +{ + "Co-op", // GT_COOP + "Competition", // GT_COMPETITION + "Race", // GT_RACE + + "Match", // GT_MATCH + "Team Match", // GT_TEAMMATCH + + "Tag", // GT_TAG + "Hide and Seek", // GT_HIDEANDSEEK + + "CTF" // GT_CTF +}; + +// +// G_GetGametypeByName +// +// Returns the number for the given gametype name string, or -1 if not valid. +// +INT32 G_GetGametypeByName(const char *gametypestr) +{ + INT32 i; + + for (i = 0; i < NUMGAMETYPES; i++) + if (!stricmp(gametypestr, Gametype_Names[i])) + return i; + + return -1; // unknown gametype +} + // // G_IsSpecialStage // diff --git a/src/g_game.h b/src/g_game.h index 5259eacbb..87ddb3103 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -163,6 +163,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); void G_StopDemo(void); boolean G_CheckDemoStatus(void); +INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); boolean G_GametypeHasTeams(void); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e34e5c35c..f624e39de 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1952,19 +1952,17 @@ static void HU_DrawCEcho(void) static void HU_drawGametype(void) { - INT32 i = 0; + const char *strvalue = NULL; - for (i = 0; gametype_cons_t[i].strvalue; i++) - { - if (gametype_cons_t[i].value == gametype) - { - if (splitscreen) - V_DrawString(4, 184, 0, gametype_cons_t[i].strvalue); - else - V_DrawString(4, 192, 0, gametype_cons_t[i].strvalue); - return; - } - } + if (gametype < 0 || gametype >= NUMGAMETYPES) + return; // not a valid gametype??? + + strvalue = Gametype_Names[gametype]; + + if (splitscreen) + V_DrawString(4, 184, 0, strvalue); + else + V_DrawString(4, 192, 0, strvalue); } // diff --git a/src/m_menu.c b/src/m_menu.c index 65647d2a6..a833ace21 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -347,23 +347,9 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; // This gametype list is integral for many different reasons. -// When you add gametypes here, don't forget to update them in CV_AddValue! -CV_PossibleValue_t gametype_cons_t[] = -{ - {GT_COOP, "Co-op"}, +// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! +CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; - {GT_COMPETITION, "Competition"}, - {GT_RACE, "Race"}, - - {GT_MATCH, "Match"}, - {GT_TEAMMATCH, "Team Match"}, - - {GT_TAG, "Tag"}, - {GT_HIDEANDSEEK, "Hide and Seek"}, - - {GT_CTF, "CTF"}, - {0, NULL} -}; consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t serversort_cons_t[] = { @@ -6545,7 +6531,7 @@ static void M_DrawRoomMenu(void) static void M_DrawConnectMenu(void) { - UINT16 i, j; + UINT16 i; const char *gt = "Unknown"; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; @@ -6591,11 +6577,8 @@ static void M_DrawConnectMenu(void) va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); gt = "Unknown"; - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == serverlist[slindex].info.gametype) - gt = gametype_cons_t[j].strvalue; - } + if (serverlist[slindex].info.gametype < NUMGAMETYPES) + gt = Gametype_Names[serverlist[slindex].info.gametype]; V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); From 4be82dc30f5a078f89a7941881b50ef8144d1668 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 22:59:27 -0500 Subject: [PATCH 193/382] Don't resync position until off for two tics in a row This patches over a few trouble spots, like Misty Maze, causing consistent resyncs and screwing up playback. --- src/g_game.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 313156d31..02f703167 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -323,6 +323,8 @@ static struct { INT32 kartitem, kartamount, kartbumpers; boolean kartresync; //@TODO backwards compat with old replays. remove eventually + UINT8 desyncframes; // Don't try to resync unless we've been off for two frames, to monkeypatch a few trouble spots + // EZT_HIT UINT16 hits; mobj_t **hitlist; @@ -5548,16 +5550,25 @@ void G_ConsGhostTic(INT32 playernum) if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) { - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; + ghostext[playernum].desyncframes++; - P_UnsetThingPosition(testmo); - testmo->x = oldghost[playernum].x; - testmo->y = oldghost[playernum].y; - P_SetThingPosition(testmo); - testmo->z = oldghost[playernum].z; + if (ghostext[playernum].desyncframes >= 2) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + + P_UnsetThingPosition(testmo); + testmo->x = oldghost[playernum].x; + testmo->y = oldghost[playernum].y; + P_SetThingPosition(testmo); + testmo->z = oldghost[playernum].z; + + ghostext[playernum].desyncframes = 2; + } } + else + ghostext[playernum].desyncframes = 0; if ( ghostext[playernum].kartresync && ( From d6167ef35ae75e24b171d2c6c027907d45fe419e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:02:17 -0500 Subject: [PATCH 194/382] Keep record attack replays base-game-compatible for now --- src/g_game.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 02f703167..54cd3f0c9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5337,9 +5337,11 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) if (ghost->player) { if ( - ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || - ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || - ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] + !modeattacking && ( //@TODO: This is a temporary check to keep netreplays EXE record attack replays compatible with base Kart. + ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || + ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || + ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] + ) ) { ghostext[playernum].flags |= EZT_KART; From 3a96ee70af3e3763ad55b56006f053b3134f9059 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:08:32 -0500 Subject: [PATCH 195/382] Rename recordmultiplayerdemos to netdemo_record Begins the process of namespacing demo recording commands. --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 54cd3f0c9..916b6ce1a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -339,7 +339,7 @@ boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; -consvar_t cv_recordmultiplayerdemos = {"recordmultiplayerdemos", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static UINT8 *savebuffer; From 62281de40a8177f9c2cf728a5ae70743996216b3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:38:26 -0500 Subject: [PATCH 196/382] Fix MAXMOM being above the max value GZT_MOM* could store This caused a lot of """desyncs""" when players were moving between 128-255 FU/T, which was exacerbated by this next commit... --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 916b6ce1a..0b52c5280 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5258,7 +5258,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) ziptic_p = demo_p++; // the ziptic, written at the end of this function - #define MAXMOM (0xFFFF<<8) + #define MAXMOM (0x7FFF<<8) // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. if (abs(ghost->x-oldghost[playernum].x) > MAXMOM From fa28feb8dbf23f8303e9602596d49b7f2258d392 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:39:04 -0500 Subject: [PATCH 197/382] Add command to lower netreplay sync frequency This makes for smaller replay files while keeping sync checks in place! --- src/d_netcmd.c | 1 + src/g_game.c | 12 ++++++++++-- src/g_game.h | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0522fd715..b13df51ec 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -811,6 +811,7 @@ 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); diff --git a/src/g_game.c b/src/g_game.c index 0b52c5280..7335939c2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -341,6 +341,9 @@ INT16 prevmap, nextmap; static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t netdemosyncquality_cons_t[] = {{1, "MIN"}, {35, "MAX"}, {0, NULL}}; +consvar_t cv_netdemosyncquality = {"netdemo_syncquality", "1", CV_SAVE, netdemosyncquality_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + static UINT8 *savebuffer; // Analog Control @@ -5221,7 +5224,7 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim) void G_WriteAllGhostTics(void) { - INT32 i; + INT32 i, counter = leveltime; for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -5230,6 +5233,11 @@ void G_WriteAllGhostTics(void) if (!players[i].mo) continue; + counter++; + + if (counter % cv_netdemosyncquality.value != 0) // Only write 1 in this many ghost datas per tic to cut down on multiplayer replay size. + continue; + WRITEUINT8(demo_p, i); G_WriteGhostTic(players[i].mo, i); } @@ -5264,7 +5272,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) if (abs(ghost->x-oldghost[playernum].x) > MAXMOM || abs(ghost->y-oldghost[playernum].y) > MAXMOM || abs(ghost->z-oldghost[playernum].z) > MAXMOM - || (leveltime & 255) == 1) // Hack to enable slightly nicer resyncing + || ((UINT8)(leveltime & 255) > 0 && (UINT8)(leveltime & 255) <= (UINT8)cv_netdemosyncquality.value)) // Hack to enable slightly nicer resyncing { oldghost[playernum].x = ghost->x; oldghost[playernum].y = ghost->y; diff --git a/src/g_game.h b/src/g_game.h index e5f947936..f78a06d06 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -38,7 +38,7 @@ extern boolean playeringame[MAXPLAYERS]; // demoplaying back and demo recording extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo, demosaved, demodefersave, demo_loadfiles, demo_ignorefiles; extern tic_t demosavebutton; -extern consvar_t cv_recordmultiplayerdemos; +extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; // Quit after playing a demo from cmdline. extern boolean singledemo; From ab0bb33d6ece9cac7b45df2440bb1bbce550e4fe Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:45:45 -0500 Subject: [PATCH 198/382] Self-reminder... --- src/p_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.c b/src/p_setup.c index b891bc76c..07a72e7f7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3164,6 +3164,7 @@ boolean P_SetupLevel(boolean skipprecip) : mapheaderinfo[gamemap - 1]->numlaps); //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. + //@TODO I'd like to fix dedis crashing when recording replays for the future too... if (!demoplayback && multiplayer && !dedicated) { static char buf[256]; sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap)); From 9518939a9d246d49c914af97bd6143c87083fee7 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Thu, 21 Mar 2019 00:32:27 -0500 Subject: [PATCH 199/382] Fix Visual Studio compiling --- src/hardware/r_opengl/r_opengl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index cb2b6ae43..9fcc8d157 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1988,10 +1988,10 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) if (special_splitscreen) { used_fov = atan(tan(used_fov*M_PIl/360.0l)*0.8l)*360/M_PIl; - GLPerspective(used_fov, 2*ASPECT_RATIO); + GLPerspective((GLfloat)used_fov, 2*ASPECT_RATIO); } else - GLPerspective(used_fov, ASPECT_RATIO); + GLPerspective((GLfloat)used_fov, ASPECT_RATIO); pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) pglMatrixMode(GL_MODELVIEW); From d13134bae276ea4f8e65f18539e7879e66f7a5ee Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 17:47:24 -0500 Subject: [PATCH 200/382] Prepare for a demo format upgrade! --- src/doomdef.h | 3 +++ src/g_game.c | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index a4a8ff224..793537f82 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -157,6 +157,9 @@ extern FILE *logstream; // Otherwise we can't force updates! #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 diff --git a/src/g_game.c b/src/g_game.c index 5ea653e40..f4110b2a9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4756,7 +4756,7 @@ char *G_BuildMapTitle(INT32 mapnum) // DEMO RECORDING // -#define DEMOVERSION 0x0001 +#define DEMOVERSION 0x0002 #define DEMOHEADER "\xF0" "KartReplay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -6522,6 +6522,10 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) { case DEMOVERSION: // latest always supported break; +#ifdef DEMO_COMPAT_100 + case 0x0001: + I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); +#endif // too old, cannot support. default: CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); @@ -6664,6 +6668,10 @@ void G_DoPlayDemo(char *defdemoname) { case DEMOVERSION: // latest always supported break; +#ifdef DEMO_COMPAT_100 + case 0x0001: + I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); +#endif // too old, cannot support. default: snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); @@ -7033,6 +7041,10 @@ void G_AddGhost(char *defdemoname) { case DEMOVERSION: // latest always supported break; +#ifdef DEMO_COMPAT_100 + case 0x0001: + I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); +#endif // too old, cannot support. default: CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname); @@ -7233,6 +7245,10 @@ void G_UpdateStaffGhostName(lumpnum_t l) { case DEMOVERSION: // latest always supported break; +#ifdef DEMO_COMPAT_100 + case 0x0001: + I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); +#endif // too old, cannot support. default: goto fail; @@ -7344,6 +7360,10 @@ void G_DoPlayMetal(void) { case DEMOVERSION: // latest always supported break; +#ifdef DEMO_COMPAT_100 + case 0x0001: + I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); +#endif // too old, cannot support. default: CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n")); From 0c6c401d888a1f835f54f34f3460bc0821e2048b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 18:48:14 -0500 Subject: [PATCH 201/382] Add title to netreplays and do some format cleanup --- src/d_clisrv.c | 4 ++ src/d_clisrv.h | 1 + src/doomstat.h | 2 + src/g_game.c | 175 +++++++++++++++++++++++++++---------------------- src/hu_stuff.c | 5 ++ 5 files changed, 107 insertions(+), 80 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 79ed85d72..8e5fad287 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -140,6 +140,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; @@ -2320,6 +2321,9 @@ static void CL_ConnectToServer(boolean viams) { INT32 j; 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++) { diff --git a/src/d_clisrv.h b/src/d_clisrv.h index f195fcc9d..2387754a1 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -532,6 +532,7 @@ 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; diff --git a/src/doomstat.h b/src/doomstat.h index 834b3a7cf..c2da75c88 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -487,6 +487,8 @@ extern UINT32 timesBeaten; // # of times the game has been beaten. extern UINT32 timesBeatenWithEmeralds; //extern UINT32 timesBeatenUltimate; +extern char demotitle[65]; + // =========================== // Internal parameters, fixed. // =========================== diff --git a/src/g_game.c b/src/g_game.c index f4110b2a9..13027e5db 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -289,6 +289,7 @@ UINT32 timesBeatenWithEmeralds; //@TODO put these all in a struct for namespacing purposes? static char demoname[64]; +char demotitle[65]; boolean demorecording, demosaved, demodefersave, demoplayback; boolean demo_loadfiles, demo_ignorefiles; // Demo file loading options tic_t demosavebutton; @@ -6061,13 +6062,6 @@ void G_BeginRecording(void) demo_p = demobuffer; demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<important) { - // file list - m = demo_p;/* file count */ - demo_p += 1; + nameonly(( filename = va("%s", wadfiles[i]->filename) )); + WRITESTRINGN(demo_p, filename, 64); + WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); - totalfiles = 0; - for (i = mainwads; ++i < numwadfiles; ) - if (wadfiles[i]->important) - { - nameonly(( filename = va("%s", wadfiles[i]->filename) )); - WRITESTRINGN(demo_p, filename, 64); - WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); - - totalfiles++; - } - - WRITEUINT8(m, totalfiles); + totalfiles++; } + WRITEUINT8(m, totalfiles); + switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 @@ -6471,6 +6467,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) I_Assert(c == SUBVERSION); s = READUINT16(p); I_Assert(s == DEMOVERSION); + p += 64; // full demo title p += 16; // demo checksum I_Assert(!memcmp(p, "PLAY", 4)); p += 4; // PLAY @@ -6521,10 +6518,11 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) switch(oldversion) // demoversion { case DEMOVERSION: // latest always supported + p += 64; // full demo title break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); + I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); #endif // too old, cannot support. default: @@ -6667,10 +6665,15 @@ void G_DoPlayDemo(char *defdemoname) switch(demoversion) { case DEMOVERSION: // latest always supported + // demo title + M_Memcpy(demotitle, demo_p, 64); + CONS_Printf("Demo title: %s\n", demotitle); + demo_p += 64; + break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); + I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); #endif // too old, cannot support. default: @@ -6700,68 +6703,73 @@ void G_DoPlayDemo(char *defdemoname) demo_p += 16; // mapmd5 demoflags = READUINT8(demo_p); - if (demoflags & DF_FILELIST) +#ifdef DEMO_COMPAT_100 + if (demoversion != 0x0001) { - if (titledemo) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. - G_SkipDemoExtraFiles(&demo_p); - else if (demo_loadfiles) - G_LoadDemoExtraFiles(&demo_p); - else if (demo_ignorefiles) - G_SkipDemoExtraFiles(&demo_p); - else +#endif + gametype = READUINT8(demo_p); + + if (titledemo) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. + G_SkipDemoExtraFiles(&demo_p); + else if (demo_loadfiles) + G_LoadDemoExtraFiles(&demo_p); + else if (demo_ignorefiles) + G_SkipDemoExtraFiles(&demo_p); + else + { + UINT8 error = G_CheckDemoExtraFiles(&demo_p); + + if (error) { - UINT8 error = G_CheckDemoExtraFiles(&demo_p); - - if (error) + switch (error) { - switch (error) - { - case DFILE_ERROR_NOTLOADED: - snprintf(msg, 1024, - M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), - pdemoname); - break; + case DFILE_ERROR_NOTLOADED: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), + pdemoname); + break; - case DFILE_ERROR_OUTOFORDER: - snprintf(msg, 1024, - M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; + case DFILE_ERROR_OUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; - case DFILE_ERROR_INCOMPLETEOUTOFORDER: - snprintf(msg, 1024, - M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), - pdemoname); - break; + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), + pdemoname); + break; - case DFILE_ERROR_CANNOTLOAD: - snprintf(msg, 1024, - M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; + case DFILE_ERROR_CANNOTLOAD: + snprintf(msg, 1024, + M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; - case DFILE_ERROR_EXTRAFILES: - snprintf(msg, 1024, - M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; - } - - CONS_Alert(CONS_ERROR, "%s", msg); - if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demoplayback = false; - titledemo = false; - return; + case DFILE_ERROR_EXTRAFILES: + snprintf(msg, 1024, + M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; } + + CONS_Alert(CONS_ERROR, "%s", msg); + if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; } } +#ifdef DEMO_COMPAT_100 + } +#endif modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; multiplayer = !!(demoflags & DF_MULTIPLAYER); - gametype = (demoflags & DF_GAMETYPEMASK)>>DF_GAMESHIFT; CON_ToggleOff(); hu_demotime = UINT32_MAX; @@ -7043,7 +7051,7 @@ void G_AddGhost(char *defdemoname) break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); + I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); #endif // too old, cannot support. default: @@ -7244,10 +7252,11 @@ void G_UpdateStaffGhostName(lumpnum_t l) switch(ghostversion) { case DEMOVERSION: // latest always supported + p += 64; // full demo title break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); + CONS_Printf("You need to implement demo compat here, doofus! %s:%d\n", __FILE__, __LINE__); #endif // too old, cannot support. default: @@ -7362,7 +7371,7 @@ void G_DoPlayMetal(void) break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%s", __FILE__, __LINE__); + I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); #endif // too old, cannot support. default: @@ -7534,13 +7543,19 @@ void G_SaveDemo(void) UINT8 *p = demobuffer+16; // checksum position #ifdef NOMD5 UINT8 i; +#endif + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + M_Memcpy(p, demotitle, 64); // Write demo title here + p += 64; + +#ifdef NOMD5 for (i = 0; i < 16; i++, p++) - *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. + *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. #else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. #endif + demosaved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. free(demobuffer); demorecording = false; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 12633ed4d..a8cf35eb8 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2204,6 +2204,11 @@ 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]); } + else + { + V_DrawRightAlignedThinString(BASEVIDWIDTH-2, BASEVIDHEIGHT-10, V_ALLOWLOWERCASE, demotitle); + } + if (modeattacking) { V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:"); From 77aea850ba9d98107a0bfa19c2c22146263e9c66 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:14:34 -0500 Subject: [PATCH 202/382] Clean up demo header read/write code --- src/g_game.c | 287 +++++++++++++++++++++++++-------------------------- 1 file changed, 142 insertions(+), 145 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 13027e5db..c82c368ec 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4765,11 +4765,14 @@ char *G_BuildMapTitle(INT32 mapnum) #define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares! #define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? #define DF_ATTACKSHIFT 1 +#define DF_ENCORE 0x40 +#define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode! + +#ifdef DEMO_COMPAT_100 #define DF_FILELIST 0x08 // This demo contains an extra files list #define DF_GAMETYPEMASK 0x30 #define DF_GAMESHIFT 4 -#define DF_ENCORE 0x40 -#define DF_MULTIPLAYER 0x80 // This demo contains a dynamic number of players! +#endif #define DEMO_SPECTATOR 0x40 @@ -6123,93 +6126,45 @@ void G_BeginRecording(void) WRITEUINT32(demo_p,P_GetInitSeed()); - if (demoflags & DF_MULTIPLAYER) { - // Netvars first :) - CV_SaveNetVars(&demo_p, true); + // Save netvars + CV_SaveNetVars(&demo_p, true); - // Now store a SIMPLIFIED data struct for each in-game player - for (p = 0; p < MAXPLAYERS; p++) { - if (playeringame[p]) { - player = &players[p]; + // Now store some info for each in-game player + for (p = 0; p < MAXPLAYERS; p++) { + if (playeringame[p]) { + player = &players[p]; - WRITEUINT8(demo_p, p | (player->spectator ? DEMO_SPECTATOR : 0)); + WRITEUINT8(demo_p, p | (player->spectator ? DEMO_SPECTATOR : 0)); - // Name - memset(name, 0, 16); - strncpy(name, player_names[p], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; + // Name + memset(name, 0, 16); + strncpy(name, player_names[p], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; - // Skin - memset(name, 0, 16); - strncpy(name, skins[player->skin].name, 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; + // Skin + memset(name, 0, 16); + strncpy(name, skins[player->skin].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; - // Color - memset(name, 0, 16); - strncpy(name, KartColor_Names[player->skincolor], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; + // Color + memset(name, 0, 16); + strncpy(name, KartColor_Names[player->skincolor], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; - // Score, since Kart uses this to determine where you start on the map - WRITEUINT32(demo_p, player->score); - } + // Score, since Kart uses this to determine where you start on the map + WRITEUINT32(demo_p, player->score); + + // Kart speed and weight + WRITEUINT8(demo_p, skins[player->skin].kartspeed); + WRITEUINT8(demo_p, skins[player->skin].kartweight); } - - WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing - - goto initcmdandghost; } - // Name - for (i = 0; i < 16 && cv_playername.string[i]; i++) - name[i] = cv_playername.string[i]; - for (; i < 16; i++) - name[i] = '\0'; - M_Memcpy(demo_p,name,16); - demo_p += 16; + WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing - // Skin - for (i = 0; i < 16 && cv_skin.string[i]; i++) - name[i] = cv_skin.string[i]; - for (; i < 16; i++) - name[i] = '\0'; - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Color - for (i = 0; i < 16 && cv_playercolor.string[i]; i++) - name[i] = cv_playercolor.string[i]; - for (; i < 16; i++) - name[i] = '\0'; - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Stats - WRITEUINT8(demo_p,player->charability); - WRITEUINT8(demo_p,player->charability2); - WRITEUINT8(demo_p,player->actionspd>>FRACBITS); - WRITEUINT8(demo_p,player->mindash>>FRACBITS); - WRITEUINT8(demo_p,player->maxdash>>FRACBITS); - // SRB2kart - WRITEUINT8(demo_p,player->kartspeed); - WRITEUINT8(demo_p,player->kartweight); - // - WRITEUINT8(demo_p,player->normalspeed>>FRACBITS); - WRITEUINT8(demo_p,player->runspeed>>FRACBITS); - WRITEUINT8(demo_p,player->thrustfactor); - WRITEUINT8(demo_p,player->accelstart); - WRITEUINT8(demo_p,player->acceleration); - - // Trying to convert it back to % causes demo desync due to precision loss. - // Don't do it. - WRITEFIXED(demo_p, player->jumpfactor); - - // Save netvar data (SONICCD, etc) - CV_SaveNetVars(&demo_p, false); //@TODO can this be true? it's not necessary for now but would be nice for consistency - -initcmdandghost: memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); memset(&ghostext,0,sizeof(ghostext)); @@ -6594,12 +6549,14 @@ void G_DoPlayDemo(char *defdemoname) UINT8 i, p; lumpnum_t l; char skin[17],color[17],*n,*pdemoname; - UINT8 version,subversion,kartspeed=5,kartweight=5; + UINT8 version,subversion; UINT32 randseed; char msg[1024]; #if defined(SKIPERRORS) && !defined(DEVELOP) boolean skiperrors = false; #endif + boolean spectator; + UINT8 slots[MAXPLAYERS], kartspeed[MAXPLAYERS], kartweight[MAXPLAYERS], numslots = 0; skin[16] = '\0'; color[16] = '\0'; @@ -6795,7 +6752,8 @@ void G_DoPlayDemo(char *defdemoname) // Random seed randseed = READUINT32(demo_p); - if (!multiplayer) { +#ifdef DEMO_COMPAT_100 + if (demoversion == 0x0001) { // Player name M_Memcpy(player_names[0],demo_p,16); demo_p += 16; @@ -6810,8 +6768,8 @@ void G_DoPlayDemo(char *defdemoname) demo_p += 5; // Backwards compat - some stats // SRB2kart - kartspeed = READUINT8(demo_p); - kartweight = READUINT8(demo_p); + kartspeed[0] = READUINT8(demo_p); + kartweight[0] = READUINT8(demo_p); // demo_p += 9; // Backwards compat - more stats @@ -6848,7 +6806,48 @@ void G_DoPlayDemo(char *defdemoname) players[0].skincolor = i; break; } + + // net var data + CV_LoadNetVars(&demo_p); + + // Sigh ... it's an empty demo. + if (*demo_p == DEMOMARKER) + { + snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } + + Z_Free(pdemoname); + + memset(&oldcmd,0,sizeof(oldcmd)); + memset(&oldghost,0,sizeof(oldghost)); + memset(&ghostext,0,sizeof(ghostext)); + + CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n")); + + // console warning messages +#if defined(SKIPERRORS) && !defined(DEVELOP) + demosynced = (!skiperrors); +#else + demosynced = true; +#endif + + // didn't start recording right away. + demo_start = false; + + displayplayer = consoleplayer = 0; + memset(playeringame, 0, sizeof(playeringame)); + playeringame[0] = true; + + goto post_compat; } +#endif // net var data CV_LoadNetVars(&demo_p); @@ -6894,72 +6893,74 @@ void G_DoPlayDemo(char *defdemoname) #endif*/ displayplayer = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); - playeringame[0] = !multiplayer; - if (multiplayer) { - boolean spectator; - UINT8 slots[MAXPLAYERS], numslots = 0; + // Load players that were in-game when the map started + p = READUINT8(demo_p); - // Load players that were in-game when the map started - p = READUINT8(demo_p); + secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = INT32_MAX; - secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = INT32_MAX; + while (p != 0xFF) + { + spectator = false; + if (p & DEMO_SPECTATOR) { + spectator = true; + p &= ~DEMO_SPECTATOR; + } + slots[numslots] = p; numslots++; - while (p != 0xFF) - { - spectator = false; - if (p & DEMO_SPECTATOR) { - spectator = true; - p &= ~DEMO_SPECTATOR; + if (!playeringame[displayplayer] || players[displayplayer].spectator) + displayplayer = consoleplayer = serverplayer = p; + + playeringame[p] = true; + players[p].spectator = spectator; + + // Name + M_Memcpy(player_names[p],demo_p,16); + demo_p += 16; + + // Skin + M_Memcpy(skin,demo_p,16); + demo_p += 16; + SetPlayerSkin(p, skin); + + // Color + M_Memcpy(color,demo_p,16); + demo_p += 16; + for (i = 0; i < MAXSKINCOLORS; i++) + if (!stricmp(KartColor_Names[i],color)) // SRB2kart + { + players[p].skincolor = i; + break; } - slots[numslots] = p; numslots++; - if (!playeringame[displayplayer] || players[displayplayer].spectator) - displayplayer = consoleplayer = serverplayer = p; + // Score, since Kart uses this to determine where you start on the map + players[p].score = READUINT32(demo_p); - playeringame[p] = true; - players[p].spectator = spectator; + // Kart stats, temporarily + kartspeed[p] = READUINT8(demo_p); + kartweight[p] = READUINT8(demo_p); - // Name - M_Memcpy(player_names[p],demo_p,16); - demo_p += 16; - - // Skin - M_Memcpy(skin,demo_p,16); - demo_p += 16; - SetPlayerSkin(p, skin); - - // Color - M_Memcpy(color,demo_p,16); - demo_p += 16; - for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i],color)) // SRB2kart - { - players[p].skincolor = i; - break; - } - - // Score, since Kart uses this to determine where you start on the map - players[p].score = READUINT32(demo_p); - - // Look for the next player - p = READUINT8(demo_p); - } - - splitscreen = 0; - - if (titledemo) - { - splitscreen = M_RandomKey(6)-1; - splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views - - for (p = 0; p <= splitscreen; p++) - G_ResetView(p+1, slots[M_RandomKey(numslots)], false); - } - - R_ExecuteSetViewSize(); + // Look for the next player + p = READUINT8(demo_p); } + splitscreen = 0; + + if (titledemo) + { + splitscreen = M_RandomKey(6)-1; + splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views + + for (p = 0; p <= splitscreen; p++) + G_ResetView(p+1, slots[M_RandomKey(numslots)], false); + } + + R_ExecuteSetViewSize(); + +#ifdef DEMO_COMPAT_100 +post_compat: +#endif + P_SetRandSeed(randseed); G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. @@ -6972,16 +6973,12 @@ void G_DoPlayDemo(char *defdemoname) oldghost[i].y = players[i].mo->y; oldghost[i].z = players[i].mo->z; } - } - - if (!multiplayer) { - //CV_StealthSetValue(&cv_playercolor, players[0].skincolor); -- as far as I can tell this is more trouble than it's worth // Set saved attribute values // No cheat checking here, because even if they ARE wrong... // it would only break the replay if we clipped them. - players[0].kartspeed = kartspeed; - players[0].kartweight = kartweight; + players[i].kartspeed = kartspeed[i]; + players[i].kartweight = kartweight[i]; } demo_start = true; From b922c2289e95d82fc1b90d50441866913bbb17e9 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:19:57 -0500 Subject: [PATCH 203/382] Add some checks against invalid replays --- src/g_game.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index c82c368ec..608ab33ab 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6630,7 +6630,8 @@ void G_DoPlayDemo(char *defdemoname) break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); + CONS_Printf("You need to implement demo compat here, doofus! %s:%d\n", __FILE__, __LINE__); + break; #endif // too old, cannot support. default: @@ -6661,7 +6662,21 @@ void G_DoPlayDemo(char *defdemoname) demoflags = READUINT8(demo_p); #ifdef DEMO_COMPAT_100 - if (demoversion != 0x0001) + if (demoversion == 0x0001) + { + if (demoflags & DF_MULTIPLAYER) + { + snprintf(msg, 1024, M_GetText("%s is an alpha multiplayer replay and cannot be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } + } + else { #endif gametype = READUINT8(demo_p); @@ -6902,12 +6917,38 @@ void G_DoPlayDemo(char *defdemoname) while (p != 0xFF) { spectator = false; - if (p & DEMO_SPECTATOR) { + if (p & DEMO_SPECTATOR) + { spectator = true; p &= ~DEMO_SPECTATOR; + + if (modeattacking) + { + snprintf(msg, 1024, M_GetText("%s is a record attack replay with spectators, and is thus invalid.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } } slots[numslots] = p; numslots++; + + if (modeattacking && numslots > 1) + { + snprintf(msg, 1024, M_GetText("%s is a record attack replay with multiple players, and is thus invalid.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } + if (!playeringame[displayplayer] || players[displayplayer].spectator) displayplayer = consoleplayer = serverplayer = p; From 1941ba09b0c6ffa53861e9f1aef6972a083a6bf3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:41:25 -0500 Subject: [PATCH 204/382] Use skin with closest stats if the expected one wasn't found This allows people to watch replays without the characters loaded, without making everyone be Sonic. --- src/g_game.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 608ab33ab..319c4a00b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4855,6 +4855,26 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) return dest; } +// Finds a skin with the closest stats if the expected skin doesn't exist. +static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) +{ + INT32 i, closest_skin = 0; + UINT8 closest_stats = UINT8_MAX, stat_diff; + + for (i = 0; i < numskins; i++) + { + stat_diff = abs(skins[i].kartspeed - kartspeed) + abs(skins[i].kartweight - kartweight); + if (stat_diff < closest_stats) + { + closest_stats = stat_diff; + closest_skin = i; + } + } + + CONS_Printf("Using %s instead...\n", skins[closest_skin].name); + SetPlayerSkinByNum(p, closest_skin); +} + void G_ReadDemoExtraData(void) { INT32 p, extradata, i; @@ -4875,10 +4895,22 @@ void G_ReadDemoExtraData(void) } if (extradata & DXD_SKIN) { + UINT8 kartspeed, kartweight; + // Skin M_Memcpy(name, demo_p, 16); demo_p += 16; SetPlayerSkin(p, name); + + kartspeed = READUINT8(demo_p); + kartweight = READUINT8(demo_p); + + + if (stricmp(skins[players[p].skin].name, name) != 0) + FindClosestSkinForStats(p, kartspeed, kartweight); + + players[p].kartspeed = kartspeed; + players[p].kartweight = kartweight; } if (extradata & DXD_COLOR) { @@ -4999,6 +5031,9 @@ void G_WriteDemoExtraData(void) strncpy(name, skins[players[i].skin].name, 16); M_Memcpy(demo_p,name,16); demo_p += 16; + + WRITEUINT8(demo_p, skins[players[i].skin].kartspeed); + WRITEUINT8(demo_p, skins[players[i].skin].kartweight); } if (demo_extradata[i] & DXD_COLOR) { @@ -6981,6 +7016,9 @@ void G_DoPlayDemo(char *defdemoname) kartspeed[p] = READUINT8(demo_p); kartweight[p] = READUINT8(demo_p); + if (stricmp(skins[players[p].skin].name, skin) != 0) + FindClosestSkinForStats(p, kartspeed[p], kartweight[p]); + // Look for the next player p = READUINT8(demo_p); } From 557ac6f0d3fc8db7db5a41e2e392043e8e404997 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:57:11 -0500 Subject: [PATCH 205/382] Move save replay prompt into the upper-right corner --- src/st_stuff.c | 4 ++-- src/y_inter.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 3899864fd..d87a805d7 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2018,9 +2018,9 @@ static void ST_overlayDrawer(void) if (demorecording && multiplayer && demosavebutton && demosavebutton + 3*TICRATE < leveltime) { if (demodefersave || cv_recordmultiplayerdemos.value == 2) - V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_HUDTRANSHALF|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); else - V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_HUDTRANSHALF|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Press Look Backward to save the replay"); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Look Backward: Save replay"); } ST_drawDebugInfo(); diff --git a/src/y_inter.c b/src/y_inter.c index 24c4f93e1..778ab5ad3 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -563,9 +563,9 @@ dotimer: } if (demorecording && cv_recordmultiplayerdemos.value == 1) - V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_ALLOWLOWERCASE|hilicol, "Press Look Backward to save the replay"); - else if (demosaved) - V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_ALLOWLOWERCASE|hilicol, "Replay saved!"); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Look Backward: Save replay"); + else if (demosaved && !demoplayback) + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Replay saved!"); // Make it obvious that scrambling is happening next round. if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) From f162dc0270f4f007620eef40ffa67597eb2a352d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 20:36:22 -0500 Subject: [PATCH 206/382] Use demo title as filename for multiplayer replays --- src/d_main.c | 2 ++ src/g_game.c | 41 ++++++++++++++++++++++++++++++++++++++++- src/m_menu.c | 2 ++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 84d5a6f32..674cf365d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1529,6 +1529,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 diff --git a/src/g_game.c b/src/g_game.c index 319c4a00b..8e58c975c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -288,7 +288,7 @@ UINT32 timesBeatenWithEmeralds; //UINT32 timesBeatenUltimate; //@TODO put these all in a struct for namespacing purposes? -static char demoname[64]; +static char demoname[128]; char demotitle[65]; boolean demorecording, demosaved, demodefersave, demoplayback; boolean demo_loadfiles, demo_ignorefiles; // Demo file loading options @@ -7625,6 +7625,45 @@ void G_SaveDemo(void) M_Memcpy(p, demotitle, 64); // Write demo title here p += 64; + if (multiplayer) + { + // Change the demo's name to be a slug of the title + char demo_slug[128]; + char *writepoint; + size_t i, strindex = 0; + boolean dash = true; + + for (i = 0; demotitle[i] && i < 127; i++) + { + if ((demotitle[i] >= 'a' && demotitle[i] <= 'z') || (demotitle[i] >= '0' && demotitle[i] <= '9')) + { + demo_slug[strindex] = demotitle[i]; + strindex++; + dash = false; + } + else if (demotitle[i] >= 'A' && demotitle[i] <= 'Z') + { + demo_slug[strindex] = demotitle[i] + 'a' - 'A'; + strindex++; + dash = false; + } + else if (!dash) + { + demo_slug[strindex] = '-'; + strindex++; + dash = true; + } + } + + demo_slug[strindex] = 0; + if (dash) demo_slug[strindex-1] = 0; + CONS_Printf("%s\n%s\n", demotitle, demo_slug); + + writepoint = strstr(demoname, "-") + 1; + demo_slug[128 - (writepoint - demoname) - 4] = 0; + sprintf(writepoint, "%s.lmp", demo_slug); + } + #ifdef NOMD5 for (i = 0; i < 16; i++, p++) *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. diff --git a/src/m_menu.c b/src/m_menu.c index 0fc622330..fa88d601b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7579,6 +7579,8 @@ static void M_StartServer(INT32 choice) multiplayer = true; + strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); + // Still need to reset devmode cv_debug = 0; From f60e92aa70fbedb740f583f1eca01211b8c7f06f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 21:32:15 -0500 Subject: [PATCH 207/382] Move public demo vars to a single struct --- src/d_clisrv.c | 18 ++--- src/d_main.c | 2 +- src/d_netcmd.c | 30 ++++---- src/dehacked.c | 2 +- src/doomstat.h | 2 - src/f_finale.c | 10 +-- src/g_game.c | 180 +++++++++++++++++++++----------------------- src/g_game.h | 28 +++++-- src/hu_stuff.c | 10 +-- src/k_kart.c | 10 +-- src/m_cheat.c | 2 +- src/m_menu.c | 12 +-- src/p_inter.c | 2 +- src/p_map.c | 4 +- src/p_mobj.c | 2 +- src/p_setup.c | 10 +-- src/p_spec.c | 4 +- src/p_tick.c | 16 ++-- src/p_user.c | 18 ++--- src/r_data.c | 2 +- src/r_main.c | 6 +- src/r_things.c | 2 +- src/s_sound.c | 4 +- src/sdl/i_system.c | 4 +- src/st_stuff.c | 6 +- src/win32/win_sys.c | 4 +- src/y_inter.c | 18 ++--- 27 files changed, 209 insertions(+), 199 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 8e5fad287..d8ce0f963 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1742,8 +1742,8 @@ static void CL_LoadReceivedSavegame(void) } paused = false; - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; automapactive = false; // load a base level @@ -2541,7 +2541,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; @@ -2642,7 +2642,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) demo_extradata[playernum] |= DXD_PLAYSTATE; - if (server && !demoplayback) + 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 @@ -2717,7 +2717,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) RemoveAdminPlayer(playernum); // don't stay admin after you're gone } - if (playernum == displayplayer && !demoplayback) + if (playernum == displayplayer && !demo.playback) displayplayer = consoleplayer; // don't look through someone's view who isn't there #ifdef HAVE_BLUA @@ -2738,7 +2738,7 @@ void CL_Reset(void) G_StopMetalRecording(); if (metalplayback) G_StopMetalDemo(); - if (demorecording) + if (demo.recording) G_CheckDemoStatus(); // reset client/server code @@ -3657,7 +3657,7 @@ boolean Playing(void) boolean SV_SpawnServer(void) { - if (demoplayback) + if (demo.playback) G_StopDemo(); // reset engine parameter if (metalplayback) G_StopMetalDemo(); @@ -5245,7 +5245,7 @@ void TryRunTics(tic_t realtics) NetUpdate(); - if (demoplayback) + if (demo.playback) { neededtic = gametic + realtics * (gamestate == GS_LEVEL ? cv_playbackspeed.value : 1); // start a game after a demo @@ -5508,7 +5508,7 @@ FILESTAMP } else { - if (!demoplayback) + if (!demo.playback) { INT32 counts; diff --git a/src/d_main.c b/src/d_main.c index 674cf365d..6edb1cf44 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1502,7 +1502,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 diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b13df51ec..d4ffe27a8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2005,7 +2005,7 @@ static void Command_View_f(void) default: viewnum = 1; } - if (viewnum > 1 && !( multiplayer && demoplayback )) + if (viewnum > 1 && !( multiplayer && demo.playback )) { CONS_Alert(CONS_NOTICE, "You must be viewing a multiplayer replay to use this.\n"); @@ -2083,7 +2083,7 @@ static void Command_SetViews_f(void) UINT8 splits; UINT8 newsplits; - if (!( demoplayback && multiplayer )) + if (!( demo.playback && multiplayer )) { CONS_Alert(CONS_NOTICE, "You must be viewing a multiplayer replay to use this.\n"); @@ -2137,7 +2137,7 @@ static void Command_Playdemo_f(void) } // disconnect from server here? - if (demoplayback) + if (demo.playback) G_StopDemo(); if (metalplayback) G_StopMetalDemo(); @@ -2148,8 +2148,8 @@ 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; + 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 @@ -2176,7 +2176,7 @@ static void Command_Timedemo_f(void) } // disconnect from server here? - if (demoplayback) + if (demo.playback) G_StopDemo(); if (metalplayback) G_StopMetalDemo(); @@ -2610,7 +2610,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) CON_ToggleOff(); CON_ClearHUD(); - if (demoplayback && !timingdemo) + if (demo.playback && !demo.timing) precache = false; if (resetplayer) @@ -2628,18 +2628,18 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) #endif*/ demosaved = demodefersave = false; - demosavebutton = 0; + 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) @@ -2695,7 +2695,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) paused = READUINT8(*cp); dedicatedpause = READUINT8(*cp); - if (!demoplayback) + if (!demo.playback) { if (netgame) { @@ -4668,7 +4668,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() @@ -5108,7 +5108,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); diff --git a/src/dehacked.c b/src/dehacked.c index 4f41ac0cd..20c2964b7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9873,7 +9873,7 @@ static inline int lib_getenum(lua_State *L) lua_pushinteger(L, mapmusflags); return 1; } else if (fastcmp(word,"server")) { - if ((!multiplayer || !(netgame || demoplayback)) && !playeringame[serverplayer]) + if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer]) return 0; LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); return 1; diff --git a/src/doomstat.h b/src/doomstat.h index c2da75c88..834b3a7cf 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -487,8 +487,6 @@ extern UINT32 timesBeaten; // # of times the game has been beaten. extern UINT32 timesBeatenWithEmeralds; //extern UINT32 timesBeatenUltimate; -extern char demotitle[65]; - // =========================== // Internal parameters, fixed. // =========================== diff --git a/src/f_finale.c b/src/f_finale.c index cdde54f3c..d184a2833 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -909,9 +909,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; @@ -1098,9 +1098,9 @@ void F_TitleScreenTicker(boolean run) }*/ loadreplay: - titledemo = fromtitledemo = true; - demo_ignorefiles = true; - demo_loadfiles = false; + demo.title = demo.fromtitle = true; + demo.ignorefiles = true; + demo.loadfiles = false; G_DoPlayDemo(dname); } } diff --git a/src/g_game.c b/src/g_game.c index 8e58c975c..ef8a41968 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -101,7 +101,6 @@ UINT8 numDemos = 0; //3; -- i'm FED UP of losing my skincolour to a broken UINT32 demoDelayTime = 15*TICRATE; UINT32 demoIdleTime = 3*TICRATE; -boolean timingdemo; // if true, exit with report on completion boolean nodrawers; // for comparative timing purposes boolean noblit; // for comparative timing purposes static tic_t demostarttime; // for comparative timing purposes @@ -289,21 +288,16 @@ UINT32 timesBeatenWithEmeralds; //@TODO put these all in a struct for namespacing purposes? static char demoname[128]; -char demotitle[65]; -boolean demorecording, demosaved, demodefersave, demoplayback; -boolean demo_loadfiles, demo_ignorefiles; // Demo file loading options -tic_t demosavebutton; -boolean titledemo; // Title Screen demo can be cancelled by any key -boolean fromtitledemo; // SRB2Kart: Don't stop the music +boolean demosaved, demodefersave; static UINT8 *demobuffer = NULL; static UINT8 *demo_p, *demotime_p; static UINT8 *demoend; static UINT8 demoflags; static UINT16 demoversion; -boolean singledemo; // quit after playing a demo from cmdline -boolean demo_start; // don't start playing demo right away static boolean demosynced = true; // console warning message +struct demovars_s demo; + boolean metalrecording; // recording as metal sonic mobj_t *metalplayback; static UINT8 *metalbuffer = NULL; @@ -1252,7 +1246,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) static boolean keyboard_look, keyboard_look2, keyboard_look3, keyboard_look4; // true if lookup/down using keyboard static boolean resetdown, resetdown2, resetdown3, resetdown4; // don't cam reset every frame - if (demoplayback) return; + if (demo.playback) return; switch (ssplayer) { @@ -1842,8 +1836,8 @@ static INT32 spectatedelay, spectatedelay2, spectatedelay3, spectatedelay4 = 0; boolean G_Responder(event_t *ev) { // any other key pops up menu if in demos - if (gameaction == ga_nothing && !singledemo && - ((demoplayback && !modeattacking && !titledemo && !multiplayer) || gamestate == GS_TITLESCREEN)) + if (gameaction == ga_nothing && !demo.quitafterplaying && + ((demo.playback && !modeattacking && !demo.title && !multiplayer) || gamestate == GS_TITLESCREEN)) { if (ev->type == ev_keydown && ev->data1 != 301) { @@ -1852,7 +1846,7 @@ boolean G_Responder(event_t *ev) } return false; } - else if (demoplayback && titledemo) + else if (demo.playback && demo.title) { // Title demo uses intro responder if (F_IntroResponder(ev)) @@ -1922,21 +1916,21 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL && ev->type == ev_keydown && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) { - if (!demoplayback && (splitscreen || !netgame)) + if (!demo.playback && (splitscreen || !netgame)) displayplayer = consoleplayer; else { G_AdjustView(1, 1, true); // change statusbar also if playing back demo - if (singledemo) + if (demo.quitafterplaying) ST_changeDemoView(); return true; } } - if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demoplayback) + if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback) { if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { @@ -2106,7 +2100,7 @@ boolean G_CouldView(INT32 playernum) return false; // I don't know if we want this actually, but I'll humor the suggestion anyway - if (G_BattleGametype() && !demoplayback) + if (G_BattleGametype() && !demo.playback) { if (player->kartstuff[k_bumper] <= 0) return false; @@ -2284,7 +2278,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) } } - if (viewnum == 1 && demoplayback) + if (viewnum == 1 && demo.playback) consoleplayer = displayplayer; } @@ -2415,7 +2409,7 @@ void G_Ticker(boolean run) switch (gamestate) { case GS_LEVEL: - if (titledemo) + if (demo.title) F_TitleDemoTicker(); P_Ticker(run); // tic the game ST_Ticker(); @@ -2545,7 +2539,7 @@ static inline void G_PlayerFinishLevel(INT32 player) // SRB2kart: Increment the "matches played" counter. if (player == consoleplayer) { - if (legitimateexit && !demoplayback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified) + if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified) { matchesplayed++; if (M_UpdateUnlockablesAndExtraEmblems(true)) @@ -3331,7 +3325,7 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); - if (multiplayer && demorecording && cv_recordmultiplayerdemos.value == 2) + if (multiplayer && demo.recording && cv_recordmultiplayerdemos.value == 2) G_SaveDemo(); } } @@ -3397,7 +3391,7 @@ boolean G_GametypeHasSpectators(void) #if 0 return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); #else - return (netgame || (multiplayer && demoplayback)); //true + return (netgame || (multiplayer && demo.playback)); //true #endif } @@ -3723,7 +3717,7 @@ static void G_DoCompleted(void) } // play some generic music if there's no win/cool/lose music going on (for exitlevel commands) - if (G_RaceGametype() && ((multiplayer && demoplayback) || j == splitscreen+1) && (cv_inttime.value > 0)) + if (G_RaceGametype() && ((multiplayer && demo.playback) || j == splitscreen+1) && (cv_inttime.value > 0)) S_ChangeMusicInternal("racent", true); if (automapactive) @@ -3733,7 +3727,7 @@ static void G_DoCompleted(void) prevmap = (INT16)(gamemap-1); - if (demoplayback) goto demointermission; + if (demo.playback) goto demointermission; // go to next level // nextmap is 0-based, unlike gamemap @@ -3860,7 +3854,7 @@ void G_AfterIntermission(void) HU_ClearCEcho(); //G_NextLevel(); - if (demoplayback) + if (demo.playback) { G_StopDemo(); D_StartTitle(); @@ -4441,7 +4435,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) } save_p += VERSIONSIZE; - if (demoplayback) // reset game engine + if (demo.playback) // reset game engine G_StopDemo(); // paused = false; @@ -4540,7 +4534,7 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar UINT8 color = 0; paused = false; - if (demoplayback) + if (demo.playback) COM_BufAddText("stopdemo\n"); while (ghosts) @@ -4602,7 +4596,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool legitimateexit = false; // SRB2Kart comebackshowninfo = false; - if (!demoplayback && !netgame) // Netgame sets random seed elsewhere, demo playback sets seed just before us! + if (!demo.playback && !netgame) // Netgame sets random seed elsewhere, demo playback sets seed just before us! P_SetRandSeed(M_RandomizedSeed()); // Use a more "Random" random seed //SRB2Kart - Score is literally the only thing you SHOULDN'T reset at all times @@ -4648,7 +4642,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool players[i].marescore = 0; - if (resetplayer && !(multiplayer && demoplayback)) // SRB2Kart + if (resetplayer && !(multiplayer && demo.playback)) // SRB2Kart { players[i].score = 0; } @@ -5094,7 +5088,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) { UINT8 ziptic; - if (!demo_p || !demo_start) + if (!demo_p || !demo.deferstart) return; ziptic = READUINT8(demo_p); @@ -5202,35 +5196,35 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) void G_GhostAddThok(INT32 playernum) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_THOK; } void G_GhostAddSpin(INT32 playernum) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_SPIN; } void G_GhostAddRev(INT32 playernum) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_REV; } void G_GhostAddFlip(INT32 playernum) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; ghostext[playernum].flags |= EZT_FLIP; } void G_GhostAddColor(INT32 playernum, ghostcolor_t color) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; if (ghostext[playernum].lastcolor == (UINT8)color) { @@ -5243,7 +5237,7 @@ void G_GhostAddColor(INT32 playernum, ghostcolor_t color) void G_GhostAddScale(INT32 playernum, fixed_t scale) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; if (ghostext[playernum].lastscale == scale) { @@ -5256,7 +5250,7 @@ void G_GhostAddScale(INT32 playernum, fixed_t scale) void G_GhostAddHit(INT32 playernum, mobj_t *victim) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!demo.recording || !(demoflags & DF_GHOST)) return; ghostext[playernum].flags |= EZT_HIT; ghostext[playernum].hits++; @@ -5490,7 +5484,7 @@ void G_ConsGhostTic(INT32 playernum) fixed_t syncleeway; boolean nightsfail = false; - if (!demo_p || !demo_start) + if (!demo_p || !demo.deferstart) return; if (!(demoflags & DF_GHOST)) return; // No ghost data to use. @@ -6068,7 +6062,7 @@ void G_RecordDemo(const char *name) demobuffer = malloc(maxsize); demoend = demobuffer + maxsize; - demorecording = true; + demo.recording = true; } void G_RecordMetal(void) @@ -6111,7 +6105,7 @@ void G_BeginRecording(void) // Full replay title demo_p += 64; - snprintf(demotitle, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Record Attack" : connectedservername); + snprintf(demo.titlename, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Record Attack" : connectedservername); // demo checksum demo_p += 16; @@ -6253,7 +6247,7 @@ void G_BeginMetal(void) void G_SetDemoTime(UINT32 ptime, UINT32 plap) { - if (!demorecording || !demotime_p) + if (!demo.recording || !demotime_p) return; if (demoflags & DF_RECORDATTACK) { @@ -6637,7 +6631,7 @@ void G_DoPlayDemo(char *defdemoname) // read demo header gameaction = ga_nothing; - demoplayback = true; + demo.playback = true; if (memcmp(demo_p, DEMOHEADER, 12)) { snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname); @@ -6645,8 +6639,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } demo_p += 12; // DEMOHEADER @@ -6658,8 +6652,8 @@ void G_DoPlayDemo(char *defdemoname) { case DEMOVERSION: // latest always supported // demo title - M_Memcpy(demotitle, demo_p, 64); - CONS_Printf("Demo title: %s\n", demotitle); + M_Memcpy(demo.titlename, demo_p, 64); + CONS_Printf("Demo title: %s\n", demo.titlename); demo_p += 64; break; @@ -6675,8 +6669,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } demo_p += 16; // demo checksum @@ -6687,8 +6681,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } demo_p += 4; // "PLAY" @@ -6706,8 +6700,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } } @@ -6716,11 +6710,11 @@ void G_DoPlayDemo(char *defdemoname) #endif gametype = READUINT8(demo_p); - if (titledemo) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. + if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. G_SkipDemoExtraFiles(&demo_p); - else if (demo_loadfiles) + else if (demo.loadfiles) G_LoadDemoExtraFiles(&demo_p); - else if (demo_ignorefiles) + else if (demo.ignorefiles) G_SkipDemoExtraFiles(&demo_p); else { @@ -6766,8 +6760,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } } @@ -6831,8 +6825,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } @@ -6844,8 +6838,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } @@ -6868,8 +6862,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } @@ -6889,7 +6883,7 @@ void G_DoPlayDemo(char *defdemoname) #endif // didn't start recording right away. - demo_start = false; + demo.deferstart = false; displayplayer = consoleplayer = 0; memset(playeringame, 0, sizeof(playeringame)); @@ -6910,8 +6904,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } @@ -6936,7 +6930,7 @@ void G_DoPlayDemo(char *defdemoname) #endif // didn't start recording right away. - demo_start = false; + demo.deferstart = false; /*#ifdef HAVE_BLUA LUAh_MapChange(gamemap); @@ -6964,8 +6958,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } } @@ -6979,8 +6973,8 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); Z_Free(pdemoname); Z_Free(demobuffer); - demoplayback = false; - titledemo = false; + demo.playback = false; + demo.title = false; return; } @@ -7025,7 +7019,7 @@ void G_DoPlayDemo(char *defdemoname) splitscreen = 0; - if (titledemo) + if (demo.title) { splitscreen = M_RandomKey(6)-1; splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views @@ -7060,7 +7054,7 @@ post_compat: players[i].kartweight = kartweight[i]; } - demo_start = true; + demo.deferstart = true; } #undef SKIPERRORS @@ -7397,7 +7391,7 @@ void G_TimeDemo(const char *name) restorecv_vidwait = cv_vidwait.value; if (cv_vidwait.value) CV_Set(&cv_vidwait, "0"); - timingdemo = true; + demo.timing = true; singletics = true; framecount = 0; demostarttime = I_GetTime(); @@ -7531,11 +7525,11 @@ void G_StopDemo(void) { Z_Free(demobuffer); demobuffer = NULL; - demoplayback = false; - if (titledemo) + demo.playback = false; + if (demo.title) modeattacking = false; - titledemo = false; - timingdemo = false; + demo.title = false; + demo.timing = false; singletics = false; if (gamestate == GS_LEVEL && rendermode != render_none) @@ -7566,7 +7560,7 @@ boolean G_CheckDemoStatus(void) // DO NOT end metal sonic demos here - if (timingdemo) + if (demo.timing) { INT32 demotime; double f1, f2; @@ -7574,7 +7568,7 @@ boolean G_CheckDemoStatus(void) if (!demotime) return true; G_StopDemo(); - timingdemo = false; + demo.timing = false; f1 = (double)demotime; f2 = (double)framecount*TICRATE; CONS_Printf(M_GetText("timed %u gametics in %d realtics\n%f seconds, %f avg fps\n"), leveltime,demotime,f1/TICRATE,f2/f1); @@ -7584,12 +7578,12 @@ boolean G_CheckDemoStatus(void) return true; } - if (demoplayback) + if (demo.playback) { - if (singledemo) + if (demo.quitafterplaying) I_Quit(); - if (multiplayer && !titledemo) + if (multiplayer && !demo.title) G_ExitLevel(); else { @@ -7604,12 +7598,12 @@ boolean G_CheckDemoStatus(void) return true; } - if (demorecording && (!multiplayer || cv_recordmultiplayerdemos.value == 2)) + if (demo.recording && (!multiplayer || cv_recordmultiplayerdemos.value == 2)) { G_SaveDemo(); return true; } - demorecording = false; + demo.recording = false; return false; } @@ -7622,7 +7616,7 @@ void G_SaveDemo(void) #endif WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - M_Memcpy(p, demotitle, 64); // Write demo title here + M_Memcpy(p, demo.titlename, 64); // Write demo title here p += 64; if (multiplayer) @@ -7633,17 +7627,18 @@ void G_SaveDemo(void) size_t i, strindex = 0; boolean dash = true; - for (i = 0; demotitle[i] && i < 127; i++) + for (i = 0; demo.titlename[i] && i < 127; i++) { - if ((demotitle[i] >= 'a' && demotitle[i] <= 'z') || (demotitle[i] >= '0' && demotitle[i] <= '9')) + if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') || + (demo.titlename[i] >= '0' && demo.titlename[i] <= '9')) { - demo_slug[strindex] = demotitle[i]; + demo_slug[strindex] = demo.titlename[i]; strindex++; dash = false; } - else if (demotitle[i] >= 'A' && demotitle[i] <= 'Z') + else if (demo.titlename[i] >= 'A' && demo.titlename[i] <= 'Z') { - demo_slug[strindex] = demotitle[i] + 'a' - 'A'; + demo_slug[strindex] = demo.titlename[i] + 'a' - 'A'; strindex++; dash = false; } @@ -7657,7 +7652,6 @@ void G_SaveDemo(void) demo_slug[strindex] = 0; if (dash) demo_slug[strindex-1] = 0; - CONS_Printf("%s\n%s\n", demotitle, demo_slug); writepoint = strstr(demoname, "-") + 1; demo_slug[128 - (writepoint - demoname) - 4] = 0; @@ -7673,7 +7667,7 @@ void G_SaveDemo(void) demosaved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. free(demobuffer); - demorecording = false; + demo.recording = false; if (modeattacking != ATTACKING_RECORD) { diff --git a/src/g_game.h b/src/g_game.h index f78a06d06..ffe98d739 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -36,13 +36,31 @@ extern boolean playeringame[MAXPLAYERS]; // ====================================== // demoplaying back and demo recording -extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo, demosaved, demodefersave, demo_loadfiles, demo_ignorefiles; -extern tic_t demosavebutton; +extern boolean demosaved, demodefersave; extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; -// Quit after playing a demo from cmdline. -extern boolean singledemo; -extern boolean demo_start; +// Publicly-accessible demo vars +struct demovars_s { + char titlename[65]; + boolean recording, playback, timing; + boolean title; // Title Screen demo can be cancelled by any key + + boolean loadfiles, ignorefiles; // Demo file loading options + boolean fromtitle; // SRB2Kart: Don't stop the music + 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; extern mobj_t *metalplayback; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a8cf35eb8..9affc72f6 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2206,7 +2206,7 @@ static void HU_DrawDemoInfo(void) } else { - V_DrawRightAlignedThinString(BASEVIDWIDTH-2, BASEVIDHEIGHT-10, V_ALLOWLOWERCASE, demotitle); + V_DrawRightAlignedThinString(BASEVIDWIDTH-2, BASEVIDHEIGHT-10, V_ALLOWLOWERCASE, demo.titlename); } if (modeattacking) @@ -2326,7 +2326,7 @@ void HU_Drawer(void) if (cechotimer) HU_DrawCEcho(); - if (!( Playing() || demoplayback ) + if (!( Playing() || demo.playback ) || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND @@ -2346,7 +2346,7 @@ void HU_Drawer(void) LUAh_ScoresHUD(); #endif } - if (demoplayback) + if (demo.playback) { HU_DrawDemoInfo(); } @@ -2356,7 +2356,7 @@ void HU_Drawer(void) 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) HU_DrawCrosshair(); @@ -3009,7 +3009,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 ? displayplayer : consoleplayer; scorelines = 0; memset(completed, 0, sizeof (completed)); diff --git a/src/k_kart.c b/src/k_kart.c index 8a68cafe5..3918e8f94 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7115,7 +7115,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI else if ((drawtime/TICRATE) & 1) V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99")); - if (emblemmap && (modeattacking || (mode == 1)) && !demoplayback) // emblem time! + if (emblemmap && (modeattacking || (mode == 1)) && !demo.playback) // emblem time! { INT32 workx = TX + 96, worky = TY+18; SINT8 curemb = 0; @@ -8731,7 +8731,7 @@ void K_drawKartHUD(void) && comeback && stplyr->playerstate == PST_LIVE))); - if (!titledemo && (!battlefullscreen || splitscreen)) + if (!demo.title && (!battlefullscreen || splitscreen)) { // Draw the CHECK indicator before the other items, so it's overlapped by everything else if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) @@ -8768,7 +8768,7 @@ void K_drawKartHUD(void) K_drawKartItem(); // If not splitscreen, draw... - if (!splitscreen && !titledemo) + if (!splitscreen && !demo.title) { // Draw the timestamp #ifdef HAVE_BLUA @@ -8788,7 +8788,7 @@ void K_drawKartHUD(void) if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode { - if (titledemo) // Draw title logo instead in titledemos + if (demo.title) // Draw title logo instead in demo.titles { INT32 x = BASEVIDWIDTH - 32, y = 128, offs; @@ -8838,7 +8838,7 @@ void K_drawKartHUD(void) #endif K_DrawKartPositionNum(stplyr->kartstuff[k_position]); } - else //if (!(demoplayback && hu_showscores)) + else //if (!(demo.playback && hu_showscores)) { // Draw the input UI #ifdef HAVE_BLUA diff --git a/src/m_cheat.c b/src/m_cheat.c index 2fc2e85c9..e7e877ada 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -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)\ diff --git a/src/m_menu.c b/src/m_menu.c index fa88d601b..392310348 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2445,7 +2445,7 @@ boolean M_Responder(event_t *ev) static INT32 lastx = 0, lasty = 0; void (*routine)(INT32 choice); // for some casting problem - if (dedicated || (demoplayback && titledemo) + if (dedicated || (demo.playback && demo.title) || gamestate == GS_INTRO || gamestate == GS_CUTSCENE || gamestate == GS_GAMEEND || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) return false; @@ -2917,7 +2917,7 @@ void M_Drawer(void) void M_StartControlPanel(void) { // time attack HACK - if (modeattacking && demoplayback) + if (modeattacking && demo.playback) { G_CheckDemoStatus(); S_ChangeMusicInternal("racent", true); @@ -6946,7 +6946,7 @@ static void M_HandleStaffReplay(INT32 choice) break; M_ClearMenus(true); modeattacking = ATTACKING_RECORD; - demo_loadfiles = false; demo_ignorefiles = true; // Just assume that record attack replays have the files needed + demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed G_DoPlayDemo(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value)); break; default: @@ -6967,7 +6967,7 @@ static void M_ReplayTimeAttack(INT32 choice) const char *which; M_ClearMenus(true); modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows - demo_loadfiles = false; demo_ignorefiles = true; // Just assume that record attack replays have the files needed + demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed if (currentMenu == &SP_ReplayDef) { @@ -7164,7 +7164,7 @@ static void M_ExitGameResponse(INT32 ch) static void M_EndGame(INT32 choice) { (void)choice; - if (demoplayback) + if (demo.playback) return; if (!Playing()) @@ -7589,7 +7589,7 @@ static void M_StartServer(INT32 choice) else joinpasswordset = false; - if (demoplayback) + if (demo.playback) G_StopDemo(); if (metalrecording) G_StopMetalDemo(); diff --git a/src/p_inter.c b/src/p_inter.c index 90e7a06f5..f70bcf3ee 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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; diff --git a/src/p_map.c b/src/p_map.c index 256c9cef1..9b0db658b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -212,7 +212,7 @@ 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; @@ -1264,7 +1264,7 @@ 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; diff --git a/src/p_mobj.c b/src/p_mobj.c index 484d34fbd..f31075f36 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10789,7 +10789,7 @@ void P_SpawnPlayer(INT32 playernum) } // spawn as spectator determination - if (multiplayer && demoplayback); // Don't mess with spectator values since the demo setup handles them already. + 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) diff --git a/src/p_setup.c b/src/p_setup.c index 07a72e7f7..f73aef99c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2729,7 +2729,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; @@ -3113,9 +3113,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()) @@ -3163,9 +3163,9 @@ boolean P_SetupLevel(boolean skipprecip) ? cv_basenumlaps.value : mapheaderinfo[gamemap - 1]->numlaps); - //@TODO NET REPLAYS NEED BETTER FILE NAMING STUFF. ALSO OPTIONS. FUCK. + // 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 (!demoplayback && multiplayer && !dedicated) { + if (!demo.playback && multiplayer && !dedicated) { static char buf[256]; sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap)); diff --git a/src/p_spec.c b/src/p_spec.c index 67bb74720..6b5f09f6d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3834,7 +3834,7 @@ 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; @@ -7841,7 +7841,7 @@ 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]) { diff --git a/src/p_tick.c b/src/p_tick.c index 6fd2e09f0..a9f786623 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -599,7 +599,7 @@ void P_Ticker(boolean run) if (run) { - if (demorecording) + if (demo.recording) { if (!multiplayer) { G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); @@ -610,7 +610,7 @@ void P_Ticker(boolean run) G_WriteDemoTiccmd(&players[i].cmd, i); } } - if (demoplayback) + if (demo.playback) { if (!multiplayer) { @@ -629,7 +629,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)) @@ -728,23 +728,23 @@ void P_Ticker(boolean run) if (multiplayer) { - if (demorecording) + if (demo.recording) { G_WriteAllGhostTics(); - if (demosavebutton && demosavebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) + if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) demodefersave = true; } - if (demoplayback) // Use Ghost data for consistency checks. + if (demo.playback) // Use Ghost data for consistency checks. { G_ConsAllGhostTics(); } } else { - if (demorecording) + if (demo.recording) G_WriteGhostTic(players[consoleplayer].mo, consoleplayer); - if (demoplayback) // Use Ghost data for consistency checks. + if (demo.playback) // Use Ghost data for consistency checks. G_ConsGhostTic(0); } if (modeattacking) diff --git a/src/p_user.c b/src/p_user.c index 72949c929..18b14f426 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -169,7 +169,7 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move) boolean P_AutoPause(void) { // Don't pause even on menu-up or focus-lost in netgames or record attack - if (netgame || modeattacking || titledemo) + if (netgame || modeattacking || demo.title) return false; return (menuactive || ( window_notinfocus && cv_pauseifunfocused.value )); @@ -1147,7 +1147,7 @@ boolean P_EndingMusic(player_t *player) if (!P_IsLocalPlayer(player)) // Only applies to a local player return false; - if (multiplayer && demoplayback) // Don't play this in multiplayer replays + if (multiplayer && demo.playback) // Don't play this in multiplayer replays return false; // Event - Level Finish @@ -1707,7 +1707,7 @@ void P_SpawnThokMobj(player_t *player) } P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do - if (demorecording) + if (demo.recording) G_GhostAddThok((INT32) (player - players)); } @@ -1776,7 +1776,7 @@ void P_DoPlayerExit(player_t *player) || (splitscreen && player == &players[secondarydisplayplayer]) || (splitscreen > 1 && player == &players[thirddisplayplayer]) || (splitscreen > 2 && player == &players[fourthdisplayplayer])) - && (!player->spectator && !demoplayback)) + && (!player->spectator && !demo.playback)) legitimateexit = true; if (G_RaceGametype()) // If in Race Mode, allow @@ -1836,7 +1836,7 @@ void P_DoPlayerExit(player_t *player) player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation if (player == &players[consoleplayer]) - demosavebutton = leveltime; + demo.savebutton = leveltime; /*if (playeringame[player-players] && netgame && !circuitmap) CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/ @@ -3878,7 +3878,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. // Now spawn the color thok circle. P_SpawnSpinMobj(player, player->revitem); - if (demorecording) + if (demo.recording) G_GhostAddRev((INT32) (player - players)); } } @@ -6767,7 +6767,7 @@ static void P_MovePlayer(player_t *player) if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<mo->scale) && !(player->pflags & PF_JUMPED)) { P_SpawnSpinMobj(player, player->spinitem); - if (demorecording) + if (demo.recording) G_GhostAddSpin((INT32) (player - players)); } */ @@ -7958,7 +7958,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // if (leveltime > 0 && timeinmap <= 0) // return true; - if (demoplayback) + if (demo.playback) { focusangle = mo->angle; focusaiming = 0; @@ -8670,7 +8670,7 @@ void P_DoTimeOver(player_t *player) || (splitscreen && player == &players[secondarydisplayplayer]) || (splitscreen > 1 && player == &players[thirddisplayplayer]) || (splitscreen > 2 && player == &players[fourthdisplayplayer])) - && !demoplayback) + && !demo.playback) legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p if (player->mo) diff --git a/src/r_data.c b/src/r_data.c index 1a74f7336..7fb11855f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -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() diff --git a/src/r_main.c b/src/r_main.c index 36182d0e8..b4dcd9183 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -193,7 +193,7 @@ void SplitScreen_OnChange(void) // recompute screen size R_ExecuteSetViewSize(); - if (!demoplayback && !botingame) + if (!demo.playback && !botingame) { for (i = 1; i < 3; i++) { @@ -879,7 +879,7 @@ 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]) { @@ -1141,7 +1141,7 @@ 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]) { diff --git a/src/r_things.c b/src/r_things.c index baba42116..efc5dd466 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2660,7 +2660,7 @@ 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); diff --git a/src/s_sound.c b/src/s_sound.c index 2ddffa3f5..9653d8ff6 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1920,7 +1920,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) #endif if (S_MusicDisabled() - || titledemo) // SRB2Kart: Demos don't interrupt title screen music + || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; // No Music (empty string) @@ -1955,7 +1955,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) void S_StopMusic(void) { if (!I_SongPlaying() - || titledemo) // SRB2Kart: Demos don't interrupt title screen music + || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; if (I_SongPaused()) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index f92f1f14a..c0fca64da 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -3061,7 +3061,7 @@ void I_Quit(void) //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. - if (demorecording) + if (demo.recording) G_CheckDemoStatus(); if (metalrecording) G_StopMetalRecording(); @@ -3179,7 +3179,7 @@ void I_Error(const char *error, ...) G_SaveGameData(false); // Tails 12-08-2002 // Shutdown. Here might be other errors. - if (demorecording) + if (demo.recording) G_CheckDemoStatus(); if (metalrecording) G_StopMetalRecording(); diff --git a/src/st_stuff.c b/src/st_stuff.c index d87a805d7..2dd045c17 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1894,7 +1894,7 @@ static void ST_overlayDrawer(void) V_DrawScaledPatch(hudinfo[HUD_GRAVBOOTSICO].x, STRINGY(hudinfo[HUD_GRAVBOOTSICO].y), V_SNAPTORIGHT, gravboots); */ - if (!(multiplayer && demoplayback)) + if (!(multiplayer && demo.playback)) { if(!P_IsLocalPlayer(stplyr)) { @@ -1907,7 +1907,7 @@ static void ST_overlayDrawer(void) V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]); } } - else if (!titledemo) + else if (!demo.title) { if (!splitscreen) @@ -2015,7 +2015,7 @@ static void ST_overlayDrawer(void) } // Replay manual-save stuff - if (demorecording && multiplayer && demosavebutton && demosavebutton + 3*TICRATE < leveltime) + if (demo.recording && multiplayer && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime) { if (demodefersave || cv_recordmultiplayerdemos.value == 2) V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 472503341..a98aa8615 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -644,7 +644,7 @@ void I_Error(const char *error, ...) // save demo, could be useful for debug // NOTE: demos are normally not saved here. - if (demorecording) + if (demo.recording) G_CheckDemoStatus(); if (metalrecording) G_StopMetalRecording(); @@ -730,7 +730,7 @@ void I_Quit(void) DWORD mode; // when recording a demo, should exit using 'q', // but sometimes we forget and use Alt+F4, so save here too. - if (demorecording) + if (demo.recording) G_CheckDemoStatus(); if (metalrecording) G_StopMetalRecording(); diff --git a/src/y_inter.c b/src/y_inter.c index 778ab5ad3..5a8791d4a 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -351,7 +351,7 @@ void Y_IntermissionDrawer(void) V_DrawFadeScreen(0xFF00, 22); if (!splitscreen) - whiteplayer = demoplayback ? displayplayer : consoleplayer; + whiteplayer = demo.playback ? displayplayer : consoleplayer; if (cons_menuhighlight.value) hilicol = cons_menuhighlight.value; @@ -360,7 +360,7 @@ void Y_IntermissionDrawer(void) else hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP); - if (sorttic != -1 && intertic > sorttic && !demoplayback) + if (sorttic != -1 && intertic > sorttic && !demo.playback) { INT32 count = (intertic - sorttic); @@ -553,7 +553,7 @@ dotimer: char *string; INT32 tickdown = (timer+1)/TICRATE; - if (multiplayer && demoplayback) + if (multiplayer && demo.playback) string = va("Replay ends in %d", tickdown); else string = va("%s starts in %d", cv_advancemap.string, tickdown); @@ -562,9 +562,9 @@ dotimer: string); } - if (demorecording && cv_recordmultiplayerdemos.value == 1) + if (demo.recording && cv_recordmultiplayerdemos.value == 1) V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Look Backward: Save replay"); - else if (demosaved && !demoplayback) + else if (demosaved && !demo.playback) V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Replay saved!"); // Make it obvious that scrambling is happening next round. @@ -582,7 +582,7 @@ void Y_Ticker(void) if (intertype == int_none) return; - if (demorecording && cv_recordmultiplayerdemos.value == 1 && (demodefersave || InputDown(gc_lookback, 1))) + if (demo.recording && cv_recordmultiplayerdemos.value == 1 && (demodefersave || InputDown(gc_lookback, 1))) { demodefersave = false; G_SaveDemo(); @@ -631,7 +631,7 @@ void Y_Ticker(void) { if (sorttic == -1) sorttic = intertic + max((cv_inttime.value/2)-2, 2)*TICRATE; // 8 second pause after match results - else if (!(multiplayer && demoplayback)) // Don't advance to rankings in replays + else if (!(multiplayer && demo.playback)) // Don't advance to rankings in replays { if (!data.match.rankingsmode && (intertic >= sorttic + 8)) Y_CalculateMatchData(1, Y_CompareRank); @@ -780,7 +780,7 @@ void Y_StartIntermission(void) { if (cv_inttime.value == 0 && gametype == GT_COOP) timer = 0; - else if (demoplayback) // Override inttime (which is pulled from the replay anyway + else if (demo.playback) // Override inttime (which is pulled from the replay anyway timer = 10*TICRATE; else { @@ -816,7 +816,7 @@ void Y_StartIntermission(void) } case int_race: // (time-only race) { - if (!majormods && !multiplayer && !demoplayback) // remove this once we have a proper time attack screen + if (!majormods && !multiplayer && !demo.playback) // remove this once we have a proper time attack screen { // Update visitation flags mapvisited[gamemap-1] |= MV_BEATEN; From 8d9462d4aa7ae3fbd413eba2ef01f82a197ac89d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 21:55:08 -0500 Subject: [PATCH 208/382] Refactor replay saving handler for later use --- src/d_netcmd.c | 2 +- src/g_game.c | 14 ++++++++++---- src/g_game.h | 1 - src/p_tick.c | 2 +- src/st_stuff.c | 19 ++++++++++++++++--- src/y_inter.c | 27 ++++++++++++++++++++------- 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d4ffe27a8..50f0a2e8f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2627,7 +2627,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) LUAh_MapChange(mapnumber); #endif*/ - demosaved = demodefersave = false; + demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING; demo.savebutton = 0; G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene); if (demo.playback && !demo.timing) diff --git a/src/g_game.c b/src/g_game.c index ef8a41968..fc6365377 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -288,7 +288,6 @@ UINT32 timesBeatenWithEmeralds; //@TODO put these all in a struct for namespacing purposes? static char demoname[128]; -boolean demosaved, demodefersave; static UINT8 *demobuffer = NULL; static UINT8 *demo_p, *demotime_p; static UINT8 *demoend; @@ -3325,7 +3324,7 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); - if (multiplayer && demo.recording && cv_recordmultiplayerdemos.value == 2) + if (multiplayer && demo.recording && (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE)) G_SaveDemo(); } } @@ -3860,6 +3859,9 @@ void G_AfterIntermission(void) D_StartTitle(); return; } + else if (demo.recording && demo.savemode != DSM_NOTSAVING) + G_SaveDemo(); + if (modeattacking) // End the run. { M_EndModeAttackRun(); @@ -4004,6 +4006,9 @@ static void G_DoContinued(void) // when something new is added. void G_EndGame(void) { + if (demo.recording && demo.savemode != DSM_NOTSAVING) + G_SaveDemo(); + // Only do evaluation and credits in coop games. if (gametype == GT_COOP) { @@ -7665,13 +7670,14 @@ void G_SaveDemo(void) md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. #endif - demosaved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. + if (FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer)) // finally output the file. + demo.savemode = DSM_SAVED; free(demobuffer); demo.recording = false; if (modeattacking != ATTACKING_RECORD) { - if (demosaved) + if (demo.savemode == DSM_SAVED) CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); else CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); diff --git a/src/g_game.h b/src/g_game.h index ffe98d739..c9bcaf01b 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -36,7 +36,6 @@ extern boolean playeringame[MAXPLAYERS]; // ====================================== // demoplaying back and demo recording -extern boolean demosaved, demodefersave; extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; // Publicly-accessible demo vars diff --git a/src/p_tick.c b/src/p_tick.c index a9f786623..03ce05c3e 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -733,7 +733,7 @@ void P_Ticker(boolean run) G_WriteAllGhostTics(); if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) - demodefersave = true; + demo.savemode = DSM_WILLSAVE; // DSM_TITLEENTRY } if (demo.playback) // Use Ghost data for consistency checks. { diff --git a/src/st_stuff.c b/src/st_stuff.c index 2dd045c17..dec7ee0cf 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2017,10 +2017,23 @@ static void ST_overlayDrawer(void) // Replay manual-save stuff if (demo.recording && multiplayer && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime) { - if (demodefersave || cv_recordmultiplayerdemos.value == 2) - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); - else + switch (demo.savemode) + { + case DSM_NOTSAVING: V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Look Backward: Save replay"); + break; + + case DSM_WILLAUTOSAVE: + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved." /*" (Look Backward: Change title)"*/); + break; + + case DSM_WILLSAVE: + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); + break; + + default: // Don't render anything + break; + } } ST_drawDebugInfo(); diff --git a/src/y_inter.c b/src/y_inter.c index 5a8791d4a..1e6d945c4 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -562,10 +562,20 @@ dotimer: string); } - if (demo.recording && cv_recordmultiplayerdemos.value == 1) - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Look Backward: Save replay"); - else if (demosaved && !demo.playback) - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Replay saved!"); + if ((demo.recording || demo.savemode == DSM_SAVED) && !demo.playback) + switch (demo.savemode) + { + case DSM_NOTSAVING: + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Look Backward: Save replay"); + break; + + case DSM_SAVED: + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Replay saved!"); + break; + + default: // Don't render any text here + break; + } // Make it obvious that scrambling is happening next round. if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) @@ -582,10 +592,13 @@ void Y_Ticker(void) if (intertype == int_none) return; - if (demo.recording && cv_recordmultiplayerdemos.value == 1 && (demodefersave || InputDown(gc_lookback, 1))) + if (demo.recording) { - demodefersave = false; - G_SaveDemo(); + if (demo.savemode == DSM_NOTSAVING && InputDown(gc_lookback, 1)) + demo.savemode = DSM_WILLSAVE; // DSM_TITLEENTRY + + if (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE) + G_SaveDemo(); } // Check for pause or menu up in single player From 91868fc3a4187c144b559434a5d5c2367b8ba027 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 22:40:52 -0500 Subject: [PATCH 209/382] Allow entering a title for replays on save --- src/d_main.c | 6 ++++++ src/g_game.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- src/g_game.h | 1 + src/p_tick.c | 2 +- src/st_stuff.c | 36 ++++++++++++++++++++++++++++++++++- src/st_stuff.h | 3 +++ src/y_inter.c | 6 +++++- 7 files changed, 101 insertions(+), 4 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 6edb1cf44..16a70519f 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -248,6 +248,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 diff --git a/src/g_game.c b/src/g_game.c index fc6365377..ca2f02080 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7603,7 +7603,7 @@ boolean G_CheckDemoStatus(void) return true; } - if (demo.recording && (!multiplayer || cv_recordmultiplayerdemos.value == 2)) + if (demo.recording && demo.savemode != DSM_NOTSAVING) { G_SaveDemo(); return true; @@ -7684,6 +7684,55 @@ void G_SaveDemo(void) } } +boolean G_DemoTitleResponder(event_t *ev) +{ + size_t len; + INT32 ch; + + if (ev->type != ev_keydown) + return false; + + ch = (INT32)ev->data1; + + // Only ESC and non-keyboard keys abort connection + if (ch == KEY_ESCAPE) + { + demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING; + return true; + } + + if (ch == KEY_ENTER || ch >= KEY_MOUSE1) + { + demo.savemode = DSM_WILLSAVE; + return true; + } + + if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART]) + || ch == ' ') // Allow spaces, of course + { + len = strlen(demo.titlename); + if (len < 64) + { + demo.titlename[len+1] = 0; + demo.titlename[len] = CON_ShiftChar(ch); + } + } + else if (ch == KEY_BACKSPACE) + { + if (shiftdown) + memset(demo.titlename, 0, sizeof(demo.titlename)); + else + { + len = strlen(demo.titlename); + + if (len > 0) + demo.titlename[len-1] = 0; + } + } + + return true; +} + // // G_SetGamestate // diff --git a/src/g_game.h b/src/g_game.h index c9bcaf01b..d97752b26 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -230,6 +230,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); void G_StopDemo(void); boolean G_CheckDemoStatus(void); void G_SaveDemo(void); +boolean G_DemoTitleResponder(event_t *ev); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); diff --git a/src/p_tick.c b/src/p_tick.c index 03ce05c3e..177f3b657 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -733,7 +733,7 @@ void P_Ticker(boolean run) G_WriteAllGhostTics(); if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) - demo.savemode = DSM_WILLSAVE; // DSM_TITLEENTRY + demo.savemode = DSM_TITLEENTRY; } if (demo.playback) // Use Ghost data for consistency checks. { diff --git a/src/st_stuff.c b/src/st_stuff.c index dec7ee0cf..acb01fb69 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2024,13 +2024,17 @@ static void ST_overlayDrawer(void) break; case DSM_WILLAUTOSAVE: - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved." /*" (Look Backward: Change title)"*/); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved. (Look Backward: Change title)"); break; case DSM_WILLSAVE: V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); break; + case DSM_TITLEENTRY: + ST_DrawDemoTitleEntry(); + break; + default: // Don't render anything break; } @@ -2039,6 +2043,36 @@ static void ST_overlayDrawer(void) ST_drawDebugInfo(); } +void ST_DrawDemoTitleEntry(void) +{ + static UINT8 skullAnimCounter = 0; + char *nametodraw; + + skullAnimCounter++; + skullAnimCounter %= 8; + + nametodraw = demo.titlename; + while (V_StringWidth(nametodraw, 0) > MAXSTRINGLENGTH*8 - 8) + nametodraw++; + +#define x (BASEVIDWIDTH/2 - 139) +#define y (BASEVIDHEIGHT/2) + M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); + V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, nametodraw); + if (skullAnimCounter < 4) + V_DrawCharacter(x + 8 + V_StringWidth(nametodraw, 0), y + 12, + '_' | 0x80, false); + + M_DrawTextBox(x + 30, y - 24, 26, 1); + V_DrawString(x + 38, y - 16, V_ALLOWLOWERCASE, "Enter the name of the replay."); + + M_DrawTextBox(x + 50, y + 20, 20, 1); + V_DrawThinString(x + 58, y + 28, V_ALLOWLOWERCASE, "Escape - Cancel"); + V_DrawRightAlignedThinString(x + 220, y + 28, V_ALLOWLOWERCASE, "Enter - Confirm"); +#undef x +#undef y +} + // MayonakaStatic: draw Midnight Channel's TV-like borders static void ST_MayonakaStatic(void) { diff --git a/src/st_stuff.h b/src/st_stuff.h index f96aee938..16f7b8811 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -26,6 +26,9 @@ // Called by main loop. void ST_Ticker(void); +// Called when naming a replay. +void ST_DrawDemoTitleEntry(void); + // Called by main loop. void ST_Drawer(void); diff --git a/src/y_inter.c b/src/y_inter.c index 1e6d945c4..256a8566a 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -573,6 +573,10 @@ dotimer: V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Replay saved!"); break; + case DSM_TITLEENTRY: + ST_DrawDemoTitleEntry(); + break; + default: // Don't render any text here break; } @@ -595,7 +599,7 @@ void Y_Ticker(void) if (demo.recording) { if (demo.savemode == DSM_NOTSAVING && InputDown(gc_lookback, 1)) - demo.savemode = DSM_WILLSAVE; // DSM_TITLEENTRY + demo.savemode = DSM_TITLEENTRY; if (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE) G_SaveDemo(); From f6143dafb01a1bd0274dc598ff336cc7a9f81f79 Mon Sep 17 00:00:00 2001 From: jameds Date: Mon, 19 Mar 2018 23:15:16 -0700 Subject: [PATCH 210/382] Scroll console immediately upon pressing PageUp --- src/console.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/console.c b/src/console.c index 5c173e459..fbb9ac43e 100644 --- a/src/console.c +++ b/src/console.c @@ -1539,8 +1539,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; From a8aea17469bab152aa9d5063a2f37fc55d67afe2 Mon Sep 17 00:00:00 2001 From: jameds Date: Wed, 21 Mar 2018 21:12:48 -0700 Subject: [PATCH 211/382] Keep color across wrapped lines And this works by inserting the same color code on each wrapped line. --- src/console.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/console.c b/src/console.c index fbb9ac43e..032615e1e 100644 --- a/src/console.c +++ b/src/console.c @@ -1106,6 +1106,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; @@ -1131,7 +1132,7 @@ static void CON_Print(char *msg) { if (*msg & 0x80) { - con_line[con_cx++] = *(msg++); + color = con_line[con_cx++] = *(msg++); controlchars++; continue; } @@ -1139,12 +1140,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 { @@ -1152,7 +1155,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') @@ -1167,7 +1171,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++; @@ -1184,7 +1189,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 From f995e8c241848484c1456a556b7030e357c14adf Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 12:30:02 -0700 Subject: [PATCH 212/382] Resize console upon resolution change Basically, changing to a lower resolution won't cause your console to extend past the screen anymore. --- src/console.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/console.c b/src/console.c index 032615e1e..9718bb481 100644 --- a/src/console.c +++ b/src/console.c @@ -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); @@ -447,6 +448,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 @@ -496,6 +503,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) @@ -584,16 +605,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 From d7ad7a4f409d44b0ab62d6d50e153e40256be947 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 12:59:13 -0700 Subject: [PATCH 213/382] Remove redundant CON_ClearHUD calls --- src/d_main.c | 1 - src/d_netcmd.c | 1 - src/f_finale.c | 7 ------- 3 files changed, 9 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index dd2cfe0e5..6933ee1a1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1397,7 +1397,6 @@ void D_SRB2Main(void) else if (M_CheckParm("-skipintro")) { CON_ToggleOff(); - CON_ClearHUD(); F_StartTitleScreen(); } else diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 11b9413a8..ed4be044b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1832,7 +1832,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) } CON_ToggleOff(); - CON_ClearHUD(); if (demoplayback && !timingdemo) precache = false; diff --git a/src/f_finale.c b/src/f_finale.c index bcdac295a..d4a468c57 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -444,7 +444,6 @@ void F_StartIntro(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); F_NewCutscene(introtext[0]); intro_scenenum = 0; @@ -1146,7 +1145,6 @@ void F_StartCredits(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); S_StopMusic(); S_ChangeMusicInternal("credit", false); @@ -1313,7 +1311,6 @@ void F_StartGameEvaluation(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); finalecount = 0; } @@ -1423,7 +1420,6 @@ void F_StartGameEnd(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); S_StopMusic(); // In case menus are still up?!! @@ -1626,7 +1622,6 @@ void F_StartContinue(void) keypressed = false; paused = false; CON_ToggleOff(); - CON_ClearHUD(); // In case menus are still up?!! M_ClearMenus(true); @@ -1797,8 +1792,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; From 841daf940fadf3c27d9beef59c991273f22285ba Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 13:04:11 -0700 Subject: [PATCH 214/382] Don't close console when changing map --- src/d_main.c | 4 ++-- src/d_netcmd.c | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index dd2cfe0e5..5b29cb415 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1396,13 +1396,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"; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 11b9413a8..bee6b4091 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1831,9 +1831,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) CONS_Printf(M_GetText("Speeding off to level...\n")); } - CON_ToggleOff(); - CON_ClearHUD(); - if (demoplayback && !timingdemo) precache = false; From 7ebf19fd00d619bf7027964023a9bccb063f0429 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 13:05:19 -0700 Subject: [PATCH 215/382] Don't close console when starting title screen --- src/d_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 5b29cb415..1b2d73d7d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -726,7 +726,6 @@ void D_StartTitle(void) paused = false; advancedemo = false; F_StartTitleScreen(); - CON_ToggleOff(); // Reset the palette if (rendermode != render_none) From 714b4068ca8255cefbb7c6f5211c3199626a0fa0 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 29 Mar 2019 22:00:47 -0700 Subject: [PATCH 216/382] Grab mouse on window focus Window focus does not necessarily imply mouse movement. --- src/sdl/i_video.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 9fbe57b39..74f789804 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -359,6 +359,14 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) return 0; } +static void SDLdoGrabMouse(void) +{ + SDL_ShowCursor(SDL_DISABLE); + SDL_SetWindowGrab(window, SDL_TRUE); + if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful + wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore? +} + static void SDLdoUngrabMouse(void) { SDL_ShowCursor(SDL_ENABLE); @@ -629,6 +637,9 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) //else firsttimeonmouse = SDL_FALSE; capslock = !!( SDL_GetModState() & KMOD_CAPS );// in case CL changes + + if (USE_MOUSEINPUT) + SDLdoGrabMouse(); } else if (!mousefocus && !kbfocus) { @@ -708,9 +719,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) // -- Monster Iestyn if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window) { - SDL_SetWindowGrab(window, SDL_TRUE); - if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful - wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore? + SDLdoGrabMouse(); } } } @@ -1277,7 +1286,7 @@ void I_StartupMouse(void) else firsttimeonmouse = SDL_FALSE; if (cv_usemouse.value) - return; + SDLdoGrabMouse(); else SDLdoUngrabMouse(); } From 93e07ae745689857c9ca1b5a2868144e8a03d06e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 30 Mar 2019 17:25:54 -0500 Subject: [PATCH 217/382] Move menu options around 1 Player now goes directly to Time Attack, and Extras is now a submenu with Unlockables, Statistics, and a currently-dummied option for Replay Hut. --- src/m_menu.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 392310348..18bf0d41c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -233,7 +233,9 @@ static char *M_GetConditionString(condition_t cond); menu_t SR_MainDef, SR_UnlockChecklistDef; // Misc. Main Menu +#if 0 // Bring this back when we have actual single-player static void M_SinglePlayerMenu(INT32 choice); +#endif static void M_Options(INT32 choice); static void M_Manual(INT32 choice); static void M_SelectableClearMenus(INT32 choice); @@ -500,12 +502,13 @@ static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaf // --------- static menuitem_t MainMenu[] = { - {IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_UnlockChecklistDef, 76}, - {IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84}, - {IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92}, - {IT_CALL |IT_STRING, NULL, "Options", M_Options, 100}, - {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108}, - {IT_CALL |IT_STRING, NULL, "Quit Game", M_QuitSRB2, 116}, + {IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_MainDef, 76}, + //{IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84}, + {IT_CALL |IT_STRING, NULL, "Time Attack", M_TimeAttack, 84}, + {IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92}, + {IT_CALL |IT_STRING, NULL, "Options", M_Options, 100}, + {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108}, + {IT_CALL |IT_STRING, NULL, "Quit Game", M_QuitSRB2, 116}, }; typedef enum @@ -695,7 +698,9 @@ static menuitem_t SR_PandorasBox[] = // Sky Room Custom Unlocks static menuitem_t SR_MainMenu[] = { - {IT_STRING|IT_SUBMENU,NULL, "Secrets Checklist", &SR_UnlockChecklistDef, 0}, + {IT_STRING|IT_SUBMENU, NULL, "Unlockables", &SR_UnlockChecklistDef, 0}, + {IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 10}, + {IT_CALL|IT_STRING, NULL, "Replay Hut", M_Statistics, 20}, {IT_DISABLED, NULL, "", NULL, 0}, // Custom1 {IT_DISABLED, NULL, "", NULL, 0}, // Custom2 {IT_DISABLED, NULL, "", NULL, 0}, // Custom3 @@ -1681,7 +1686,8 @@ menu_t SR_MainDef = sizeof (SR_MainMenu)/sizeof (menuitem_t), &MainDef, SR_MainMenu, - M_DrawSkyRoom, + M_DrawGenericMenu, + //M_DrawSkyRoom, 60, 40, 0, NULL @@ -1693,7 +1699,7 @@ menu_t SR_UnlockChecklistDef = { NULL, 1, - &MainDef, //&SR_MainDef + &SR_MainDef, SR_UnlockChecklistMenu, M_DrawChecklist, 280, 185, @@ -1731,7 +1737,7 @@ menu_t SP_LevelStatsDef = { "M_STATS", 1, - &SP_MainDef, + &SR_MainDef, SP_LevelStatsMenu, M_DrawLevelStats, 280, 185, @@ -5619,6 +5625,7 @@ static void M_Credits(INT32 choice) // SINGLE PLAYER MENU // ================== +#if 0 // Bring this back when we have actual single-player static void M_SinglePlayerMenu(INT32 choice) { (void)choice; @@ -5629,6 +5636,7 @@ static void M_SinglePlayerMenu(INT32 choice) M_SetupNextMenu(&SP_MainDef); } +#endif /*static void M_LoadGameLevelSelect(INT32 choice) { From a54a7de02d3c8b49c2dab59d0b57761495b79d6d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 30 Mar 2019 20:57:53 -0500 Subject: [PATCH 218/382] Start on the replay hut menu! --- src/filesrch.c | 75 +++++++++++++++++++------------- src/filesrch.h | 2 +- src/m_menu.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 154 insertions(+), 38 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 0276e1c90..69a6c5c73 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -368,9 +368,10 @@ void searchfilemenu(char *tempname) return; } -boolean preparefilemenu(boolean samedepth) +boolean preparefilemenu(boolean samedepth, boolean replayhut) { (void)samedepth; + (void)replayhut; return false; } @@ -437,9 +438,10 @@ void searchfilemenu(char *tempname) return; } -boolean preparefilemenu(boolean samedepth) +boolean preparefilemenu(boolean samedepth, boolean replayhut) { (void)samedepth; + (void)replayhut; return false; } @@ -710,7 +712,7 @@ void searchfilemenu(char *tempname) } } -boolean preparefilemenu(boolean samedepth) +boolean preparefilemenu(boolean samedepth, boolean replayhut) { DIR *dirhandle; struct dirent *dent; @@ -759,9 +761,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 +835,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 diff --git a/src/filesrch.h b/src/filesrch.h index 01a528482..dbcc5fc37 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -94,6 +94,6 @@ typedef enum void closefilemenu(boolean validsize); void searchfilemenu(char *tempname); -boolean preparefilemenu(boolean samedepth); +boolean preparefilemenu(boolean samedepth, boolean replayhut); #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index 18bf0d41c..a6957f3a6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -336,6 +336,10 @@ static patch_t *addonsp[NUM_EXT+5]; #define numaddonsshown 4 +// Replay hut +static void M_ReplayHut(INT32 choice); +static void M_DrawReplayHut(void); + // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawCenteredMenu(void); @@ -526,6 +530,13 @@ static menuitem_t MISC_AddonsMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func }; +static menuitem_t MISC_ReplayHutMenu[] = +{ + {IT_SUBMENU |IT_STRING, NULL, "Replay Options...", NULL, 0}, + + {IT_KEYHANDLER|IT_NOTHING, NULL, "", NULL, 20}, // Dummy menuitem for the replay list +}; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -700,7 +711,7 @@ static menuitem_t SR_MainMenu[] = { {IT_STRING|IT_SUBMENU, NULL, "Unlockables", &SR_UnlockChecklistDef, 0}, {IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 10}, - {IT_CALL|IT_STRING, NULL, "Replay Hut", M_Statistics, 20}, + {IT_CALL|IT_STRING, NULL, "Replay Hut", M_ReplayHut, 20}, {IT_DISABLED, NULL, "", NULL, 0}, // Custom1 {IT_DISABLED, NULL, "", NULL, 0}, // Custom2 {IT_DISABLED, NULL, "", NULL, 0}, // Custom3 @@ -1583,6 +1594,18 @@ menu_t MISC_AddonsDef = NULL }; +menu_t MISC_ReplayHutDef = +{ + "M_REPLAY", + sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t), + &MainDef, + MISC_ReplayHutMenu, + M_DrawReplayHut, + 30, 80, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -4471,7 +4494,7 @@ static void M_Addons(INT32 choice) else --menupathindex[menudepthleft]; - if (!preparefilemenu(false)) + if (!preparefilemenu(false, false)) { M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n", (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)),NULL,MM_NOTHING); return; @@ -4595,7 +4618,7 @@ static void M_AddonsClearName(INT32 choice) // returns whether to do message draw static boolean M_AddonsRefresh(void) { - if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) + if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true, false)) { UNEXIST; if (refreshdirname) @@ -4844,7 +4867,7 @@ static void M_HandleAddons(INT32 choice) if (dirmenu && dirmenu[dir_on[menudepthleft]]) tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL #if 0 // much slower - if (!preparefilemenu(true)) + if (!preparefilemenu(true, false)) { UNEXIST; return; @@ -4898,13 +4921,13 @@ static void M_HandleAddons(INT32 choice) menupathindex[--menudepthleft] = strlen(menupath); menupath[menupathindex[menudepthleft]] = 0; - if (!preparefilemenu(false)) + if (!preparefilemenu(false, false)) { S_StartSound(NULL, sfx_s224); M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu(true)) + if (!preparefilemenu(true, false)) { UNEXIST; return; @@ -4927,7 +4950,7 @@ static void M_HandleAddons(INT32 choice) case EXT_UP: S_StartSound(NULL, sfx_menu1); menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu(false)) + if (!preparefilemenu(false, false)) { UNEXIST; return; @@ -4984,6 +5007,84 @@ static void M_HandleAddons(INT32 choice) } } +// ---- REPLAY HUT ----- + +static INT16 replayOn = 0; + +static void M_ReplayHut(INT32 choice) +{ + (void)choice; + + snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); + + if (!preparefilemenu(false, true)) + { + M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING); + return; + } + else + dir_on[menudepthleft] = 0; + + M_SetupNextMenu(&MISC_ReplayHutDef); + G_SetGamestate(GS_TIMEATTACK); + + S_ChangeMusicInternal("replst", true); +} + +static void M_DrawReplayHut(void) +{ + INT32 x, y, cursory = 0; + INT16 i; + + (void)cursory; + + V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + M_DrawMenuTitle(); + + // Draw menu choices + x = currentMenu->x; + y = currentMenu->y; + + if (itemOn == currentMenu->numitems-1) + { + INT32 maxy; + // Scroll menu items if needed + cursory = y + currentMenu->menuitems[currentMenu->numitems-1].alphaKey + replayOn*10; + maxy = y + currentMenu->menuitems[currentMenu->numitems-1].alphaKey + sizedirmenu*10; + + if (cursory > maxy - 70) + cursory = maxy - 70; + + if (cursory > 130) + y -= (cursory-130); + } + + // Draw static menu items + for (i = 0; i < currentMenu->numitems-1; i++) + { + if (i == itemOn) + cursory = y; + + if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) + V_DrawString(x, y + currentMenu->menuitems[i].alphaKey, 0, currentMenu->menuitems[i].text); + else + V_DrawString(x, y + currentMenu->menuitems[i].alphaKey, highlightflags, currentMenu->menuitems[i].text); + } + + y += currentMenu->menuitems[currentMenu->numitems-1].alphaKey; + + for (i = 0; i < (INT16)sizedirmenu; i++) + { + V_DrawString(x, y+i*10, V_ALLOWLOWERCASE, dirmenu[i]+DIR_STRING); + } + + // Draw the cursor + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, + W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); +} + static void M_PandorasBox(INT32 choice) { (void)choice; From 29a80e01eb645c93cb953b46e9df5c96943270bf Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 01:22:41 -0500 Subject: [PATCH 219/382] List demos by title in the replay hut --- src/filesrch.c | 2 + src/g_game.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ src/g_game.h | 20 ++++++++ src/m_menu.c | 113 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 243 insertions(+), 14 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 69a6c5c73..6827dc57e 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -896,6 +896,8 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) 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; } diff --git a/src/g_game.c b/src/g_game.c index ca2f02080..09a3db52d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6564,6 +6564,128 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) return c; } +void G_LoadDemoInfo(menudemo_t *pdemo) +{ + UINT8 *infobuffer, *info_p; + UINT8 version, subversion, pdemoflags; + UINT16 pdemoversion, cvarcount; + + if (!FIL_ReadFile(pdemo->filepath, &infobuffer)) + { + CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + + return; + } + + info_p = infobuffer; + + if (memcmp(info_p, DEMOHEADER, 12)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } + + pdemo->type = MD_LOADED; + + info_p += 12; // DEMOHEADER + + version = READUINT8(info_p); + subversion = READUINT8(info_p); + pdemoversion = READUINT16(info_p); + + switch(pdemoversion) + { + case DEMOVERSION: // latest always supported + // demo title + M_Memcpy(pdemo->title, info_p, 64); + info_p += 64; + + break; +#ifdef DEMO_COMPAT_100 + case 0x0001: + pdemo->type = MD_OUTDATED; + sprintf(pdemo->title, "Legacy Replay"); + break; +#endif + // too old, cannot support. + default: + CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } + + if (version != VERSION || subversion != SUBVERSION) + pdemo->type = MD_OUTDATED; + + info_p += 16; // demo checksum + if (memcmp(info_p, "PLAY", 4)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } + demo_p += 4; // "PLAY" + pdemo->map = READINT16(info_p); + demo_p += 16; // mapmd5 + + pdemoflags = READUINT8(info_p); + + // temp? + if (!(pdemoflags & DF_MULTIPLAYER)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is not a multiplayer replay and can't be listed on this menu fully yet.\n"), pdemo->filepath); + Z_Free(infobuffer); + return; + } + + pdemo->gametype = READUINT8(info_p); + + G_SkipDemoExtraFiles(&info_p); //@TODO see if this information is useful for display? + demo_p += 4; // RNG seed + + // Pared down version of CV_LoadNetVars to find the kart speed + cvarcount = READUINT16(info_p); + while (cvarcount--) + { + UINT16 netid; + char *svalue; + + netid = READUINT16(info_p); + svalue = (char *)info_p; + SKIPSTRING(info_p); + info_p++; // stealth + + if (netid == cv_kartspeed.netid) + { + for (cvarcount = 0; kartspeed_cons_t[cvarcount].value; cvarcount++) + { + if (!strcasecmp(kartspeed_cons_t[cvarcount].strvalue, svalue)) + { + pdemo->kartspeed = kartspeed_cons_t[cvarcount].value; + break; + } + } + + break; + } + } + + if (pdemoflags & DF_ENCORE) + pdemo->kartspeed |= DF_ENCORE; + + // I think that's everything we need? + free(infobuffer); +} + // // G_PlayDemo // diff --git a/src/g_game.h b/src/g_game.h index d97752b26..5b07d053c 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -61,6 +61,25 @@ struct demovars_s { 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 gametype; + UINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk +} menudemo_t; + + extern mobj_t *metalplayback; // gametic at level start @@ -147,6 +166,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. diff --git a/src/m_menu.c b/src/m_menu.c index a6957f3a6..a5f51f2a9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -338,6 +338,7 @@ static patch_t *addonsp[NUM_EXT+5]; // Replay hut static void M_ReplayHut(INT32 choice); +static void M_HandleReplayHutList(INT32 choice); static void M_DrawReplayHut(void); // Drawing functions @@ -532,9 +533,10 @@ static menuitem_t MISC_AddonsMenu[] = static menuitem_t MISC_ReplayHutMenu[] = { - {IT_SUBMENU |IT_STRING, NULL, "Replay Options...", NULL, 0}, + {IT_SUBMENU |IT_STRING, NULL, "Replay Options...", NULL, 0}, - {IT_KEYHANDLER|IT_NOTHING, NULL, "", NULL, 20}, // Dummy menuitem for the replay list + {IT_KEYHANDLER|IT_NOTHING, NULL, "", M_HandleReplayHutList, 20}, // Dummy menuitem for the replay list + {IT_NOTHING, NULL, "", NULL, 20}, // Dummy for handling wrapping to the top of the menu.. }; // --------------------------------- @@ -1602,7 +1604,7 @@ menu_t MISC_ReplayHutDef = MISC_ReplayHutMenu, M_DrawReplayHut, 30, 80, - 0, + (sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t)) - 2, // Start on the replay list NULL }; @@ -5008,9 +5010,35 @@ static void M_HandleAddons(INT32 choice) } // ---- REPLAY HUT ----- +menudemo_t *demolist; static INT16 replayOn = 0; +static void PrepReplayList(void) +{ + size_t i; + + if (demolist) + Z_Free(demolist); + + demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); + + for (i = 0; i < sizedirmenu; i++) + { + if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) + { + demolist[i].type = MD_SUBDIR; + strncpy(demolist[i].title, dirmenu[i] + DIR_STRING, 64); + } + else + { + demolist[i].type = MD_NOTLOADED; + snprintf(demolist[i].filepath, 255, "%s%s", menupath, dirmenu[i] + DIR_STRING); + sprintf(demolist[i].title, "....."); + } + } +} + static void M_ReplayHut(INT32 choice) { (void)choice; @@ -5026,18 +5054,46 @@ static void M_ReplayHut(INT32 choice) else dir_on[menudepthleft] = 0; + PrepReplayList(); + M_SetupNextMenu(&MISC_ReplayHutDef); G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("replst", true); } +static void M_HandleReplayHutList(INT32 choice) +{ + switch (choice) + { + case KEY_UPARROW: + if (replayOn) + replayOn--; + else + M_PrevOpt(); + + S_StartSound(NULL, sfx_menu1); + break; + + case KEY_DOWNARROW: + if (replayOn < (INT16)sizedirmenu-1) + replayOn++; + else + itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item + + S_StartSound(NULL, sfx_menu1); + break; + } +} + static void M_DrawReplayHut(void) { INT32 x, y, cursory = 0; INT16 i; + INT16 replaylistitem = currentMenu->numitems-2; + boolean processed_one_this_frame = false; - (void)cursory; + static UINT16 replayhutmenuy = 0; V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); M_DrawMenuTitle(); @@ -5046,25 +5102,41 @@ static void M_DrawReplayHut(void) x = currentMenu->x; y = currentMenu->y; - if (itemOn == currentMenu->numitems-1) + if (itemOn > replaylistitem) + { + itemOn = replaylistitem; + replayOn = sizedirmenu-1; + } + else if (itemOn < replaylistitem) + { + replayOn = 0; + } + + if (itemOn == replaylistitem) { INT32 maxy; // Scroll menu items if needed - cursory = y + currentMenu->menuitems[currentMenu->numitems-1].alphaKey + replayOn*10; - maxy = y + currentMenu->menuitems[currentMenu->numitems-1].alphaKey + sizedirmenu*10; + cursory = y + currentMenu->menuitems[replaylistitem].alphaKey + replayOn*10; + maxy = y + currentMenu->menuitems[replaylistitem].alphaKey + sizedirmenu*10; - if (cursory > maxy - 70) - cursory = maxy - 70; + if (cursory > maxy - 20) + cursory = maxy - 20; - if (cursory > 130) - y -= (cursory-130); + if (cursory - replayhutmenuy > 150) + replayhutmenuy += (cursory-150-replayhutmenuy)/2; + else if (cursory - replayhutmenuy < 110) + replayhutmenuy += (max(0, cursory-110)-replayhutmenuy)/2; } + else + replayhutmenuy /= 2; + + y -= replayhutmenuy; // Draw static menu items - for (i = 0; i < currentMenu->numitems-1; i++) + for (i = 0; i < replaylistitem; i++) { if (i == itemOn) - cursory = y; + cursory = y + currentMenu->menuitems[i].alphaKey; if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) V_DrawString(x, y + currentMenu->menuitems[i].alphaKey, 0, currentMenu->menuitems[i].text); @@ -5076,7 +5148,20 @@ static void M_DrawReplayHut(void) for (i = 0; i < (INT16)sizedirmenu; i++) { - V_DrawString(x, y+i*10, V_ALLOWLOWERCASE, dirmenu[i]+DIR_STRING); + INT32 localy = y+i*10; + if (localy >= 0 && localy < 200 && demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) + { + processed_one_this_frame = true; + G_LoadDemoInfo(&demolist[i]); + } + + if (itemOn == replaylistitem && i == replayOn) + { + cursory = localy; + V_DrawString(x, localy, highlightflags|V_ALLOWLOWERCASE, demolist[i].title); + } + else + V_DrawString(x, localy, V_ALLOWLOWERCASE, demolist[i].title); } // Draw the cursor From f00f9c9a0a4c92fd3d438a5f0bcc04ee86fb5266 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 02:54:09 -0500 Subject: [PATCH 220/382] Display infobox for the currently-selected replay --- src/g_game.c | 30 ++++++------ src/g_game.h | 12 +++++ src/m_menu.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 155 insertions(+), 19 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 09a3db52d..94f8bd8d1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6346,12 +6346,8 @@ static void G_SkipDemoExtraFiles(UINT8 **pp) } // 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. -static UINT8 G_CheckDemoExtraFiles(UINT8 **pp) +// Enabling quick prevents filesystem checks to see if needed files are available to load. +static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) { UINT8 totalfiles, filesloaded, nmusfilecount; char filename[MAX_WADPATH]; @@ -6405,7 +6401,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp) if (numwadfiles >= MAX_WADFILES) error = DFILE_ERROR_CANNOTLOAD; - else if (findfile(filename, md5sum, false) != FS_FOUND) + else if (!quick && findfile(filename, md5sum, false) != FS_FOUND) error = DFILE_ERROR_CANNOTLOAD; else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) error |= DFILE_ERROR_NOTLOADED; @@ -6633,9 +6629,9 @@ void G_LoadDemoInfo(menudemo_t *pdemo) Z_Free(infobuffer); return; } - demo_p += 4; // "PLAY" + info_p += 4; // "PLAY" pdemo->map = READINT16(info_p); - demo_p += 16; // mapmd5 + info_p += 16; // mapmd5 pdemoflags = READUINT8(info_p); @@ -6649,8 +6645,8 @@ void G_LoadDemoInfo(menudemo_t *pdemo) pdemo->gametype = READUINT8(info_p); - G_SkipDemoExtraFiles(&info_p); //@TODO see if this information is useful for display? - demo_p += 4; // RNG seed + pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true); + info_p += 4; // RNG seed // Pared down version of CV_LoadNetVars to find the kart speed cvarcount = READUINT16(info_p); @@ -6666,9 +6662,9 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (netid == cv_kartspeed.netid) { - for (cvarcount = 0; kartspeed_cons_t[cvarcount].value; cvarcount++) + for (cvarcount = 0; kartspeed_cons_t[cvarcount].strvalue; cvarcount++) { - if (!strcasecmp(kartspeed_cons_t[cvarcount].strvalue, svalue)) + if (!stricmp(kartspeed_cons_t[cvarcount].strvalue, svalue)) { pdemo->kartspeed = kartspeed_cons_t[cvarcount].value; break; @@ -6682,6 +6678,12 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (pdemoflags & DF_ENCORE) pdemo->kartspeed |= DF_ENCORE; + // Temporary info until this is actually present in replays. + sprintf(pdemo->winnername, "transrights420"); + pdemo->winnerskin = 1; + pdemo->winnercolor = SKINCOLOR_MOONSLAM; + pdemo->winnertime = 6666; + // I think that's everything we need? free(infobuffer); } @@ -6845,7 +6847,7 @@ void G_DoPlayDemo(char *defdemoname) G_SkipDemoExtraFiles(&demo_p); else { - UINT8 error = G_CheckDemoExtraFiles(&demo_p); + UINT8 error = G_CheckDemoExtraFiles(&demo_p, false); if (error) { diff --git a/src/g_game.h b/src/g_game.h index 5b07d053c..af85bd029 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -75,8 +75,13 @@ typedef struct menudemo_s { 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 + + char winnername[17]; + UINT8 winnerskin, winnercolor; + UINT32 winnertime; } menudemo_t; @@ -239,6 +244,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); diff --git a/src/m_menu.c b/src/m_menu.c index a5f51f2a9..db31a4a54 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5012,7 +5012,10 @@ static void M_HandleAddons(INT32 choice) // ---- REPLAY HUT ----- menudemo_t *demolist; +#define DF_ENCORE 0x40 static INT16 replayOn = 0; +static INT16 replayScrollTitle = 0; +static INT8 replayScrollDelay = TICRATE, replayScrollDir = 1; static void PrepReplayList(void) { @@ -5073,6 +5076,7 @@ static void M_HandleReplayHutList(INT32 choice) M_PrevOpt(); S_StartSound(NULL, sfx_menu1); + replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; break; case KEY_DOWNARROW: @@ -5082,6 +5086,7 @@ static void M_HandleReplayHutList(INT32 choice) itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item S_StartSound(NULL, sfx_menu1); + replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; break; } } @@ -5096,7 +5101,6 @@ static void M_DrawReplayHut(void) static UINT16 replayhutmenuy = 0; V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); - M_DrawMenuTitle(); // Draw menu choices x = currentMenu->x; @@ -5106,10 +5110,12 @@ static void M_DrawReplayHut(void) { itemOn = replaylistitem; replayOn = sizedirmenu-1; + replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; } else if (itemOn < replaylistitem) { replayOn = 0; + replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; } if (itemOn == replaylistitem) @@ -5123,9 +5129,9 @@ static void M_DrawReplayHut(void) cursory = maxy - 20; if (cursory - replayhutmenuy > 150) - replayhutmenuy += (cursory-150-replayhutmenuy)/2; + replayhutmenuy += (cursory-150-replayhutmenuy + 1)/2; else if (cursory - replayhutmenuy < 110) - replayhutmenuy += (max(0, cursory-110)-replayhutmenuy)/2; + replayhutmenuy += (max(0, cursory-110)-replayhutmenuy - 1)/2; } else replayhutmenuy /= 2; @@ -5149,7 +5155,13 @@ static void M_DrawReplayHut(void) for (i = 0; i < (INT16)sizedirmenu; i++) { INT32 localy = y+i*10; - if (localy >= 0 && localy < 200 && demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) + + if (localy < 65) + continue; + if (localy >= 200) + break; + + if (demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) { processed_one_this_frame = true; G_LoadDemoInfo(&demolist[i]); @@ -5158,7 +5170,31 @@ static void M_DrawReplayHut(void) if (itemOn == replaylistitem && i == replayOn) { cursory = localy; - V_DrawString(x, localy, highlightflags|V_ALLOWLOWERCASE, demolist[i].title); + + if (replayScrollDelay) + replayScrollDelay--; + else if (replayScrollDir > 0) + { + if (replayScrollTitle < (V_StringWidth(demolist[i].title, 0) - (BASEVIDWIDTH - (x<<1)))<<1) + replayScrollTitle++; + else + { + replayScrollDelay = TICRATE; + replayScrollDir = -1; + } + } + else + { + if (replayScrollTitle > 0) + replayScrollTitle--; + else + { + replayScrollDelay = TICRATE; + replayScrollDir = 1; + } + } + + V_DrawString(x - (replayScrollTitle>>1), localy, highlightflags|V_ALLOWLOWERCASE, demolist[i].title); } else V_DrawString(x, localy, V_ALLOWLOWERCASE, demolist[i].title); @@ -5168,6 +5204,92 @@ static void M_DrawReplayHut(void) V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); + + // Now draw some replay info! + V_DrawFill(10, 10, 300, 60, 239); + + if (itemOn == replaylistitem) + { + switch (demolist[replayOn].type) + { + case MD_NOTLOADED: + V_DrawCenteredString(160, 40, 0, "Loading replay information..."); + break; + + case MD_INVALID: + V_DrawCenteredString(160, 40, warningflags, "This replay cannot be played."); + break; + + case MD_SUBDIR: + break; // Can't think of anything to draw here right now + + case MD_OUTDATED: + V_DrawThinString(17, 60, V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); + /*fallthru*/ + default: + { // Draw level stuff + lumpnum_t lumpnum; + patch_t *PictureOfLevel; + INT32 w, h; + x = 15; y = 15; + //INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; + + // A 160x100 image of the level as entry MAPxxP + CONS_Printf("%d %s\n", demolist[replayOn].map, G_BuildMapName(demolist[replayOn].map)); + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[replayOn].map))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + if (!(demolist[replayOn].kartspeed & DF_ENCORE)) + V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); + else + { + w = SHORT(PictureOfLevel->width); + h = SHORT(PictureOfLevel->height); + V_DrawFixedPatch((x+w)<>ANGLETOFINESHIFT); + V_DrawFixedPatch((x+w/2)<width), y+20, 0, facewantprefix[demolist[replayOn].winnerskin], colormap); + } + } + + break; + } + } } static void M_PandorasBox(INT32 choice) From c21072ec291d14632418dbd470248627e829194b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 12:49:42 -0500 Subject: [PATCH 221/382] Show music credit for credits --- src/f_finale.c | 5 +++++ src/hu_stuff.c | 2 +- src/hu_stuff.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index d184a2833..5d57d34a9 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -584,6 +584,7 @@ void F_StartCredits(void) S_StopMusic(); S_ChangeMusicInternal("credit", false); + S_ShowMusicCredit(); finalecount = 0; animtimer = 0; @@ -644,6 +645,10 @@ void F_CreditDrawer(void) break; } + // draw song credits + if (cv_songcredits.value) + HU_DrawSongCredits(); + if (!credits[i] && y <= 120< Date: Sun, 31 Mar 2019 13:50:20 -0500 Subject: [PATCH 222/382] Enable exiting and playing demos from replay hut properly --- src/m_menu.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index db31a4a54..203531ea8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -340,6 +340,7 @@ static patch_t *addonsp[NUM_EXT+5]; static void M_ReplayHut(INT32 choice); static void M_HandleReplayHutList(INT32 choice); static void M_DrawReplayHut(void); +static boolean M_QuitReplayHut(void); // Drawing functions static void M_DrawGenericMenu(void); @@ -1598,14 +1599,14 @@ menu_t MISC_AddonsDef = menu_t MISC_ReplayHutDef = { - "M_REPLAY", + NULL, sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t), - &MainDef, + NULL, MISC_ReplayHutMenu, M_DrawReplayHut, 30, 80, (sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t)) - 2, // Start on the replay list - NULL + M_QuitReplayHut }; menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); @@ -5016,6 +5017,7 @@ menudemo_t *demolist; static INT16 replayOn = 0; static INT16 replayScrollTitle = 0; static INT8 replayScrollDelay = TICRATE, replayScrollDir = 1; +static boolean inreplayhut = false; static void PrepReplayList(void) { @@ -5046,8 +5048,12 @@ static void M_ReplayHut(INT32 choice) { (void)choice; - snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); - menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); + if (!inreplayhut) + { + snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); + } + inreplayhut = true; if (!preparefilemenu(false, true)) { @@ -5088,6 +5094,17 @@ static void M_HandleReplayHutList(INT32 choice) S_StartSound(NULL, sfx_menu1); replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; break; + + case KEY_ESCAPE: + M_QuitReplayHut(); + break; + + case KEY_ENTER: + M_ClearMenus(false); + demo.loadfiles = true; demo.ignorefiles = false; //@TODO prompt + + G_DoPlayDemo(demolist[replayOn].filepath); + break; } } @@ -5292,6 +5309,21 @@ static void M_DrawReplayHut(void) } } +static boolean M_QuitReplayHut(void) +{ + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + + if (demolist) + Z_Free(demolist); + demolist = NULL; + + inreplayhut = false; + + return true; +} + static void M_PandorasBox(INT32 choice) { (void)choice; From 17b30c0e3e1b983824bd40d0ee7fd3e99964a9c0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 13:50:29 -0500 Subject: [PATCH 223/382] Add replay options screen --- src/m_menu.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 203531ea8..d6436ffa8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -341,9 +341,11 @@ static void M_ReplayHut(INT32 choice); static void M_HandleReplayHutList(INT32 choice); static void M_DrawReplayHut(void); static boolean M_QuitReplayHut(void); +static void M_EnterReplayOptions(INT32 choice); // Drawing functions static void M_DrawGenericMenu(void); +static void M_DrawGenericBackgroundMenu(void); static void M_DrawCenteredMenu(void); static void M_DrawAddons(void); static void M_DrawSkyRoom(void); @@ -534,12 +536,18 @@ static menuitem_t MISC_AddonsMenu[] = static menuitem_t MISC_ReplayHutMenu[] = { - {IT_SUBMENU |IT_STRING, NULL, "Replay Options...", NULL, 0}, + {IT_CALL |IT_STRING, NULL, "Replay Options...", M_EnterReplayOptions, 0}, {IT_KEYHANDLER|IT_NOTHING, NULL, "", M_HandleReplayHutList, 20}, // Dummy menuitem for the replay list {IT_NOTHING, NULL, "", NULL, 20}, // Dummy for handling wrapping to the top of the menu.. }; +static menuitem_t MISC_ReplayOptionsMenu[] = +{ + {IT_CVAR|IT_STRING, NULL, "Record Replays", &cv_recordmultiplayerdemos, 0}, + {IT_CVAR|IT_STRING, NULL, "Sync Check Interval", &cv_netdemosyncquality, 10}, +}; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -1608,6 +1616,17 @@ menu_t MISC_ReplayHutDef = (sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t)) - 2, // Start on the replay list M_QuitReplayHut }; +menu_t MISC_ReplayOptionsDef = +{ + NULL, + sizeof (MISC_ReplayOptionsMenu)/sizeof (menuitem_t), + &MISC_ReplayHutDef, + MISC_ReplayOptionsMenu, + M_DrawGenericBackgroundMenu, + 27, 40, + 0, + NULL +}; menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); @@ -3713,6 +3732,12 @@ static void M_DrawGenericMenu(void) } } +static void M_DrawGenericBackgroundMenu(void) +{ + V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + M_DrawGenericMenu(); +} + static void M_DrawPauseMenu(void) { #if 0 @@ -5324,6 +5349,15 @@ static boolean M_QuitReplayHut(void) return true; } +static void M_EnterReplayOptions(INT32 choice) +{ + (void)choice; + + // We can't just use M_SetupNextMenu because that'll boot us back to the title screen! + currentMenu = &MISC_ReplayOptionsDef; + itemOn = currentMenu->lastOn; +} + static void M_PandorasBox(INT32 choice) { (void)choice; From 03af8595352c274e03228aeb6738faccfbd66767 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 16:28:18 -0500 Subject: [PATCH 224/382] Support directory navigation properly --- src/g_game.c | 10 +++++ src/m_menu.c | 123 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 102 insertions(+), 31 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 94f8bd8d1..e56362b66 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6642,6 +6642,16 @@ void G_LoadDemoInfo(menudemo_t *pdemo) Z_Free(infobuffer); return; } +#ifdef DEMO_COMPAT_100 + else if (pdemoversion == 0x0001) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is a legacy multiplayer replay and cannot be played.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } +#endif pdemo->gametype = READUINT8(info_p); diff --git a/src/m_menu.c b/src/m_menu.c index d6436ffa8..013eb354d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5039,7 +5039,6 @@ static void M_HandleAddons(INT32 choice) menudemo_t *demolist; #define DF_ENCORE 0x40 -static INT16 replayOn = 0; static INT16 replayScrollTitle = 0; static INT8 replayScrollDelay = TICRATE, replayScrollDir = 1; static boolean inreplayhut = false; @@ -5055,7 +5054,12 @@ static void PrepReplayList(void) for (i = 0; i < sizedirmenu; i++) { - if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) + if (dirmenu[i][DIR_TYPE] == EXT_UP) + { + demolist[i].type = MD_SUBDIR; + sprintf(demolist[i].title, "UP"); + } + else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) { demolist[i].type = MD_SUBDIR; strncpy(demolist[i].title, dirmenu[i] + DIR_STRING, 64); @@ -5078,15 +5082,14 @@ static void M_ReplayHut(INT32 choice) snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); } - inreplayhut = true; - if (!preparefilemenu(false, true)) { M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING); return; } - else + else if (!inreplayhut) dir_on[menudepthleft] = 0; + inreplayhut = true; PrepReplayList(); @@ -5101,8 +5104,8 @@ static void M_HandleReplayHutList(INT32 choice) switch (choice) { case KEY_UPARROW: - if (replayOn) - replayOn--; + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; else M_PrevOpt(); @@ -5111,8 +5114,8 @@ static void M_HandleReplayHutList(INT32 choice) break; case KEY_DOWNARROW: - if (replayOn < (INT16)sizedirmenu-1) - replayOn++; + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; else itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item @@ -5125,10 +5128,59 @@ static void M_HandleReplayHutList(INT32 choice) break; case KEY_ENTER: - M_ClearMenus(false); - demo.loadfiles = true; demo.ignorefiles = false; //@TODO prompt + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false, true)) + { + S_StartSound(NULL, sfx_s224); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true, true)) + { + M_QuitReplayHut(); + return; + } + } + else + { + S_StartSound(NULL, sfx_menu1); + dir_on[menudepthleft] = 1; + PrepReplayList(); + } + } + else + { + S_StartSound(NULL, sfx_s26d); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_menu1); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false, true)) + { + M_QuitReplayHut(); + return; + } + PrepReplayList(); + break; + default: + currentMenu->lastOn = itemOn; + M_ClearMenus(false); + demo.loadfiles = true; demo.ignorefiles = false; //@TODO prompt + + G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); + } - G_DoPlayDemo(demolist[replayOn].filepath); break; } } @@ -5151,12 +5203,12 @@ static void M_DrawReplayHut(void) if (itemOn > replaylistitem) { itemOn = replaylistitem; - replayOn = sizedirmenu-1; + dir_on[menudepthleft] = sizedirmenu-1; replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; } else if (itemOn < replaylistitem) { - replayOn = 0; + dir_on[menudepthleft] = 0; replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; } @@ -5164,7 +5216,7 @@ static void M_DrawReplayHut(void) { INT32 maxy; // Scroll menu items if needed - cursory = y + currentMenu->menuitems[replaylistitem].alphaKey + replayOn*10; + cursory = y + currentMenu->menuitems[replaylistitem].alphaKey + dir_on[menudepthleft]*10; maxy = y + currentMenu->menuitems[replaylistitem].alphaKey + sizedirmenu*10; if (cursory > maxy - 20) @@ -5209,7 +5261,7 @@ static void M_DrawReplayHut(void) G_LoadDemoInfo(&demolist[i]); } - if (itemOn == replaylistitem && i == replayOn) + if (itemOn == replaylistitem && i == (INT16)dir_on[menudepthleft]) { cursory = localy; @@ -5252,7 +5304,7 @@ static void M_DrawReplayHut(void) if (itemOn == replaylistitem) { - switch (demolist[replayOn].type) + switch (demolist[dir_on[menudepthleft]].type) { case MD_NOTLOADED: V_DrawCenteredString(160, 40, 0, "Loading replay information..."); @@ -5277,14 +5329,14 @@ static void M_DrawReplayHut(void) //INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; // A 160x100 image of the level as entry MAPxxP - CONS_Printf("%d %s\n", demolist[replayOn].map, G_BuildMapName(demolist[replayOn].map)); - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[replayOn].map))); + //CONS_Printf("%d %s\n", demolist[dir_on[menudepthleft]].map, G_BuildMapName(demolist[dir_on[menudepthleft]].map)); + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[dir_on[menudepthleft]].map))); if (lumpnum != LUMPERROR) PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - if (!(demolist[replayOn].kartspeed & DF_ENCORE)) + if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); else { @@ -5302,30 +5354,39 @@ static void M_DrawReplayHut(void) x += 85; - if (mapheaderinfo[demolist[replayOn].map-1]) - V_DrawString(x, y, 0, G_BuildMapTitle(demolist[replayOn].map)); + if (mapheaderinfo[demolist[dir_on[menudepthleft]].map-1]) + V_DrawString(x, y, 0, G_BuildMapTitle(demolist[dir_on[menudepthleft]].map)); else V_DrawString(x, y, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded."); - V_DrawString(x, y+20, V_ALLOWLOWERCASE, demolist[replayOn].gametype == GT_RACE ? - va("Race (%s speed)", kartspeed_cons_t[demolist[replayOn].kartspeed & ~DF_ENCORE].strvalue) : + V_DrawString(x, y+20, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].gametype == GT_RACE ? + va("Race (%s speed)", kartspeed_cons_t[demolist[dir_on[menudepthleft]].kartspeed & ~DF_ENCORE].strvalue) : "Battle Mode"); V_DrawThinString(x, y+29, highlightflags, "WINNER"); - V_DrawString(x+38, y+30, V_ALLOWLOWERCASE, demolist[replayOn].winnername); + V_DrawString(x+38, y+30, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].winnername); V_DrawThinString(x, y+39, highlightflags, "TIME"); V_DrawString(x+28, y+40, 0, va("%2d'%02d\"%02d", - G_TicsToMinutes(demolist[replayOn].winnertime, true), - G_TicsToSeconds(demolist[replayOn].winnertime), - G_TicsToCentiseconds(demolist[replayOn].winnertime) + G_TicsToMinutes(demolist[dir_on[menudepthleft]].winnertime, true), + G_TicsToSeconds(demolist[dir_on[menudepthleft]].winnertime), + G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].winnertime) )); // Character face! - if (W_CheckNumForName(skins[demolist[replayOn].winnerskin].facewant) != LUMPERROR) + if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].winnerskin].facewant) != LUMPERROR) { - UINT8 *colormap = R_GetTranslationColormap(demolist[replayOn].winnerskin, demolist[replayOn].winnercolor, GTC_MENUCACHE); - V_DrawMappedPatch(BASEVIDWIDTH-15 - SHORT(facewantprefix[demolist[replayOn].winnerskin]->width), y+20, 0, facewantprefix[demolist[replayOn].winnerskin], colormap); + UINT8 *colormap = R_GetTranslationColormap( + demolist[dir_on[menudepthleft]].winnerskin, + demolist[dir_on[menudepthleft]].winnercolor, + GTC_MENUCACHE); + V_DrawMappedPatch( + BASEVIDWIDTH-15 - SHORT(facewantprefix[demolist[dir_on[menudepthleft]].winnerskin]->width), + y+20, + 0, + facewantprefix[demolist[dir_on[menudepthleft]].winnerskin], + colormap + ); } } From 0ae4c905ad9d7f9ee9d81a6a52be2f247fec8e7b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 16:28:29 -0500 Subject: [PATCH 225/382] Don't pause while the menu's up during replays --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 18b14f426..509cc4d76 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -172,7 +172,7 @@ boolean P_AutoPause(void) if (netgame || modeattacking || demo.title) return false; - return (menuactive || ( window_notinfocus && cv_pauseifunfocused.value )); + return ((menuactive && !demo.playback) || ( window_notinfocus && cv_pauseifunfocused.value )); } // From e93927b911d0fe728ffada5f0fc9325f909fdc92 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 17:29:41 -0500 Subject: [PATCH 226/382] Add subscreen to confirm replay watching This will have other goodies on it later! --- src/m_menu.c | 294 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 203 insertions(+), 91 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 013eb354d..7e8c36387 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -337,11 +337,14 @@ static patch_t *addonsp[NUM_EXT+5]; #define numaddonsshown 4 // Replay hut +menu_t MISC_ReplayHutDef; static void M_ReplayHut(INT32 choice); static void M_HandleReplayHutList(INT32 choice); static void M_DrawReplayHut(void); +static void M_DrawReplayStartMenu(void); static boolean M_QuitReplayHut(void); static void M_EnterReplayOptions(INT32 choice); +static void M_HutStartReplay(INT32 choice); // Drawing functions static void M_DrawGenericMenu(void); @@ -542,6 +545,14 @@ static menuitem_t MISC_ReplayHutMenu[] = {IT_NOTHING, NULL, "", NULL, 20}, // Dummy for handling wrapping to the top of the menu.. }; +static menuitem_t MISC_ReplayStartMenu[] = +{ + {IT_CALL |IT_STRING, NULL, "Load Addons and Watch", M_HutStartReplay, 0}, + {IT_CALL |IT_STRING, NULL, "Watch Without Addons", M_HutStartReplay, 10}, + {IT_CALL |IT_STRING, NULL, "Watch Replay", M_HutStartReplay, 10}, + {IT_SUBMENU |IT_STRING, NULL, "Back", &MISC_ReplayHutDef, 30}, +}; + static menuitem_t MISC_ReplayOptionsMenu[] = { {IT_CVAR|IT_STRING, NULL, "Record Replays", &cv_recordmultiplayerdemos, 0}, @@ -1616,6 +1627,7 @@ menu_t MISC_ReplayHutDef = (sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t)) - 2, // Start on the replay list M_QuitReplayHut }; + menu_t MISC_ReplayOptionsDef = { NULL, @@ -1628,6 +1640,18 @@ menu_t MISC_ReplayOptionsDef = NULL }; +menu_t MISC_ReplayStartDef = +{ + NULL, + sizeof (MISC_ReplayStartMenu)/sizeof (menuitem_t), + &MISC_ReplayHutDef, + MISC_ReplayStartMenu, + M_DrawReplayStartMenu, + 30, 90, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -5174,11 +5198,137 @@ static void M_HandleReplayHutList(INT32 choice) PrepReplayList(); break; default: + // We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! currentMenu->lastOn = itemOn; - M_ClearMenus(false); - demo.loadfiles = true; demo.ignorefiles = false; //@TODO prompt + currentMenu = &MISC_ReplayStartDef; - G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); + switch (demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + // Only show "Watch Replay Without Addons" + MISC_ReplayStartMenu[0].status = IT_DISABLED; + MISC_ReplayStartMenu[1].status = IT_CALL|IT_STRING; + //MISC_ReplayStartMenu[1].alphaKey = 0; + MISC_ReplayStartMenu[2].status = IT_DISABLED; + itemOn = 1; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + // Show "Load Addons and Watch Replay" and "Watch Replay Without Addons" + MISC_ReplayStartMenu[0].status = IT_CALL|IT_STRING; + MISC_ReplayStartMenu[1].status = IT_CALL|IT_STRING; + //MISC_ReplayStartMenu[1].alphaKey = 10; + MISC_ReplayStartMenu[2].status = IT_DISABLED; + itemOn = 0; + break; + + case DFILE_ERROR_EXTRAFILES: + case DFILE_ERROR_OUTOFORDER: + default: + // Show "Watch Replay" + MISC_ReplayStartMenu[0].status = IT_DISABLED; + MISC_ReplayStartMenu[1].status = IT_DISABLED; + MISC_ReplayStartMenu[2].status = IT_CALL|IT_STRING; + //MISC_ReplayStartMenu[2].alphaKey = 0; + itemOn = 2; + break; + } + + /*demo.loadfiles = true; demo.ignorefiles = false; //@TODO prompt + + G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath);*/ + } + + break; + } +} + +static void DrawReplayHutReplayInfo(void) +{ + lumpnum_t lumpnum; + patch_t *PictureOfLevel; + INT32 x, y, w, h; + + switch (demolist[dir_on[menudepthleft]].type) + { + case MD_NOTLOADED: + V_DrawCenteredString(160, 40, 0, "Loading replay information..."); + break; + + case MD_INVALID: + V_DrawCenteredString(160, 40, warningflags, "This replay cannot be played."); + break; + + case MD_SUBDIR: + break; // Can't think of anything to draw here right now + + case MD_OUTDATED: + V_DrawThinString(17, 64, V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); + /*fallthru*/ + default: + // Draw level stuff + x = 15; y = 15; + + // A 160x100 image of the level as entry MAPxxP + //CONS_Printf("%d %s\n", demolist[dir_on[menudepthleft]].map, G_BuildMapName(demolist[dir_on[menudepthleft]].map)); + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[dir_on[menudepthleft]].map))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) + V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); + else + { + w = SHORT(PictureOfLevel->width); + h = SHORT(PictureOfLevel->height); + V_DrawFixedPatch((x+w)<>ANGLETOFINESHIFT); + V_DrawFixedPatch((x+w/2)<width), + y+20, + 0, + facewantprefix[demolist[dir_on[menudepthleft]].winnerskin], + colormap + ); } break; @@ -5304,97 +5454,47 @@ static void M_DrawReplayHut(void) if (itemOn == replaylistitem) { - switch (demolist[dir_on[menudepthleft]].type) - { - case MD_NOTLOADED: - V_DrawCenteredString(160, 40, 0, "Loading replay information..."); - break; - - case MD_INVALID: - V_DrawCenteredString(160, 40, warningflags, "This replay cannot be played."); - break; - - case MD_SUBDIR: - break; // Can't think of anything to draw here right now - - case MD_OUTDATED: - V_DrawThinString(17, 60, V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); - /*fallthru*/ - default: - { // Draw level stuff - lumpnum_t lumpnum; - patch_t *PictureOfLevel; - INT32 w, h; - x = 15; y = 15; - //INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; - - // A 160x100 image of the level as entry MAPxxP - //CONS_Printf("%d %s\n", demolist[dir_on[menudepthleft]].map, G_BuildMapName(demolist[dir_on[menudepthleft]].map)); - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[dir_on[menudepthleft]].map))); - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) - V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); - else - { - w = SHORT(PictureOfLevel->width); - h = SHORT(PictureOfLevel->height); - V_DrawFixedPatch((x+w)<>ANGLETOFINESHIFT); - V_DrawFixedPatch((x+w/2)<width), - y+20, - 0, - facewantprefix[demolist[dir_on[menudepthleft]].winnerskin], - colormap - ); - } - } - - break; - } + DrawReplayHutReplayInfo(); } } +static void M_DrawReplayStartMenu(void) +{ + const char *warning; + + M_DrawGenericBackgroundMenu(); + V_DrawFill(10, 10, 300, 60, 239); + DrawReplayHutReplayInfo(); + + V_DrawString(10, 72, highlightflags|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].title); + + // Draw a warning prompt if needed + switch (demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + warning = "Some addons in this replay cannot be loaded.\nYou can watch anyway, but desyncs may occur."; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + warning = "Loading addons will mark your game as modified, and record attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur."; + break; + + case DFILE_ERROR_EXTRAFILES: + warning = "You have addons loaded that were not present in this replay.\nYou can watch anyway, but desyncs may occur."; + break; + + case DFILE_ERROR_OUTOFORDER: + warning = "You have this replay's addons loaded, but they are out of order.\nYou can watch anyway, but desyncs may occur."; + break; + + default: + return; + } + + V_DrawSmallString(4, BASEVIDHEIGHT-14, V_ALLOWLOWERCASE, warning); +} + static boolean M_QuitReplayHut(void) { // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. @@ -5419,6 +5519,18 @@ static void M_EnterReplayOptions(INT32 choice) itemOn = currentMenu->lastOn; } +static void M_HutStartReplay(INT32 choice) +{ + (void)choice; + + M_ClearMenus(false); + demo.loadfiles = (itemOn == 0); + demo.ignorefiles = (itemOn != 0); + + G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); +} + + static void M_PandorasBox(INT32 choice) { (void)choice; From 3dd4e4aac751c7ef5223096ec1dbad589e9838cb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 19:26:53 -0500 Subject: [PATCH 227/382] Return to replay hut after watching a replay --- src/g_game.c | 7 ++++++- src/g_game.h | 1 + src/m_menu.c | 13 ++++++------- src/m_menu.h | 2 ++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e56362b66..bf28425cd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3856,7 +3856,12 @@ void G_AfterIntermission(void) if (demo.playback) { G_StopDemo(); - D_StartTitle(); + + if (demo.inreplayhut) + M_ReplayHut(0); + else + D_StartTitle(); + return; } else if (demo.recording && demo.savemode != DSM_NOTSAVING) diff --git a/src/g_game.h b/src/g_game.h index af85bd029..324af06bb 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -46,6 +46,7 @@ struct demovars_s { 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 diff --git a/src/m_menu.c b/src/m_menu.c index 7e8c36387..0942f1ee5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -338,7 +338,6 @@ static patch_t *addonsp[NUM_EXT+5]; // Replay hut menu_t MISC_ReplayHutDef; -static void M_ReplayHut(INT32 choice); static void M_HandleReplayHutList(INT32 choice); static void M_DrawReplayHut(void); static void M_DrawReplayStartMenu(void); @@ -5065,7 +5064,6 @@ menudemo_t *demolist; #define DF_ENCORE 0x40 static INT16 replayScrollTitle = 0; static INT8 replayScrollDelay = TICRATE, replayScrollDir = 1; -static boolean inreplayhut = false; static void PrepReplayList(void) { @@ -5097,11 +5095,11 @@ static void PrepReplayList(void) } } -static void M_ReplayHut(INT32 choice) +void M_ReplayHut(INT32 choice) { (void)choice; - if (!inreplayhut) + if (!demo.inreplayhut) { snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); @@ -5111,12 +5109,13 @@ static void M_ReplayHut(INT32 choice) M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING); return; } - else if (!inreplayhut) + else if (!demo.inreplayhut) dir_on[menudepthleft] = 0; - inreplayhut = true; + demo.inreplayhut = true; PrepReplayList(); + menuactive = true; M_SetupNextMenu(&MISC_ReplayHutDef); G_SetGamestate(GS_TIMEATTACK); @@ -5505,7 +5504,7 @@ static boolean M_QuitReplayHut(void) Z_Free(demolist); demolist = NULL; - inreplayhut = false; + demo.inreplayhut = false; return true; } diff --git a/src/m_menu.h b/src/m_menu.h index 33dc1e407..f49c6ca64 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -235,6 +235,8 @@ void Screenshot_option_Onchange(void); // Addons menu updating void Addons_option_Onchange(void); +void M_ReplayHut(INT32 choice); + INT32 HU_GetHighlightColor(void); // These defines make it a little easier to make menus From 746f13a999b054355f7bf879742b883850bcf0db Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 19:29:05 -0500 Subject: [PATCH 228/382] Don't draw options menu entry above replay infobox --- src/m_menu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 0942f1ee5..551a5c89a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5384,13 +5384,18 @@ static void M_DrawReplayHut(void) // Draw static menu items for (i = 0; i < replaylistitem; i++) { + INT32 localy = y + currentMenu->menuitems[i].alphaKey; + + if (localy < 65) + continue; + if (i == itemOn) - cursory = y + currentMenu->menuitems[i].alphaKey; + cursory = localy; if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) - V_DrawString(x, y + currentMenu->menuitems[i].alphaKey, 0, currentMenu->menuitems[i].text); + V_DrawString(x, localy, 0, currentMenu->menuitems[i].text); else - V_DrawString(x, y + currentMenu->menuitems[i].alphaKey, highlightflags, currentMenu->menuitems[i].text); + V_DrawString(x, localy, highlightflags, currentMenu->menuitems[i].text); } y += currentMenu->menuitems[currentMenu->numitems-1].alphaKey; From e8260f9f361bde68920aade2840e5ef0c72ecdf2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 12:25:12 -0500 Subject: [PATCH 229/382] Draw icons for directories --- src/m_menu.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 551a5c89a..5d4e0731f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5403,6 +5403,7 @@ static void M_DrawReplayHut(void) for (i = 0; i < (INT16)sizedirmenu; i++) { INT32 localy = y+i*10; + INT32 localx = x; if (localy < 65) continue; @@ -5415,6 +5416,12 @@ static void M_DrawReplayHut(void) G_LoadDemoInfo(&demolist[i]); } + if (demolist[i].type == MD_SUBDIR) + { + localx += 8; + V_DrawFixedPatch(x<>1), localy, highlightflags|V_ALLOWLOWERCASE, demolist[i].title); + V_DrawString(localx - (replayScrollTitle>>1), localy, highlightflags|V_ALLOWLOWERCASE, demolist[i].title); } else - V_DrawString(x, localy, V_ALLOWLOWERCASE, demolist[i].title); + V_DrawString(localx, localy, V_ALLOWLOWERCASE, demolist[i].title); } // Draw the cursor From 733d8c1f7be2beaa8076e4bd63e1ca0e5d64158f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 12:28:01 -0500 Subject: [PATCH 230/382] Fix normal speed replays showing as easy speed --- src/g_game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_game.c b/src/g_game.c index bf28425cd..ca27ec5af 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6664,6 +6664,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) info_p += 4; // RNG seed // Pared down version of CV_LoadNetVars to find the kart speed + pdemo->kartspeed = 1; // Default to normal speed cvarcount = READUINT16(info_p); while (cvarcount--) { From aa1546a533e05d3e2c920465a9c9c2e40e185287 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 12:56:23 -0500 Subject: [PATCH 231/382] Show non-default lap count on replay screen too --- src/g_game.c | 9 ++------- src/g_game.h | 1 + src/m_menu.c | 3 +++ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index ca27ec5af..723d2b5ee 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6679,16 +6679,11 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (netid == cv_kartspeed.netid) { for (cvarcount = 0; kartspeed_cons_t[cvarcount].strvalue; cvarcount++) - { if (!stricmp(kartspeed_cons_t[cvarcount].strvalue, svalue)) - { pdemo->kartspeed = kartspeed_cons_t[cvarcount].value; - break; - } - } - - break; } + else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE) + pdemo->numlaps = atoi(svalue); } if (pdemoflags & DF_ENCORE) diff --git a/src/g_game.h b/src/g_game.h index 324af06bb..aa20dee49 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -79,6 +79,7 @@ typedef struct menudemo_s { 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; char winnername[17]; UINT8 winnerskin, winnercolor; diff --git a/src/m_menu.c b/src/m_menu.c index 5d4e0731f..379023109 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5300,6 +5300,9 @@ static void DrawReplayHutReplayInfo(void) else V_DrawString(x, y, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded."); + if (demolist[dir_on[menudepthleft]].numlaps) + V_DrawThinString(x, y+9, V_ALLOWLOWERCASE, va("(%d laps)", demolist[dir_on[menudepthleft]].numlaps)); + V_DrawString(x, y+20, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].gametype == GT_RACE ? va("Race (%s speed)", kartspeed_cons_t[demolist[dir_on[menudepthleft]].kartspeed & ~DF_ENCORE].strvalue) : "Battle Mode"); From f753e8edee9fb567217902aa8328e66ff0b63095 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 13:10:35 -0500 Subject: [PATCH 232/382] [FORMAT CHANGE] Add space for extrainfo pointer --- src/g_game.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 723d2b5ee..f2463832d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -289,7 +289,7 @@ UINT32 timesBeatenWithEmeralds; //@TODO put these all in a struct for namespacing purposes? static char demoname[128]; static UINT8 *demobuffer = NULL; -static UINT8 *demo_p, *demotime_p; +static UINT8 *demo_p, *demotime_p, *demoinfo_p; static UINT8 *demoend; static UINT8 demoflags; static UINT16 demoversion; @@ -6165,6 +6165,10 @@ void G_BeginRecording(void) WRITEUINT32(demo_p,P_GetInitSeed()); + // Reserved for extrainfo location from start of file + demoinfo_p = demo_p; + WRITEUINT32(demo_p, 0); + // Save netvars CV_SaveNetVars(&demo_p, true); @@ -6567,7 +6571,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) void G_LoadDemoInfo(menudemo_t *pdemo) { - UINT8 *infobuffer, *info_p; + UINT8 *infobuffer, *info_p, *extrainfo_p; UINT8 version, subversion, pdemoflags; UINT16 pdemoversion, cvarcount; @@ -6663,6 +6667,8 @@ void G_LoadDemoInfo(menudemo_t *pdemo) pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true); info_p += 4; // RNG seed + extrainfo_p = infobuffer + READUINT32(info_p); + // Pared down version of CV_LoadNetVars to find the kart speed pdemo->kartspeed = 1; // Default to normal speed cvarcount = READUINT16(info_p); @@ -6690,6 +6696,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) pdemo->kartspeed |= DF_ENCORE; // Temporary info until this is actually present in replays. + (void)extrainfo_p; sprintf(pdemo->winnername, "transrights420"); pdemo->winnerskin = 1; pdemo->winnercolor = SKINCOLOR_MOONSLAM; @@ -6935,6 +6942,7 @@ void G_DoPlayDemo(char *defdemoname) // Random seed randseed = READUINT32(demo_p); + demo_p += 4; // Extrainfo location #ifdef DEMO_COMPAT_100 if (demoversion == 0x0001) { From b8ef18e983a90b9a6c53f410ce0c8c12c66f7158 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 15:07:27 -0500 Subject: [PATCH 233/382] Read and write standings to replays --- src/g_game.c | 112 ++++++++++++++++++++++++++++++++++++++++++++------ src/g_game.h | 10 +++-- src/m_menu.c | 104 ++++++++++++++++++++++++++++++++++++++-------- src/y_inter.c | 9 ++++ 4 files changed, 203 insertions(+), 32 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index f2463832d..0a20b1040 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3324,8 +3324,7 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); - if (multiplayer && demo.recording && (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE)) - G_SaveDemo(); + // Don't save demos immediately here! Let standings write first } } @@ -4799,6 +4798,9 @@ static ticcmd_t oldcmd[MAXPLAYERS]; #define DW_EXTRASTUFF 0xFE // Numbers below this are reserved for writing player slot data +// Below consts are only used for demo extrainfo sections +#define DW_STANDING 0x00 + // For Metal Sonic and time attack ghosts #define GZT_XYZ 0x01 #define GZT_MOMXY 0x02 @@ -6259,6 +6261,41 @@ void G_BeginMetal(void) oldmetal.angle = mo->angle; } +void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val) +{ + char temp[16]; + + if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + { + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + WRITEUINT32(demoinfo_p, demo_p - demobuffer); + } + + WRITEUINT8(demo_p, DW_STANDING); + WRITEUINT8(demo_p, ranking); + + // Name + memset(temp, 0, 16); + strncpy(temp, name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Skin + memset(temp, 0, 16); + strncpy(temp, skins[skinnum].name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Color + memset(temp, 0, 16); + strncpy(temp, KartColor_Names[color], 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Score/time/whatever + WRITEUINT32(demo_p, val); +} + void G_SetDemoTime(UINT32 ptime, UINT32 plap) { if (!demo.recording || !demotime_p) @@ -6573,7 +6610,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) { UINT8 *infobuffer, *info_p, *extrainfo_p; UINT8 version, subversion, pdemoflags; - UINT16 pdemoversion, cvarcount; + UINT16 pdemoversion, count; if (!FIL_ReadFile(pdemo->filepath, &infobuffer)) { @@ -6671,8 +6708,8 @@ void G_LoadDemoInfo(menudemo_t *pdemo) // Pared down version of CV_LoadNetVars to find the kart speed pdemo->kartspeed = 1; // Default to normal speed - cvarcount = READUINT16(info_p); - while (cvarcount--) + count = READUINT16(info_p); + while (count--) { UINT16 netid; char *svalue; @@ -6684,9 +6721,10 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (netid == cv_kartspeed.netid) { - for (cvarcount = 0; kartspeed_cons_t[cvarcount].strvalue; cvarcount++) - if (!stricmp(kartspeed_cons_t[cvarcount].strvalue, svalue)) - pdemo->kartspeed = kartspeed_cons_t[cvarcount].value; + UINT8 j; + for (j = 0; kartspeed_cons_t[j].strvalue; j++) + if (!stricmp(kartspeed_cons_t[j].strvalue, svalue)) + pdemo->kartspeed = kartspeed_cons_t[j].value; } else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE) pdemo->numlaps = atoi(svalue); @@ -6695,12 +6733,53 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (pdemoflags & DF_ENCORE) pdemo->kartspeed |= DF_ENCORE; - // Temporary info until this is actually present in replays. + /*// Temporary info until this is actually present in replays. (void)extrainfo_p; sprintf(pdemo->winnername, "transrights420"); pdemo->winnerskin = 1; pdemo->winnercolor = SKINCOLOR_MOONSLAM; - pdemo->winnertime = 6666; + pdemo->winnertime = 6666;*/ + + // Read standings! + count = 0; + + while (READUINT8(extrainfo_p) == DW_STANDING) // Assume standings are always first in the extrainfo + { + INT32 i; + char temp[16]; + + pdemo->standings[count].ranking = READUINT8(extrainfo_p); + + // Name + M_Memcpy(pdemo->standings[count].name, extrainfo_p, 16); + extrainfo_p += 16; + + // Skin + M_Memcpy(temp,extrainfo_p,16); + extrainfo_p += 16; + pdemo->standings[count].skin = UINT8_MAX; + for (i = 0; i < numskins; i++) + if (stricmp(skins[i].name, temp) == 0) + { + pdemo->standings[count].skin = i; + break; + } + + // Color + M_Memcpy(temp,extrainfo_p,16); + extrainfo_p += 16; + for (i = 0; i < MAXSKINCOLORS; i++) + if (!stricmp(KartColor_Names[i],temp)) // SRB2kart + { + pdemo->standings[count].color = i; + break; + } + + // Score/time/whatever + pdemo->standings[count].timeorscore = READUINT32(extrainfo_p); + + count++; + } // I think that's everything we need? free(infobuffer); @@ -7763,7 +7842,14 @@ void G_SaveDemo(void) UINT8 i; #endif - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + // Ensure extrainfo pointer is always available, even if no info is present. + if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + { + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + WRITEUINT32(demoinfo_p, (UINT32)(demo_p - demobuffer)); + } + WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data. + M_Memcpy(p, demo.titlename, 64); // Write demo title here p += 64; @@ -7810,9 +7896,11 @@ void G_SaveDemo(void) for (i = 0; i < 16; i++, p++) *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. #else - md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. + // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. + md5_buffer((char *)p+16, (demobuffer + (UINT32)*demoinfo_p) - (p+16), p); #endif + if (FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer)) // finally output the file. demo.savemode = DSM_SAVED; free(demobuffer); diff --git a/src/g_game.h b/src/g_game.h index aa20dee49..c44691e8c 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -81,9 +81,12 @@ typedef struct menudemo_s { UINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk UINT8 numlaps; - char winnername[17]; - UINT8 winnerskin, winnercolor; - UINT32 winnertime; + struct { + UINT8 ranking; + char name[17]; + UINT8 skin, color; + UINT32 timeorscore; + } standings[MAXPLAYERS]; } menudemo_t; @@ -190,6 +193,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); diff --git a/src/m_menu.c b/src/m_menu.c index 379023109..4d334a47d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5113,6 +5113,8 @@ void M_ReplayHut(INT32 choice) dir_on[menudepthleft] = 0; demo.inreplayhut = true; + replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; + PrepReplayList(); menuactive = true; @@ -5201,6 +5203,8 @@ static void M_HandleReplayHutList(INT32 choice) currentMenu->lastOn = itemOn; currentMenu = &MISC_ReplayStartDef; + replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; + switch (demolist[dir_on[menudepthleft]].addonstatus) { case DFILE_ERROR_CANNOTLOAD: @@ -5233,10 +5237,6 @@ static void M_HandleReplayHutList(INT32 choice) itemOn = 2; break; } - - /*demo.loadfiles = true; demo.ignorefiles = false; //@TODO prompt - - G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath);*/ } break; @@ -5308,27 +5308,35 @@ static void DrawReplayHutReplayInfo(void) "Battle Mode"); V_DrawThinString(x, y+29, highlightflags, "WINNER"); - V_DrawString(x+38, y+30, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].winnername); + V_DrawString(x+38, y+30, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[0].name); - V_DrawThinString(x, y+39, highlightflags, "TIME"); - V_DrawString(x+28, y+40, 0, va("%2d'%02d\"%02d", - G_TicsToMinutes(demolist[dir_on[menudepthleft]].winnertime, true), - G_TicsToSeconds(demolist[dir_on[menudepthleft]].winnertime), - G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].winnertime) - )); + if (demolist[dir_on[menudepthleft]].gametype == GT_RACE) + { + V_DrawThinString(x, y+39, highlightflags, "TIME"); + V_DrawRightAlignedString(x+84, y+40, 0, va("%d'%02d\"%02d", + G_TicsToMinutes(demolist[dir_on[menudepthleft]].standings[0].timeorscore, true), + G_TicsToSeconds(demolist[dir_on[menudepthleft]].standings[0].timeorscore), + G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].standings[0].timeorscore) + )); + } + else + { + V_DrawThinString(x, y+39, highlightflags, "SCORE"); + V_DrawString(x+32, y+40, 0, va("%d", demolist[dir_on[menudepthleft]].standings[0].timeorscore)); + } // Character face! - if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].winnerskin].facewant) != LUMPERROR) + if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[0].skin].facewant) != LUMPERROR) { UINT8 *colormap = R_GetTranslationColormap( - demolist[dir_on[menudepthleft]].winnerskin, - demolist[dir_on[menudepthleft]].winnercolor, + demolist[dir_on[menudepthleft]].standings[0].skin, + demolist[dir_on[menudepthleft]].standings[0].color, GTC_MENUCACHE); V_DrawMappedPatch( - BASEVIDWIDTH-15 - SHORT(facewantprefix[demolist[dir_on[menudepthleft]].winnerskin]->width), + BASEVIDWIDTH-15 - SHORT(facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin]->width), y+20, 0, - facewantprefix[demolist[dir_on[menudepthleft]].winnerskin], + facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin], colormap ); } @@ -5422,7 +5430,7 @@ static void M_DrawReplayHut(void) if (demolist[i].type == MD_SUBDIR) { localx += 8; - V_DrawFixedPatch(x<>1) + // Draw rankings beyond first + for (i = 1; i < MAXPLAYERS && demolist[dir_on[menudepthleft]].standings[i].ranking; i++) + { + V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, highlightflags, va("%2d", demolist[dir_on[menudepthleft]].standings[i].ranking)); + V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[i].name); + + if (demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1) + V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20 + 9, 0, "NO CONTEST"); + else if (demolist[dir_on[menudepthleft]].gametype == GT_RACE) + V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, 0, va("%d'%02d\"%02d", + G_TicsToMinutes(demolist[dir_on[menudepthleft]].standings[i].timeorscore, true), + G_TicsToSeconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore), + G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore) + )); + else + V_DrawString(BASEVIDWIDTH-96, STARTY + i*20 + 9, 0, va("%d", demolist[dir_on[menudepthleft]].standings[i].timeorscore)); + + // Character face! + if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facerank) != LUMPERROR) + { + UINT8 *colormap = R_GetTranslationColormap( + demolist[dir_on[menudepthleft]].standings[i].skin, + demolist[dir_on[menudepthleft]].standings[i].color, + GTC_MENUCACHE); + V_DrawMappedPatch( + BASEVIDWIDTH-5 - SHORT(facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin]->width), + STARTY + i*20, + 0, + facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin], + colormap + ); + } + } +#undef STARTY + + // Handle scrolling rankings + if (replayScrollDelay) + replayScrollDelay--; + else if (replayScrollDir > 0) + { + if (replayScrollTitle < (i*20 - 100)<<1) + replayScrollTitle++; + else + { + replayScrollDelay = TICRATE; + replayScrollDir = -1; + } + } + else + { + if (replayScrollTitle > 0) + replayScrollTitle--; + else + { + replayScrollDelay = TICRATE; + replayScrollDir = 1; + } + } + V_DrawFill(10, 10, 300, 60, 239); DrawReplayHutReplayInfo(); diff --git a/src/y_inter.c b/src/y_inter.c index 256a8566a..4fce58cc2 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -304,6 +304,15 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) players[i].score += data.match.increase[i]; } + if (demo.recording) + G_WriteStanding( + data.match.pos[data.match.numplayers], + data.match.name[data.match.numplayers], + *data.match.character[data.match.numplayers], + *data.match.color[data.match.numplayers], + data.match.val[data.match.numplayers] + ); + data.match.numplayers++; } } From c5e166f25912a81da7bcee4a5608e8b1d72a8a1f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 17:14:45 -0500 Subject: [PATCH 234/382] Fix old replays not loading --- src/g_game.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 0a20b1040..5aa28a070 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7021,6 +7021,9 @@ void G_DoPlayDemo(char *defdemoname) // Random seed randseed = READUINT32(demo_p); +#ifdef DEMO_COMPAT_100 + if (demoversion != 0x0001) +#endif demo_p += 4; // Extrainfo location #ifdef DEMO_COMPAT_100 From 4d3542d421053d951db7b6f4a4f9efc8b5b0f60c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 20:17:36 -0500 Subject: [PATCH 235/382] Fix encore stage rendering on replay hut --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 4d334a47d..5e18e7e84 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5283,12 +5283,12 @@ static void DrawReplayHutReplayInfo(void) { w = SHORT(PictureOfLevel->width); h = SHORT(PictureOfLevel->height); - V_DrawFixedPatch((x+w)<>1), y, V_FLIP, PictureOfLevel); { static angle_t rubyfloattime = 0; const fixed_t rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); - V_DrawFixedPatch((x+w/2)<>2))<>2))< Date: Mon, 1 Apr 2019 20:30:24 -0500 Subject: [PATCH 236/382] Draw placeholder when no standings are available --- src/m_menu.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 5e18e7e84..7a9f83b54 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5307,6 +5307,15 @@ static void DrawReplayHutReplayInfo(void) va("Race (%s speed)", kartspeed_cons_t[demolist[dir_on[menudepthleft]].kartspeed & ~DF_ENCORE].strvalue) : "Battle Mode"); + if (!demolist[dir_on[menudepthleft]].standings[0].ranking) + { + // No standings were loaded! + V_DrawString(x, y+39, V_ALLOWLOWERCASE|V_TRANSLUCENT, "No standings available."); + + + break; + } + V_DrawThinString(x, y+29, highlightflags, "WINNER"); V_DrawString(x+38, y+30, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[0].name); From d633ba9421e3d1cd5c87f18686196f4550984a64 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 23:34:53 -0500 Subject: [PATCH 237/382] something something character placeholders im tired --- src/m_menu.c | 83 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 7a9f83b54..c841d50e0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5246,7 +5246,8 @@ static void M_HandleReplayHutList(INT32 choice) static void DrawReplayHutReplayInfo(void) { lumpnum_t lumpnum; - patch_t *PictureOfLevel; + patch_t *patch; + UINT8 *colormap; INT32 x, y, w, h; switch (demolist[dir_on[menudepthleft]].type) @@ -5273,17 +5274,17 @@ static void DrawReplayHutReplayInfo(void) //CONS_Printf("%d %s\n", demolist[dir_on[menudepthleft]].map, G_BuildMapName(demolist[dir_on[menudepthleft]].map)); lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[dir_on[menudepthleft]].map))); if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + patch = W_CachePatchNum(lumpnum, PU_CACHE); else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + patch = W_CachePatchName("BLANKLVL", PU_CACHE); if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) - V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); + V_DrawSmallScaledPatch(x, y, 0, patch); else { - w = SHORT(PictureOfLevel->width); - h = SHORT(PictureOfLevel->height); - V_DrawSmallScaledPatch(x+(w>>1), y, V_FLIP, PictureOfLevel); + w = SHORT(patch->width); + h = SHORT(patch->height); + V_DrawSmallScaledPatch(x+(w>>1), y, V_FLIP, patch); { static angle_t rubyfloattime = 0; @@ -5337,18 +5338,22 @@ static void DrawReplayHutReplayInfo(void) // Character face! if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[0].skin].facewant) != LUMPERROR) { - UINT8 *colormap = R_GetTranslationColormap( + patch = facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin]; + colormap = R_GetTranslationColormap( demolist[dir_on[menudepthleft]].standings[0].skin, demolist[dir_on[menudepthleft]].standings[0].color, GTC_MENUCACHE); - V_DrawMappedPatch( - BASEVIDWIDTH-15 - SHORT(facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin]->width), - y+20, - 0, - facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin], - colormap - ); } + else + { + patch = W_CachePatchName("MISSINGW", PU_CACHE); + colormap = R_GetTranslationColormap( + TC_RAINBOW, + demolist[dir_on[menudepthleft]].standings[0].color, + GTC_MENUCACHE); + } + + V_DrawMappedPatch(BASEVIDWIDTH-15 - SHORT(patch->width), y+20, 0, patch, colormap); break; } @@ -5500,11 +5505,14 @@ static void M_DrawReplayStartMenu(void) // Draw rankings beyond first for (i = 1; i < MAXPLAYERS && demolist[dir_on[menudepthleft]].standings[i].ranking; i++) { + patch_t *patch; + UINT8 *colormap; + V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, highlightflags, va("%2d", demolist[dir_on[menudepthleft]].standings[i].ranking)); V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[i].name); if (demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1) - V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20 + 9, 0, "NO CONTEST"); + V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, 0, "NO CONTEST"); else if (demolist[dir_on[menudepthleft]].gametype == GT_RACE) V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, 0, va("%d'%02d\"%02d", G_TicsToMinutes(demolist[dir_on[menudepthleft]].standings[i].timeorscore, true), @@ -5512,23 +5520,48 @@ static void M_DrawReplayStartMenu(void) G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore) )); else - V_DrawString(BASEVIDWIDTH-96, STARTY + i*20 + 9, 0, va("%d", demolist[dir_on[menudepthleft]].standings[i].timeorscore)); + V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, 0, va("%d", demolist[dir_on[menudepthleft]].standings[i].timeorscore)); +/* + // Character face! + if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[0].skin].facewant) != LUMPERROR) + { + patch = facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin]; + colormap = R_GetTranslationColormap( + demolist[dir_on[menudepthleft]].standings[0].skin, + demolist[dir_on[menudepthleft]].standings[0].color, + GTC_MENUCACHE); + } + else + { + patch = W_CachePatchName("MISSING", PU_CACHE); + colormap = R_GetTranslationColormap( + TC_RAINBOW, + demolist[dir_on[menudepthleft]].standings[0].color, + GTC_MENUCACHE); + } + + V_DrawMappedPatch(BASEVIDWIDTH-15 - SHORT(patch->width), y+20, 0, patch, colormap); +*/ // Character face! if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facerank) != LUMPERROR) { - UINT8 *colormap = R_GetTranslationColormap( + patch = facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin]; + colormap = R_GetTranslationColormap( demolist[dir_on[menudepthleft]].standings[i].skin, demolist[dir_on[menudepthleft]].standings[i].color, GTC_MENUCACHE); - V_DrawMappedPatch( - BASEVIDWIDTH-5 - SHORT(facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin]->width), - STARTY + i*20, - 0, - facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin], - colormap - ); } + else + { + patch = W_CachePatchName("MISSINGR", PU_CACHE); + colormap = R_GetTranslationColormap( + TC_RAINBOW, + demolist[dir_on[menudepthleft]].standings[i].color, + GTC_MENUCACHE); + } + + V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, 0, patch, colormap); } #undef STARTY From c4664129022f555f1ceae26af0479ae2f4084b07 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 5 Apr 2019 02:38:48 -0500 Subject: [PATCH 238/382] Begin work on playback menu --- src/d_main.c | 2 +- src/d_netcmd.c | 2 +- src/g_game.c | 47 +++++++++--- src/g_game.h | 2 +- src/m_menu.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 232 insertions(+), 16 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 16a70519f..a86a4f97e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -556,7 +556,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; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 50f0a2e8f..21a8e2a36 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2689,7 +2689,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) return; } - if (modeattacking) + if (modeattacking && !demo.playback) return; paused = READUINT8(*cp); diff --git a/src/g_game.c b/src/g_game.c index 5aa28a070..df1c82355 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1949,6 +1949,33 @@ boolean G_Responder(event_t *ev) return true; } + + // Allow pausing + if ( + ev->data1 == gamecontrol[gc_pause][0] + || ev->data1 == gamecontrol[gc_pause][1] + || ev->data1 == KEY_PAUSE + ) + { + paused = !paused; + if (paused) + S_PauseAudio(); + else + S_ResumeAudio(); + + return true; + } + + // Anything else opens the menu if not already open, except for a few keys... + if (!( + // Rankings + ev->data1 == gamecontrol[gc_scores][0] || ev->data1 == gamecontrol[gc_scores][1] + )) + { + M_StartControlPanel(); + + return true; + } } // update keys current state @@ -2171,16 +2198,16 @@ boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive) // Return the next player that can be viewed on a view, wraps forward. // An out of range startview is corrected. // -INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive) +INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive, boolean reverse) { - INT32 i; + INT32 i, dir = reverse ? -1 : 1; startview = min(max(startview, 0), MAXPLAYERS); - for (i = startview; i < MAXPLAYERS; ++i) + for (i = startview; i < MAXPLAYERS && i >= 0; i += dir) { if (G_CanView(i, viewnum, onlyactive)) return i; } - for (i = 0; i < startview; ++i) + for (i = (reverse ? MAXPLAYERS-1 : 0); i != startview; i += dir) { if (G_CanView(i, viewnum, onlyactive)) return i; @@ -2251,12 +2278,14 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) R_ExecuteSetViewSize(); } - /* Check if anyone is available to view. */ - if (( playernum = G_FindView(playernum, viewnum, onlyactive) ) == -1) - return; - /* Focus our target view first so that we don't take its player. */ displayplayerp = (G_GetDisplayplayerPtr(viewnum)); olddisplayplayer = (*displayplayerp); + + /* Check if anyone is available to view. */ + if (( playernum = G_FindView(playernum, viewnum, onlyactive, playernum < olddisplayplayer) ) == -1) + return; + + /* Focus our target view first so that we don't take its player. */ (*displayplayerp) = playernum; if ((*displayplayerp) != olddisplayplayer) { @@ -2271,7 +2300,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) displayplayerp = (G_GetDisplayplayerPtr(viewd)); camerap = (P_GetCameraPtr(viewd)); - (*displayplayerp) = G_FindView(0, viewd, onlyactive); + (*displayplayerp) = G_FindView(0, viewd, onlyactive, false); P_ResetCamera(&players[(*displayplayerp)], camerap); } diff --git a/src/g_game.h b/src/g_game.h index c44691e8c..42623dfac 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -294,7 +294,7 @@ INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); boolean G_CouldView(INT32 playernum); boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive); -INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive); +INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive, boolean reverse); INT32 G_CountPlayersPotentiallyViewable(boolean active); void G_ResetViews(void); diff --git a/src/m_menu.c b/src/m_menu.c index c841d50e0..96e4075d9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -345,6 +345,13 @@ static boolean M_QuitReplayHut(void); static void M_EnterReplayOptions(INT32 choice); static void M_HutStartReplay(INT32 choice); +static void M_DrawPlaybackMenu(void); +static void M_PlaybackPause(INT32 choice); +static void M_PlaybackFastForward(INT32 choice); +static void M_PlaybackAdvance(INT32 choice); +static void M_PlaybackSetViews(INT32 choice); +static void M_PlaybackAdjustView(INT32 choice); + // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawGenericBackgroundMenu(void); @@ -558,6 +565,43 @@ static menuitem_t MISC_ReplayOptionsMenu[] = {IT_CVAR|IT_STRING, NULL, "Sync Check Interval", &cv_netdemosyncquality, 10}, }; +static menuitem_t PlaybackMenu[] = +{ + {IT_CALL | IT_STRING, NULL, "Hide Menu", M_SelectableClearMenus, 0}, + + {IT_CALL | IT_STRING, NULL, "Rewind", M_SelectableClearMenus, 24}, + {IT_CALL | IT_STRING, NULL, "Pause", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, NULL, "Resume", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, NULL, "Fast-Foward", M_PlaybackFastForward, 56}, + {IT_CALL | IT_STRING, NULL, "Advance Frame", M_PlaybackAdvance, 56}, + + {IT_ARROWS | IT_STRING, NULL, "View Count", M_PlaybackSetViews, 80}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint", M_PlaybackAdjustView, 96}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint 2", M_PlaybackAdjustView, 112}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint 3", M_PlaybackAdjustView, 128}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint 4", M_PlaybackAdjustView, 144}, + + + {IT_CALL | IT_STRING, NULL, "More Options...", M_ReplayHut, 168}, + {IT_CALL | IT_STRING, NULL, "Stop Playback", M_ReplayHut, 184}, +}; +typedef enum +{ + playback_hide, + playback_rewind, + playback_pause, + playback_resume, + playback_fastforward, + playback_advanceframe, + playback_viewcount, + playback_view1, + playback_view2, + playback_view3, + playback_view4, + playback_moreoptions, + playback_quit +} playback_e; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -1651,6 +1695,17 @@ menu_t MISC_ReplayStartDef = NULL }; +menu_t PlaybackMenuDef = { + NULL, + sizeof (PlaybackMenu)/sizeof (menuitem_t), + NULL, + PlaybackMenu, + M_DrawPlaybackMenu, + BASEVIDWIDTH/2 - 100, 2, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -2639,8 +2694,6 @@ boolean M_Responder(event_t *ev) } } } - else if (ev->type == ev_keydown) // Preserve event for other responders - ch = ev->data1; if (ch == -1) return false; @@ -2786,6 +2839,19 @@ boolean M_Responder(event_t *ev) routine = M_ChangeCvar; } + if (currentMenu == &PlaybackMenuDef) + { + // Flip left/right with up/down for the playback menu, since it's a horizontal icon row. + switch (ch) + { + case KEY_LEFTARROW: ch = KEY_UPARROW; break; + case KEY_UPARROW: ch = KEY_RIGHTARROW; break; + case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; + case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; + default: break; + } + } + // Keys usable within menu switch (ch) { @@ -2944,7 +3010,7 @@ void M_Drawer(void) if (menuactive) { // now that's more readable with a faded background (yeah like Quake...) - if (!WipeInAction) + if (!WipeInAction && currentMenu != &PlaybackMenuDef) // Replay playback has its own background V_DrawFadeScreen(0xFF00, 16); if (currentMenu->drawroutine) @@ -3007,7 +3073,11 @@ void M_StartControlPanel(void) menuactive = true; - if (!Playing()) + if (demo.playback) + { + currentMenu = &PlaybackMenuDef; + } + else if (!Playing()) { // Secret menu! //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); @@ -5656,6 +5726,123 @@ static void M_HutStartReplay(INT32 choice) G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); } +static void M_DrawPlaybackMenu(void) +{ + INT16 i; + patch_t *icon; + UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE); + + // Toggle items + if (paused) + { + PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_DISABLED; + PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_CALL|IT_STRING; + } + else + { + PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_CALL|IT_STRING; + PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_DISABLED; + } + for (i = 0; i <= splitscreen; i++) + PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; + for (i = splitscreen+1; i < 4; i++) + PlaybackMenu[playback_view1+i].status = IT_DISABLED; + + // wip + //M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15); + //M_DrawCenteredMenu(); + + for (i = 0; i < currentMenu->numitems; i++) + { + UINT8 *inactivemap = NULL; + + if (i >= playback_view1 && i <= playback_view4) + { + if (splitscreen >= i - playback_view1) + { + INT32 ply = *G_GetDisplayplayerPtr(i - playback_view1 + 1); + + icon = facerankprefix[players[ply].skin]; + if (i != itemOn) + inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); + } + else if (currentMenu->menuitems[i].patch && W_GetNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + else + icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp + } + else if (currentMenu->menuitems[i].status == IT_DISABLED) + continue; + else if (currentMenu->menuitems[i].patch && W_GetNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + else + icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp + + if (i == playback_fastforward && cv_playbackspeed.value > 1) + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SILVER, GTC_MENUCACHE)); + else + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, (i == itemOn) ? activemap : inactivemap); + + if (i == itemOn) + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + } +} + +static void M_PlaybackPause(INT32 choice) +{ + (void)choice; + + paused = !paused; + + if (paused) + { + itemOn = playback_resume; + S_PauseAudio(); + } + else + { + itemOn = playback_pause; + S_ResumeAudio(); + } + + CV_SetValue(&cv_playbackspeed, 1); +} + +static void M_PlaybackFastForward(INT32 choice) +{ + (void)choice; + + CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); +} + +static void M_PlaybackAdvance(INT32 choice) +{ + (void)choice; + + paused = false; + TryRunTics(1); + paused = true; +} + + +static void M_PlaybackSetViews(INT32 choice) +{ + if (choice > 0) + { + if (splitscreen < 3) + G_AdjustView(splitscreen + 2, 0, true); + } + else if (splitscreen) + { + splitscreen--; + R_ExecuteSetViewSize(); + } +} + +static void M_PlaybackAdjustView(INT32 choice) +{ + G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); +} static void M_PandorasBox(INT32 choice) { From ce7577eb3a93c3644a333a4643052b115d5ff5d8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 02:17:30 -0500 Subject: [PATCH 239/382] Reference graphics for menu and other stuff --- src/m_menu.c | 62 +++++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 96e4075d9..730eba0df 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -567,23 +567,22 @@ static menuitem_t MISC_ReplayOptionsMenu[] = static menuitem_t PlaybackMenu[] = { - {IT_CALL | IT_STRING, NULL, "Hide Menu", M_SelectableClearMenus, 0}, + {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu", M_SelectableClearMenus, 0}, - {IT_CALL | IT_STRING, NULL, "Rewind", M_SelectableClearMenus, 24}, - {IT_CALL | IT_STRING, NULL, "Pause", M_PlaybackPause, 40}, - {IT_CALL | IT_STRING, NULL, "Resume", M_PlaybackPause, 40}, - {IT_CALL | IT_STRING, NULL, "Fast-Foward", M_PlaybackFastForward, 56}, - {IT_CALL | IT_STRING, NULL, "Advance Frame", M_PlaybackAdvance, 56}, + {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_SelectableClearMenus, 24}, + {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 56}, + {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 56}, - {IT_ARROWS | IT_STRING, NULL, "View Count", M_PlaybackSetViews, 80}, - {IT_ARROWS | IT_STRING, NULL, "Viewpoint", M_PlaybackAdjustView, 96}, - {IT_ARROWS | IT_STRING, NULL, "Viewpoint 2", M_PlaybackAdjustView, 112}, - {IT_ARROWS | IT_STRING, NULL, "Viewpoint 3", M_PlaybackAdjustView, 128}, - {IT_ARROWS | IT_STRING, NULL, "Viewpoint 4", M_PlaybackAdjustView, 144}, + {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 80}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint", M_PlaybackAdjustView, 96}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2", M_PlaybackAdjustView, 112}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3", M_PlaybackAdjustView, 128}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 144}, - - {IT_CALL | IT_STRING, NULL, "More Options...", M_ReplayHut, 168}, - {IT_CALL | IT_STRING, NULL, "Stop Playback", M_ReplayHut, 184}, + {IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 168}, + {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_ReplayHut, 184}, }; typedef enum { @@ -1673,7 +1672,7 @@ menu_t MISC_ReplayHutDef = menu_t MISC_ReplayOptionsDef = { - NULL, + "M_REPOPT", sizeof (MISC_ReplayOptionsMenu)/sizeof (menuitem_t), &MISC_ReplayHutDef, MISC_ReplayOptionsMenu, @@ -5346,7 +5345,7 @@ static void DrawReplayHutReplayInfo(void) if (lumpnum != LUMPERROR) patch = W_CachePatchNum(lumpnum, PU_CACHE); else - patch = W_CachePatchName("BLANKLVL", PU_CACHE); + patch = W_CachePatchName("M_NOLVL", PU_CACHE); if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) V_DrawSmallScaledPatch(x, y, 0, patch); @@ -5416,7 +5415,7 @@ static void DrawReplayHutReplayInfo(void) } else { - patch = W_CachePatchName("MISSINGW", PU_CACHE); + patch = W_CachePatchName("M_NOWANT", PU_CACHE); colormap = R_GetTranslationColormap( TC_RAINBOW, demolist[dir_on[menudepthleft]].standings[0].color, @@ -5514,7 +5513,7 @@ static void M_DrawReplayHut(void) if (demolist[i].type == MD_SUBDIR) { localx += 8; - V_DrawFixedPatch((x - 4)<width), y+20, 0, patch, colormap); -*/ // Character face! if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facerank) != LUMPERROR) { @@ -5624,7 +5602,7 @@ static void M_DrawReplayStartMenu(void) } else { - patch = W_CachePatchName("MISSINGR", PU_CACHE); + patch = W_CachePatchName("M_NORANK", PU_CACHE); colormap = R_GetTranslationColormap( TC_RAINBOW, demolist[dir_on[menudepthleft]].standings[i].color, @@ -5766,14 +5744,14 @@ static void M_DrawPlaybackMenu(void) if (i != itemOn) inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); } - else if (currentMenu->menuitems[i].patch && W_GetNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); else icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp } else if (currentMenu->menuitems[i].status == IT_DISABLED) continue; - else if (currentMenu->menuitems[i].patch && W_GetNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); else icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp From c7125c862c4abcbe4d44f4139571de237df96314 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 11:16:19 -0500 Subject: [PATCH 240/382] Support non-green resolutions in the replay hut --- src/m_menu.c | 82 ++++++++++++++++++++++++++------------------------- src/v_video.c | 7 +++-- 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 730eba0df..a9c917247 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5312,6 +5312,8 @@ static void M_HandleReplayHutList(INT32 choice) } } +#define SCALEDVIEWWIDTH (vid.width/vid.dupx) +#define SCALEDVIEWHEIGHT (vid.height/vid.dupy) static void DrawReplayHutReplayInfo(void) { lumpnum_t lumpnum; @@ -5322,18 +5324,18 @@ static void DrawReplayHutReplayInfo(void) switch (demolist[dir_on[menudepthleft]].type) { case MD_NOTLOADED: - V_DrawCenteredString(160, 40, 0, "Loading replay information..."); + V_DrawCenteredString(160, 40, V_SNAPTOTOP, "Loading replay information..."); break; case MD_INVALID: - V_DrawCenteredString(160, 40, warningflags, "This replay cannot be played."); + V_DrawCenteredString(160, 40, V_SNAPTOTOP|warningflags, "This replay cannot be played."); break; case MD_SUBDIR: break; // Can't think of anything to draw here right now case MD_OUTDATED: - V_DrawThinString(17, 64, V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); + V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); /*fallthru*/ default: // Draw level stuff @@ -5348,17 +5350,17 @@ static void DrawReplayHutReplayInfo(void) patch = W_CachePatchName("M_NOLVL", PU_CACHE); if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) - V_DrawSmallScaledPatch(x, y, 0, patch); + V_DrawSmallScaledPatch(x, y, V_SNAPTOTOP, patch); else { w = SHORT(patch->width); h = SHORT(patch->height); - V_DrawSmallScaledPatch(x+(w>>1), y, V_FLIP, patch); + V_DrawSmallScaledPatch(x+(w>>1), y, V_SNAPTOTOP|V_FLIP, patch); { static angle_t rubyfloattime = 0; const fixed_t rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); - V_DrawFixedPatch((x+(w>>2))<>2))<>2))<>2))<width), y+20, 0, patch, colormap); + V_DrawMappedPatch(BASEVIDWIDTH-15 - SHORT(patch->width), y+20, V_SNAPTOTOP, patch, colormap); break; } @@ -5465,8 +5467,8 @@ static void M_DrawReplayHut(void) if (cursory > maxy - 20) cursory = maxy - 20; - if (cursory - replayhutmenuy > 150) - replayhutmenuy += (cursory-150-replayhutmenuy + 1)/2; + if (cursory - replayhutmenuy > SCALEDVIEWHEIGHT-50) + replayhutmenuy += (cursory-SCALEDVIEWHEIGHT-replayhutmenuy + 51)/2; else if (cursory - replayhutmenuy < 110) replayhutmenuy += (max(0, cursory-110)-replayhutmenuy - 1)/2; } @@ -5487,9 +5489,9 @@ static void M_DrawReplayHut(void) cursory = localy; if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) - V_DrawString(x, localy, 0, currentMenu->menuitems[i].text); + V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT, currentMenu->menuitems[i].text); else - V_DrawString(x, localy, highlightflags, currentMenu->menuitems[i].text); + V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[i].text); } y += currentMenu->menuitems[currentMenu->numitems-1].alphaKey; @@ -5501,7 +5503,7 @@ static void M_DrawReplayHut(void) if (localy < 65) continue; - if (localy >= 200) + if (localy >= SCALEDVIEWHEIGHT) break; if (demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) @@ -5513,7 +5515,7 @@ static void M_DrawReplayHut(void) if (demolist[i].type == MD_SUBDIR) { localx += 8; - V_DrawScaledPatch(x - 4, localy, 0, W_CachePatchName(dirmenu[i][DIR_TYPE] == EXT_UP ? "M_RBACK" : "M_RFLDR", PU_CACHE)); + V_DrawScaledPatch(x - 4, localy, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName(dirmenu[i][DIR_TYPE] == EXT_UP ? "M_RBACK" : "M_RFLDR", PU_CACHE)); } if (itemOn == replaylistitem && i == (INT16)dir_on[menudepthleft]) @@ -5524,7 +5526,7 @@ static void M_DrawReplayHut(void) replayScrollDelay--; else if (replayScrollDir > 0) { - if (replayScrollTitle < (V_StringWidth(demolist[i].title, 0) - (BASEVIDWIDTH - (x<<1)))<<1) + if (replayScrollTitle < (V_StringWidth(demolist[i].title, 0) - (SCALEDVIEWWIDTH - (x<<1)))<<1) replayScrollTitle++; else { @@ -5543,19 +5545,19 @@ static void M_DrawReplayHut(void) } } - V_DrawString(localx - (replayScrollTitle>>1), localy, highlightflags|V_ALLOWLOWERCASE, demolist[i].title); + V_DrawString(localx - (replayScrollTitle>>1), localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags|V_ALLOWLOWERCASE, demolist[i].title); } else - V_DrawString(localx, localy, V_ALLOWLOWERCASE, demolist[i].title); + V_DrawString(localx, localy, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE, demolist[i].title); } // Draw the cursor - V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, + V_DrawScaledPatch(currentMenu->x - 24, cursory, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); + V_DrawString(currentMenu->x, cursory, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[itemOn].text); // Now draw some replay info! - V_DrawFill(10, 10, 300, 60, 239); + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|239); if (itemOn == replaylistitem) { @@ -5577,19 +5579,19 @@ static void M_DrawReplayStartMenu(void) patch_t *patch; UINT8 *colormap; - V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, highlightflags, va("%2d", demolist[dir_on[menudepthleft]].standings[i].ranking)); - V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[i].name); + V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, V_SNAPTOTOP|highlightflags, va("%2d", demolist[dir_on[menudepthleft]].standings[i].ranking)); + V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_SNAPTOTOP|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[i].name); if (demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1) - V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, 0, "NO CONTEST"); + V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST"); else if (demolist[dir_on[menudepthleft]].gametype == GT_RACE) - V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, 0, va("%d'%02d\"%02d", + V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d", G_TicsToMinutes(demolist[dir_on[menudepthleft]].standings[i].timeorscore, true), G_TicsToSeconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore), G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore) )); else - V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, 0, va("%d", demolist[dir_on[menudepthleft]].standings[i].timeorscore)); + V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", demolist[dir_on[menudepthleft]].standings[i].timeorscore)); // Character face! if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facerank) != LUMPERROR) @@ -5609,7 +5611,7 @@ static void M_DrawReplayStartMenu(void) GTC_MENUCACHE); } - V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, 0, patch, colormap); + V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, V_SNAPTOTOP, patch, colormap); } #undef STARTY @@ -5618,7 +5620,7 @@ static void M_DrawReplayStartMenu(void) replayScrollDelay--; else if (replayScrollDir > 0) { - if (replayScrollTitle < (i*20 - 100)<<1) + if (replayScrollTitle < (i*20 - SCALEDVIEWHEIGHT + 100)<<1) replayScrollTitle++; else { @@ -5637,10 +5639,10 @@ static void M_DrawReplayStartMenu(void) } } - V_DrawFill(10, 10, 300, 60, 239); + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|239); DrawReplayHutReplayInfo(); - V_DrawString(10, 72, highlightflags|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].title); + V_DrawString(10, 72, V_SNAPTOTOP|highlightflags|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].title); // Draw a warning prompt if needed switch (demolist[dir_on[menudepthleft]].addonstatus) @@ -5666,7 +5668,7 @@ static void M_DrawReplayStartMenu(void) return; } - V_DrawSmallString(4, BASEVIDHEIGHT-14, V_ALLOWLOWERCASE, warning); + V_DrawSmallString(4, BASEVIDHEIGHT-14, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, warning); } static boolean M_QuitReplayHut(void) diff --git a/src/v_video.c b/src/v_video.c index 1f5020dd7..29acc12b5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1460,8 +1460,11 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) { dupx = dupy = 1; scrwidth = vid.width/vid.dupx; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; + if (!(option & V_SNAPTOLEFT)) + { + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + } } charflags = (option & V_CHARCOLORMASK); From 25ff05fdd0768b577018557aaf89ba94ccdffb62 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 14:51:00 -0500 Subject: [PATCH 241/382] Add demo rewinding Preview is fairly basic, and only shows players rewinding. Full state is restored via reloading the replay and jumping to the timestamp once the rewind is done. --- src/d_main.c | 3 + src/g_game.c | 229 ++++++++++++++++++++++++++++++++++++++++++++------ src/g_game.h | 7 ++ src/m_menu.c | 40 +++++++-- src/p_setup.c | 4 +- src/p_tick.c | 11 +++ src/s_sound.c | 4 +- src/v_video.c | 9 +- 8 files changed, 266 insertions(+), 41 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index a86a4f97e..d1a820c8f 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -568,6 +568,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; diff --git a/src/g_game.c b/src/g_game.c index df1c82355..d3f8d7987 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5875,6 +5875,168 @@ void G_GhostTicker(void) } } +// Demo rewinding functions +typedef struct rewindinfo_s { + tic_t leveltime; + + struct { + boolean ingame; + player_t player; + mobj_t mobj; + } playerinfo[MAXPLAYERS]; + + struct rewindinfo_s *prev; +} rewindinfo_t; + +static tic_t currentrewindnum; +static rewindinfo_t *rewindhead = NULL; // Reverse chronological order + +void G_InitDemoRewind(void) +{ + while (rewindhead) + { + rewindinfo_t *p = rewindhead->prev; + Z_Free(rewindhead); + rewindhead = p; + } + + currentrewindnum = 0; +} + +void G_StoreRewindInfo(void) +{ + static UINT8 timetolog = 8; + rewindinfo_t *info; + size_t i; + + if (timetolog-- > 0) + return; + timetolog = 8; + + info = Z_Calloc(sizeof(rewindinfo_t), PU_STATIC, NULL); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + { + info->playerinfo[i].ingame = false; + continue; + } + + info->playerinfo[i].ingame = true; + memcpy(&info->playerinfo[i].player, &players[i], sizeof(player_t)); + if (players[i].mo) + memcpy(&info->playerinfo[i].mobj, players[i].mo, sizeof(mobj_t)); + } + + info->leveltime = leveltime; + info->prev = rewindhead; + rewindhead = info; +} + +void G_PreviewRewind(tic_t previewtime) +{ + size_t i, j; + fixed_t tweenvalue = 0; + rewindinfo_t *info = rewindhead, *next_info = rewindhead; + while (info->leveltime > previewtime && info->prev) + { + next_info = info; + info = info->prev; + } + if (info != next_info) + tweenvalue = FixedDiv(previewtime - info->leveltime, next_info->leveltime - info->leveltime); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + { + if (info->playerinfo[i].player.mo) + { + //@TODO spawn temp object to act as a player display + } + + continue; + } + + if (!info->playerinfo[i].ingame || !info->playerinfo[i].player.mo) + { + if (players[i].mo) + players[i].mo->flags2 |= MF2_DONTDRAW; + + continue; + } + + if (!players[i].mo) + continue; //@TODO spawn temp object to act as a player display + + players[i].mo->flags2 &= ~MF2_DONTDRAW; + + P_UnsetThingPosition(players[i].mo); +#define TWEEN(pr) info->playerinfo[i].mobj.pr + FixedMul((INT32) (next_info->playerinfo[i].mobj.pr - info->playerinfo[i].mobj.pr), tweenvalue) + players[i].mo->x = TWEEN(x); + players[i].mo->y = TWEEN(y); + players[i].mo->z = TWEEN(z); + players[i].mo->angle = TWEEN(angle); +#undef TWEEN + P_SetThingPosition(players[i].mo); + + players[i].frameangle = info->playerinfo[i].player.frameangle + FixedMul((INT32) (next_info->playerinfo[i].player.frameangle - info->playerinfo[i].player.frameangle), tweenvalue); + + players[i].mo->sprite = info->playerinfo[i].mobj.sprite; + players[i].mo->frame = info->playerinfo[i].mobj.frame; + + players[i].realtime = info->playerinfo[i].player.realtime; + for (j = 0; j < NUMKARTSTUFF; j++) + players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j]; + } + + for (i = splitscreen+1; i > 0; i--) + P_ResetCamera(&players[(*G_GetDisplayplayerPtr(i))], P_GetCameraPtr(i)); +} + +void G_ConfirmRewind(tic_t rewindtime) +{ + tic_t i; + boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled, olddigitaldisabled = digital_disabled; + + INT32 olddp1 = displayplayer, olddp2 = secondarydisplayplayer, olddp3 = thirddisplayplayer, olddp4 = fourthdisplayplayer; + UINT8 oldss = splitscreen; + + cv_renderview.value = 0; + + menuactive = false; // Prevent loops + sound_disabled = /*digital_disabled =*/ true; // Prevent sound spam + demo.rewinding = true; // may not need later + G_DoPlayDemo(NULL); // Restart the current demo + + for (i = 0; i < rewindtime && leveltime < rewindtime; i++) + { + //TryRunTics(1); + G_Ticker((i % NEWTICRATERATIO) == 0); + } + + demo.rewinding = false; + menuactive = oldmenuactive; // Bring the menu back up + sound_disabled = oldsounddisabled; // Re-enable SFX + digital_disabled = olddigitaldisabled; + + wipegamestate = gamestate; // No fading back in! + + cv_renderview.value = 1; + + splitscreen = oldss; + displayplayer = olddp1; + secondarydisplayplayer = olddp2; + thirddisplayplayer = olddp3; + fourthdisplayplayer = olddp4; + R_ExecuteSetViewSize(); + G_ResetViews(); + + for (i = splitscreen+1; i > 0; i--) + P_ResetCamera(&players[(*G_GetDisplayplayerPtr(i))], P_GetCameraPtr(i)); +} + void G_ReadMetalTic(mobj_t *metal) { UINT8 ziptic; @@ -6842,46 +7004,57 @@ void G_DoPlayDemo(char *defdemoname) boolean spectator; UINT8 slots[MAXPLAYERS], kartspeed[MAXPLAYERS], kartweight[MAXPLAYERS], numslots = 0; + G_InitDemoRewind(); + skin[16] = '\0'; color[16] = '\0'; - n = defdemoname+strlen(defdemoname); - while (*n != '/' && *n != '\\' && n != defdemoname) - n--; - if (n != defdemoname) - n++; - pdemoname = ZZ_Alloc(strlen(n)+1); - strcpy(pdemoname,n); - - // Internal if no extension, external if one exists - if (FIL_CheckExtension(defdemoname)) + // No demo name means we're restarting the current demo + if (defdemoname == NULL) { - //FIL_DefaultExtension(defdemoname, ".lmp"); - if (!FIL_ReadFile(defdemoname, &demobuffer)) + demo_p = demobuffer; + pdemoname = ZZ_Alloc(1); // Easier than adding checks for this everywhere it's freed + } + else + { + n = defdemoname+strlen(defdemoname); + while (*n != '/' && *n != '\\' && n != defdemoname) + n--; + if (n != defdemoname) + n++; + pdemoname = ZZ_Alloc(strlen(n)+1); + strcpy(pdemoname,n); + + // Internal if no extension, external if one exists + if (FIL_CheckExtension(defdemoname)) { - snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname); + //FIL_DefaultExtension(defdemoname, ".lmp"); + if (!FIL_ReadFile(defdemoname, &demobuffer)) + { + snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + gameaction = ga_nothing; + M_StartMessage(msg, NULL, MM_NOTHING); + return; + } + demo_p = demobuffer; + } + // load demo resource from WAD + else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) + { + snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname); CONS_Alert(CONS_ERROR, "%s", msg); gameaction = ga_nothing; M_StartMessage(msg, NULL, MM_NOTHING); return; } - demo_p = demobuffer; - } - // load demo resource from WAD - else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) - { - snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - gameaction = ga_nothing; - M_StartMessage(msg, NULL, MM_NOTHING); - return; - } - else // it's an internal demo - { - demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC); + else // it's an internal demo + { + demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC); #if defined(SKIPERRORS) && !defined(DEVELOP) - skiperrors = true; // SRB2Kart: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes... + skiperrors = true; // SRB2Kart: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes... #endif + } } // read demo header diff --git a/src/g_game.h b/src/g_game.h index 42623dfac..190608099 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -43,6 +43,7 @@ struct demovars_s { char titlename[65]; boolean recording, playback, timing; 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 @@ -234,6 +235,12 @@ 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); diff --git a/src/m_menu.c b/src/m_menu.c index a9c917247..0213847d7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -346,6 +346,7 @@ static void M_EnterReplayOptions(INT32 choice); static void M_HutStartReplay(INT32 choice); static void M_DrawPlaybackMenu(void); +static void M_PlaybackRewind(INT32 choice); static void M_PlaybackPause(INT32 choice); static void M_PlaybackFastForward(INT32 choice); static void M_PlaybackAdvance(INT32 choice); @@ -569,11 +570,11 @@ static menuitem_t PlaybackMenu[] = { {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu", M_SelectableClearMenus, 0}, - {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_SelectableClearMenus, 24}, - {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 40}, - {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 40}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 56}, - {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 56}, + {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 24}, + {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 56}, + {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 56}, {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 80}, {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint", M_PlaybackAdjustView, 96}, @@ -5713,7 +5714,7 @@ static void M_DrawPlaybackMenu(void) UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE); // Toggle items - if (paused) + if (paused && !demo.rewinding) { PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_DISABLED; PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_CALL|IT_STRING; @@ -5768,13 +5769,32 @@ static void M_DrawPlaybackMenu(void) } } +static void M_PlaybackRewind(INT32 choice) +{ + (void)choice; + + if (!demo.rewinding) + demo.rewinding = paused = true; + else + G_ConfirmRewind(leveltime); + + // temp + //G_ConfirmRewind(starttime + 90*TICRATE); +} + static void M_PlaybackPause(INT32 choice) { (void)choice; paused = !paused; - if (paused) + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = true; + S_PauseAudio(); + } + else if (paused) { itemOn = playback_resume; S_PauseAudio(); @@ -5792,6 +5812,12 @@ static void M_PlaybackFastForward(INT32 choice) { (void)choice; + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = false; + S_ResumeAudio(); + } CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); } diff --git a/src/p_setup.c b/src/p_setup.c index f73aef99c..8c1c9ae72 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2829,7 +2829,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; @@ -2881,7 +2881,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); diff --git a/src/p_tick.c b/src/p_tick.c index 177f3b657..9b4f7a214 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -591,7 +591,15 @@ void P_Ticker(boolean run) // Check for pause or menu up in single player if (paused || P_AutoPause()) + { + if (demo.rewinding && leveltime > 0) + { + leveltime = (leveltime-1) & ~3; + G_PreviewRewind(leveltime); + } + return; + } postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none; @@ -768,6 +776,9 @@ void P_Ticker(boolean run) P_MapEnd(); + if (demo.playback) + G_StoreRewindInfo(); + // Z_CheckMemCleanup(); } diff --git a/src/s_sound.c b/src/s_sound.c index 9653d8ff6..1585753f9 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1733,7 +1733,7 @@ void S_ShowMusicCredit(void) { musicdef_t *def = musicdefstart; - if (!cv_songcredits.value) + if (!cv_songcredits.value || demo.rewinding) return; if (!def) // No definitions @@ -1920,6 +1920,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) #endif if (S_MusicDisabled() + || demo.rewinding // Don't mess with music while rewinding! || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; @@ -1955,6 +1956,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) void S_StopMusic(void) { if (!I_SongPlaying() + || demo.rewinding // Don't mess with music while rewinding! || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; diff --git a/src/v_video.c b/src/v_video.c index 29acc12b5..dfad4c3a4 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1234,9 +1234,12 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength) #endif { - const UINT8 *fadetable = ((color & 0xFF00) // Color is not palette index? - ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. - : ((UINT8 *)transtables + ((9-strength)< 0xFFF0) // Grab a specific colormap palette? + ? R_GetTranslationColormap(color | 0xFFFF0000, strength, GTC_CACHE) + : ((color & 0xFF00) // Color is not palette index? + ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. + : ((UINT8 *)transtables + ((9-strength)< Date: Sat, 6 Apr 2019 15:36:53 -0500 Subject: [PATCH 242/382] Allow backwards frame advance while paused --- src/m_menu.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 0213847d7..915643acd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5774,7 +5774,16 @@ static void M_PlaybackRewind(INT32 choice) (void)choice; if (!demo.rewinding) - demo.rewinding = paused = true; + { + if (paused) + { + G_ConfirmRewind(leveltime-1); + paused = true; + S_PauseAudio(); + } + else + demo.rewinding = paused = true; + } else G_ConfirmRewind(leveltime); @@ -5792,6 +5801,7 @@ static void M_PlaybackPause(INT32 choice) { G_ConfirmRewind(leveltime); paused = true; + itemOn = playback_resume; S_PauseAudio(); } else if (paused) From d9e061d999311636cc980b0c7351e959ff9d445b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 18:06:02 -0500 Subject: [PATCH 243/382] Various fixes and tweaks to rewinds --- src/g_game.c | 25 ++++++++++++++++++------- src/m_menu.c | 12 ++++++++---- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d3f8d7987..701f06738 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5939,6 +5939,10 @@ void G_PreviewRewind(tic_t previewtime) size_t i, j; fixed_t tweenvalue = 0; rewindinfo_t *info = rewindhead, *next_info = rewindhead; + + if (!info) + return; + while (info->leveltime > previewtime && info->prev) { next_info = info; @@ -5947,6 +5951,7 @@ void G_PreviewRewind(tic_t previewtime) if (info != next_info) tweenvalue = FixedDiv(previewtime - info->leveltime, next_info->leveltime - info->leveltime); + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -5998,16 +6003,23 @@ void G_PreviewRewind(tic_t previewtime) void G_ConfirmRewind(tic_t rewindtime) { tic_t i; - boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled, olddigitaldisabled = digital_disabled; + boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; INT32 olddp1 = displayplayer, olddp2 = secondarydisplayplayer, olddp3 = thirddisplayplayer, olddp4 = fourthdisplayplayer; UINT8 oldss = splitscreen; - cv_renderview.value = 0; - menuactive = false; // Prevent loops - sound_disabled = /*digital_disabled =*/ true; // Prevent sound spam - demo.rewinding = true; // may not need later + + CV_StealthSetValue(&cv_renderview, 0); + + if (rewindtime > starttime) + { + sound_disabled = true; // Prevent sound spam + demo.rewinding = true; + } + else + demo.rewinding = false; + G_DoPlayDemo(NULL); // Restart the current demo for (i = 0; i < rewindtime && leveltime < rewindtime; i++) @@ -6019,11 +6031,10 @@ void G_ConfirmRewind(tic_t rewindtime) demo.rewinding = false; menuactive = oldmenuactive; // Bring the menu back up sound_disabled = oldsounddisabled; // Re-enable SFX - digital_disabled = olddigitaldisabled; wipegamestate = gamestate; // No fading back in! - cv_renderview.value = 1; + COM_BufInsertText("renderview on\n"); splitscreen = oldss; displayplayer = olddp1; diff --git a/src/m_menu.c b/src/m_menu.c index 915643acd..c3d2397fb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5759,7 +5759,7 @@ static void M_DrawPlaybackMenu(void) else icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp - if (i == playback_fastforward && cv_playbackspeed.value > 1) + if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding)) V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SILVER, GTC_MENUCACHE)); else V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, (i == itemOn) ? activemap : inactivemap); @@ -5771,6 +5771,8 @@ static void M_DrawPlaybackMenu(void) static void M_PlaybackRewind(INT32 choice) { + static tic_t lastconfirmtime; + (void)choice; if (!demo.rewinding) @@ -5784,11 +5786,13 @@ static void M_PlaybackRewind(INT32 choice) else demo.rewinding = paused = true; } - else + else if (lastconfirmtime + TICRATE/2 < I_GetTime()) + { + lastconfirmtime = I_GetTime(); G_ConfirmRewind(leveltime); + } - // temp - //G_ConfirmRewind(starttime + 90*TICRATE); + CV_SetValue(&cv_playbackspeed, 1); } static void M_PlaybackPause(INT32 choice) From 3787e9078117c1677270093f9743bab89f4439bd Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 18:17:56 -0500 Subject: [PATCH 244/382] Fix title menu not working if you leave a replay early --- src/m_menu.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index c3d2397fb..7c82bc316 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -352,6 +352,7 @@ static void M_PlaybackFastForward(INT32 choice); static void M_PlaybackAdvance(INT32 choice); static void M_PlaybackSetViews(INT32 choice); static void M_PlaybackAdjustView(INT32 choice); +static void M_PlaybackQuit(INT32 choice); // Drawing functions static void M_DrawGenericMenu(void); @@ -583,7 +584,7 @@ static menuitem_t PlaybackMenu[] = {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 144}, {IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 168}, - {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_ReplayHut, 184}, + {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 184}, }; typedef enum { @@ -5864,6 +5865,19 @@ static void M_PlaybackAdjustView(INT32 choice) G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); } +static void M_PlaybackQuit(INT32 choice) +{ + (void)choice; + G_StopDemo(); + + if (demo.inreplayhut) + M_ReplayHut(choice); + else if (modeattacking) + S_ChangeMusicInternal("racent", true); // ??? + else + D_StartTitle(); +} + static void M_PandorasBox(INT32 choice) { (void)choice; From 77c71ca94455c2e0ca9bfd14807b6fba4d678190 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 18:59:11 -0500 Subject: [PATCH 245/382] Support playback menu for record attack replays too --- src/g_game.c | 2 ++ src/m_menu.c | 73 +++++++++++++++++++++++++++++++++------------------- src/m_menu.h | 1 + 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 701f06738..f7f0457a8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7036,6 +7036,8 @@ void G_DoPlayDemo(char *defdemoname) pdemoname = ZZ_Alloc(strlen(n)+1); strcpy(pdemoname,n); + M_SetPlaybackMenuPointer(); + // Internal if no extension, external if one exists if (FIL_CheckExtension(defdemoname)) { diff --git a/src/m_menu.c b/src/m_menu.c index 7c82bc316..d8d8f4a13 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -571,20 +571,20 @@ static menuitem_t PlaybackMenu[] = { {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu", M_SelectableClearMenus, 0}, - {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 24}, - {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 40}, - {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 40}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 56}, - {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 56}, + {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, + {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, + {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, - {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 80}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint", M_PlaybackAdjustView, 96}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2", M_PlaybackAdjustView, 112}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3", M_PlaybackAdjustView, 128}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 144}, + {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 72}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint", M_PlaybackAdjustView, 88}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2", M_PlaybackAdjustView, 104}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3", M_PlaybackAdjustView, 120}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 136}, - {IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 168}, - {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 184}, + {IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 156}, + {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, }; typedef enum { @@ -1702,7 +1702,7 @@ menu_t PlaybackMenuDef = { NULL, PlaybackMenu, M_DrawPlaybackMenu, - BASEVIDWIDTH/2 - 100, 2, + BASEVIDWIDTH/2 - 94, 2, 0, NULL }; @@ -3057,14 +3057,6 @@ void M_Drawer(void) // void M_StartControlPanel(void) { - // time attack HACK - if (modeattacking && demo.playback) - { - G_CheckDemoStatus(); - S_ChangeMusicInternal("racent", true); - return; - } - // intro might call this repeatedly if (menuactive) { @@ -5708,6 +5700,11 @@ static void M_HutStartReplay(INT32 choice) G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); } +void M_SetPlaybackMenuPointer(void) +{ + itemOn = playback_pause; +} + static void M_DrawPlaybackMenu(void) { INT16 i; @@ -5725,10 +5722,29 @@ static void M_DrawPlaybackMenu(void) PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_CALL|IT_STRING; PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_DISABLED; } - for (i = 0; i <= splitscreen; i++) - PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; - for (i = splitscreen+1; i < 4; i++) - PlaybackMenu[playback_view1+i].status = IT_DISABLED; + + if (modeattacking) + { + for (i = playback_viewcount; i <= playback_view4; i++) + PlaybackMenu[i].status = IT_DISABLED; + + PlaybackMenu[playback_moreoptions].alphaKey = 72; + PlaybackMenu[playback_quit].alphaKey = 88; + + currentMenu->x = BASEVIDWIDTH/2 - 52; + } + else + { + for (i = 0; i <= splitscreen; i++) + PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; + for (i = splitscreen+1; i < 4; i++) + PlaybackMenu[playback_view1+i].status = IT_DISABLED; + + PlaybackMenu[playback_moreoptions].alphaKey = 156; + PlaybackMenu[playback_quit].alphaKey = 172; + + currentMenu->x = BASEVIDWIDTH/2 - 94; + } // wip //M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15); @@ -5740,6 +5756,8 @@ static void M_DrawPlaybackMenu(void) if (i >= playback_view1 && i <= playback_view4) { + if (modeattacking) continue; + if (splitscreen >= i - playback_view1) { INT32 ply = *G_GetDisplayplayerPtr(i - playback_view1 + 1); @@ -5873,7 +5891,10 @@ static void M_PlaybackQuit(INT32 choice) if (demo.inreplayhut) M_ReplayHut(choice); else if (modeattacking) - S_ChangeMusicInternal("racent", true); // ??? + { + M_EndModeAttackRun(); + S_ChangeMusicInternal("racent", true); + } else D_StartTitle(); } diff --git a/src/m_menu.h b/src/m_menu.h index f49c6ca64..ef0381d11 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -236,6 +236,7 @@ void Screenshot_option_Onchange(void); void Addons_option_Onchange(void); void M_ReplayHut(INT32 choice); +void M_SetPlaybackMenuPointer(void); INT32 HU_GetHighlightColor(void); From 4f86a447cae69f8fed5d978ea4f1ff99028e72fb Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 6 Apr 2019 23:42:02 -0400 Subject: [PATCH 246/382] Expose cv_numlaps as global variable --- src/dehacked.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 1c88fe832..3fcfd50bf 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9925,6 +9925,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; } From fb3d5ec7f0b81dfca04847a1e657f9a66c51ef2e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 7 Apr 2019 17:59:32 -0500 Subject: [PATCH 247/382] Record demos consistently and also other stuff --- src/g_game.c | 39 ++++++++++++++++++++------------------- src/g_game.h | 1 + src/p_tick.c | 46 +++++++++++++++++++++++----------------------- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index f7f0457a8..2f4f8531f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -292,7 +292,6 @@ static UINT8 *demobuffer = NULL; static UINT8 *demo_p, *demotime_p, *demoinfo_p; static UINT8 *demoend; static UINT8 demoflags; -static UINT16 demoversion; static boolean demosynced = true; // console warning message struct demovars_s demo; @@ -315,7 +314,6 @@ static struct { // EZT_KART INT32 kartitem, kartamount, kartbumpers; - boolean kartresync; //@TODO backwards compat with old replays. remove eventually UINT8 desyncframes; // Don't try to resync unless we've been off for two frames, to monkeypatch a few trouble spots @@ -5422,11 +5420,9 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) if (ghost->player) { if ( - !modeattacking && ( //@TODO: This is a temporary check to keep netreplays EXE record attack replays compatible with base Kart. - ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || - ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || - ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] - ) + ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || + ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || + ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] ) { ghostext[playernum].flags |= EZT_KART; @@ -5621,7 +5617,6 @@ void G_ConsGhostTic(INT32 playernum) ghostext[playernum].kartitem = READINT32(demo_p); ghostext[playernum].kartamount = READINT32(demo_p); ghostext[playernum].kartbumpers = READINT32(demo_p); - ghostext[playernum].kartresync = true; } } @@ -5651,6 +5646,9 @@ void G_ConsGhostTic(INT32 playernum) P_SetThingPosition(testmo); testmo->z = oldghost[playernum].z; + if (abs(testmo->z - testmo->floorz) < 4*FRACUNIT) + testmo->z = testmo->floorz; // Sync players to the ground when they're likely supposed to be there... + ghostext[playernum].desyncframes = 2; } } @@ -5658,10 +5656,14 @@ void G_ConsGhostTic(INT32 playernum) ghostext[playernum].desyncframes = 0; if ( - ghostext[playernum].kartresync && ( - players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem || - players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount || - players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers) +#ifdef DEMO_COMPAT_100 + demo.version != 0x0001 && +#endif + ( + players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem || + players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount || + players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers + ) ) { if (demosynced) @@ -7088,19 +7090,17 @@ void G_DoPlayDemo(char *defdemoname) version = READUINT8(demo_p); subversion = READUINT8(demo_p); - demoversion = READUINT16(demo_p); - switch(demoversion) + demo.version = READUINT16(demo_p); + switch(demo.version) { case DEMOVERSION: // latest always supported // demo title M_Memcpy(demo.titlename, demo_p, 64); - CONS_Printf("Demo title: %s\n", demo.titlename); demo_p += 64; break; #ifdef DEMO_COMPAT_100 case 0x0001: - CONS_Printf("You need to implement demo compat here, doofus! %s:%d\n", __FILE__, __LINE__); break; #endif // too old, cannot support. @@ -7132,7 +7132,7 @@ void G_DoPlayDemo(char *defdemoname) demoflags = READUINT8(demo_p); #ifdef DEMO_COMPAT_100 - if (demoversion == 0x0001) + if (demo.version == 0x0001) { if (demoflags & DF_MULTIPLAYER) { @@ -7237,12 +7237,13 @@ void G_DoPlayDemo(char *defdemoname) // Random seed randseed = READUINT32(demo_p); #ifdef DEMO_COMPAT_100 - if (demoversion != 0x0001) + if (demo.version != 0x0001) #endif demo_p += 4; // Extrainfo location #ifdef DEMO_COMPAT_100 - if (demoversion == 0x0001) { + if (demo.version == 0x0001) + { // Player name M_Memcpy(player_names[0],demo_p,16); demo_p += 16; diff --git a/src/g_game.h b/src/g_game.h index 190608099..148a5e52b 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -42,6 +42,7 @@ extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; 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 diff --git a/src/p_tick.c b/src/p_tick.c index 9b4f7a214..a5f6313b3 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -609,26 +609,29 @@ void P_Ticker(boolean run) { if (demo.recording) { - if (!multiplayer) { - G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); - } else { - G_WriteDemoExtraData(); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - G_WriteDemoTiccmd(&players[i].cmd, i); - } + G_WriteDemoExtraData(); + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + G_WriteDemoTiccmd(&players[i].cmd, i); } if (demo.playback) { - if (!multiplayer) { +#ifdef DEMO_COMPAT_100 + if (demo.version == 0x0001) + { G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); - } else { + } + else + { +#endif G_ReadDemoExtraData(); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) G_ReadDemoTiccmd(&players[i].cmd, i); +#ifdef DEMO_COMPAT_100 } +#endif } for (i = 0; i < MAXPLAYERS; i++) @@ -734,27 +737,24 @@ void P_Ticker(boolean run) if (metalrecording) G_WriteMetalTic(players[consoleplayer].mo); - if (multiplayer) + if (demo.recording) { - if (demo.recording) - { - G_WriteAllGhostTics(); + 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; - } - if (demo.playback) // Use Ghost data for consistency checks. - { - G_ConsAllGhostTics(); - } } - else + else if (demo.playback) // Use Ghost data for consistency checks. { - if (demo.recording) - G_WriteGhostTic(players[consoleplayer].mo, consoleplayer); - 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(); From bea8f51253c466b8e78208d3890d114e4a3bec99 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 7 Apr 2019 18:51:42 -0500 Subject: [PATCH 248/382] Fix record attack not recording + staff names load for all replay types --- src/g_game.c | 73 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 2f4f8531f..2bf89a9e4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3890,7 +3890,7 @@ void G_AfterIntermission(void) return; } - else if (demo.recording && demo.savemode != DSM_NOTSAVING) + else if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) G_SaveDemo(); if (modeattacking) // End the run. @@ -4037,7 +4037,7 @@ static void G_DoContinued(void) // when something new is added. void G_EndGame(void) { - if (demo.recording && demo.savemode != DSM_NOTSAVING) + if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) G_SaveDemo(); // Only do evaluation and credits in coop games. @@ -7411,7 +7411,6 @@ void G_DoPlayDemo(char *defdemoname) } slots[numslots] = p; numslots++; - if (modeattacking && numslots > 1) { snprintf(msg, 1024, M_GetText("%s is a record attack replay with multiple players, and is thus invalid.\n"), pdemoname); @@ -7752,53 +7751,62 @@ void G_UpdateStaffGhostName(lumpnum_t l) UINT16 ghostversion; UINT8 flags; - UINT8 totalfiles; - UINT8 md5sum[16]; - buffer = p = W_CacheLumpNum(l, PU_CACHE); // read demo header if (memcmp(p, DEMOHEADER, 12)) { goto fail; - } p += 12; // DEMOHEADER + } + + p += 12; // DEMOHEADER p++; // VERSION p++; // SUBVERSION + ghostversion = READUINT16(p); switch(ghostversion) { case DEMOVERSION: // latest always supported p += 64; // full demo title break; + #ifdef DEMO_COMPAT_100 case 0x0001: - CONS_Printf("You need to implement demo compat here, doofus! %s:%d\n", __FILE__, __LINE__); + break; #endif + // too old, cannot support. default: goto fail; } + p += 16; // demo checksum + if (memcmp(p, "PLAY", 4)) { goto fail; - } p += 4; // "PLAY" + } + + p += 4; // "PLAY" p += 2; // gamemap p += 16; // mapmd5 (possibly check for consistency?) + flags = READUINT8(p); - if (flags & DF_FILELIST) // file list - { - totalfiles = READUINT8(p); - for (; totalfiles > 0; --totalfiles) - { - SKIPSTRING(p) - READMEM(p, md5sum, 16) - } - } if (!(flags & DF_GHOST)) { goto fail; // we don't NEED to do it here, but whatever } + +#ifdef DEMO_COMPAT_100 + if (ghostversion != 0x0001) +#endif + p++; // Gametype + +#ifdef DEMO_COMPAT_100 + if (ghostversion != 0x0001) +#endif + G_SkipDemoExtraFiles(&p); + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 @@ -7812,9 +7820,34 @@ void G_UpdateStaffGhostName(lumpnum_t l) default: // 3 break; } + p += 4; // random seed - // Player name + +#ifdef DEMO_COMPAT_100 + if (ghostversion == 0x0001) + { + // Player name + M_Memcpy(dummystaffname, p,16); + dummystaffname[16] = '\0'; + goto fail; // Not really a failure but whatever + } +#endif + + p += 4; // Extrainfo location marker + + // Ehhhh don't need ghostversion here (?) so I'll reuse the var here + ghostversion = READUINT16(p); + while (ghostversion--) + { + p += 2; + SKIPSTRING(p); + p++; // stealth + } + + // Assert first player is in and then read name + if (READUINT8(p) != 0) + goto fail; M_Memcpy(dummystaffname, p,16); dummystaffname[16] = '\0'; @@ -8044,7 +8077,7 @@ boolean G_CheckDemoStatus(void) return true; } - if (demo.recording && demo.savemode != DSM_NOTSAVING) + if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) { G_SaveDemo(); return true; From 73153b7db9372d607ff80a39074b34a7215c2b3e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 8 Apr 2019 00:30:04 -0500 Subject: [PATCH 249/382] Support new-format ghosts or some bullshit like that maybe future fickle will add support for multiple ghosts from one replay for some sick memery but idgaf right now --- src/g_game.c | 202 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 164 insertions(+), 38 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 2bf89a9e4..6233fb99a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4889,7 +4889,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) } // Finds a skin with the closest stats if the expected skin doesn't exist. -static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) +static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) { INT32 i, closest_skin = 0; UINT8 closest_stats = UINT8_MAX, stat_diff; @@ -4904,6 +4904,13 @@ static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) } } + return closest_skin; +} + +static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) +{ + INT32 closest_skin = GetSkinNumClosestToStats(kartspeed, kartweight); + CONS_Printf("Using %s instead...\n", skins[closest_skin].name); SetPlayerSkinByNum(p, closest_skin); } @@ -5691,6 +5698,38 @@ void G_GhostTicker(void) { // Skip normal demo data. UINT8 ziptic = READUINT8(g->p); + +#ifdef DEMO_COMPAT_100 + if (g->version != 0x0001) + { +#endif + while (ziptic != DW_END) // Get rid of extradata stuff + { + if (ziptic == 0) // Only support player 0 info for now + { + ziptic = READUINT8(g->p); + if (ziptic & DXD_SKIN) + g->p += 18; // We _could_ read this info, but it shouldn't change anything in record attack... + if (ziptic & DXD_COLOR) + g->p += 16; // Same tbh + if (ziptic & DXD_NAME) + g->p += 16; // yea + if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + } + else if (ziptic == DW_RNG) + g->p += 4; // RNG seed + else + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + + ziptic = READUINT8(g->p); + } + + ziptic = READUINT8(g->p); // Back to actual ziptic stuff +#ifdef DEMO_COMPAT_100 + } +#endif + if (ziptic & ZT_FWD) g->p++; if (ziptic & ZT_SIDE) @@ -5708,6 +5747,19 @@ void G_GhostTicker(void) // Grab ghost data. ziptic = READUINT8(g->p); + +#ifdef DEMO_COMPAT_100 + if (g->version != 0x0001) + { +#endif + if (ziptic == 0xFF) + goto skippedghosttic; // Didn't write ghost info this frame + else if (ziptic != 0) + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + ziptic = READUINT8(g->p); +#ifdef DEMO_COMPAT_100 + } +#endif if (ziptic & GZT_XYZ) { g->oldmo.x = READFIXED(g->p); @@ -5848,6 +5900,17 @@ void G_GhostTicker(void) g->p += 12; // kartitem, kartamount, kartbumpers } +#ifdef DEMO_COMPAT_100 + if (g->version != 0x0001) + { +#endif + if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here. + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this +#ifdef DEMO_COMPAT_100 + } +#endif + +skippedghosttic: // Tick ghost colors (Super and Mario Invincibility flashing) switch(g->color) { @@ -7514,6 +7577,7 @@ void G_AddGhost(char *defdemoname) mapthing_t *mthing; UINT16 count, ghostversion; skin_t *ghskin = &skins[0]; + UINT8 kartspeed = UINT8_MAX, kartweight = UINT8_MAX; name[16] = '\0'; skin[16] = '\0'; @@ -7556,17 +7620,21 @@ void G_AddGhost(char *defdemoname) Z_Free(pdemoname); Z_Free(buffer); return; - } p += 12; // DEMOHEADER + } + + p += 12; // DEMOHEADER p++; // VERSION p++; // SUBVERSION + ghostversion = READUINT16(p); switch(ghostversion) { case DEMOVERSION: // latest always supported + p += 64; // title break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); + break; #endif // too old, cannot support. default: @@ -7575,6 +7643,7 @@ void G_AddGhost(char *defdemoname) Z_Free(buffer); return; } + M_Memcpy(md5, p, 16); p += 16; // demo checksum for (gh = ghosts; gh; gh = gh->next) if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum? @@ -7584,20 +7653,21 @@ void G_AddGhost(char *defdemoname) Z_Free(buffer); return; } + if (memcmp(p, "PLAY", 4)) { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname); Z_Free(pdemoname); Z_Free(buffer); return; - } p += 4; // "PLAY" + } + + p += 4; // "PLAY" p += 2; // gamemap p += 16; // mapmd5 (possibly check for consistency?) + flags = READUINT8(p); - if (flags & DF_FILELIST) - { - G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. - } + if (!(flags & DF_GHOST)) { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); @@ -7605,6 +7675,16 @@ void G_AddGhost(char *defdemoname) Z_Free(buffer); return; } + +#ifdef DEMO_COMPAT_100 + if (ghostversion != 0x0001) +#endif + p++; // gametype + +#ifdef DEMO_COMPAT_100 + if (ghostversion != 0x0001) +#endif + G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 @@ -7621,34 +7701,41 @@ void G_AddGhost(char *defdemoname) p += 4; // random seed - // Player name (TODO: Display this somehow if it doesn't match cv_playername!) - M_Memcpy(name, p,16); - p += 16; +#ifdef DEMO_COMPAT_100 + if (ghostversion == 0x0001) + { + // Player name (TODO: Display this somehow if it doesn't match cv_playername!) + M_Memcpy(name, p,16); + p += 16; - // Skin - M_Memcpy(skin, p,16); - p += 16; + // Skin + M_Memcpy(skin, p,16); + p += 16; - // Color - M_Memcpy(color, p,16); - p += 16; + // Color + M_Memcpy(color, p,16); + p += 16; - // Ghosts do not have a player structure to put this in. - p++; // charability - p++; // charability2 - p++; // actionspd - p++; // mindash - p++; // maxdash - // SRB2kart - p++; // kartspeed - p++; // kartweight - // - p++; // normalspeed - p++; // runspeed - p++; // thrustfactor - p++; // accelstart - p++; // acceleration - p += 4; // jumpfactor + // Ghosts do not have a player structure to put this in. + p++; // charability + p++; // charability2 + p++; // actionspd + p++; // mindash + p++; // maxdash + // SRB2kart + p++; // kartspeed + p++; // kartweight + // + p++; // normalspeed + p++; // runspeed + p++; // thrustfactor + p++; // accelstart + p++; // acceleration + p += 4; // jumpfactor + } + else +#endif + p += 4; // Extra data location reference // net var data count = READUINT16(p); @@ -7667,6 +7754,46 @@ void G_AddGhost(char *defdemoname) return; } +#ifdef DEMO_COMPAT_100 + if (ghostversion != 0x0001) + { +#endif + if (READUINT8(p) != 0) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + // Player name (TODO: Display this somehow if it doesn't match cv_playername!) + M_Memcpy(name, p, 16); + p += 16; + + // Skin + M_Memcpy(skin, p, 16); + p += 16; + + // Color + M_Memcpy(color, p, 16); + p += 16; + + p += 4; // score + + kartspeed = READUINT8(p); + kartweight = READUINT8(p); + + if (READUINT8(p) != 0xFF) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } +#ifdef DEMO_COMPAT_100 + } +#endif + for (i = 0; i < numskins; i++) if (!stricmp(skins[i].name,skin)) { @@ -7676,11 +7803,10 @@ void G_AddGhost(char *defdemoname) if (i == numskins) { - //@TODO nah this should fallback - CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid character.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; + if (kartspeed != UINT8_MAX && kartweight != UINT8_MAX) + ghskin = &skins[GetSkinNumClosestToStats(kartspeed, kartweight)]; + + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Invalid character. Falling back to %s.\n"), pdemoname, ghskin->name); } gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); From f573e4089d2ca318a4f1a50d86bae07ba06a8db2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 8 Apr 2019 00:45:19 -0500 Subject: [PATCH 250/382] Support RA time comparisons in new format I don't care enough about supporting old replays, and they're old anyway. Force-overwrite them. :) --- src/g_game.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 6233fb99a..6284ea663 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6772,10 +6772,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 2; // gamemap p += 16; // map md5 flags = READUINT8(p); // demoflags - if (flags & DF_FILELIST) // file list - { - G_SkipDemoExtraFiles(&p); - } + p++; // gametype + G_SkipDemoExtraFiles(&p); aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK); I_Assert(aflags); @@ -6820,7 +6818,10 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) break; #ifdef DEMO_COMPAT_100 case 0x0001: - I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__); + // Old replays gotta go :] + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' outdated version. It will be overwritten. Nyeheheh.\n"), oldname); + Z_Free(buffer); + return UINT8_MAX; #endif // too old, cannot support. default: @@ -6838,10 +6839,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 2; // gamemap p += 16; // mapmd5 flags = READUINT8(p); - if (flags & DF_FILELIST) // file list - { - G_SkipDemoExtraFiles(&p); - } + p++; // gametype + G_SkipDemoExtraFiles(&p); if (!(flags & aflags)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); From 03c27101df37246c7718b243d60c3b8080e11d31 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 8 Apr 2019 15:48:20 -0700 Subject: [PATCH 251/382] "NEWPING" might as well be the only ping --- src/d_clisrv.c | 16 ------------ src/d_clisrv.h | 8 ------ src/d_net.c | 66 ++++---------------------------------------------- src/d_netcmd.c | 4 --- src/d_netcmd.h | 2 -- src/doomdef.h | 3 --- src/doomstat.h | 2 -- src/m_menu.c | 2 -- 8 files changed, 5 insertions(+), 98 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e227ce2ed..4f5e762d3 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -91,12 +91,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) @@ -3094,12 +3092,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; @@ -3172,10 +3168,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) @@ -4630,7 +4624,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) @@ -4660,7 +4653,6 @@ FILESTAMP } break; -#endif case PT_SERVERCFG: break; case PT_FILEFRAGMENT: @@ -5298,7 +5290,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. @@ -5382,11 +5373,9 @@ static inline void PingUpdate(void) pingmeasurecount = 1; //Reset count } -#endif static tic_t gametime = 0; -#ifdef NEWPING static void UpdatePingTable(void) { INT32 i; @@ -5401,7 +5390,6 @@ static void UpdatePingTable(void) pingmeasurecount++; } } -#endif // Handle timeouts to prevent definitive freezes from happenning static void HandleNodeTimeouts(void) @@ -5426,9 +5414,7 @@ void NetKeepAlive(void) if (realtics <= 0) // nothing new to update return; -#ifdef NEWPING UpdatePingTable(); -#endif if (server) CL_SendClientKeepAlive(); @@ -5475,9 +5461,7 @@ void NetUpdate(void) gametime = nowtime; -#ifdef NEWPING UpdatePingTable(); -#endif if (client) maketic = neededtic; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index f3a9011eb..f4db85129 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -93,9 +93,7 @@ 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_PING, // Packet sent to tell clients the other client's latency to server. -#endif NUMPACKETTYPE } packettype_t; @@ -473,9 +471,7 @@ typedef struct msaskinfo_pak msaskinfo; // 22 bytes plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) -#ifdef NEWPING UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes -#endif } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; @@ -509,9 +505,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 @@ -536,12 +530,10 @@ extern SINT8 servernode; 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 diff --git a/src/d_net.c b/src/d_net.c index 9f7199673..9cff9278a 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -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,(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) @@ -1412,28 +1372,12 @@ boolean D_CheckNetGame(void) void Command_Ping_f(void) { -#ifndef NEWPING - if(server) + INT32 i; + for (i = 0; i < MAXPLAYERS;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 + if (playeringame[i] && i != 0) + CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]); } - else - CONS_Printf(M_GetText("Only the server can use this.\n")); -#endif } void D_CloseConnection(void) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 08bf33185..0173b5db4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -434,7 +434,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 +444,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}; @@ -674,11 +672,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); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 166c5e008..e6c327abf 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -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; diff --git a/src/doomdef.h b/src/doomdef.h index 6664ff51a..51052a0b9 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -601,9 +601,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 diff --git a/src/doomstat.h b/src/doomstat.h index 834b3a7cf..4b0c2e3e8 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -543,9 +543,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]; diff --git a/src/m_menu.c b/src/m_menu.c index 3ad076ff7..afb085c4e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2331,10 +2331,8 @@ static void M_ChangeCvar(INT32 choice) choice *= (TICRATE/7); else if (cv == &cv_maxsend) choice *= 512; -#ifdef NEWPING else if (cv == &cv_maxping) choice *= 50; -#endif #endif CV_AddValue(cv,choice); } From 2fa20751e99d1046213daa7c7e282bf32f0a4f44 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 8 Apr 2019 15:57:23 -0700 Subject: [PATCH 252/382] Replace ping command with a condensed and sorted version --- src/d_net.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/src/d_net.c b/src/d_net.c index 9cff9278a..94b11d518 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1370,13 +1370,72 @@ 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) { + struct pingcell pingv[MAXPLAYERS]; + INT32 pingc; + + int name_width = 0; + int ms_width = 0; + + int n; INT32 i; - for (i = 0; i < MAXPLAYERS;i++) + + pingc = 0; + for (i = 1; i < MAXPLAYERS; ++i) + if (playeringame[i]) { - if (playeringame[i] && i != 0) - CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]); + 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]); } } From 25f55b63515c33f273c5f30ee4e3faa468a69e4f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 8 Apr 2019 23:21:11 -0500 Subject: [PATCH 253/382] Add VHS pause/rewind effect --- src/d_main.c | 6 +++++ src/d_netcmd.c | 2 ++ src/screen.c | 4 ++++ src/screen.h | 2 +- src/v_video.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/v_video.h | 3 +++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index d1a820c8f..6feedb18e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -571,6 +571,9 @@ static void D_Display(void) if (demo.rewinding) V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM); + if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1))) + V_DrawVhsEffect(demo.rewinding); + // vid size change is now finished if it was on... vid.recalc = 0; @@ -628,6 +631,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 } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 21a8e2a36..36774a80f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -932,6 +932,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); diff --git a/src/screen.c b/src/screen.c index 4de2abd05..4cb8bac5d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -59,6 +59,8 @@ INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}}; +static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}}; + //added : 03-02-98: default screen mode, as loaded/saved in config #ifdef WII consvar_t cv_scr_width = {"scr_width", "640", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -70,6 +72,8 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_vhseffect = {"vhspause", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_shittyscreen = {"televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static void SCR_ChangeFullscreen (void); diff --git a/src/screen.h b/src/screen.h index 5b4a8e583..2e4d29b95 100644 --- a/src/screen.h +++ b/src/screen.h @@ -158,7 +158,7 @@ extern INT32 setmodeneeded; // mode number to set if needed, or 0 extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen; +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen; // wait for page flipping to end or not extern consvar_t cv_vidwait; diff --git a/src/v_video.c b/src/v_video.c index dfad4c3a4..16d784f44 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1214,6 +1214,65 @@ void V_DrawPatchFill(patch_t *pat) } } +void V_DrawVhsEffect(boolean rewind) +{ + static fixed_t upbary = 100, downbary = 150; + + UINT8 *buf = screens[0], *tmp = screens[4]; + UINT16 x, y; + UINT32 pos = 0; + + UINT8 *normalmapstart = ((UINT8 *)transtables + (8<>1; + + if (rewind) + V_DrawVhsEffect(false); // experimentation + + upbary -= vid.dupy * (rewind ? 3 : 1.8f); + downbary += vid.dupy * (rewind ? 2 : 1); + if (upbary < -barsize) upbary = vid.height; + if (downbary > vid.height) downbary = -barsize; + + for (y = 0; y < vid.height; y++) + { + randommask = 0x0700; + thismapstart = normalmapstart; + offs = 0; + + if (y >= upbary && y < upbary+barsize) + { + //randommask = 0x0300; + thismapstart -= (2<= downbary && y < downbary+barsize) + { + //randommask = 0x0300; + //thismapstart = barmapstart; + thismapstart -= (2< 0) offs = 0; + + for (x = 0; x < vid.rowbytes; x++, pos++) + tmp[pos] = thismapstart[/*(M_RandomFixed()&randommask)|*/buf[pos+offs]]; + } + (void)randommask; + + memcpy(buf, tmp, vid.rowbytes*vid.height); +} + // // Fade all the screen buffer, so that the menu is more readable, // especially now that we use the small hufont in the menus... diff --git a/src/v_video.h b/src/v_video.h index c48c7a118..c8485c179 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -153,6 +153,9 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c); // fill a box with a flat as a pattern void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); +// draw wobbly VHS pause stuff +void V_DrawVhsEffect(boolean rewind); + // fade down the screen buffer before drawing the menu over void V_DrawFadeScreen(UINT16 color, UINT8 strength); From b98639e8520067bd64daa71added876ee129f9fb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 01:09:13 -0500 Subject: [PATCH 254/382] Potentially apply VHS distortion semi-transparently? Pros: fuckin SMOOTH effect especially for 256-color sw Cons: might lose the intended color distortion, maybe not a great idea for FPS Conclusion: put it behind an ifdef for now --- src/v_video.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 16d784f44..646e60159 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1223,7 +1223,9 @@ void V_DrawVhsEffect(boolean rewind) UINT32 pos = 0; UINT8 *normalmapstart = ((UINT8 *)transtables + (8<= upbary && y < upbary+barsize) { - //randommask = 0x0300; thismapstart -= (2<= downbary && y < downbary+barsize) { - //randommask = 0x0300; - //thismapstart = barmapstart; thismapstart -= (2< 0) offs = 0; for (x = 0; x < vid.rowbytes; x++, pos++) - tmp[pos] = thismapstart[/*(M_RandomFixed()&randommask)|*/buf[pos+offs]]; + { + tmp[pos] = thismapstart[buf[pos+offs]]; +#ifdef HQ_VHS + tmp[pos] = tmapstart[buf[pos]<<8 | tmp[pos]]; +#endif + } } - (void)randommask; memcpy(buf, tmp, vid.rowbytes*vid.height); } From 5535f8936f3db29d3545a57a08bd096e6d716c0e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 01:18:10 -0500 Subject: [PATCH 255/382] Unused var --- src/v_video.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 646e60159..83bfff730 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1227,7 +1227,6 @@ void V_DrawVhsEffect(boolean rewind) UINT8 *tmapstart = ((UINT8 *)transtables + (6< Date: Tue, 9 Apr 2019 19:34:34 +0100 Subject: [PATCH 256/382] Turn the INT8's into SINT8's --- src/m_menu.c | 2 +- src/v_video.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d8d8f4a13..c74614267 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5126,7 +5126,7 @@ menudemo_t *demolist; #define DF_ENCORE 0x40 static INT16 replayScrollTitle = 0; -static INT8 replayScrollDelay = TICRATE, replayScrollDir = 1; +static SINT8 replayScrollDelay = TICRATE, replayScrollDir = 1; static void PrepReplayList(void) { diff --git a/src/v_video.c b/src/v_video.c index 83bfff730..2d8ca8120 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1227,7 +1227,7 @@ void V_DrawVhsEffect(boolean rewind) UINT8 *tmapstart = ((UINT8 *)transtables + (6< Date: Tue, 9 Apr 2019 20:15:35 +0100 Subject: [PATCH 257/382] Z_Free not free. --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 6284ea663..37aa4a5e6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7048,7 +7048,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) } // I think that's everything we need? - free(infobuffer); + Z_Free(infobuffer); } // From c4ee58cfab4b61ac0c87b9136903c1f05e703aee Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 23:00:39 -0500 Subject: [PATCH 258/382] Only calculate vfx every other row to try to improve performance --- src/v_video.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 83bfff730..59522cb38 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1219,8 +1219,8 @@ void V_DrawVhsEffect(boolean rewind) static fixed_t upbary = 100, downbary = 150; UINT8 *buf = screens[0], *tmp = screens[4]; - UINT16 x, y; - UINT32 pos = 0; + UINT16 y; + UINT32 x, pos = 0; UINT8 *normalmapstart = ((UINT8 *)transtables + (8< vid.height) downbary = -barsize; - for (y = 0; y < vid.height; y++) + for (y = 0; y < vid.height; y+=2) { thismapstart = normalmapstart; offs = 0; @@ -1260,9 +1260,9 @@ void V_DrawVhsEffect(boolean rewind) // lazy way to avoid crashes if (y == 0 && offs < 0) offs = 0; - else if (y == vid.height-1 && offs > 0) offs = 0; + else if (y >= vid.height-2 && offs > 0) offs = 0; - for (x = 0; x < vid.rowbytes; x++, pos++) + for (x = pos+vid.rowbytes*2; pos < x; pos++) { tmp[pos] = thismapstart[buf[pos+offs]]; #ifdef HQ_VHS From 273db8f5c18b2bb0eabad406e2df64c211b56788 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 23:55:25 -0500 Subject: [PATCH 259/382] Fix thrown items desyncing during frame advance --- src/g_game.c | 10 +++++++--- src/p_tick.c | 11 +++++++++++ src/p_user.c | 13 +++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 37aa4a5e6..0dd24ecb2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2407,6 +2407,7 @@ void G_Ticker(boolean run) buf = gametic % BACKUPTICS; + if (!demo.playback) // read/write demo and check turbo cheat for (i = 0; i < MAXPLAYERS; i++) { @@ -2414,15 +2415,18 @@ void G_Ticker(boolean run) if (playeringame[i]) { + //@TODO all this throwdir stuff shouldn't be here! But it stays for now to maintain 1.0.4 compat... + // Remove for 1.1! + // SRB2kart // Save the dir the player is holding // to allow items to be thrown forward or backward. if (cmd->buttons & BT_FORWARD) - players[i].kartstuff[k_throwdir] = 1; + players[i].kartstuff[k_throwdir] = 1; else if (cmd->buttons & BT_BACKWARD) - players[i].kartstuff[k_throwdir] = -1; + players[i].kartstuff[k_throwdir] = -1; else - players[i].kartstuff[k_throwdir] = 0; + players[i].kartstuff[k_throwdir] = 0; G_CopyTiccmd(cmd, &netcmds[buf][i], 1); diff --git a/src/p_tick.c b/src/p_tick.c index a5f6313b3..038d00a2a 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -628,7 +628,18 @@ void P_Ticker(boolean run) 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 diff --git a/src/p_user.c b/src/p_user.c index 509cc4d76..26ee9f8c4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8779,6 +8779,19 @@ void P_PlayerThink(player_t *player) cmd = &player->cmd; + //@TODO This fixes a one-tic latency on direction handling, AND makes behavior consistent while paused, but is not BC with 1.0.4. Do this for 1.1! +#if 0 + // SRB2kart + // Save the dir the player is holding + // to allow items to be thrown forward or backward. + if (cmd->buttons & BT_FORWARD) + player->kartstuff[k_throwdir] = 1; + else if (cmd->buttons & BT_BACKWARD) + player->kartstuff[k_throwdir] = -1; + else + player->kartstuff[k_throwdir] = 0; +#endif + // Add some extra randomization. if (cmd->forwardmove) P_RandomFixed(); From 65e272f89287ff94fb3805edcb31da8c08786dde Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 10 Apr 2019 09:10:09 -0500 Subject: [PATCH 260/382] Proposal: VHS effect over the replay hut background? --- src/m_menu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index c74614267..7a4ea6786 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5435,6 +5435,9 @@ static void M_DrawReplayHut(void) V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + if (cv_vhseffect.value) + V_DrawVhsEffect(false); + // Draw menu choices x = currentMenu->x; y = currentMenu->y; From aec9e721dc3438a755d32dbc5f50cdddf6ca504d Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 12 Apr 2019 00:35:35 -0500 Subject: [PATCH 261/382] Generic model terminology --- src/hardware/hw_main.c | 6 +++--- src/hardware/hw_main.h | 2 +- src/hardware/hw_md2.c | 44 +++++++++++++++++++++--------------------- src/m_menu.c | 2 +- src/r_main.c | 2 +- src/v_video.c | 2 +- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5c09a0bca..af0546dc1 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5261,14 +5261,14 @@ static void HWR_DrawSprites(void) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { // 8/1/19: Only don't display player models if no default SPR_PLAY is found. - if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && (md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f))) + if (!cv_grmdls.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && (md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f))) HWR_DrawSprite(spr); else HWR_DrawMD2(spr); } else { - if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) HWR_DrawSprite(spr); else HWR_DrawMD2(spr); @@ -5435,7 +5435,7 @@ static void HWR_ProjectSprite(mobj_t *thing) tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); // thing is behind view plane? - if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear + if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmdls.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear return; // The above can stay as it works for cutting sprites that are too close diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 8c9590e9c..335240c5c 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -79,7 +79,7 @@ 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_grfog; extern consvar_t cv_grfogcolor; extern consvar_t cv_grfogdensity; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 07ccd3d8a..d217f4094 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -164,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); @@ -297,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) @@ -492,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; } @@ -510,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. @@ -545,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; @@ -564,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; } @@ -603,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; @@ -616,14 +616,14 @@ 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; } @@ -867,7 +867,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) md2_t *md2; UINT8 color[4]; - if (!cv_grmd2.value) + if (!cv_grmdls.value) return; if (spr->precip) @@ -951,8 +951,8 @@ 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) @@ -1034,7 +1034,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; #ifdef USE_MODEL_NEXTFRAME - if (cv_grmd2.value == 1 && tics <= durs) + 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) diff --git a/src/m_menu.c b/src/m_menu.c index 3ad076ff7..9a98bb73a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1217,7 +1217,7 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 90}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmd2, 105}, + {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmdls, 105}, {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 115}, #endif }; diff --git a/src/r_main.c b/src/r_main.c index 1a72d6165..9e355a09c 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1569,7 +1569,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grcoronas); CV_RegisterVar(&cv_grcoronasize); #endif - CV_RegisterVar(&cv_grmd2); + CV_RegisterVar(&cv_grmdls); #endif #ifdef HWRENDER diff --git a/src/v_video.c b/src/v_video.c index 16d39e1d0..bac0faea5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -79,7 +79,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0 //static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; // console variables in development -consvar_t cv_grmd2 = {"gr_md2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grmdls = {"gr_mdls", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif const UINT8 gammatable[5][256] = From c7be2769a2570a849bd596f70ab4e2fd6682742c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 12 Apr 2019 00:46:52 -0500 Subject: [PATCH 262/382] Allow argument substitution in aliases --- src/command.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/command.c b/src/command.c index a5d45bc1e..543df6ce9 100644 --- a/src/command.c +++ b/src/command.c @@ -537,10 +537,48 @@ 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 != '\0') + { + if (*seek == '$') + { + 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; + } + else + seek++; + } + memcpy(write, read, seek-read); + write += seek-read; + *write = '\0'; + + recursion++; + COM_BufInsertText(buf); + } return; } } From 9d408b474b50b68244f78c72a8ecc9114e9b00fb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 10:16:54 -0500 Subject: [PATCH 263/382] Use strchr? --- src/command.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/command.c b/src/command.c index 543df6ce9..8e2d0037e 100644 --- a/src/command.c +++ b/src/command.c @@ -543,38 +543,31 @@ static void COM_ExecuteString(char *ptext) char buf[1024]; char *write = buf, *read = a->value, *seek = read; - while (*seek != '\0') + while ((seek = strchr(seek, '$')) != NULL) { - if (*seek == '$') + memcpy(write, read, seek-read); + write += seek-read; + + seek++; + + if (*seek >= '1' && *seek <= '9') { - memcpy(write, read, seek-read); - write += seek-read; - + 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++; - - 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; } else - seek++; + { + *write = '$'; + write++; + } + + read = seek; } - memcpy(write, read, seek-read); - write += seek-read; - *write = '\0'; + WRITESTRING(write, read); recursion++; COM_BufInsertText(buf); From 0318bf7116e50cc41c2f9967e6739d4de25607c2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 10:25:56 -0500 Subject: [PATCH 264/382] Preserve quote and etc in aliases --- src/command.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/command.c b/src/command.c index 8e2d0037e..7d7a357a8 100644 --- a/src/command.c +++ b/src/command.c @@ -594,8 +594,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) { @@ -608,19 +606,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. From 1ba5412bfedc0a91e652751ca4359f4141bfab4e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 14:22:48 -0500 Subject: [PATCH 265/382] Fix being able to carry rewind state where it shouldn't be --- src/g_game.c | 9 ++++++++- src/m_menu.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 0dd24ecb2..539392136 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1956,7 +1956,14 @@ boolean G_Responder(event_t *ev) ) { paused = !paused; - if (paused) + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = true; + S_PauseAudio(); + } + else if (paused) S_PauseAudio(); else S_ResumeAudio(); diff --git a/src/m_menu.c b/src/m_menu.c index 7a4ea6786..cbbff403b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5184,6 +5184,8 @@ void M_ReplayHut(INT32 choice) M_SetupNextMenu(&MISC_ReplayHutDef); G_SetGamestate(GS_TIMEATTACK); + demo.rewinding = false; + S_ChangeMusicInternal("replst", true); } From 830b608a1573bba75d864dcb3c7fb682a5657453 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 14:42:15 -0500 Subject: [PATCH 266/382] Playback menu improvements --- src/m_menu.c | 70 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cbbff403b..970630a50 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -573,8 +573,9 @@ static menuitem_t PlaybackMenu[] = {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20}, + {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 72}, @@ -591,8 +592,9 @@ typedef enum playback_hide, playback_rewind, playback_pause, - playback_resume, playback_fastforward, + playback_backframe, + playback_resume, playback_advanceframe, playback_viewcount, playback_view1, @@ -5719,13 +5721,19 @@ static void M_DrawPlaybackMenu(void) // Toggle items if (paused && !demo.rewinding) { - PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_DISABLED; - PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_CALL|IT_STRING; + PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = PlaybackMenu[playback_rewind].status = IT_DISABLED; + PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING; + + if (itemOn >= playback_rewind && itemOn <= playback_fastforward) + itemOn += playback_backframe - playback_rewind; } else { - PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_CALL|IT_STRING; - PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_DISABLED; + PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING; + PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = PlaybackMenu[playback_backframe].status = IT_DISABLED; + + if (itemOn >= playback_backframe && itemOn <= playback_advanceframe) + itemOn -= playback_backframe - playback_rewind; } if (modeattacking) @@ -5789,7 +5797,50 @@ static void M_DrawPlaybackMenu(void) V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, (i == itemOn) ? activemap : inactivemap); if (i == itemOn) + { V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + + if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS) + { + char *str; + + if (!(i == playback_viewcount && splitscreen == 3)) + V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 28 - (skullAnimCounter/5), + '\x1A' | highlightflags, false); // up arrow + + if (!(i == playback_viewcount && splitscreen == 0)) + V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 48 + (skullAnimCounter/5), + '\x1B' | highlightflags, false); // down arrow + + switch (i) + { + case playback_viewcount: + str = va("%d", splitscreen+1); + break; + + case playback_view1: + str = player_names[displayplayer]; + break; + + case playback_view2: + str = player_names[secondarydisplayplayer]; + break; + + case playback_view3: + str = player_names[thirddisplayplayer]; + break; + + case playback_view4: + str = player_names[fourthdisplayplayer]; + break; + + default: // shouldn't ever be reached but whatever + continue; + } + + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_ALLOWLOWERCASE|highlightflags, str); + } + } } } @@ -5829,19 +5880,12 @@ static void M_PlaybackPause(INT32 choice) { G_ConfirmRewind(leveltime); paused = true; - itemOn = playback_resume; S_PauseAudio(); } else if (paused) - { - itemOn = playback_resume; S_PauseAudio(); - } else - { - itemOn = playback_pause; S_ResumeAudio(); - } CV_SetValue(&cv_playbackspeed, 1); } From 5e703807eb543536cfc52e53c4eb353d998441f6 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 15:23:23 -0500 Subject: [PATCH 267/382] Change color of active playback items --- src/m_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 970630a50..484c653cb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5792,12 +5792,15 @@ static void M_DrawPlaybackMenu(void) icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding)) - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SILVER, GTC_MENUCACHE)); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); else V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, (i == itemOn) ? activemap : inactivemap); if (i == itemOn) { + V_DrawCharacter(currentMenu->x + currentMenu->menuitems[i].alphaKey + 4, currentMenu->y + 14, + '\x1A' | highlightflags, false); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS) From 5b1c3efb863fdb9f52188cc3ad416207d1d9c4db Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 15:23:31 -0500 Subject: [PATCH 268/382] Temporarily disable Extra Options menu --- src/m_menu.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 484c653cb..c6a93bc41 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -584,8 +584,9 @@ static menuitem_t PlaybackMenu[] = {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3", M_PlaybackAdjustView, 120}, {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 136}, - {IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 156}, - {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, + //{IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 156}, + //{IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, + {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 156}, }; typedef enum { @@ -601,7 +602,7 @@ typedef enum playback_view2, playback_view3, playback_view4, - playback_moreoptions, + //playback_moreoptions, playback_quit } playback_e; @@ -1704,7 +1705,8 @@ menu_t PlaybackMenuDef = { NULL, PlaybackMenu, M_DrawPlaybackMenu, - BASEVIDWIDTH/2 - 94, 2, + //BASEVIDWIDTH/2 - 94, 2, + BASEVIDWIDTH/2 - 88, 2, 0, NULL }; @@ -5741,10 +5743,12 @@ static void M_DrawPlaybackMenu(void) for (i = playback_viewcount; i <= playback_view4; i++) PlaybackMenu[i].status = IT_DISABLED; - PlaybackMenu[playback_moreoptions].alphaKey = 72; - PlaybackMenu[playback_quit].alphaKey = 88; + //PlaybackMenu[playback_moreoptions].alphaKey = 72; + //PlaybackMenu[playback_quit].alphaKey = 88; + PlaybackMenu[playback_quit].alphaKey = 72; - currentMenu->x = BASEVIDWIDTH/2 - 52; + //currentMenu->x = BASEVIDWIDTH/2 - 52; + currentMenu->x = BASEVIDWIDTH/2 - 44; } else { @@ -5753,10 +5757,12 @@ static void M_DrawPlaybackMenu(void) for (i = splitscreen+1; i < 4; i++) PlaybackMenu[playback_view1+i].status = IT_DISABLED; - PlaybackMenu[playback_moreoptions].alphaKey = 156; - PlaybackMenu[playback_quit].alphaKey = 172; + //PlaybackMenu[playback_moreoptions].alphaKey = 156; + //PlaybackMenu[playback_quit].alphaKey = 172; + PlaybackMenu[playback_quit].alphaKey = 156; - currentMenu->x = BASEVIDWIDTH/2 - 94; + //currentMenu->x = BASEVIDWIDTH/2 - 94; + currentMenu->x = BASEVIDWIDTH/2 - 88; } // wip From 7c75397b6755af418338c165325578a0ef9aa1e8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 17:08:04 -0500 Subject: [PATCH 269/382] Fix writing corrupt standings that break replay hut --- src/g_game.c | 3 +++ src/y_inter.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 539392136..85077c7bf 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7056,6 +7056,9 @@ void G_LoadDemoInfo(menudemo_t *pdemo) pdemo->standings[count].timeorscore = READUINT32(extrainfo_p); count++; + + if (count >= MAXPLAYERS) + break; //@TODO still cycle through the rest of these if extra demo data is ever used } // I think that's everything we need? diff --git a/src/y_inter.c b/src/y_inter.c index 4fce58cc2..f37084282 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -304,7 +304,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) players[i].score += data.match.increase[i]; } - if (demo.recording) + if (demo.recording && !rankingsmode) G_WriteStanding( data.match.pos[data.match.numplayers], data.match.name[data.match.numplayers], From b28221bdb2dc92fd285a964d32be54e7bac3b49f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 14 Apr 2019 15:17:47 -0700 Subject: [PATCH 270/382] Don't count down wait timer when executing a command --- src/command.c | 20 ++++++++++++++------ src/command.h | 3 +++ src/d_clisrv.c | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/command.c b/src/command.c index ba0095e07..edc04bed1 100644 --- a/src/command.c +++ b/src/command.c @@ -148,6 +148,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) @@ -157,12 +171,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 diff --git a/src/command.h b/src/command.h index e6767825c..4682ba4a4 100644 --- a/src/command.h +++ b/src/command.h @@ -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); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a0f9f40ab..1b0cb523f 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4563,7 +4563,7 @@ void TryRunTics(tic_t realtics) if (realtics >= 1) { - COM_BufExecute(); + COM_BufTicker(); if (mapchangepending) D_MapChange(-1, 0, ultimatemode, false, 2, false, fromlevelselect); // finish the map change } From 7911558ebac4d111ed6a3a727e8edcb53c685ee9 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 23:17:12 -0500 Subject: [PATCH 271/382] Add scroll bar to replay hut --- src/m_menu.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index c6a93bc41..6d9ccaf15 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5497,7 +5497,7 @@ static void M_DrawReplayHut(void) V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[i].text); } - y += currentMenu->menuitems[currentMenu->numitems-1].alphaKey; + y += currentMenu->menuitems[replaylistitem].alphaKey; for (i = 0; i < (INT16)sizedirmenu; i++) { @@ -5554,6 +5554,14 @@ static void M_DrawReplayHut(void) V_DrawString(localx, localy, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE, demolist[i].title); } + // Draw scrollbar + y = sizedirmenu*10 + currentMenu->menuitems[replaylistitem].alphaKey + 30; + if (y > SCALEDVIEWHEIGHT-80) + { + V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|239); + V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|229); + } + // Draw the cursor V_DrawScaledPatch(currentMenu->x - 24, cursory, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName("M_CURSOR", PU_CACHE)); From a6879cca69bf56f6a67b618405e9375345103945 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 23:22:24 -0500 Subject: [PATCH 272/382] Keep playback menu bar on the top in non-green reses --- src/m_menu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6d9ccaf15..4eb184462 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5806,16 +5806,16 @@ static void M_DrawPlaybackMenu(void) icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding)) - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); else - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, (i == itemOn) ? activemap : inactivemap); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); if (i == itemOn) { V_DrawCharacter(currentMenu->x + currentMenu->menuitems[i].alphaKey + 4, currentMenu->y + 14, - '\x1A' | highlightflags, false); + '\x1A' | V_SNAPTOTOP|highlightflags, false); - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS) { @@ -5823,11 +5823,11 @@ static void M_DrawPlaybackMenu(void) if (!(i == playback_viewcount && splitscreen == 3)) V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 28 - (skullAnimCounter/5), - '\x1A' | highlightflags, false); // up arrow + '\x1A' | V_SNAPTOTOP|highlightflags, false); // up arrow if (!(i == playback_viewcount && splitscreen == 0)) V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 48 + (skullAnimCounter/5), - '\x1B' | highlightflags, false); // down arrow + '\x1B' | V_SNAPTOTOP|highlightflags, false); // down arrow switch (i) { @@ -5855,7 +5855,7 @@ static void M_DrawPlaybackMenu(void) continue; } - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_ALLOWLOWERCASE|highlightflags, str); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_SNAPTOTOP|V_ALLOWLOWERCASE|highlightflags, str); } } } From fcc188ec0b184529d97abe8efdf0e5b7c6071eaa Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 23:52:03 -0500 Subject: [PATCH 273/382] Show player names on the bottom in 4p Also adjust margins to better match other HUD stuff --- src/st_stuff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index acb01fb69..bbfa4c047 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1919,13 +1919,13 @@ static void ST_overlayDrawer(void) { char name[MAXPLAYERNAME+12]; - INT32 y = (stplyr == &players[displayplayer]) ? 8 : BASEVIDHEIGHT/2-16; + INT32 y = (stplyr == &players[displayplayer]) ? 4 : BASEVIDHEIGHT/2-12; sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name); } else if (splitscreen) { - V_DrawCenteredThinString(BASEVIDWIDTH/4, 4, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP), player_names[stplyr-players]); + V_DrawCenteredThinString((vid.width/vid.dupx)/4, BASEVIDHEIGHT/2 - 12, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT), player_names[stplyr-players]); } } From 877e1499084e3dd0fe377e180a43cf77b53a1018 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 16 Apr 2019 15:05:09 -0400 Subject: [PATCH 274/382] Don't enable UPnP support if NONET is defined. --- src/win32/Makefile.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index def2fe682..1880abf18 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -24,8 +24,10 @@ ifndef NOASM USEASM=1 endif +ifndef NONET ifndef MINGW64 #miniupnc is broken with MINGW64 HAVE_MINIUPNPC=1 +endif endif OPTS=-DSTDC_HEADERS From 7253f0e499df39626a40e940e6206f99eeaaa47c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:09:10 -0500 Subject: [PATCH 275/382] Strip out things that limit wad files added by filename --- src/d_main.c | 4 +--- src/d_netcmd.c | 11 +---------- src/d_netfil.c | 3 --- src/filesrch.c | 2 -- src/filesrch.h | 3 --- src/m_menu.c | 5 +---- src/w_wad.c | 20 +------------------- 7 files changed, 4 insertions(+), 44 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 84d5a6f32..636356f74 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -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" @@ -1257,8 +1257,6 @@ void D_SRB2Main(void) #endif //ifndef DEVELOP - mainwadstally = packetsizetally; - // // search for maps // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 08bf33185..7ac146678 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4045,14 +4045,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); @@ -4167,8 +4159,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); diff --git a/src/d_netfil.c b/src/d_netfil.c index 99a058403..4e6e76a1d 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -373,9 +373,6 @@ INT32 CL_CheckFiles(void) return 1; } - // See W_LoadWadFile in w_wad.c - packetsize = packetsizetally; - for (i = 1; i < fileneedednum; i++) { CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); diff --git a/src/filesrch.c b/src/filesrch.c index 0276e1c90..78917f738 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -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, diff --git a/src/filesrch.h b/src/filesrch.h index 01a528482..1a94aaa1b 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -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, diff --git a/src/m_menu.c b/src/m_menu.c index 3ad076ff7..7ecf8cd4c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4664,10 +4664,7 @@ static void M_DrawAddons(void) y = FRACUNIT; else { - x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< y) - y = x; + y = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< FRACUNIT) // happens because of how we're shrinkin' it a little y = FRACUNIT; } diff --git a/src/w_wad.c b/src/w_wad.c index 915701840..da82a276d 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -652,7 +652,6 @@ UINT16 W_InitFile(const char *filename) restype_t type; UINT16 numlumps = 0; size_t i; - size_t packetsize; UINT8 md5sum[16]; boolean important; @@ -684,24 +683,7 @@ UINT16 W_InitFile(const char *filename) if ((handle = W_OpenWadFile(&filename, true)) == NULL) return INT16_MAX; - // Check if wad files will overflow fileneededbuffer. Only the filename part - // is send in the packet; cf. - // see PutFileNeeded in d_netfil.c - if ((important = !W_VerifyNMUSlumps(filename))) - { - packetsize = packetsizetally + nameonlylength(filename) + 22; - - if (packetsize > MAXFILENEEDED*sizeof(UINT8)) - { - CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); - refreshdirmenu |= REFRESHDIR_MAX; - if (handle) - fclose(handle); - return INT16_MAX; - } - - packetsizetally = packetsize; - } + important = !W_VerifyNMUSlumps(filename); #ifndef NOMD5 // From 8aa719108dfa40d5f59a11a23cae5c7c4bebb239 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:29:27 -0500 Subject: [PATCH 276/382] Paginate PutFileNeeded --- src/d_clisrv.c | 6 +----- src/d_clisrv.h | 2 ++ src/d_netfil.c | 33 ++++++++++++++++++++++++++++----- src/d_netfil.h | 3 ++- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e227ce2ed..86ebb3455 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1433,7 +1433,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)); } @@ -2022,10 +2022,6 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) } cl_mode = CL_ASKDOWNLOADFILES; - - // no problem if can't send packet, we will retry later - //if (CL_SendRequestFile()) - // cl_mode = CL_DOWNLOADFILES; } } else diff --git a/src/d_clisrv.h b/src/d_clisrv.h index f3a9011eb..a4324d690 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -376,6 +376,8 @@ typedef struct #define MAXSERVERNAME 32 #define MAXFILENEEDED 915 +#define MAXFILENEEDEDPAGES MAX_WADFILES +#define FILENEEDED_MORE 0x80 // This packet is too large typedef struct { diff --git a/src/d_netfil.c b/src/d_netfil.c index 4e6e76a1d..efb0fb817 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -101,25 +101,49 @@ char downloaddir[512] = "DOWNLOAD"; INT32 lastfilenum = -1; #endif +UINT16 fileneededpages = 0; +static size_t fileneededpagestart[MAXFILENEEDEDPAGES]; + /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. * Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c * */ -UINT8 *PutFileNeeded(void) +UINT8 *PutFileNeeded(UINT16 page) { - size_t i, count = 0; + size_t i; + UINT8 count = 0; UINT8 *p = netbuffer->u.serverinfo.fileneeded; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - for (i = 0; i < numwadfiles; i++) + if (page > fileneededpages) + I_Error("Fileneeded page %d accessed before a prior page", page); + else if (page == 0) + { + fileneededpages = 0; + memset(fileneededpagestart, 0, sizeof(fileneededpagestart)); // ??? I guess. + fileneededpagestart[0] = mainwads; + } + + for (i = fileneededpagestart[page]; i < (fileneededpagestart[page+1] ?: numwadfiles); i++) { // If it has only music/sound lumps, don't put it in the list if (!wadfiles[i]->important) continue; + nameonly(strcpy(wadfilename, wadfiles[i]->filename)); + + if (p + 1 + 4 + strlen(wadfilename) + 16 > netbuffer->u.serverinfo.fileneeded + MAXFILENEEDED) + { + // Too many files for this page, so mark the next page to start here and finish up. + fileneededpagestart[page+1] = i; + fileneededpages = page+1; + count |= FILENEEDED_MORE; + 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,11 +158,10 @@ 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; + netbuffer->u.serverinfo.fileneedednum = count; return p; } diff --git a/src/d_netfil.h b/src/d_netfil.h index 3d7c2ed59..3a40c13af 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -53,7 +53,8 @@ extern char downloaddir[512]; extern INT32 lastfilenum; #endif -UINT8 *PutFileNeeded(void); +extern UINT16 fileneededpages; +UINT8 *PutFileNeeded(UINT16 page); void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr); void CL_PrepareDownloadSaveGame(const char *tmpsave); From ebf03678288e56d6c70996b9dae1ed9fb02ddd2a Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:42:49 -0500 Subject: [PATCH 277/382] Some stuff toward reading those files --- src/d_clisrv.c | 120 +++++++++++++++++++++++++++---------------------- src/d_netfil.c | 10 ++--- src/d_netfil.h | 2 +- 3 files changed, 73 insertions(+), 59 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 86ebb3455..1543bf684 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1129,6 +1129,7 @@ typedef enum #endif CL_CONNECTED, CL_ABORTED, + CL_ASKFULLFILELIST, CL_ASKDOWNLOADFILES, CL_WAITDOWNLOADFILESRESPONSE, CL_CHALLENGE @@ -1924,6 +1925,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 ??? @@ -1967,62 +2028,15 @@ 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.fileneedednum & FILENEEDED_MORE) { - 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; + 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; - } + if (!CL_FinishedFileList()) + return false; } else cl_mode = CL_ASKJOIN; // files need not be checked for the server. diff --git a/src/d_netfil.c b/src/d_netfil.c index efb0fb817..7e8fe0b88 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -168,19 +168,19 @@ UINT8 *PutFileNeeded(UINT16 page) /** 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 & ~FILENEEDED_MORE); 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 diff --git a/src/d_netfil.h b/src/d_netfil.h index 3a40c13af..97a0d0fe6 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -55,7 +55,7 @@ extern INT32 lastfilenum; extern UINT16 fileneededpages; UINT8 *PutFileNeeded(UINT16 page); -void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr); +void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile); void CL_PrepareDownloadSaveGame(const char *tmpsave); INT32 CL_CheckFiles(void); From d7ed880e81659267fea6837a03540f4b124f21ce Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:51:15 -0500 Subject: [PATCH 278/382] Wait, we don't need pages, just first file index... --- src/d_clisrv.c | 2 +- src/d_clisrv.h | 3 +-- src/d_netfil.c | 35 ++++++++++++++--------------------- src/d_netfil.h | 3 +-- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1543bf684..1ce6256be 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2029,7 +2029,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) if (client) { D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded, 0); - if (serverlist[i].info.fileneedednum & FILENEEDED_MORE) + if (serverlist[i].info.kartvars & SV_LOTSOFADDONS) { cl_mode = CL_ASKFULLFILELIST; return true; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a4324d690..dff15f352 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -371,13 +371,12 @@ typedef struct } ATTRPACK joinchallenge_pak; #define SV_SPEEDMASK 0x03 +#define SV_LOTSOFADDONS 0x20 #define SV_DEDICATED 0x40 #define SV_PASSWORD 0x80 #define MAXSERVERNAME 32 #define MAXFILENEEDED 915 -#define MAXFILENEEDEDPAGES MAX_WADFILES -#define FILENEEDED_MORE 0x80 // This packet is too large typedef struct { diff --git a/src/d_netfil.c b/src/d_netfil.c index 7e8fe0b88..42f7621c4 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -101,46 +101,39 @@ char downloaddir[512] = "DOWNLOAD"; INT32 lastfilenum = -1; #endif -UINT16 fileneededpages = 0; -static size_t fileneededpagestart[MAXFILENEEDEDPAGES]; - /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. * Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c * */ -UINT8 *PutFileNeeded(UINT16 page) +UINT8 *PutFileNeeded(UINT16 firstfile) { size_t i; UINT8 count = 0; - UINT8 *p = netbuffer->u.serverinfo.fileneeded; + UINT8 *p_start = netbuffer->u.serverinfo.fileneeded; + UINT8 *p = p_start; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - if (page > fileneededpages) - I_Error("Fileneeded page %d accessed before a prior page", page); - else if (page == 0) - { - fileneededpages = 0; - memset(fileneededpagestart, 0, sizeof(fileneededpagestart)); // ??? I guess. - fileneededpagestart[0] = mainwads; - } - - for (i = fileneededpagestart[page]; i < (fileneededpagestart[page+1] ?: 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)); - if (p + 1 + 4 + strlen(wadfilename) + 16 > netbuffer->u.serverinfo.fileneeded + MAXFILENEEDED) + if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED) { - // Too many files for this page, so mark the next page to start here and finish up. - fileneededpagestart[page+1] = i; - fileneededpages = page+1; - count |= FILENEEDED_MORE; + // Too many files to send all at once + netbuffer->u.serverinfo.kartvars |= SV_LOTSOFADDONS; break; } @@ -178,7 +171,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi UINT8 *p; UINT8 filestatus; - fileneedednum = firstfile + (fileneedednum_parm & ~FILENEEDED_MORE); + fileneedednum = firstfile + fileneedednum_parm; p = (UINT8 *)fileneededstr; for (i = firstfile; i < fileneedednum; i++) { diff --git a/src/d_netfil.h b/src/d_netfil.h index 97a0d0fe6..2f0333311 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -53,8 +53,7 @@ extern char downloaddir[512]; extern INT32 lastfilenum; #endif -extern UINT16 fileneededpages; -UINT8 *PutFileNeeded(UINT16 page); +UINT8 *PutFileNeeded(UINT16 firstfile); void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile); void CL_PrepareDownloadSaveGame(const char *tmpsave); From a83f887cb38016c54c93fcab07e97ee79d3b8989 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 18 Apr 2019 00:30:28 -0500 Subject: [PATCH 279/382] Send the rest of the file list --- src/d_clisrv.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/d_clisrv.h | 13 +++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1ce6256be..08f28d176 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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" @@ -1140,6 +1141,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]; @@ -1316,6 +1318,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 @@ -2032,6 +2042,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) if (serverlist[i].info.kartvars & SV_LOTSOFADDONS) { cl_mode = CL_ASKFULLFILELIST; + cl_lastcheckedfilecount = 0; return true; } @@ -2087,6 +2098,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++) @@ -3969,6 +3996,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) { diff --git a/src/d_clisrv.h b/src/d_clisrv.h index dff15f352..5b68def21 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -93,6 +93,9 @@ 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. + + 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)" #ifdef NEWPING PT_PING, // Packet sent to tell clients the other client's latency to server. #endif @@ -442,6 +445,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 // @@ -474,6 +485,8 @@ typedef struct msaskinfo_pak msaskinfo; // 22 bytes plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) + INT32 filesneedednum; // 4 bytes + filesneededconfig_pak filesneededcfg; // ??? bytes #ifdef NEWPING UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes #endif From 9c8e35794f1ef9284b2a522daf3b3bb030dfcf8f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 18 Apr 2019 00:37:08 -0500 Subject: [PATCH 280/382] Read the file list properly --- src/d_netfil.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 42f7621c4..4dcd3da4a 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -111,7 +111,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) { size_t i; UINT8 count = 0; - UINT8 *p_start = netbuffer->u.serverinfo.fileneeded; + 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; @@ -133,7 +133,10 @@ UINT8 *PutFileNeeded(UINT16 firstfile) if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once - netbuffer->u.serverinfo.kartvars |= SV_LOTSOFADDONS; + if (netbuffer->packettype == PT_MOREFILESNEEDED) + netbuffer->u.filesneededcfg.more = 1; + else + netbuffer->u.serverinfo.kartvars |= SV_LOTSOFADDONS; break; } @@ -154,7 +157,10 @@ UINT8 *PutFileNeeded(UINT16 firstfile) WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITEMEM(p, wadfiles[i]->md5sum, 16); } - netbuffer->u.serverinfo.fileneedednum = count; + if (netbuffer->packettype == PT_MOREFILESNEEDED) + netbuffer->u.filesneededcfg.num = count; + else + netbuffer->u.serverinfo.fileneedednum = count; return p; } @@ -354,7 +360,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 @@ -362,7 +369,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) { @@ -389,12 +396,12 @@ INT32 CL_CheckFiles(void) return 1; } - 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) && @@ -410,8 +417,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++; From cc7699a3710013b7198743a801e98827c3562674 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 18 Apr 2019 00:39:54 -0500 Subject: [PATCH 281/382] Show when we're waiting for the full wadlist --- src/d_clisrv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 08f28d176..f534a60bd 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1259,6 +1259,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..."); From 089be795a21af12d9466658fbe046f96f728159f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 18 Apr 2019 03:08:11 -0400 Subject: [PATCH 282/382] Huge splitscreen refactor Did not get to finish all refactoring or even compile this, I'll continue later --- src/d_clisrv.c | 36 ++-- src/d_main.c | 154 ++++++---------- src/d_netcmd.c | 160 ++++++++-------- src/dehacked.c | 2 +- src/doomstat.h | 15 +- src/g_game.c | 297 ++++++++++++------------------ src/g_game.h | 8 +- src/hu_stuff.c | 20 +- src/k_kart.c | 160 +++++++--------- src/lua_consolelib.c | 4 +- src/lua_hudlib.c | 14 +- src/lua_mobjlib.c | 14 +- src/lua_playerlib.c | 14 +- src/m_menu.c | 25 +-- src/m_misc.c | 10 +- src/p_enemy.c | 10 +- src/p_floor.c | 16 +- src/p_inter.c | 52 +++--- src/p_local.h | 4 +- src/p_map.c | 79 ++++---- src/p_maputl.c | 16 +- src/p_mobj.c | 186 ++++++++----------- src/p_polyobj.c | 14 +- src/p_saveg.c | 14 +- src/p_setup.c | 51 +++--- src/p_spec.c | 99 +++++----- src/p_telept.c | 69 +++---- src/p_tick.c | 21 +-- src/p_user.c | 428 ++++++++++++++++++++++--------------------- src/r_bsp.c | 33 ++-- src/r_bsp.h | 2 +- src/r_main.c | 197 ++++++++++---------- src/r_plane.c | 8 +- src/r_state.h | 3 +- src/r_things.c | 8 +- src/r_things.h | 2 +- src/s_sound.c | 175 +++++++++--------- src/st_stuff.c | 54 +++--- src/y_inter.c | 21 +-- 39 files changed, 1144 insertions(+), 1351 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d8ce0f963..b79d2ba0b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2369,7 +2369,7 @@ static void CL_ConnectToServer(boolean viams) #endif DEBFILE(va("Synchronisation Finished\n")); - displayplayer = consoleplayer; + displayplayers[0] = consoleplayer; } #ifndef NONET @@ -2717,8 +2717,8 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) RemoveAdminPlayer(playernum); // don't stay admin after you're gone } - if (playernum == displayplayer && !demo.playback) - 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]); @@ -3448,6 +3448,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) { INT16 node, newplayernum; UINT8 splitscreenplayer = 0; + UINT8 i; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -3481,34 +3482,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(); diff --git a/src/d_main.c b/src/d_main.c index 6feedb18e..b3ae0adea 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -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 @@ -280,6 +274,7 @@ static void D_Display(void) boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; + UINT8 i; if (dedicated) return; @@ -428,109 +423,75 @@ 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])); - - 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]); + } } } @@ -750,7 +711,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.. @@ -829,7 +790,8 @@ 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; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 36774a80f..76f72dd94 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1145,11 +1145,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)); @@ -1257,11 +1257,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); } } @@ -1396,8 +1396,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; @@ -1446,7 +1446,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; @@ -1485,14 +1485,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) @@ -1519,8 +1519,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; @@ -1561,7 +1561,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; @@ -1600,14 +1600,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) @@ -1634,8 +1634,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; @@ -1684,7 +1684,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; @@ -1723,14 +1723,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) @@ -1760,12 +1760,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 @@ -1788,8 +1788,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) 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; @@ -1826,11 +1826,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 @@ -1917,7 +1917,7 @@ 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 */ @@ -2014,7 +2014,7 @@ static void Command_View_f(void) return; } - displayplayerp = G_GetDisplayplayerPtr(viewnum); + displayplayerp = &displayplayers[viewnum]; if (COM_Argc() > 1)/* switch to player */ { @@ -2302,7 +2302,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(); @@ -2354,12 +2354,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); @@ -3006,11 +3002,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 @@ -3097,11 +3093,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 @@ -3188,11 +3184,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 @@ -3589,8 +3585,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()) { @@ -3598,11 +3594,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); } } @@ -5208,13 +5204,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. @@ -5425,7 +5421,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(); @@ -5436,7 +5432,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(); @@ -5447,7 +5443,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(); @@ -5488,12 +5484,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); } } @@ -5502,12 +5498,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); } } @@ -5516,12 +5512,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); } } @@ -5562,7 +5558,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(); @@ -5570,7 +5566,7 @@ static void Color2_OnChange(void) else { CV_StealthSetValue(&cv_playercolor2, - players[secondarydisplayplayer].skincolor); + players[displayplayers[1]].skincolor); } } @@ -5579,7 +5575,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(); @@ -5587,7 +5583,7 @@ static void Color3_OnChange(void) else { CV_StealthSetValue(&cv_playercolor3, - players[thirddisplayplayer].skincolor); + players[displayplayers[2]].skincolor); } } @@ -5596,7 +5592,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(); @@ -5604,7 +5600,7 @@ static void Color4_OnChange(void) else { CV_StealthSetValue(&cv_playercolor4, - players[fourthdisplayplayer].skincolor); + players[displayplayers[3]].skincolor); } } diff --git a/src/dehacked.c b/src/dehacked.c index 20c2964b7..b0052c6c6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9799,7 +9799,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; diff --git a/src/doomstat.h b/src/doomstat.h index 834b3a7cf..4c4270bec 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -106,14 +106,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 +116,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; diff --git a/src/g_game.c b/src/g_game.c index 85077c7bf..109c2baa5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -112,10 +112,7 @@ boolean addedtogame; player_t players[MAXPLAYERS]; INT32 consoleplayer; // player taking events and displaying -INT32 displayplayer; // view being displayed -INT32 secondarydisplayplayer; // for splitscreen -INT32 thirddisplayplayer; -INT32 fourthdisplayplayer; +INT32 displayplayers[MAXSPLITSCREENPLAYERS]; // view being displayed tic_t gametic; tic_t levelstarttic; // gametic at level start @@ -1220,9 +1217,9 @@ INT32 JoyAxis(axis_input_e axissel, UINT8 p) // // set secondaryplayer true to build player 2's ticcmd in splitscreen mode // -INT32 localaiming, localaiming2, localaiming3, localaiming4; -angle_t localangle, localangle2, localangle3, localangle4; -boolean camspin, camspin2, camspin3, camspin4; +INT32 localaiming[MAXSPLITSCREENPLAYERS]; // TODO: convert these 3 into MAXSPLITSCREENPLAYERS arrays +angle_t localangle[MAXSPLITSCREENPLAYERS]; +boolean camspin[MAXSPLITSCREENPLAYERS]; static fixed_t forwardmove[2] = {25<>16, 50<>16}; static fixed_t sidemove[2] = {2<>16, 4<>16}; @@ -1239,53 +1236,36 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) camera_t *thiscam; angle_t lang; - static INT32 turnheld, turnheld2, turnheld3, turnheld4; // for accelerative turning - static boolean keyboard_look, keyboard_look2, keyboard_look3, keyboard_look4; // true if lookup/down using keyboard - static boolean resetdown, resetdown2, resetdown3, resetdown4; // don't cam reset every frame + static INT32 turnheld[MAXSPLITSCREENPLAYERS]; // for accelerative turning + static boolean keyboard_look[MAXSPLITSCREENPLAYERS]; // true if lookup/down using keyboard + static boolean resetdown[MAXSPLITSCREENPLAYERS]; // don't cam reset every frame if (demo.playback) return; + player = &players[displayplayers[ssplayer-1]]; + if (ssplayer == 2) + thiscam = (player->bot == 2 ? &camera[0] : &camera[ssplayer-1]); + else + thiscam = &camera[ssplayer-1]; + lang = localangle[ssplayer-1]; + laim = localaiming[ssplayer-1]; + th = turnheld[ssplayer-1]; + kbl = keyboard_look[ssplayer-1]; + rd = resetdown[ssplayer-1]; + switch (ssplayer) { case 2: - player = &players[secondarydisplayplayer]; - thiscam = (player->bot == 2 ? &camera : &camera2); - lang = localangle2; - laim = localaiming2; - th = turnheld2; - kbl = keyboard_look2; - rd = resetdown2; G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); break; case 3: - player = &players[thirddisplayplayer]; - thiscam = &camera3; - lang = localangle3; - laim = localaiming3; - th = turnheld3; - kbl = keyboard_look3; - rd = resetdown3; G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1); break; case 4: - player = &players[fourthdisplayplayer]; - thiscam = &camera4; - lang = localangle4; - laim = localaiming4; - th = turnheld4; - kbl = keyboard_look4; - rd = resetdown4; G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1); break; case 1: default: - player = &players[consoleplayer]; - thiscam = &camera; - lang = localangle; - laim = localaiming; - th = turnheld; - kbl = keyboard_look; - rd = resetdown; G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver break; } @@ -1576,42 +1556,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (!hu_stopped) { - switch (ssplayer) - { - case 2: - localangle2 = lang; - localaiming2 = laim; - keyboard_look2 = kbl; - turnheld2 = th; - resetdown2 = rd; - camspin2 = InputDown(gc_lookback, ssplayer); - break; - case 3: - localangle3 = lang; - localaiming3 = laim; - keyboard_look3 = kbl; - turnheld3 = th; - resetdown3 = rd; - camspin3 = InputDown(gc_lookback, ssplayer); - break; - case 4: - localangle4 = lang; - localaiming4 = laim; - keyboard_look4 = kbl; - turnheld4 = th; - resetdown4 = rd; - camspin4 = InputDown(gc_lookback, ssplayer); - break; - case 1: - default: - localangle = lang; - localaiming = laim; - keyboard_look = kbl; - turnheld = th; - resetdown = rd; - camspin = InputDown(gc_lookback, ssplayer); - break; - } + localangle[ssplayer-1] = lang; + localaiming[ssplayer-1] = laim; + keyboard_look[ssplayer-1] = kbl; + turnheld[ssplayer-1] = th; + resetdown[ssplayer-1] = rd; + camspin[ssplayer-1] = InputDown(gc_lookback, ssplayer); } /* Lua: Allow this hook to overwrite ticcmd. @@ -1631,8 +1581,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) //Reset away view if a command is given. if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) - && displayplayer != consoleplayer && ssplayer == 1) - displayplayer = consoleplayer; + && displayplayers[0] != consoleplayer && ssplayer == 1) + displayplayers[0] = consoleplayer; } @@ -1784,27 +1734,24 @@ void G_DoLoadLevel(boolean resetplayer) if (!resetplayer) P_FindEmerald(); - displayplayer = consoleplayer; // view the guy you are playing - if (!splitscreen && !botingame) - secondarydisplayplayer = consoleplayer; - if (splitscreen < 2) - thirddisplayplayer = consoleplayer; - if (splitscreen < 3) - fourthdisplayplayer = consoleplayer; + displayplayers[0] = consoleplayer; // view the guy you are playing + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (i > 0 && !(i == 1 && botingame) && splitscreen < i) + displayplayers[i] = consoleplayer; + } gameaction = ga_nothing; #ifdef PARANOIA Z_CheckHeap(-2); #endif - if (camera.chase) - P_ResetCamera(&players[displayplayer], &camera); - if (camera2.chase && splitscreen) - P_ResetCamera(&players[secondarydisplayplayer], &camera2); - if (camera3.chase && splitscreen > 1) - P_ResetCamera(&players[thirddisplayplayer], &camera3); - if (camera4.chase && splitscreen > 2) - P_ResetCamera(&players[fourthdisplayplayer], &camera4); + for (i = 0; i <= splitscreen; i++) + { + if (camera[i].chase) + P_ResetCamera(&players[displayplayers[i]], &camera[i]); + } // clear cmd building stuff memset(gamekeydown, 0, sizeof (gamekeydown)); @@ -1914,7 +1861,7 @@ boolean G_Responder(event_t *ev) && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) { if (!demo.playback && (splitscreen || !netgame)) - displayplayer = consoleplayer; + displayplayers[0] = consoleplayer; else { G_AdjustView(1, 1, true); @@ -2184,13 +2131,13 @@ boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive) for (viewd = 1; viewd < viewnum; ++viewd) { - displayplayerp = (G_GetDisplayplayerPtr(viewd)); + displayplayerp = (&displayplayers[viewd-1]); if ((*displayplayerp) == playernum) return false; } for (viewd = viewnum + 1; viewd <= splits; ++viewd) { - displayplayerp = (G_GetDisplayplayerPtr(viewd)); + displayplayerp = (&displayplayers[viewd-1]); if ((*displayplayerp) == playernum) return false; } @@ -2232,17 +2179,6 @@ INT32 G_CountPlayersPotentiallyViewable(boolean active) return total; } -INT32 *G_GetDisplayplayerPtr(UINT8 viewnum) -{ - switch (viewnum) - { - case 2: return &secondarydisplayplayer; - case 3: return &thirddisplayplayer; - case 4: return &fourthdisplayplayer; - } - return &displayplayer; -} - // // G_ResetView // Correct a viewpoint to playernum or the next available, wraps forward. @@ -2276,14 +2212,14 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) /* Prepare extra views for G_FindView to pass. */ for (viewd = splits+1; viewd < viewnum; ++viewd) { - displayplayerp = (G_GetDisplayplayerPtr(viewd)); + displayplayerp = (&displayplayers[viewd-1]); (*displayplayerp) = INT32_MAX; } R_ExecuteSetViewSize(); } - displayplayerp = (G_GetDisplayplayerPtr(viewnum)); + displayplayerp = (&displayplayers[viewnum-1]); olddisplayplayer = (*displayplayerp); /* Check if anyone is available to view. */ @@ -2294,7 +2230,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) (*displayplayerp) = playernum; if ((*displayplayerp) != olddisplayplayer) { - camerap = (P_GetCameraPtr(viewnum)); + camerap = &camera[viewnum-1]; P_ResetCamera(&players[(*displayplayerp)], camerap); } @@ -2302,8 +2238,8 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) { for (viewd = splits+1; viewd < viewnum; ++viewd) { - displayplayerp = (G_GetDisplayplayerPtr(viewd)); - camerap = (P_GetCameraPtr(viewd)); + displayplayerp = (&displayplayers[viewd-1]); + camerap = &camera[viewd]; (*displayplayerp) = G_FindView(0, viewd, onlyactive, false); @@ -2312,7 +2248,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) } if (viewnum == 1 && demo.playback) - consoleplayer = displayplayer; + consoleplayer = displayplayers[0]; } // @@ -2323,7 +2259,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive) { INT32 *displayplayerp, oldview; - displayplayerp = G_GetDisplayplayerPtr(viewnum); + displayplayerp = &displayplayers[viewnum-1]; oldview = (*displayplayerp); G_ResetView(viewnum, ( (*displayplayerp) + offset ), onlyactive); @@ -2864,22 +2800,22 @@ void G_PlayerReborn(INT32 player) { if (p == &players[consoleplayer]) CV_SetValue(&cv_playercolor, skincolor_redteam); - else if (p == &players[secondarydisplayplayer]) + else if (p == &players[displayplayers[1]]) CV_SetValue(&cv_playercolor2, skincolor_redteam); - else if (p == &players[thirddisplayplayer]) + else if (p == &players[displayplayers[2]]) CV_SetValue(&cv_playercolor3, skincolor_redteam); - else if (p == &players[fourthdisplayplayer]) + else if (p == &players[displayplayers[3]]) CV_SetValue(&cv_playercolor4, skincolor_redteam); } else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) { if (p == &players[consoleplayer]) CV_SetValue(&cv_playercolor, skincolor_blueteam); - else if (p == &players[secondarydisplayplayer]) + else if (p == &players[displayplayers[1]]) CV_SetValue(&cv_playercolor2, skincolor_blueteam); - else if (p == &players[thirddisplayplayer]) + else if (p == &players[displayplayers[2]]) CV_SetValue(&cv_playercolor3, skincolor_blueteam); - else if (p == &players[fourthdisplayplayer]) + else if (p == &players[displayplayers[3]]) CV_SetValue(&cv_playercolor4, skincolor_blueteam); } }*/ @@ -2984,18 +2920,18 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) if (nummapthings) { if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); spawnpoint = &mapthings[0]; } else { if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); //P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL. } @@ -3015,9 +2951,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (!numredctfstarts && !numbluectfstarts) //why even bother, eh? { if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n")); return NULL; } @@ -3027,9 +2963,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (!numredctfstarts) { if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("No Red Team starts in this map!\n")); return NULL; } @@ -3042,9 +2978,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum) } if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Red Team starts!\n")); return NULL; } @@ -3053,9 +2989,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (!numbluectfstarts) { if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("No Blue Team starts in this map!\n")); return NULL; } @@ -3067,9 +3003,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum) return bluectfstarts[i]; } if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Blue Team starts!\n")); return NULL; } @@ -3090,17 +3026,17 @@ mapthing_t *G_FindMatchStart(INT32 playernum) return deathmatchstarts[i]; } if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Deathmatch starts!\n")); return NULL; } if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("No Deathmatch starts in this map!\n")); return NULL; } @@ -3166,17 +3102,17 @@ mapthing_t *G_FindRaceStart(INT32 playernum) //return playerstarts[0]; if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Race starts!\n")); return NULL; } if (playernum == consoleplayer - || (splitscreen && playernum == secondarydisplayplayer) - || (splitscreen > 1 && playernum == thirddisplayplayer) - || (splitscreen > 2 && playernum == fourthdisplayplayer)) + || (splitscreen && playernum == displayplayers[1]) + || (splitscreen > 1 && playernum == displayplayers[2]) + || (splitscreen > 2 && playernum == displayplayers[3])) CONS_Alert(CONS_WARNING, M_GetText("No Race starts in this map!\n")); return NULL; } @@ -3268,14 +3204,11 @@ void G_DoReborn(INT32 playernum) if (player->starpostnum) // SRB2kart starpost = true; - if (camera.chase) - P_ResetCamera(&players[displayplayer], &camera); - if (camera2.chase && splitscreen > 0) - P_ResetCamera(&players[secondarydisplayplayer], &camera2); - if (camera3.chase && splitscreen > 1) - P_ResetCamera(&players[thirddisplayplayer], &camera3); - if (camera4.chase && splitscreen > 2) - P_ResetCamera(&players[fourthdisplayplayer], &camera4); + for (i = 0; i <= splitscreen; i++) + { + if (camera[i].chase) + P_ResetCamera(&players[displayplayers[i]], &camera[i]); + } // clear cmd building stuff memset(gamekeydown, 0, sizeof (gamekeydown)); @@ -3297,8 +3230,8 @@ void G_DoReborn(INT32 playernum) if (botingame) { // Bots respawn next to their master. - players[secondarydisplayplayer].playerstate = PST_REBORN; - G_SpawnPlayer(secondarydisplayplayer, false); + players[displayplayers[1]].playerstate = PST_REBORN; + G_SpawnPlayer(displayplayers[1], false); } } else @@ -4418,7 +4351,7 @@ static void M_ForceLoadGameResponse(INT32 ch) //set cursaveslot to -1 so nothing gets saved. cursaveslot = -1; - displayplayer = consoleplayer; + displayplayers[0] = consoleplayer; multiplayer = false; splitscreen = 0; SplitScreen_OnChange(); // not needed? @@ -4508,7 +4441,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) // gameaction = ga_nothing; // G_SetGamestate(GS_LEVEL); - displayplayer = consoleplayer; + displayplayers[0] = consoleplayer; multiplayer = false; splitscreen = 0; SplitScreen_OnChange(); // not needed? @@ -4573,7 +4506,7 @@ void G_SaveGame(UINT32 savegameslot) // // G_DeferedInitNew // Can be called by the startup code or the menu task, -// consoleplayer, displayplayer, playeringame[] should be set. +// consoleplayer, displayplayers[], playeringame[] should be set. // void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS) { @@ -5167,12 +5100,12 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) G_CopyTiccmd(cmd, &oldcmd[playernum], 1); // SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam - if (((players[displayplayer].mo && players[displayplayer].speed > 0) // Moving + if (((players[displayplayers[0]].mo && players[displayplayers[0]].speed > 0) // Moving || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn - || (players[displayplayer].kartstuff[k_respawn]) // Respawning - || (players[displayplayer].spectator || objectplacing)) // Not a physical player - && !(players[displayplayer].kartstuff[k_spinouttimer] && players[displayplayer].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout - localangle += (cmd->angleturn<<16); + || (players[displayplayers[0]].kartstuff[k_respawn]) // Respawning + || (players[displayplayers[0]].spectator || objectplacing)) // Not a physical player + && !(players[displayplayers[0]].kartstuff[k_spinouttimer] && players[displayplayers[0]].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout + localangle[0] += (cmd->angleturn<<16); if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) { @@ -6073,7 +6006,7 @@ void G_PreviewRewind(tic_t previewtime) } for (i = splitscreen+1; i > 0; i--) - P_ResetCamera(&players[(*G_GetDisplayplayerPtr(i))], P_GetCameraPtr(i)); + P_ResetCamera(&players[displayplayers[i]], &camera[i]); } void G_ConfirmRewind(tic_t rewindtime) @@ -6081,7 +6014,7 @@ void G_ConfirmRewind(tic_t rewindtime) tic_t i; boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; - INT32 olddp1 = displayplayer, olddp2 = secondarydisplayplayer, olddp3 = thirddisplayplayer, olddp4 = fourthdisplayplayer; + INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3]; UINT8 oldss = splitscreen; menuactive = false; // Prevent loops @@ -6113,15 +6046,15 @@ void G_ConfirmRewind(tic_t rewindtime) COM_BufInsertText("renderview on\n"); splitscreen = oldss; - displayplayer = olddp1; - secondarydisplayplayer = olddp2; - thirddisplayplayer = olddp3; - fourthdisplayplayer = olddp4; + displayplayers[0] = olddp1; + displayplayers[1] = olddp2; + displayplayers[2] = olddp3; + displayplayers[3] = olddp4; R_ExecuteSetViewSize(); G_ResetViews(); for (i = splitscreen+1; i > 0; i--) - P_ResetCamera(&players[(*G_GetDisplayplayerPtr(i))], P_GetCameraPtr(i)); + P_ResetCamera(&players[displayplayers[i]], &camera[i]); } void G_ReadMetalTic(mobj_t *metal) @@ -7407,7 +7340,8 @@ void G_DoPlayDemo(char *defdemoname) // didn't start recording right away. demo.deferstart = false; - displayplayer = consoleplayer = 0; + consoleplayer = 0; + memset(displayplayers, 0, sizeof(displayplayers)); memset(playeringame, 0, sizeof(playeringame)); playeringame[0] = true; @@ -7457,13 +7391,14 @@ void G_DoPlayDemo(char *defdemoname) /*#ifdef HAVE_BLUA LUAh_MapChange(gamemap); #endif*/ - displayplayer = consoleplayer = 0; + displayplayers[0] = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); // Load players that were in-game when the map started p = READUINT8(demo_p); - secondarydisplayplayer = thirddisplayplayer = fourthdisplayplayer = INT32_MAX; + for (i = 1; i < MAXSPLITSCREENPLAYERS; i++); + displayplayers[i] = INT32_MAX; while (p != 0xFF) { @@ -7499,8 +7434,8 @@ void G_DoPlayDemo(char *defdemoname) return; } - if (!playeringame[displayplayer] || players[displayplayer].spectator) - displayplayer = consoleplayer = serverplayer = p; + if (!playeringame[displayplayers[0]] || players[displayplayers[0]].spectator) + displayplayers[0] = consoleplayer = serverplayer = p; playeringame[p] = true; players[p].spectator = spectator; diff --git a/src/g_game.h b/src/g_game.h index 148a5e52b..dd6eefca3 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -152,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 @@ -297,8 +297,6 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); -INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); - boolean G_CouldView(INT32 playernum); boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index d7020e8c6..2368d1f21 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -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 @@ -1987,7 +1987,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 +2014,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 +2061,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 +2098,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 @@ -2358,16 +2358,16 @@ void HU_Drawer(void) // draw the crosshair, not when viewing demos nor with chasecam /*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(); }*/ @@ -3009,7 +3009,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 = demo.playback ? displayplayer : consoleplayer; + whiteplayer = demo.playback ? displayplayers[0] : consoleplayer; scorelines = 0; memset(completed, 0, sizeof (completed)); diff --git a/src/k_kart.c b/src/k_kart.c index 3918e8f94..1237a5920 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1027,34 +1027,14 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } // This makes the roulette produce the random noises. - if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player)) + if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player)) { -#define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->kartstuff[k_itemroulette] / 3) % 8)); - if (splitscreen) +#define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->kartstuff[k_itemroulette] / 3) % 8)) + for (i = 0; i <= splitscreen; i++) { - if (players[displayplayer].kartstuff[k_itemroulette]) - { - if (player == &players[displayplayer]) - PLAYROULETTESND; - } - else if (players[secondarydisplayplayer].kartstuff[k_itemroulette]) - { - if (player == &players[secondarydisplayplayer]) - PLAYROULETTESND; - } - else if (players[thirddisplayplayer].kartstuff[k_itemroulette] && splitscreen > 1) - { - if (player == &players[thirddisplayplayer]) - PLAYROULETTESND; - } - else if (players[fourthdisplayplayer].kartstuff[k_itemroulette] && splitscreen > 2) - { - if (player == &players[fourthdisplayplayer]) - PLAYROULETTESND; - } + if (player == &players[displayplayers[i]] && players[displayplayers[i]].kartstuff[k_itemroulette]) + PLAYROULETTESND; } - else - PLAYROULETTESND; #undef PLAYROULETTESND } @@ -1081,7 +1061,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) //player->kartstuff[k_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrole); return; } @@ -1094,7 +1074,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemblinkmode] = 2; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_dbgsal); return; } @@ -1126,7 +1106,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemamount] = 1; } - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); player->kartstuff[k_itemblink] = TICRATE; @@ -4331,10 +4311,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (!playeringame[i] || !players[i].mo || players[i].spectator || players[i].exiting) continue; - if ((i == displayplayer) - || (i == secondarydisplayplayer && splitscreen) - || (i == thirddisplayplayer && splitscreen > 1) - || (i == fourthdisplayplayer && splitscreen > 2)) + if (P_IsDisplayPlayer(&players[i])) { volumedampen += FRACUNIT; // We already know what this is gonna be, let's not waste our time. continue; @@ -5691,13 +5668,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_hyudorotimer] >= (1*TICRATE/2) && player->kartstuff[k_hyudorotimer] <= hyudorotime-(1*TICRATE/2)) { - if (player == &players[secondarydisplayplayer]) + if (player == &players[displayplayers[1]]) player->mo->eflags |= MFE_DRAWONLYFORP2; - else if (player == &players[thirddisplayplayer] && splitscreen > 1) + else if (player == &players[displayplayers[2]] && splitscreen > 1) player->mo->eflags |= MFE_DRAWONLYFORP3; - else if (player == &players[fourthdisplayplayer] && splitscreen > 2) + else if (player == &players[displayplayers[3]] && splitscreen > 2) player->mo->eflags |= MFE_DRAWONLYFORP4; - else if (player == &players[consoleplayer]) + else if (player == &players[displayplayers[0]]) player->mo->eflags |= MFE_DRAWONLYFORP1; else player->mo->flags2 |= MF2_DONTDRAW; @@ -5707,8 +5684,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else { - if (player == &players[displayplayer] - || (player != &players[displayplayer] && (player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)))) + if (P_IsDisplayPlayer(player) + || (!P_IsDisplayPlayer(player) && (player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)))) { if (leveltime & 1) player->mo->flags2 |= MF2_DONTDRAW; @@ -5808,7 +5785,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } // Play the starting countdown sounds - if (player == &players[displayplayer]) // Don't play louder in splitscreen + if (player == &players[displayplayers[0]]) // Don't play louder in splitscreen { if ((leveltime == starttime-(3*TICRATE)) || (leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE)) S_StartSound(NULL, sfx_s3ka7); @@ -6693,17 +6670,17 @@ INT32 K_calcSplitFlags(INT32 snapflags) if (splitscreen == 0) return snapflags; - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) { - if (splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) + if (splitscreen == 1 && stplyr == &players[displayplayers[1]]) { splitflags |= V_SPLITSCREEN; } else if (splitscreen > 1) { - if (stplyr == &players[thirddisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) + if (stplyr == &players[displayplayers[2]] || (splitscreen == 3 && stplyr == &players[displayplayers[3]])) splitflags |= V_SPLITSCREEN; - if (stplyr == &players[secondarydisplayplayer] || (splitscreen == 3 && stplyr == &players[fourthdisplayplayer])) + if (stplyr == &players[displayplayers[1]] || (splitscreen == 3 && stplyr == &players[displayplayers[3]])) splitflags |= V_HORZSCREEN; } } @@ -6965,25 +6942,25 @@ static void K_drawKartItem(void) } // pain and suffering defined below - if (splitscreen < 2) // don't change shit for THIS splitscreen. + if (splitscreen < 2) // don't change shit for THIS splitscreen. { fx = ITEM_X; fy = ITEM_Y; fflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); } - else // now we're having a fun game. + else // now we're having a fun game. { - if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... { fx = ITEM_X; fy = ITEM_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P3 to the bottom. + fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P3 to the bottom. } else // else, that means we're P2 or P4. { fx = ITEM2_X; fy = ITEM2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P4 to the bottom + fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P4 to the bottom flipamount = true; } } @@ -6996,10 +6973,10 @@ static void K_drawKartItem(void) // Then, the numbers: if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette]) { - V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it. + V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it. V_DrawFixedPatch(fx<kartstuff[k_itemamount])); else V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount])); @@ -7226,7 +7203,7 @@ static void K_DrawKartPositionNum(INT32 num) else if (splitscreen == 1) // for this splitscreen, we'll use case by case because it's a bit different. { fx = POSI_X; - if (stplyr == &players[displayplayer]) // for player 1: display this at the top right, above the minimap. + if (stplyr == &players[displayplayers[0]]) // for player 1: display this at the top right, above the minimap. { fy = 30; fflags = V_SNAPTOTOP|V_SNAPTORIGHT; @@ -7241,11 +7218,11 @@ static void K_DrawKartPositionNum(INT32 num) } else { - if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... { fx = POSI_X; fy = POSI_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. flipdraw = true; if (num && num >= 10) fx += W; // this seems dumb, but we need to do this in order for positions above 10 going off screen. @@ -7254,7 +7231,7 @@ static void K_DrawKartPositionNum(INT32 num) { fx = POSI2_X; fy = POSI2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom } } @@ -7580,17 +7557,17 @@ static void K_drawKartLaps(void) } else { - if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... { fx = LAPS_X; fy = LAPS_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. } else // else, that means we're P2 or P4. { fx = LAPS2_X; fy = LAPS2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom flipstring = true; // make the string right aligned and other shit } } @@ -7662,17 +7639,17 @@ static void K_drawKartBumpersOrKarma(void) // we will reuse lap coords here since it's essentially the same shit. - if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... { fx = LAPS_X; fy = LAPS_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. } else // else, that means we're P2 or P4. { fx = LAPS2_X; fy = LAPS2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom flipstring = true; } @@ -7749,7 +7726,7 @@ static void K_drawKartWanted(void) UINT8 *colormap = NULL; INT32 basex = 0, basey = 0; - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) return; for (i = 0; i < 4; i++) @@ -7829,7 +7806,7 @@ static void K_drawKartPlayerCheck(void) if (stplyr->awayviewtics) return; - if (camspin) + if (camspin[0]) return; for (i = 0; i < MAXPLAYERS; i++) @@ -7975,7 +7952,7 @@ static void K_drawKartMinimap(void) if (gamestate != GS_LEVEL) return; - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) return; lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap))); @@ -8049,7 +8026,7 @@ static void K_drawKartMinimap(void) if (!players[i].mo || players[i].spectator) continue; - if (i != displayplayer || splitscreen) + if (i != displayplayers[0] || splitscreen) { if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0) continue; @@ -8063,7 +8040,7 @@ static void K_drawKartMinimap(void) } } - if (i == displayplayer || i == secondarydisplayplayer || i == thirddisplayplayer || i == fourthdisplayplayer) + if (P_IsDisplayPlayer(&players[i])) { // Draw display players on top of everything else localplayers[numlocalplayers] = i; @@ -8133,7 +8110,7 @@ static void K_drawKartFinish(void) xval = (SHORT(kp_racefinish[pnum]->width)<kartstuff[k_cardanimation])*(xval > x ? xval : x))/TICRATE; - if (splitscreen && stplyr == &players[secondarydisplayplayer]) + if (splitscreen && stplyr == &players[displayplayers[1]]) x = -x; V_DrawFixedPatch(x + (STCD_X<>1), @@ -8152,9 +8129,9 @@ static void K_drawBattleFullscreen(void) if (splitscreen) { - if ((splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) - || (splitscreen > 1 && (stplyr == &players[thirddisplayplayer] - || (stplyr == &players[fourthdisplayplayer] && splitscreen > 2)))) + if ((splitscreen == 1 && stplyr == &players[displayplayers[1]]) + || (splitscreen > 1 && (stplyr == &players[displayplayers[2]] + || (stplyr == &players[displayplayers[3]] && splitscreen > 2)))) { y = 232-(stplyr->kartstuff[k_cardanimation]/2); splitflags = V_SNAPTOBOTTOM; @@ -8166,8 +8143,8 @@ static void K_drawBattleFullscreen(void) { scale /= 2; - if (stplyr == &players[secondarydisplayplayer] - || (stplyr == &players[fourthdisplayplayer] && splitscreen > 2)) + if (stplyr == &players[displayplayers[1]] + || (stplyr == &players[displayplayers[3]] && splitscreen > 2)) x = 3*BASEVIDWIDTH/4; else x = BASEVIDWIDTH/4; @@ -8176,7 +8153,7 @@ static void K_drawBattleFullscreen(void) { if (stplyr->exiting) { - if (stplyr == &players[secondarydisplayplayer]) + if (stplyr == &players[displayplayers[1]]) x = BASEVIDWIDTH-96; else x = 96; @@ -8188,7 +8165,7 @@ static void K_drawBattleFullscreen(void) if (stplyr->exiting) { - if (stplyr == &players[displayplayer]) + if (stplyr == &players[displayplayers[0]]) V_DrawFadeScreen(0xFF00, 16); if (stplyr->exiting < 6*TICRATE && !stplyr->spectator) { @@ -8218,9 +8195,9 @@ static void K_drawBattleFullscreen(void) { if (splitscreen > 1) ty = (BASEVIDHEIGHT/4)+33; - if ((splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) - || (stplyr == &players[thirddisplayplayer] && splitscreen > 1) - || (stplyr == &players[fourthdisplayplayer] && splitscreen > 2)) + if ((splitscreen == 1 && stplyr == &players[displayplayers[1]]) + || (stplyr == &players[displayplayers[2]] && splitscreen > 1) + || (stplyr == &players[displayplayers[3]] && splitscreen > 2)) ty += (BASEVIDHEIGHT/2); } else @@ -8273,11 +8250,11 @@ static void K_drawKartFirstPerson(void) if (stplyr->spectator || !stplyr->mo || (stplyr->mo->flags2 & MF2_DONTDRAW)) return; - if (stplyr == &players[secondarydisplayplayer] && splitscreen) + if (stplyr == &players[displayplayers[1]] && splitscreen) { pn = pnum[1]; tn = turn[1]; dr = drift[1]; } - else if (stplyr == &players[thirddisplayplayer] && splitscreen > 1) + else if (stplyr == &players[displayplayers[2]] && splitscreen > 1) { pn = pnum[2]; tn = turn[2]; dr = drift[2]; } - else if (stplyr == &players[fourthdisplayplayer] && splitscreen > 2) + else if (stplyr == &players[displayplayers[3]] && splitscreen > 2) { pn = pnum[3]; tn = turn[3]; dr = drift[3]; } else { pn = pnum[0]; tn = turn[0]; dr = drift[0]; } @@ -8402,11 +8379,11 @@ static void K_drawKartFirstPerson(void) V_DrawFixedPatch(x, y, scale, splitflags, kp_fpview[target], colmap); - if (stplyr == &players[secondarydisplayplayer] && splitscreen) + if (stplyr == &players[displayplayers[1]] && splitscreen) { pnum[1] = pn; turn[1] = tn; drift[1] = dr; } - else if (stplyr == &players[thirddisplayplayer] && splitscreen > 1) + else if (stplyr == &players[displayplayers[2]] && splitscreen > 1) { pnum[2] = pn; turn[2] = tn; drift[2] = dr; } - else if (stplyr == &players[fourthdisplayplayer] && splitscreen > 2) + else if (stplyr == &players[displayplayers[3]] && splitscreen > 2) { pnum[3] = pn; turn[3] = tn; drift[3] = dr; } else { pnum[0] = pn; turn[0] = tn; drift[0] = dr; } @@ -8627,7 +8604,7 @@ static void K_drawDistributionDebugger(void) boolean dontforcespb = false; boolean spbrush = false; - if (stplyr != &players[displayplayer]) // only for p1 + if (stplyr != &players[displayplayers[0]]) // only for p1 return; // The only code duplication from the Kart, just to avoid the actual item function from calculating pingame twice @@ -8691,7 +8668,7 @@ static void K_drawDistributionDebugger(void) static void K_drawCheckpointDebugger(void) { - if (stplyr != &players[displayplayer]) // only for p1 + if (stplyr != &players[displayplayers[0]]) // only for p1 return; if (stplyr->starpostnum >= (numstarposts - (numstarposts/2))) @@ -8705,20 +8682,21 @@ void K_drawKartHUD(void) { boolean isfreeplay = false; boolean battlefullscreen = false; + UINT8 i; // Define the X and Y for each drawn object // This is handled by console/menu values K_initKartHUD(); // Draw that fun first person HUD! Drawn ASAP so it looks more "real". - if ((stplyr == &players[displayplayer] && !camera.chase) - || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase) - || ((splitscreen > 1 && stplyr == &players[thirddisplayplayer]) && !camera3.chase) - || ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) - K_drawKartFirstPerson(); + for (i = 0; i <= splitscreen; i++) + { + if (stplyr == &players[displayplayers[i]] && !camera[i].chase) + K_drawKartFirstPerson(); + } // Draw full screen stuff that turns off the rest of the HUD - if (mapreset && stplyr == &players[displayplayer]) + if (mapreset && stplyr == &players[displayplayers[0]]) { K_drawChallengerScreen(); return; @@ -8734,7 +8712,7 @@ void K_drawKartHUD(void) if (!demo.title && (!battlefullscreen || splitscreen)) { // Draw the CHECK indicator before the other items, so it's overlapped by everything else - if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) + if (cv_kartcheck.value && !splitscreen && !players[displayplayers[0]].exiting) K_drawKartPlayerCheck(); // Draw WANTED status diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 0ea0c8097..299870e00 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -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) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index fb6814b25..31beecf09 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -797,24 +797,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; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index b56538d0f..dfb344e34 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -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); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 73d5ecbc0..4921ba7a4 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -382,13 +382,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); diff --git a/src/m_menu.c b/src/m_menu.c index 4eb184462..cb62738ad 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5787,7 +5787,7 @@ static void M_DrawPlaybackMenu(void) if (splitscreen >= i - playback_view1) { - INT32 ply = *G_GetDisplayplayerPtr(i - playback_view1 + 1); + INT32 ply = displayplayers[i - playback_view1 + 1]; icon = facerankprefix[players[ply].skin]; if (i != itemOn) @@ -5836,19 +5836,10 @@ static void M_DrawPlaybackMenu(void) break; case playback_view1: - str = player_names[displayplayer]; - break; - case playback_view2: - str = player_names[secondarydisplayplayer]; - break; - case playback_view3: - str = player_names[thirddisplayplayer]; - break; - case playback_view4: - str = player_names[fourthdisplayplayer]; + str = player_names[displayplayers[i - playback_view1]]; // 0 to 3 break; default: // shouldn't ever be reached but whatever @@ -9472,7 +9463,7 @@ static void M_SetupMultiPlayer2(INT32 choice) strcpy (setupm_name, cv_playername2.string); // set for splitscreen secondary player - setupm_player = &players[secondarydisplayplayer]; + setupm_player = &players[displayplayers[1]]; setupm_cvskin = &cv_skin2; setupm_cvcolor = &cv_playercolor2; setupm_cvname = &cv_playername2; @@ -9484,7 +9475,7 @@ static void M_SetupMultiPlayer2(INT32 choice) setupm_fakecolor = setupm_cvcolor->value; // disable skin changes if we can't actually change skins - if (splitscreen && !CanChangeSkin(secondarydisplayplayer)) + if (splitscreen && !CanChangeSkin(displayplayers[1])) MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); else MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); @@ -9503,7 +9494,7 @@ static void M_SetupMultiPlayer3(INT32 choice) strcpy(setupm_name, cv_playername3.string); // set for splitscreen third player - setupm_player = &players[thirddisplayplayer]; + setupm_player = &players[displayplayers[2]]; setupm_cvskin = &cv_skin3; setupm_cvcolor = &cv_playercolor3; setupm_cvname = &cv_playername3; @@ -9515,7 +9506,7 @@ static void M_SetupMultiPlayer3(INT32 choice) setupm_fakecolor = setupm_cvcolor->value; // disable skin changes if we can't actually change skins - if (splitscreen > 1 && !CanChangeSkin(thirddisplayplayer)) + if (splitscreen > 1 && !CanChangeSkin(displayplayers[2])) MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); else MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); @@ -9534,7 +9525,7 @@ static void M_SetupMultiPlayer4(INT32 choice) strcpy(setupm_name, cv_playername4.string); // set for splitscreen fourth player - setupm_player = &players[fourthdisplayplayer]; + setupm_player = &players[displayplayers[3]]; setupm_cvskin = &cv_skin4; setupm_cvcolor = &cv_playercolor4; setupm_cvname = &cv_playername4; @@ -9546,7 +9537,7 @@ static void M_SetupMultiPlayer4(INT32 choice) setupm_fakecolor = setupm_cvcolor->value; // disable skin changes if we can't actually change skins - if (splitscreen > 2 && !CanChangeSkin(fourthdisplayplayer)) + if (splitscreen > 2 && !CanChangeSkin(displayplayers[3])) MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); else MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); diff --git a/src/m_misc.c b/src/m_misc.c index c95aa392c..f4a4ec291 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -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"); diff --git a/src/p_enemy.c b/src/p_enemy.c index 6d5137c43..f5073deab 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -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)); diff --git a/src/p_floor.c b/src/p_floor.c index e11fe4030..ccbfd6eae 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -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; diff --git a/src/p_inter.c b/src/p_inter.c index f70bcf3ee..e6cb19993 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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; } @@ -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); @@ -2324,17 +2324,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() diff --git a/src/p_local.h b/src/p_local.h index 21fb3ddbe..5f7c4ef98 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -108,7 +108,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; @@ -126,8 +126,6 @@ extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; extern fixed_t t_cam3_dist, t_cam3_height, t_cam3_rotate; extern fixed_t t_cam4_dist, t_cam4_height, t_cam4_rotate; -camera_t *P_GetCameraPtr(UINT8 viewnum); - fixed_t P_GetPlayerHeight(player_t *player); fixed_t P_GetPlayerSpinHeight(player_t *player); void P_AddPlayerScore(player_t *player, UINT32 amount); diff --git a/src/p_map.c b/src/p_map.c index 9b0db658b..3c2aad441 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -215,13 +215,13 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) 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; } } @@ -1267,13 +1267,13 @@ static boolean PIT_CheckThing(mobj_t *thing) 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; @@ -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 { diff --git a/src/p_maputl.c b/src/p_maputl.c index c5a593d3e..355c58db8 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -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 diff --git a/src/p_mobj.c b/src/p_mobj.c index f31075f36..102af9dca 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1136,44 +1136,18 @@ static void P_PlayerFlip(mobj_t *mo) else if (mo->player->pflags & PF_FLIPCAM) { 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); + } } } } @@ -3546,17 +3520,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 +3571,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 +3621,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)) { @@ -6101,12 +6081,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 +6660,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 +6668,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 +6679,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 +6867,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 +6889,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 +8276,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 +10542,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 +10556,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 +10581,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 +10589,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 +10597,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); } } @@ -10924,15 +10904,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<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) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 34402f1ac..9967969d3 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -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] = 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; } } } diff --git a/src/p_saveg.c b/src/p_saveg.c index c1a34b2a4..2eb0d7edb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2106,13 +2106,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); diff --git a/src/p_setup.c b/src/p_setup.c index 8c1c9ae72..c85e95307 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2269,7 +2269,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; @@ -2536,29 +2536,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; } } } @@ -2793,7 +2793,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) @@ -3180,19 +3181,8 @@ boolean P_SetupLevel(boolean skipprecip) 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) @@ -3233,7 +3223,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) @@ -3312,7 +3302,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; diff --git a/src/p_spec.c b/src/p_spec.c index 6b5f09f6d..eaa7fa3d6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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) @@ -2383,33 +2383,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { 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; + } } } } @@ -2515,8 +2499,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) @@ -3837,13 +3820,13 @@ DoneSection2: 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)) @@ -7845,40 +7828,40 @@ void T_Pusher(pusher_t *p) { 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;*/ } } diff --git a/src/p_telept.c b/src/p_telept.c index 24e201fc1..74f9d462c 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -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) diff --git a/src/p_tick.c b/src/p_tick.c index 038d00a2a..2502c7213 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -583,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; } @@ -601,7 +601,8 @@ void P_Ticker(boolean run) return; } - postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none; + for (i = 0; i <= splitscreen; i++) + postimgtype[i] = postimg_none; P_MapStart(); @@ -776,14 +777,11 @@ 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(); @@ -799,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) { diff --git a/src/p_user.c b/src/p_user.c index 26ee9f8c4..8d8400264 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -654,13 +654,13 @@ static void P_DeNightserizePlayer(player_t *player) // Restore aiming angle if (player == &players[consoleplayer]) - localaiming = 0; - else if (player == &players[secondarydisplayplayer]) - localaiming2 = 0; - else if (player == &players[thirddisplayplayer]) - localaiming3 = 0; - else if (player == &players[fourthdisplayplayer]) - localaiming4 = 0; + localaiming[0] = 0; + else if (player == &players[displayplayers[1]]) + localaiming[1] = 0; + else if (player == &players[displayplayers[2]]) + localaiming[2] = 0; + else if (player == &players[displayplayers[3]]) + localaiming[3] = 0; if (player->mo->tracer) P_RemoveMobj(player->mo->tracer); @@ -1154,25 +1154,25 @@ boolean P_EndingMusic(player_t *player) // Check for if this is valid or not if (splitscreen) { - if (!((players[displayplayer].exiting || (players[displayplayer].pflags & PF_TIMEOVER)) - || (players[secondarydisplayplayer].exiting || (players[secondarydisplayplayer].pflags & PF_TIMEOVER)) - || ((splitscreen < 2) && (players[thirddisplayplayer].exiting || (players[thirddisplayplayer].pflags & PF_TIMEOVER))) - || ((splitscreen < 3) && (players[fourthdisplayplayer].exiting || (players[fourthdisplayplayer].pflags & PF_TIMEOVER))))) + if (!((players[displayplayers[0]].exiting || (players[displayplayers[0]].pflags & PF_TIMEOVER)) + || (players[displayplayers[1]].exiting || (players[displayplayers[1]].pflags & PF_TIMEOVER)) + || ((splitscreen < 2) && (players[displayplayers[2]].exiting || (players[displayplayers[2]].pflags & PF_TIMEOVER))) + || ((splitscreen < 3) && (players[displayplayers[3]].exiting || (players[displayplayers[3]].pflags & PF_TIMEOVER))))) return false; - bestlocalplayer = &players[displayplayer]; - bestlocalpos = ((players[displayplayer].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayer].kartstuff[k_position]); + bestlocalplayer = &players[displayplayers[0]]; + bestlocalpos = ((players[displayplayers[0]].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayers[0]].kartstuff[k_position]); #define setbests(p) \ if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \ { \ bestlocalplayer = &players[p]; \ bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \ } - setbests(secondarydisplayplayer); + setbests(displayplayers[1]); if (splitscreen > 1) - setbests(thirddisplayplayer); + setbests(displayplayers[2]); if (splitscreen > 2) - setbests(fourthdisplayplayer); + setbests(displayplayers[3]); #undef setbests } else @@ -1253,12 +1253,12 @@ void P_RestoreMusic(player_t *player) else if (players[p].kartstuff[k_invincibilitytimer] > bestlocaltimer) \ { wantedmus = 1; bestlocaltimer = players[p].kartstuff[k_invincibilitytimer]; } \ } - setbests(displayplayer); - setbests(secondarydisplayplayer); + setbests(displayplayers[0]); + setbests(displayplayers[1]); if (splitscreen > 1) - setbests(thirddisplayplayer); + setbests(displayplayers[2]); if (splitscreen > 2) - setbests(fourthdisplayplayer); + setbests(displayplayers[3]); #undef setbests } else @@ -1516,10 +1516,39 @@ fixed_t P_GetPlayerSpinHeight(player_t *player) // boolean P_IsLocalPlayer(player_t *player) { - return ((splitscreen > 2 && player == &players[fourthdisplayplayer]) - || (splitscreen > 1 && player == &players[thirddisplayplayer]) - || (splitscreen && player == &players[secondarydisplayplayer]) - || player == &players[consoleplayer]); + UINT8 i; + + if (player == &players[consoleplayer]) + return true; + else if (splitscreen) + { + for (i = 1; i <= splitscreen; i++) // Skip P1 + { + if (player == &players[displayplayers[i]]) + return true; + } + } + + return false; +} + +// +// P_IsDisplayPlayer +// +// Returns true if player is +// currently being watched. +// +boolean P_IsDisplayPlayer(player_t *player) +{ + UINT8 i; + + for (i = 0; i <= splitscreen; i++) // DON'T skip P1 + { + if (player == &players[displayplayers[i]]) + return true; + } + + return false; } // @@ -1772,11 +1801,7 @@ void P_DoPlayerExit(player_t *player) if (player->exiting || mapreset) return; - if ((player == &players[consoleplayer] - || (splitscreen && player == &players[secondarydisplayplayer]) - || (splitscreen > 1 && player == &players[thirddisplayplayer]) - || (splitscreen > 2 && player == &players[fourthdisplayplayer])) - && (!player->spectator && !demo.playback)) + if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback)) legitimateexit = true; if (G_RaceGametype()) // If in Race Mode, allow @@ -2515,8 +2540,7 @@ static void P_DoPlayerHeadSigns(player_t *player) // If you're "IT", show a big "IT" over your head for others to see. if (player->pflags & PF_TAGIT) { - if (!(player == &players[consoleplayer] || player == &players[displayplayer] || player == &players[secondarydisplayplayer] - || player == &players[thirddisplayplayer] || player == &players[fourthdisplayplayer])) // Don't display it on your own view. + if (!P_IsDisplayPlayer(player)) // Don't display it on your own view. { if (!(player->mo->eflags & MFE_VERTICALFLIP)) P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height, MT_TAG); @@ -3004,13 +3028,13 @@ static void P_DoClimbing(player_t *player) // SRB2kart - unused } 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 (player->climbing == 0) P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); @@ -3675,13 +3699,13 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->angle = player->mo->angle - ANGLE_180; // Turn around from the wall you were climbing. if (player == &players[consoleplayer]) - localangle = player->mo->angle; // Adjust the local control 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; // Adjust the local control 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; player->climbing = 0; // Stop climbing, duh! P_InstaThrust(player->mo, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale)); // Jump off the wall. @@ -4365,14 +4389,14 @@ boolean P_AnalogMove(player_t *player) fixed_t tempx = 0, tempy = 0; angle_t tempangle, origtempangle; - 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; + if (splitscreen > 2 && player == &players[displayplayers[3]]) + thiscam = &camera[3]; + else if (splitscreen > 1 && player == &players[displayplayers[2]]) + thiscam = &camera[2]; + else if (splitscreen && player == &players[displayplayers[1]]) + thiscam = &camera[1]; else - thiscam = &camera; + thiscam = &camera[0]; if (!cmd->forwardmove && !cmd->sidemove) return 0; @@ -4513,13 +4537,13 @@ static void P_2dMovement(player_t *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 (player->pflags & PF_GLIDING) movepushangle = player->mo->angle; @@ -6049,13 +6073,13 @@ static void P_NiGHTSMovement(player_t *player) P_SetMobjStateNF(player->mo->tracer, leveltime & 1 ? flystate : flystate+1); 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 (still) { @@ -6082,13 +6106,13 @@ static void P_NiGHTSMovement(player_t *player) movingangle = InvAngle(movingangle); if (player == &players[consoleplayer]) - localaiming = movingangle; - else if (player == &players[secondarydisplayplayer]) - localaiming2 = movingangle; - else if (player == &players[thirddisplayplayer]) - localaiming3 = movingangle; - else if (player == &players[fourthdisplayplayer]) - localaiming4 = movingangle; + localaiming[0] = movingangle; + else if (player == &players[displayplayers[1]]) + localaiming[1] = movingangle; + else if (player == &players[displayplayers[2]]) + localaiming[2] = movingangle; + else if (player == &players[displayplayers[3]]) + localaiming[3] = movingangle; player->mo->tracer->angle = player->mo->angle; @@ -6352,7 +6376,7 @@ static void P_MovePlayer(player_t *player) { if (G_IsSpecialStage(gamemap)) { - if (player == &players[displayplayer]) // only play the sound for yourself landing + if (player == &players[displayplayers[0]]) // only play the sound for yourself landing S_StartSound(NULL, sfx_s3k6a); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) @@ -6865,13 +6889,13 @@ static void P_MovePlayer(player_t *player) // Update the local angle control. 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; } #endif @@ -7193,13 +7217,13 @@ static void P_DoZoomTube(player_t *player) player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); 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 0 if (player->mo->state != &states[S_KART_SPIN]) @@ -7589,13 +7613,13 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target if (source->player) { if (source->player == &players[consoleplayer]) - localangle = source->angle; - else if (source->player == &players[secondarydisplayplayer]) - localangle2 = source->angle; - else if (source->player == &players[thirddisplayplayer]) - localangle3 = source->angle; - else if (source->player == &players[fourthdisplayplayer]) - localangle4 = source->angle; + localangle[0] = source->angle; + else if (source->player == &players[displayplayers[1]]) + localangle[1] = source->angle; + else if (source->player == &players[displayplayers[2]]) + localangle[2] = source->angle; + else if (source->player == &players[displayplayers[3]]) + localangle[3] = source->angle; } // change slope @@ -7728,7 +7752,7 @@ notrealplayer: // P_MoveCamera: make sure the camera is not outside the world and looks at the player avatar // -camera_t camera, camera2, camera3, camera4; // Four cameras, three for splitscreen +camera_t camera[MAXSPLITSCREENPLAYERS]; // Four cameras, three for splitscreen static void CV_CamRotate_OnChange(void) { @@ -7809,17 +7833,6 @@ fixed_t t_cam4_rotate = -42; #define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode) -camera_t *P_GetCameraPtr(UINT8 viewnum) -{ - switch (viewnum) - { - case 2: return &camera2; - case 3: return &camera3; - case 4: return &camera4; - } - return &camera; -} - void P_ResetCamera(player_t *player, camera_t *thiscam) { tic_t tries = 0; @@ -7844,10 +7857,10 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) thiscam->y = y; thiscam->z = z; - if (!(thiscam == &camera && (cv_cam_still.value || cv_analog.value)) - && !(thiscam == &camera2 && (cv_cam2_still.value || cv_analog2.value)) - && !(thiscam == &camera3 && (cv_cam3_still.value || cv_analog3.value)) - && !(thiscam == &camera4 && (cv_cam4_still.value || cv_analog4.value))) + if (!(thiscam == &camera[0] && (cv_cam_still.value || cv_analog.value)) + && !(thiscam == &camera[1] && (cv_cam2_still.value || cv_analog2.value)) + && !(thiscam == &camera[2] && (cv_cam3_still.value || cv_analog3.value)) + && !(thiscam == &camera[3] && (cv_cam4_still.value || cv_analog4.value))) { thiscam->angle = player->mo->angle; thiscam->aiming = 0; @@ -7905,31 +7918,32 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->spectator) // force cam off for spectators return true; - if (!cv_chasecam.value && thiscam == &camera) + if (!cv_chasecam.value && thiscam == &camera[0]) return true; - if (!cv_chasecam2.value && thiscam == &camera2) + if (!cv_chasecam2.value && thiscam == &camera[1]) return true; - if (!cv_chasecam3.value && thiscam == &camera3) + if (!cv_chasecam3.value && thiscam == &camera[2]) return true; - if (!cv_chasecam4.value && thiscam == &camera4) + if (!cv_chasecam4.value && thiscam == &camera[3]) return true; } if (!thiscam->chase && !resetcalled) { if (player == &players[consoleplayer]) - focusangle = localangle; - else if (player == &players[secondarydisplayplayer]) - focusangle = localangle2; - else if (player == &players[thirddisplayplayer]) - focusangle = localangle3; - else if (player == &players[fourthdisplayplayer]) - focusangle = localangle4; + focusangle = localangle[0]; + else if (player == &players[displayplayers[1]]) + focusangle = localangle[1]; + else if (player == &players[displayplayers[2]]) + focusangle = localangle[2]; + else if (player == &players[displayplayers[3]]) + focusangle = localangle[3]; else focusangle = mo->angle; + if (thiscam == &camera) camrotate = cv_cam_rotate.value; else if (thiscam == &camera2) @@ -7940,11 +7954,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camrotate = cv_cam4_rotate.value; else camrotate = 0; + if (leveltime < introtime) // Whoooshy camera! { const INT32 introcam = (introtime - leveltime); camrotate += introcam*5; } + thiscam->angle = focusangle + FixedAngle(camrotate*FRACUNIT); P_ResetCamera(player, thiscam); return true; @@ -7965,23 +7981,23 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } else if (player == &players[consoleplayer]) { - focusangle = localangle; - focusaiming = localaiming; + focusangle = localangle[0]; + focusaiming = localaiming[0]; } - else if (player == &players[secondarydisplayplayer]) + else if (player == &players[displayplayers[1]]) { - focusangle = localangle2; - focusaiming = localaiming2; + focusangle = localangle[1]; + focusaiming = localaiming[1]; } - else if (player == &players[thirddisplayplayer]) + else if (player == &players[displayplayers[2]]) { - focusangle = localangle3; - focusaiming = localaiming3; + focusangle = localangle[2]; + focusaiming = localaiming[2]; } - else if (player == &players[fourthdisplayplayer]) + else if (player == &players[displayplayers[3]]) { - focusangle = localangle4; - focusaiming = localaiming4; + focusangle = localangle[3]; + focusaiming = localaiming[3]; } else { @@ -7992,17 +8008,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_CameraThinker(player, thiscam, resetcalled)) return true; - if (thiscam == &camera) - { - num = 0; - camspeed = cv_cam_speed.value; - camstill = cv_cam_still.value; - camrotate = cv_cam_rotate.value; - camdist = FixedMul(cv_cam_dist.value, mapobjectscale); - camheight = FixedMul(cv_cam_height.value, mapobjectscale); - lookback = camspin; - } - else if (thiscam == &camera2) // Camera 2 + + if (thiscam == &camera[1]) // Camera 2 { num = 1; camspeed = cv_cam2_speed.value; @@ -8010,9 +8017,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camrotate = cv_cam2_rotate.value; camdist = FixedMul(cv_cam2_dist.value, mapobjectscale); camheight = FixedMul(cv_cam2_height.value, mapobjectscale); - lookback = camspin2; + lookback = camspin[1]; } - else if (thiscam == &camera3) // Camera 3 + else if (thiscam == &camera[2]) // Camera 3 { num = 2; camspeed = cv_cam3_speed.value; @@ -8020,9 +8027,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camrotate = cv_cam3_rotate.value; camdist = FixedMul(cv_cam3_dist.value, mapobjectscale); camheight = FixedMul(cv_cam3_height.value, mapobjectscale); - lookback = camspin3; + lookback = camspin[2]; } - else // Camera 4 + else if (thiscam == &camera[3]) // Camera 4 { num = 3; camspeed = cv_cam4_speed.value; @@ -8030,7 +8037,17 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camrotate = cv_cam4_rotate.value; camdist = FixedMul(cv_cam4_dist.value, mapobjectscale); camheight = FixedMul(cv_cam4_height.value, mapobjectscale); - lookback = camspin4; + lookback = camspin[3]; + } + else // Camera 1 + { + num = 0; + camspeed = cv_cam_speed.value; + camstill = cv_cam_still.value; + camrotate = cv_cam_rotate.value; + camdist = FixedMul(cv_cam_dist.value, mapobjectscale); + camheight = FixedMul(cv_cam_height.value, mapobjectscale); + lookback = camspin[0]; } if (timeover) @@ -8091,10 +8108,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } if (!resetcalled && (leveltime > starttime && timeover != 2) - && ((thiscam == &camera && t_cam_rotate != -42) - || (thiscam == &camera2 && t_cam2_rotate != -42) - || (thiscam == &camera3 && t_cam3_rotate != -42) - || (thiscam == &camera4 && t_cam4_rotate != -42))) + && ((thiscam == &camera[0] && t_cam_rotate != -42) + || (thiscam == &camera[1] && t_cam2_rotate != -42) + || (thiscam == &camera[2] && t_cam3_rotate != -42) + || (thiscam == &camera[3] && t_cam4_rotate != -42))) { angle = FixedAngle(camrotate*FRACUNIT); thiscam->angle = angle; @@ -8489,8 +8506,8 @@ boolean P_SpectatorJoinGame(player_t *player) player->playerstate = PST_REBORN; //Reset away view - if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) - displayplayer = consoleplayer; + if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer) + displayplayers[0] = consoleplayer; if (changeto == 1) CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80'); @@ -8513,8 +8530,8 @@ boolean P_SpectatorJoinGame(player_t *player) player->playerstate = PST_REBORN; //Reset away view - if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) - displayplayer = consoleplayer; + if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer) + displayplayers[0] = consoleplayer; HU_AddChatText(va(M_GetText("\x82*%s entered the game."), player_names[player-players]), false); return true; // no more player->mo, cannot continue. @@ -8528,6 +8545,7 @@ static void P_CalcPostImg(player_t *player) postimg_t *type; INT32 *param; fixed_t pviewheight; + UINT8 i; if (player->mo->eflags & MFE_VERTICALFLIP) pviewheight = player->mo->z + player->mo->height - player->viewheight; @@ -8540,25 +8558,14 @@ static void P_CalcPostImg(player_t *player) pviewheight = player->awayviewmobj->z + 20*FRACUNIT; } - if (splitscreen > 2 && player == &players[fourthdisplayplayer]) + for (i = 0; i <= splitscreen; i++) { - type = &postimgtype4; - param = &postimgparam4; - } - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - { - type = &postimgtype3; - param = &postimgparam3; - } - else if (splitscreen && player == &players[secondarydisplayplayer]) - { - type = &postimgtype2; - param = &postimgparam2; - } - else - { - type = &postimgtype; - param = &postimgparam; + if (player == &players[displayplayers[i]]) + { + type = &postimgtype[i]; + param = &postimgparam[i]; + break; + } } // see if we are in heat (no, not THAT kind of heat...) @@ -8666,11 +8673,7 @@ void P_DoTimeOver(player_t *player) player->pflags |= PF_TIMEOVER; - if ((player == &players[consoleplayer] - || (splitscreen && player == &players[secondarydisplayplayer]) - || (splitscreen > 1 && player == &players[thirddisplayplayer]) - || (splitscreen > 2 && player == &players[fourthdisplayplayer])) - && !demo.playback) + if (P_IsLocalPlayer(player) && !demo.playback) legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p if (player->mo) @@ -8717,7 +8720,7 @@ void P_PlayerThink(player_t *player) } #ifdef SEENAMES - if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)) && !splitscreen) + if (netgame && player == &players[displayplayers[0]] && !(leveltime % (TICRATE/5)) && !splitscreen) { seenplayer = NULL; @@ -9064,7 +9067,9 @@ void P_PlayerThink(player_t *player) || player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) { + UINT8 i; mobj_t *gmobj = P_SpawnGhostMobj(player->mo); + gmobj->fuse = 2; if (leveltime & 1) { @@ -9072,15 +9077,17 @@ void P_PlayerThink(player_t *player) gmobj->frame |= tr_trans70< 1 && player == &players[thirddisplayplayer] && !camera3.chase) - || (splitscreen > 2 && player == &players[fourthdisplayplayer] && !camera4.chase)) - gmobj->flags2 |= MF2_DONTDRAW; + for (i = 0; i <= splitscreen; i++) + { + if (player == &players[displayplayers[i]] && !camera[i].chase) + { + gmobj->flags2 |= MF2_DONTDRAW; + break; + } + } } #endif @@ -9280,6 +9287,7 @@ void P_PlayerAfterThink(player_t *player) ticcmd_t *cmd; //INT32 oldweapon = player->currentweapon; // SRB2kart - unused camera_t *thiscam = NULL; // if not one of the displayed players, just don't bother + UINT8 i; #ifdef PARANOIA if (!player->mo) @@ -9302,14 +9310,14 @@ void P_PlayerAfterThink(player_t *player) P_PlayerInSpecialSector(player); #endif - 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 if (player == &players[displayplayer]) - thiscam = &camera; + for (i = 0; i <= splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + { + thiscam = &camera[i]; + break; + } + } if (player->playerstate == PST_DEAD) { @@ -9494,13 +9502,13 @@ void P_PlayerAfterThink(player_t *player) player->mo->angle = player->mo->tracer->angle; 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 (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius) @@ -9568,13 +9576,13 @@ void P_PlayerAfterThink(player_t *player) player->mo->angle += cmd->sidemove< ANGLE_MAX if (player == &players[consoleplayer]) - localangle = player->mo->angle; // Adjust the local control 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; // Adjust the local control 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; } } diff --git a/src/r_bsp.c b/src/r_bsp.c index b819735e1..296cbbe87 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -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); } diff --git a/src/r_bsp.h b/src/r_bsp.h index 7810c9b5c..e3662e2e6 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -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 diff --git a/src/r_main.c b/src/r_main.c index b4dcd9183..122062431 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -65,9 +65,10 @@ size_t loopcount; fixed_t viewx, viewy, viewz; angle_t viewangle, aimingangle; +UINT8 viewnumber; 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; @@ -195,17 +196,10 @@ void SplitScreen_OnChange(void) 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 +209,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 +844,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[i]) + { + thiscam = &camera[i]; + break; + } + } + } // cut-away view stuff viewsky = true; @@ -883,23 +887,20 @@ void R_SkyboxFrame(player_t *player) { 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 +1079,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); } @@ -1145,23 +1146,20 @@ void R_SetupFrame(player_t *player, boolean skybox) { 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; + } + } } } } @@ -1323,19 +1321,24 @@ void R_RenderPlayerView(player_t *player) { portal_pair *portal; const boolean skybox = (skyboxmo[0] && cv_skybox.value); - UINT8 viewnumber; + UINT8 i; - 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; + viewnumber = 0; // default + + if (splitscreen) + { + for (i = 1; i <= splitscreen; i++) + { + if (player == &players[i]) + { + viewnumber = i; + break; + } + } + } // 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 +1346,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 +1365,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 +1389,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 +1422,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 +1447,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 +1473,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; + } + } } // ========================================================================= diff --git a/src/r_plane.c b/src/r_plane.c index 0ff97fcc3..db5bfbda2 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -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)); diff --git a/src/r_state.h b/src/r_state.h index d6d123e99..6e21e4477 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -88,8 +88,9 @@ extern side_t *sides; // extern fixed_t viewx, viewy, viewz; extern angle_t viewangle, aimingangle; +extern UINT8 viewnumber; // 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; diff --git a/src/r_things.c b/src/r_things.c index efc5dd466..71957bb54 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1702,7 +1702,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 @@ -2664,11 +2664,11 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) { 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) diff --git a/src/r_things.h b/src/r_things.h index 6f48cc5bf..499d80413 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -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); diff --git a/src/s_sound.c b/src/s_sound.c index 1585753f9..8e649d08c 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -438,7 +438,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 +450,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 +482,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 +501,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 +519,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 +537,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 +899,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; @@ -940,31 +940,31 @@ void S_UpdateSounds(void) 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 +989,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 +1007,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 +1025,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 +1060,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 +1071,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 +1247,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 { diff --git a/src/st_stuff.c b/src/st_stuff.c index bbfa4c047..3b35907b7 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -372,7 +372,7 @@ static inline void ST_InitData(void) // 'link' the statusbar display to a player, which could be // another player than consoleplayer, for example, when you // change the view in a multiplayer demo with F12. - stplyr = &players[displayplayer]; + stplyr = &players[displayplayers[0]]; st_palette = -1; } @@ -442,7 +442,7 @@ static INT32 SCY(INT32 y) if (splitscreen) { y >>= 1; - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) y += vid.height / 2; } return y; @@ -458,7 +458,7 @@ static INT32 STRINGY(INT32 y) if (splitscreen) { y >>= 1; - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) y += BASEVIDHEIGHT / 2; } return y; @@ -471,7 +471,7 @@ static INT32 SPLITFLAGS(INT32 f) // Pass this V_SNAPTO(TOP|BOTTOM) and it'll trim them to account for splitscreen! -Red if (splitscreen) { - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) f &= ~V_SNAPTOTOP; else f &= ~V_SNAPTOBOTTOM; @@ -498,7 +498,7 @@ static INT32 SCR(INT32 r) if (splitscreen) { y >>= 1; - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) y += vid.height / 2; } return FixedInt(FixedDiv(y, vid.fdupy)); @@ -701,7 +701,7 @@ static inline void ST_drawRings(void) // SRB2kart - unused. /* static void ST_drawLives(void) // SRB2kart - unused. { - const INT32 v_splitflag = (splitscreen && stplyr == &players[displayplayer] ? V_SPLITSCREEN : 0); + const INT32 v_splitflag = (splitscreen && stplyr == &players[displayplayers[0]] ? V_SPLITSCREEN : 0); if (!stplyr->skincolor) return; // Just joined a server, skin isn't loaded yet! @@ -1019,7 +1019,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused. if (G_IsSpecialStage(gamemap)) { // Since special stages share score, time, rings, etc. // disable splitscreen mode for its HUD. - if (stplyr != &players[displayplayer]) + if (stplyr != &players[displayplayers[0]]) return; nosshack = splitscreen; splitscreen = 0; @@ -1124,7 +1124,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused. V_DrawScaledPatch(locx, STRINGY(locy)-3, V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_HUDTRANS, drillfill[fillpatch]); - stplyr = &players[secondarydisplayplayer]; + stplyr = &players[displayplayers[1]]; if (stplyr->pflags & PF_DRILLING) fillpatch = (stplyr->drillmeter & 1) + 1; else @@ -1132,7 +1132,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused. V_DrawScaledPatch(locx, STRINGY(locy-3), V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); - stplyr = &players[displayplayer]; + stplyr = &players[displayplayers[0]]; splitscreen = 0; } else @@ -1881,7 +1881,7 @@ static void ST_overlayDrawer(void) ST_drawTeamName(); // Special Stage HUD - if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer]) + if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayers[0]]) ST_drawSpecialStageHUD(); // Emerald Hunt Indicators @@ -1919,7 +1919,7 @@ static void ST_overlayDrawer(void) { char name[MAXPLAYERNAME+12]; - INT32 y = (stplyr == &players[displayplayer]) ? 4 : BASEVIDHEIGHT/2-12; + INT32 y = (stplyr == &players[displayplayers[0]]) ? 4 : BASEVIDHEIGHT/2-12; sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name); } @@ -1930,10 +1930,10 @@ static void ST_overlayDrawer(void) } // This is where we draw all the fun cheese if you have the chasecam off! - /*if ((stplyr == &players[displayplayer] && !camera.chase) - || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase) - || ((splitscreen > 1 && stplyr == &players[thirddisplayplayer]) && !camera3.chase) - || ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) + /*if ((stplyr == &players[displayplayers[0]] && !camera[0].chase) + || ((splitscreen && stplyr == &players[displayplayers[1]]) && !camera[1].chase) + || ((splitscreen > 1 && stplyr == &players[displayplayers[2]]) && !camera[2].chase) + || ((splitscreen > 2 && stplyr == &players[displayplayers[3]]) && !camera[3].chase)) { ST_drawFirstPersonHUD(); }*/ @@ -2086,8 +2086,10 @@ static void ST_MayonakaStatic(void) void ST_Drawer(void) { + UINT8 i; + #ifdef SEENAMES - if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo && !mapreset) + if (cv_seenames.value && cv_allowseenames.value && displayplayers[0] == consoleplayer && seenplayer && seenplayer->mo && !mapreset) { if (cv_seenames.value == 1) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); @@ -2121,26 +2123,12 @@ void ST_Drawer(void) if (st_overlay) { // No deadview! - stplyr = &players[displayplayer]; - ST_overlayDrawer(); - - if (splitscreen) + for (i = 0; i <= splitscreen; i++) { - stplyr = &players[secondarydisplayplayer]; + stplyr = &players[displayplayers[i]]; ST_overlayDrawer(); - - if (splitscreen > 1) - { - stplyr = &players[thirddisplayplayer]; - ST_overlayDrawer(); - - if (splitscreen > 2) - { - stplyr = &players[fourthdisplayplayer]; - ST_overlayDrawer(); - } - } } + // draw Midnight Channel's overlay ontop if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. ST_MayonakaStatic(); diff --git a/src/y_inter.c b/src/y_inter.c index f37084282..f7f4845bb 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -360,7 +360,7 @@ void Y_IntermissionDrawer(void) V_DrawFadeScreen(0xFF00, 22); if (!splitscreen) - whiteplayer = demo.playback ? displayplayer : consoleplayer; + whiteplayer = demo.playback ? displayplayers[0] : consoleplayer; if (cons_menuhighlight.value) hilicol = cons_menuhighlight.value; @@ -1051,19 +1051,19 @@ void Y_VoteDrawer(void) { case 1: thiscurs = cursor2; - p = secondarydisplayplayer; + p = displayplayers[1]; break; case 2: thiscurs = cursor3; - p = thirddisplayplayer; + p = displayplayers[2]; break; case 3: thiscurs = cursor4; - p = fourthdisplayplayer; + p = displayplayers[3]; break; default: thiscurs = cursor1; - p = displayplayer; + p = displayplayers[0]; break; } @@ -1218,10 +1218,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level) S_StartSound(NULL, sfx_noooo2); // gasp else if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU)) S_StartSound(NULL, sfx_noooo1); // this is bad - else if (netgame && (pick == consoleplayer - || pick == secondarydisplayplayer - || pick == thirddisplayplayer - || pick == fourthdisplayplayer)) + else if (netgame && P_IsLocalPlayer(&players[pick])) S_StartSound(NULL, sfx_yeeeah); // yeeeah! else S_StartSound(NULL, sfx_kc48); // just a cool sound @@ -1354,13 +1351,13 @@ void Y_VoteTicker(void) switch (i) { case 1: - p = secondarydisplayplayer; + p = displayplayers[1]; break; case 2: - p = thirddisplayplayer; + p = displayplayers[2]; break; case 3: - p = fourthdisplayplayer; + p = displayplayers[3]; break; default: p = consoleplayer; From a3d2b4832922fd26e7937fa733ac258a1a75702a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 18 Apr 2019 12:20:13 -0400 Subject: [PATCH 283/382] Fix up more stuff Now in a mergable state --- src/d_main.c | 2 + src/d_net.h | 1 - src/doomstat.h | 3 + src/g_game.c | 2 +- src/hardware/hw3sound.c | 10 +-- src/hardware/hw_main.c | 167 ++++++++++++++-------------------------- src/k_kart.c | 2 +- src/p_local.h | 2 + src/p_mobj.c | 2 + src/p_spec.c | 2 + src/p_user.c | 10 +-- src/r_main.c | 20 +---- src/r_state.h | 3 +- src/r_things.c | 16 ++-- src/s_sound.c | 4 +- 15 files changed, 98 insertions(+), 148 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index b3ae0adea..313980397 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -436,6 +436,8 @@ static void D_Display(void) objectsdrawn = 0; } + viewssnum = i; + #ifdef HWRENDER if (rendermode != render_soft) HWR_RenderPlayerView(i, &players[displayplayers[i]]); diff --git a/src/d_net.h b/src/d_net.h index 8e518e404..eb657eec1 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -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) diff --git a/src/doomstat.h b/src/doomstat.h index 4c4270bec..f80efe631 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -77,7 +77,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; diff --git a/src/g_game.c b/src/g_game.c index 109c2baa5..f9c8f401c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -7397,7 +7397,7 @@ void G_DoPlayDemo(char *defdemoname) // Load players that were in-game when the map started p = READUINT8(demo_p); - for (i = 1; i < MAXSPLITSCREENPLAYERS; i++); + for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) displayplayers[i] = INT32_MAX; while (p != 0xFF) diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c index f7c6e1da0..2594a5df9 100644 --- a/src/hardware/hw3sound.c +++ b/src/hardware/hw3sound.c @@ -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); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4fcef218a..54395ab45 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -63,7 +63,7 @@ struct hwdriver_s hwdriver; // ========================================================================== -static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer); +static void HWR_AddSprites(sector_t *sec); static void HWR_ProjectSprite(mobj_t *thing); #ifdef HWPRECIP static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); @@ -3389,7 +3389,7 @@ static void HWR_AddPolyObjectPlanes(void) // : Draw one or more line segments. // Notes : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures // -----------------+ -static void HWR_Subsector(size_t num, UINT8 ssplayer) +static void HWR_Subsector(size_t num) { INT16 count; seg_t *line; @@ -3754,7 +3754,7 @@ static void HWR_Subsector(size_t num, UINT8 ssplayer) { // draw sprites first, coz they are clipped to the solidsegs of // subsectors more 'in front' - HWR_AddSprites(gr_frontsector, ssplayer); + HWR_AddSprites(gr_frontsector); //Hurdler: at this point validcount must be the same, but is not because // gr_frontsector doesn't point anymore to sub->sector due to @@ -3806,7 +3806,7 @@ static boolean HWR_CheckHackBBox(fixed_t *bb) // BP: big hack for a test in lighning ref : 1249753487AB fixed_t *hwbbox; -static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) +static void HWR_RenderBSPNode(INT32 bspnum) { /*//GZDoom code if(bspnum == -1) @@ -3846,12 +3846,12 @@ static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) if (bspnum == -1) { //*(gr_drawsubsector_p++) = 0; - HWR_Subsector(0, ssplayer); + HWR_Subsector(0); } else { //*(gr_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR); - HWR_Subsector(bspnum&(~NF_SUBSECTOR), ssplayer); + HWR_Subsector(bspnum&(~NF_SUBSECTOR)); } return; } @@ -3863,14 +3863,14 @@ static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) hwbbox = bsp->bbox[side]; // Recursively divide front space. - HWR_RenderBSPNode(bsp->children[side], ssplayer); + HWR_RenderBSPNode(bsp->children[side]); // Possibly divide back space. if (HWR_CheckBBox(bsp->bbox[side^1])) { // BP: big hack for a test in lighning ref : 1249753487AB hwbbox = bsp->bbox[side^1]; - HWR_RenderBSPNode(bsp->children[side^1], ssplayer); + HWR_RenderBSPNode(bsp->children[side^1]); } } @@ -4097,14 +4097,14 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t angle_t shadowdir; // Set direction - if (splitscreen && stplyr == &players[secondarydisplayplayer]) - shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value); - else if (splitscreen > 1 && stplyr == &players[thirddisplayplayer]) - shadowdir = localangle3 + FixedAngle(cv_cam3_rotate.value); - else if (splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) - shadowdir = localangle4 + FixedAngle(cv_cam4_rotate.value); + if (splitscreen && stplyr == &players[displayplayers[1]]) + shadowdir = localangle[1] + FixedAngle(cv_cam2_rotate.value); + else if (splitscreen > 1 && stplyr == &players[displayplayers[2]]) + shadowdir = localangle[2] + FixedAngle(cv_cam3_rotate.value); + else if (splitscreen > 2 && stplyr == &players[displayplayers[3]]) + shadowdir = localangle[3] + FixedAngle(cv_cam4_rotate.value); else - shadowdir = localangle + FixedAngle(cv_cam_rotate.value); + shadowdir = localangle[0] + FixedAngle(cv_cam_rotate.value); // Find floorheight floorheight = HWR_OpaqueFloorAtPos( @@ -5283,7 +5283,7 @@ static void HWR_DrawSprites(void) // During BSP traversal, this adds sprites by sector. // -------------------------------------------------------------------------- static UINT8 sectorlight; -static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer) +static void HWR_AddSprites(sector_t *sec) { mobj_t *thing; #ifdef HWPRECIP @@ -5316,19 +5316,19 @@ static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer) if (splitscreen) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (ssplayer != 1) + if (viewssnum != 0) continue; if (thing->eflags & MFE_DRAWONLYFORP2) - if (ssplayer != 2) + if (viewssnum != 1) continue; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (ssplayer != 3) + if (viewssnum != 2) continue; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (ssplayer != 4) + if (viewssnum != 3) continue; } @@ -5351,19 +5351,19 @@ static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer) if (splitscreen) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (ssplayer != 1) + if (viewssnum != 0) continue; if (thing->eflags & MFE_DRAWONLYFORP2) - if (ssplayer != 2) + if (viewssnum != 1) continue; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (ssplayer != 3) + if (viewssnum != 2) continue; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (ssplayer != 4) + if (viewssnum != 3) continue; } @@ -5906,33 +5906,8 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); postimg_t *type; - UINT8 ssplayer = 0; - if (splitscreen) - { - if (player == &players[secondarydisplayplayer]) - { - type = &postimgtype2; - ssplayer = 2; - } - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - { - type = &postimgtype3; - ssplayer = 3; - } - else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - { - type = &postimgtype4; - ssplayer = 4; - } - else - { - type = &postimgtype; - ssplayer = 1; - } - } - else - type = &postimgtype; + type = &postimgtype[viewnumber]; { // do we really need to save player (is it not the same)? @@ -6056,36 +6031,36 @@ if (0) validcount++; - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); + HWR_RenderBSPNode((INT32)numnodes-1); #ifndef NEWCLIP // Make a viewangle int so we can render things based on mouselook if (player == &players[consoleplayer]) - viewangle = localaiming; - else if (splitscreen && player == &players[secondarydisplayplayer]) - viewangle = localaiming2; - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - viewangle = localaiming3; - else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - viewangle = localaiming4; + viewangle = localaiming[0]; + else if (splitscreen && player == &players[displayplayers[1]]) + viewangle = localaiming[1]; + else if (splitscreen > 1 && player == &players[displayplayers[2]]) + viewangle = localaiming[2]; + else if (splitscreen > 2 && player == &players[displayplayers[3]]) + viewangle = localaiming[3]; // Handle stuff when you are looking farther up or down. if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //left + HWR_RenderBSPNode((INT32)numnodes-1); //left dup_viewangle += ANGLE_90; if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //back + HWR_RenderBSPNode((INT32)numnodes-1); //back } dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //right + HWR_RenderBSPNode((INT32)numnodes-1); //right dup_viewangle += ANGLE_90; } @@ -6149,38 +6124,13 @@ if (0) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); - postimg_t *type; - UINT8 ssplayer = 0; + postimg_t *type = &postimgtype[viewnumber]; const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on FRGBAFloat ClearColor; - if (splitscreen) - { - if (player == &players[secondarydisplayplayer]) - { - type = &postimgtype2; - ssplayer = 2; - } - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - { - type = &postimgtype3; - ssplayer = 3; - } - else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - { - type = &postimgtype4; - ssplayer = 4; - } - else - { - type = &postimgtype; - ssplayer = 1; - } - } - else - type = &postimgtype; + type = &postimgtype[viewnumber]; ClearColor.red = 0.0f; ClearColor.green = 0.0f; @@ -6315,36 +6265,36 @@ if (0) validcount++; - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); + HWR_RenderBSPNode((INT32)numnodes-1); #ifndef NEWCLIP // Make a viewangle int so we can render things based on mouselook if (player == &players[consoleplayer]) - viewangle = localaiming; - else if (splitscreen && player == &players[secondarydisplayplayer]) - viewangle = localaiming2; - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - viewangle = localaiming3; - else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - viewangle = localaiming4; + viewangle = localaiming[0]; + else if (splitscreen && player == &players[displayplayers[1]]) + viewangle = localaiming[1]; + else if (splitscreen > 1 && player == &players[displayplayers[2]]) + viewangle = localaiming[2]; + else if (splitscreen > 2 && player == &players[displayplayers[3]]) + viewangle = localaiming[3]; // Handle stuff when you are looking farther up or down. if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //left + HWR_RenderBSPNode((INT32)numnodes-1); //left dup_viewangle += ANGLE_90; if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //back + HWR_RenderBSPNode((INT32)numnodes-1); //back } dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //right + HWR_RenderBSPNode((INT32)numnodes-1); //right dup_viewangle += ANGLE_90; } @@ -6807,16 +6757,17 @@ INT32 HWR_GetTextureUsed(void) void HWR_DoPostProcessor(player_t *player) { - postimg_t *type; + postimg_t *type = &postimgtype[0]; + UINT8 i; - if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - type = &postimgtype4; - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - type = &postimgtype3; - else if (splitscreen && player == &players[secondarydisplayplayer]) - type = &postimgtype2; - else - type = &postimgtype; + for (i = splitscreen; i > 0; i--) + { + if (player == &players[displayplayers[i]]) + { + type = &postimgtype[i]; + break; + } + } // Armageddon Blast Flash! // Could this even be considered postprocessor? diff --git a/src/k_kart.c b/src/k_kart.c index 1237a5920..17885b71a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8224,7 +8224,7 @@ static void K_drawBattleFullscreen(void) // check to see if there's anyone else at all for (i = 0; i < MAXPLAYERS; i++) { - if (i == displayplayer) + if (i == displayplayers[0]) continue; if (playeringame[i] && !stplyr->spectator) return; diff --git a/src/p_local.h b/src/p_local.h index 5f7c4ef98..bfb78cef5 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -22,6 +22,7 @@ #include "p_tick.h" #include "r_defs.h" #include "p_maputl.h" +#include "doomstat.h" // MAXSPLITSCREENPLAYERS #define FLOATSPEED (FRACUNIT*4) @@ -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); diff --git a/src/p_mobj.c b/src/p_mobj.c index 102af9dca..9d583d131 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1135,6 +1135,8 @@ static void P_PlayerFlip(mobj_t *mo) } else if (mo->player->pflags & PF_FLIPCAM) { + UINT8 i; + mo->player->aiming = InvAngle(mo->player->aiming); for (i = 0; i <= splitscreen; i++) diff --git a/src/p_spec.c b/src/p_spec.c index eaa7fa3d6..9ed17eaa7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2381,6 +2381,8 @@ 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); diff --git a/src/p_user.c b/src/p_user.c index 8d8400264..df93eaac3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7944,13 +7944,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else focusangle = mo->angle; - if (thiscam == &camera) + if (thiscam == &camera[0]) camrotate = cv_cam_rotate.value; - else if (thiscam == &camera2) + else if (thiscam == &camera[1]) camrotate = cv_cam2_rotate.value; - else if (thiscam == &camera3) + else if (thiscam == &camera[2]) camrotate = cv_cam3_rotate.value; - else if (thiscam == &camera4) + else if (thiscam == &camera[3]) camrotate = cv_cam4_rotate.value; else camrotate = 0; @@ -8542,7 +8542,7 @@ boolean P_SpectatorJoinGame(player_t *player) static void P_CalcPostImg(player_t *player) { sector_t *sector = player->mo->subsector->sector; - postimg_t *type; + postimg_t *type = postimg_none; INT32 *param; fixed_t pviewheight; UINT8 i; diff --git a/src/r_main.c b/src/r_main.c index 122062431..2a7d2be96 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -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,7 +66,7 @@ size_t loopcount; fixed_t viewx, viewy, viewz; angle_t viewangle, aimingangle; -UINT8 viewnumber; +UINT8 viewssnum; fixed_t viewcos, viewsin; boolean viewsky, skyVisible; boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player @@ -1151,6 +1152,7 @@ void R_SetupFrame(player_t *player, boolean skybox) } else if (splitscreen) { + UINT8 i; for (i = 1; i <= splitscreen; i++) { if (player == &players[displayplayers[i]]) @@ -1323,20 +1325,6 @@ void R_RenderPlayerView(player_t *player) const boolean skybox = (skyboxmo[0] && cv_skybox.value); UINT8 i; - viewnumber = 0; // default - - if (splitscreen) - { - for (i = 1; i <= splitscreen; i++) - { - if (player == &players[i]) - { - viewnumber = i; - break; - } - } - } - // if this is display player 1 if (cv_homremoval.value && player == &players[displayplayers[0]]) { @@ -1367,7 +1355,7 @@ void R_RenderPlayerView(player_t *player) // load previous saved value of skyVisible for the player for (i = 0; i <= splitscreen; i++) { - if (player == &players[displayplayers[i]] + if (player == &players[displayplayers[i]]) { skyVisible = skyVisiblePerPlayer[i]; break; diff --git a/src/r_state.h b/src/r_state.h index 6e21e4477..e37bdf52e 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -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,7 +89,7 @@ extern side_t *sides; // extern fixed_t viewx, viewy, viewz; extern angle_t viewangle, aimingangle; -extern UINT8 viewnumber; // splitscreen view number +extern UINT8 viewssnum; // splitscreen view number extern boolean viewsky, skyVisible; extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player extern sector_t *viewsector; diff --git a/src/r_things.c b/src/r_things.c index 71957bb54..6af423101 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1748,19 +1748,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) 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; } @@ -1783,19 +1783,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) 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; } diff --git a/src/s_sound.c b/src/s_sound.c index 8e649d08c..a89946a54 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -935,8 +935,8 @@ 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) { From 7dae0ad87551042741646cbcd1109089208c6828 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 18 Apr 2019 22:41:50 -0700 Subject: [PATCH 284/382] Show rooms list in server browser initially If you haven't selected a room yet, you're shown the room list instead of server list. --- src/m_menu.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3ad076ff7..fefafff31 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7456,7 +7456,10 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; - M_SetupNextMenu(&MP_ConnectDef); + if (ms_RoomId < 0) + M_RoomMenu(0); // Select a room instead of staring at an empty list + else + M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; M_Refresh(0); } @@ -7529,7 +7532,15 @@ static void M_ChooseRoom(INT32 choice) } serverlistpage = 0; - M_SetupNextMenu(currentMenu->prevMenu); + /* + We were on the Multiplayer menu? That means that we must have been trying to + view the server browser, but we hadn't selected a room yet. So we need to go + to the browser next, not back there. + */ + if (currentMenu->prevMenu == &MP_MainDef) + M_SetupNextMenu(&MP_ConnectDef); + else + M_SetupNextMenu(currentMenu->prevMenu); if (currentMenu == &MP_ConnectDef) M_Refresh(0); } From c2a14da4b52695eccda4d38bf91cfca50c179ede Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 18 Apr 2019 23:42:28 -0700 Subject: [PATCH 285/382] Add a command to increment cvars --- src/command.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/command.c b/src/command.c index a5d45bc1e..74b9ef51f 100644 --- a/src/command.c +++ b/src/command.c @@ -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); @@ -291,6 +292,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); } @@ -855,6 +857,27 @@ 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 : 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; + } + + CV_AddValue(cvar, atoi(COM_Argv(2))); +} + // ========================================================================= // VARIABLE SIZE BUFFERS // ========================================================================= From 6a5bb9f23f5985a6d25a8839cf1b7a3f151b89fb Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 18 Apr 2019 23:50:29 -0700 Subject: [PATCH 286/382] Add a "-noaudio" parm to cover "-nomusic" and "-nosound" --- src/d_main.c | 25 ++++++++++++++++++------- src/s_sound.c | 6 +++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 84d5a6f32..82f3721a5 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1390,10 +1390,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 +1400,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 diff --git a/src/s_sound.c b/src/s_sound.c index 2ddffa3f5..58cc0592f 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2182,7 +2182,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 +2196,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 +2239,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; From 870f29f8616f0c99e262e5f2ab172d2228a93d48 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 21 Apr 2019 07:52:01 -0500 Subject: [PATCH 287/382] Flashing tics on respawn --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9d928a2a2..17790bf00 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1568,7 +1568,7 @@ void K_RespawnChecker(player_t *player) if (!P_IsObjectOnGround(player->mo) && !mapreset) { - player->powers[pw_flashing] = 2; + player->powers[pw_flashing] = K_GetKartFlashing(player); // Sal: The old behavior was stupid and prone to accidental usage. // Let's rip off Mania instead, and turn this into a Drop Dash! From 3e838c1e831d363c953692b73ab643cf3ba61083 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 22 Apr 2019 00:29:47 -0400 Subject: [PATCH 288/382] New IntermissionThinker hook --- src/lua_hook.h | 3 +++ src/lua_hooklib.c | 23 +++++++++++++++++++++++ src/y_inter.c | 11 ++++++++--- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 126e7e405..e61acdf13 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -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 diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 5a95877e3..c15d13a0c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -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) { diff --git a/src/y_inter.c b/src/y_inter.c index 095b4ad36..18c6ab330 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -40,6 +40,7 @@ #include "g_input.h" // PLAYER1INPUTDOWN #include "k_kart.h" // colortranslations #include "console.h" // cons_menuhighlight +#include "lua_hook.h" // IntermissionThinker hook #ifdef HWRENDER #include "hardware/hw_main.h" @@ -574,13 +575,17 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; +#ifdef HAVE_BLUA + LUAh_IntermissionThinker(); +#endif + intertic++; // Team scramble code for team match and CTF. - // Don't do this if we're going to automatically scramble teams next round. + // Don't do this if we' + // If we run out re going to automatically scramble teams next round. /*if (G_GametypeHasTeams() && cv_teamscramble.value && !cv_scrambleonchange.value && server) - { - // If we run out of time in intermission, the beauty is that + {of time in intermission, the beauty is that // the P_Ticker() team scramble code will pick it up. if ((intertic % (TICRATE/7)) == 0) P_DoTeamscrambling(); From 60428fbc29cc5725f97e0130cf6c668164825a94 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 22 Apr 2019 11:29:44 +0200 Subject: [PATCH 289/382] Add option to turn off the PLAY default md2 --- src/hardware/hw_main.c | 2 +- src/hardware/hw_main.h | 1 + src/m_menu.c | 3 ++- src/r_main.c | 1 + src/v_video.c | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4fcef218a..47148a9d0 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5261,7 +5261,7 @@ static void HWR_DrawSprites(void) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { // 8/1/19: Only don't display player models if no default SPR_PLAY is found. - if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && (md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f))) + if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && ((!cv_grdefaultmd2.value) || md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f))) HWR_DrawSprite(spr); else HWR_DrawMD2(spr); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 6978856ea..4d639fafb 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -81,6 +81,7 @@ extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronasize; #endif extern consvar_t cv_grmd2; +extern consvar_t cv_grdefaultmd2; extern consvar_t cv_grfog; extern consvar_t cv_grfogcolor; extern consvar_t cv_grfogdensity; diff --git a/src/m_menu.c b/src/m_menu.c index 3ad076ff7..ddee98744 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1218,7 +1218,8 @@ static menuitem_t OP_VideoOptionsMenu[] = #ifdef HWRENDER {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmd2, 105}, - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 115}, + {IT_STRING | IT_CVAR, NULL, "Default 3D model", &cv_grdefaultmd2, 115}, + {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 125}, #endif }; diff --git a/src/r_main.c b/src/r_main.c index 36182d0e8..92c029b9f 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1571,6 +1571,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grcoronasize); #endif CV_RegisterVar(&cv_grmd2); + CV_RegisterVar(&cv_grdefaultmd2); #endif #ifdef HWRENDER diff --git a/src/v_video.c b/src/v_video.c index 473adeedb..08ec8d3cf 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -81,6 +81,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0 //static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; // console variables in development consvar_t cv_grmd2 = {"gr_md2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grdefaultmd2 = {"gr_defaultmd2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif const UINT8 gammatable[5][256] = From 80d1181cff29a84d97a0967a334e20f300a740bc Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 22 Apr 2019 19:27:42 -0400 Subject: [PATCH 290/382] Fix mangled comment --- src/y_inter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 18c6ab330..61f17626b 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -582,10 +582,10 @@ void Y_Ticker(void) intertic++; // Team scramble code for team match and CTF. - // Don't do this if we' - // If we run out re going to automatically scramble teams next round. + // Don't do this if we're going to automatically scramble teams next round. /*if (G_GametypeHasTeams() && cv_teamscramble.value && !cv_scrambleonchange.value && server) - {of time in intermission, the beauty is that + { + // If we run out of time in intermission, the beauty is that // the P_Ticker() team scramble code will pick it up. if ((intertic % (TICRATE/7)) == 0) P_DoTeamscrambling(); From 9cac5f52779726b1cb655c817d9c0d89e7223ea9 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Mon, 22 Apr 2019 04:24:07 -0500 Subject: [PATCH 291/382] Don't cut off flashing tics when using sneakers, don't allow stealing bumpers while intangible --- src/k_kart.c | 1 - src/p_map.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9d928a2a2..79cfe8763 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3526,7 +3526,6 @@ void K_DoSneaker(player_t *player, INT32 type) { player->pflags |= PF_ATTACKDOWN; K_PlayBoostTaunt(player->mo); - player->powers[pw_flashing] = 0; // Stop flashing after boosting } } diff --git a/src/p_map.c b/src/p_map.c index 256c9cef1..07f8abbda 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -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); From 313b971e17dffbf7560875e2036d448c6cd33439 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 22 Apr 2019 10:39:42 +0200 Subject: [PATCH 292/382] Fix SPB being way too fast in current sections where the player has no control --- src/p_enemy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index d62ec7efb..31a5a61bf 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8434,6 +8434,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); From dab5469b4aa0045f0e6991688af406436d7a7566 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 23 Apr 2019 23:49:46 +0200 Subject: [PATCH 293/382] Terminology changes --- src/hardware/hw_main.c | 2 +- src/hardware/hw_main.h | 2 +- src/m_menu.c | 2 +- src/r_main.c | 2 +- src/v_video.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 47148a9d0..3bb0627ee 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5261,7 +5261,7 @@ static void HWR_DrawSprites(void) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { // 8/1/19: Only don't display player models if no default SPR_PLAY is found. - if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && ((!cv_grdefaultmd2.value) || md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f))) + if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && ((!cv_grfallbackplayermodel.value) || md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f))) HWR_DrawSprite(spr); else HWR_DrawMD2(spr); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4d639fafb..720e82ee2 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -81,7 +81,7 @@ extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronasize; #endif extern consvar_t cv_grmd2; -extern consvar_t cv_grdefaultmd2; +extern consvar_t cv_grfallbackplayermodel; extern consvar_t cv_grfog; extern consvar_t cv_grfogcolor; extern consvar_t cv_grfogdensity; diff --git a/src/m_menu.c b/src/m_menu.c index ddee98744..10f8eae03 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1218,7 +1218,7 @@ static menuitem_t OP_VideoOptionsMenu[] = #ifdef HWRENDER {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmd2, 105}, - {IT_STRING | IT_CVAR, NULL, "Default 3D model", &cv_grdefaultmd2, 115}, + {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 115}, {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 125}, #endif }; diff --git a/src/r_main.c b/src/r_main.c index 92c029b9f..a33280841 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1571,7 +1571,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grcoronasize); #endif CV_RegisterVar(&cv_grmd2); - CV_RegisterVar(&cv_grdefaultmd2); + CV_RegisterVar(&cv_grfallbackplayermodel); #endif #ifdef HWRENDER diff --git a/src/v_video.c b/src/v_video.c index 08ec8d3cf..ae4783947 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -81,7 +81,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0 //static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; // console variables in development consvar_t cv_grmd2 = {"gr_md2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grdefaultmd2 = {"gr_defaultmd2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif const UINT8 gammatable[5][256] = From cae59aad9a21a625c1a39c7a81598df833d42d6b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 25 Apr 2019 23:13:09 -0400 Subject: [PATCH 294/382] Save showjoinaddress to config --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e227ce2ed..0c440c176 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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}; From 50ae248b84defb4d399fa9794783fd51ab32f696 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 26 Apr 2019 12:59:21 -0700 Subject: [PATCH 295/382] Unfuck MS connecting and error reporting Reconnect if the socket is closed. Report the proper error from SO_ERROR and report an error from getsockopt. --- src/mserv.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index f5c4fa889..eb1e6302e 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -661,11 +661,19 @@ FUNCMATH static const char *int2str(INT32 n) #ifndef NONET static INT32 ConnectionFailed(void) { + time(&MSLastPing); con_state = MSCS_FAILED; CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n")); CloseConnection(); return MS_CONNECT_ERROR; } + +static INT32 ConnectionFailedwerrno(int no) +{ + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error: %s\n"), + strerror(no)); + return ConnectionFailed(); +} #endif /** Tries to register the local game server on the master server. @@ -682,44 +690,41 @@ static INT32 AddToMasterServer(boolean firstadd) msg_server_t *info = (msg_server_t *)msg.buffer; INT32 room = -1; fd_set tset; - time_t timestamp = time(NULL); UINT32 signature, tmp; const char *insname; + if (socket_fd == ERRSOCKET)/* Woah, our socket was closed! */ + { + if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) + return ConnectionFailedwerrno(errno); + } + M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res != ERRSOCKET && !res) + if (res == 0)/* nothing selected */ { - if (retry++ > 30) // an about 30 second timeout + /* + Timeout next call because SendPingToMasterServer + (our calling function) already calls this once + every two minutes. + */ + if (retry++ == 1) { retry = 0; CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n")); - MSLastPing = timestamp; return ConnectionFailed(); } return MS_CONNECT_ERROR; } retry = 0; - if (res == ERRSOCKET) - { - if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) - { - CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); - MSLastPing = timestamp; - return ConnectionFailed(); - } - } // so, the socket is writable, but what does that mean, that the connection is // ok, or bad... let see that! j = (socklen_t)sizeof (i); - getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j); + if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j) == ERRSOCKET) + return ConnectionFailedwerrno(errno); if (i) // it was bad - { - CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); - MSLastPing = timestamp; - return ConnectionFailed(); - } + return ConnectionFailedwerrno(i); #ifdef PARANOIA if (ms_RoomId <= 0) @@ -752,15 +757,12 @@ static INT32 AddToMasterServer(boolean firstadd) msg.length = (UINT32)sizeof (msg_server_t); msg.room = 0; if (MS_Write(&msg) < 0) - { - MSLastPing = timestamp; return ConnectionFailed(); - } if(con_state != MSCS_REGISTERED) CONS_Printf(M_GetText("Master Server update successful.\n")); - MSLastPing = timestamp; + time(&MSLastPing); con_state = MSCS_REGISTERED; CloseConnection(); #endif From 1d77716d7ebeea2bf279d690a6c0542ff155cb22 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 26 Apr 2019 13:06:26 -0700 Subject: [PATCH 296/382] Check error on select --- src/mserv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mserv.c b/src/mserv.c index eb1e6302e..1b0b41be3 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -701,6 +701,8 @@ static INT32 AddToMasterServer(boolean firstadd) M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); + if (res == -1) + return ConnectionFailedwerrno(errno); if (res == 0)/* nothing selected */ { /* From 9f0887fafca1388561c535714c60d84016f2f447 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 26 Apr 2019 13:08:35 -0700 Subject: [PATCH 297/382] Force of habit --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 1b0b41be3..5d10aa3ca 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -701,7 +701,7 @@ static INT32 AddToMasterServer(boolean firstadd) M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == -1) + if (res == ERRSOCKET) return ConnectionFailedwerrno(errno); if (res == 0)/* nothing selected */ { From 2e221946777c2d0b287059aceb59a4aa3478da86 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 26 Apr 2019 18:18:53 -0400 Subject: [PATCH 298/382] Final v1 colors - 11 new colors: Skunk, Artichoke, Pigeon, Walnut, Cinnamon, Lemonade, Quarry, Crocodile, Azure, Thunder, & Wristwatch - Updated Dawn, Sunset, Cream, Gold, Olive, Vomit, Lime, Plague, & Caribbean - Updated opposite colors for Bubblegum & Camouflage in response to the new colors --- src/dehacked.c | 17 +++++++++----- src/doomdef.h | 11 +++++++++ src/hu_stuff.c | 11 +++++++++ src/k_kart.c | 60 +++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 1c88fe832..0431eb0c7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8135,29 +8135,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 @@ -8176,8 +8182,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 @@ -8197,6 +8205,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 @@ -8206,7 +8215,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 @@ -8227,10 +8238,6 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "POMEGRANATE", // SKINCOLOR_POMEGRANATE "LILAC", // SKINCOLOR_LILAC - - - - // Special super colors // Super Sonic Yellow "SUPER1", // SKINCOLOR_SUPER1 diff --git a/src/doomdef.h b/src/doomdef.h index 6664ff51a..07761c60f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -256,22 +256,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 +296,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 +319,7 @@ typedef enum SKINCOLOR_PLAGUE, SKINCOLOR_ALGAE, SKINCOLOR_CARIBBEAN, + SKINCOLOR_AZURE, SKINCOLOR_AQUA, SKINCOLOR_TEAL, SKINCOLOR_CYAN, @@ -320,7 +329,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, diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b43570735..cb9499c6d 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -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 diff --git a/src/k_kart.c b/src/k_kart.c index 79cfe8763..df65a7c9e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -49,22 +49,28 @@ const char *KartColor_Names[MAXSKINCOLORS] = "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 @@ -83,8 +89,10 @@ const char *KartColor_Names[MAXSKINCOLORS] = "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 @@ -104,6 +112,7 @@ const char *KartColor_Names[MAXSKINCOLORS] = "Plague", // SKINCOLOR_PLAGUE "Algae", // SKINCOLOR_ALGAE "Caribbean", // SKINCOLOR_CARIBBEAN + "Azure", // SKINCOLOR_AZURE "Aqua", // SKINCOLOR_AQUA "Teal", // SKINCOLOR_TEAL "Cyan", // SKINCOLOR_CYAN @@ -113,7 +122,9 @@ const char *KartColor_Names[MAXSKINCOLORS] = "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 @@ -144,22 +155,28 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_GREY,8, // SKINCOLOR_GREY SKINCOLOR_SILVER,8, // SKINCOLOR_NICKEL SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK - SKINCOLOR_CAMOUFLAGE,8, // SKINCOLOR_FAIRY - SKINCOLOR_BUBBLEGUM,8, // SKINCOLOR_POPCORN + SKINCOLOR_SKUNK,8, // SKINCOLOR_SKUNK + SKINCOLOR_ARTICHOKE,12, // SKINCOLOR_FAIRY + SKINCOLOR_PIGEON,12, // SKINCOLOR_POPCORN + SKINCOLOR_FAIRY,12, // SKINCOLOR_ARTICHOKE + SKINCOLOR_POPCORN,12, // SKINCOLOR_PIGEON SKINCOLOR_LEATHER,6, // SKINCOLOR_SEPIA SKINCOLOR_BROWN,2, // SKINCOLOR_BEIGE + SKINCOLOR_CAMOUFLAGE,8, // SKINCOLOR_WALNUT SKINCOLOR_BEIGE,8, // SKINCOLOR_BROWN SKINCOLOR_SEPIA,8, // SKINCOLOR_LEATHER SKINCOLOR_TEA,8, // SKINCOLOR_SALMON SKINCOLOR_PISTACHIO,8, // SKINCOLOR_PINK SKINCOLOR_MOSS,8, // SKINCOLOR_ROSE SKINCOLOR_RUST,8, // SKINCOLOR_BRICK + SKINCOLOR_WRISTWATCH,6, // SKINCOLOR_CINNAMON SKINCOLOR_SAPPHIRE,8, // SKINCOLOR_RUBY SKINCOLOR_MINT,8, // SKINCOLOR_RASPBERRY SKINCOLOR_HANDHELD,10, // SKINCOLOR_CHERRY SKINCOLOR_GREEN,6, // SKINCOLOR_RED SKINCOLOR_PINETREE,6, // SKINCOLOR_CRIMSON SKINCOLOR_TOXIC,8, // SKINCOLOR_MAROON + SKINCOLOR_THUNDER,8, // SKINCOLOR_LEMONADE SKINCOLOR_CARIBBEAN,10, // SKINCOLOR_FLAME SKINCOLOR_ALGAE,10, // SKINCOLOR_SCARLET SKINCOLOR_MUSTARD,10, // SKINCOLOR_KETCHUP @@ -178,8 +195,10 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_PLATINUM,6, // SKINCOLOR_ROYAL SKINCOLOR_STEEL,8, // SKINCOLOR_BRONZE SKINCOLOR_CREAM,6, // SKINCOLOR_COPPER + SKINCOLOR_AZURE,8, // SKINCOLOR_QUARRY SKINCOLOR_AQUA,8, // SKINCOLOR_YELLOW SKINCOLOR_KETCHUP,8, // SKINCOLOR_MUSTARD + SKINCOLOR_BUBBLEGUM,8, // SKINCOLOR_CROCODILE SKINCOLOR_TEAL,8, // SKINCOLOR_OLIVE SKINCOLOR_ROBOHOOD,8, // SKINCOLOR_VOMIT SKINCOLOR_LAVENDER,6, // SKINCOLOR_GARDEN @@ -188,7 +207,7 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_SALMON,8, // SKINCOLOR_TEA SKINCOLOR_PINK,6, // SKINCOLOR_PISTACHIO SKINCOLOR_ROSE,8, // SKINCOLOR_MOSS - SKINCOLOR_FAIRY,10, // SKINCOLOR_CAMOUFLAGE + SKINCOLOR_WALNUT,8, // SKINCOLOR_CAMOUFLAGE SKINCOLOR_VOMIT,8, // SKINCOLOR_ROBOHOOD SKINCOLOR_RASPBERRY,8, // SKINCOLOR_MINT SKINCOLOR_RED,8, // SKINCOLOR_GREEN @@ -199,6 +218,7 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_NOVA,8, // SKINCOLOR_PLAGUE SKINCOLOR_SCARLET,10, // SKINCOLOR_ALGAE SKINCOLOR_FLAME,8, // SKINCOLOR_CARIBBEAN + SKINCOLOR_QUARRY,8, // SKINCOLOR_AZURE SKINCOLOR_YELLOW,8, // SKINCOLOR_AQUA SKINCOLOR_OLIVE,8, // SKINCOLOR_TEAL SKINCOLOR_PEACH,8, // SKINCOLOR_CYAN @@ -208,7 +228,9 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_ROYAL,8, // SKINCOLOR_PLATINUM SKINCOLOR_GOLD,10, // SKINCOLOR_SLATE SKINCOLOR_BRONZE,10, // SKINCOLOR_STEEL + SKINCOLOR_LEMONADE,8, // SKINCOLOR_THUNDER SKINCOLOR_BRICK,10, // SKINCOLOR_RUST + SKINCOLOR_CINNAMON,8, // SKINCOLOR_WRISTWATCH SKINCOLOR_BURGUNDY,8, // SKINCOLOR_JET SKINCOLOR_RUBY,6, // SKINCOLOR_SAPPHIRE SKINCOLOR_CREAMSICLE,8, // SKINCOLOR_PERIWINKLE @@ -219,7 +241,7 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_SUNSET,10, // SKINCOLOR_MOONSLAM SKINCOLOR_MAUVE,10, // SKINCOLOR_ULTRAVIOLET SKINCOLOR_DAWN,6, // SKINCOLOR_DUSK - SKINCOLOR_POPCORN,12, // SKINCOLOR_BUBBLEGUM + SKINCOLOR_CROCODILE,8, // SKINCOLOR_BUBBLEGUM SKINCOLOR_EMERALD,8, // SKINCOLOR_PURPLE SKINCOLOR_PASTEL,11, // SKINCOLOR_FUCHSIA SKINCOLOR_MAROON,8, // SKINCOLOR_TOXIC @@ -237,27 +259,33 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY { 3, 5, 8, 11, 15, 17, 19, 21, 23, 24, 25, 26, 27, 29, 30, 31}, // SKINCOLOR_NICKEL { 4, 7, 11, 15, 20, 22, 24, 27, 28, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_BLACK + {120, 120, 0, 2, 4, 10, 16, 22, 23, 24, 25, 26, 27, 28, 29, 31}, // SKINCOLOR_SKUNK {120, 120, 121, 121, 122, 123, 10, 14, 16, 18, 20, 22, 24, 26, 28, 31}, // SKINCOLOR_FAIRY {120, 96, 97, 98, 99, 71, 32, 11, 13, 16, 18, 21, 23, 26, 28, 31}, // SKINCOLOR_POPCORN + { 97, 176, 177, 162, 163, 179, 12, 14, 16, 18, 20, 22, 24, 26, 28, 31}, // SKINCOLOR_ARTICHOKE + { 0, 208, 209, 211, 226, 202, 14, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_PIGEON { 0, 1, 3, 5, 7, 9, 34, 36, 38, 40, 42, 44, 60, 61, 62, 63}, // SKINCOLOR_SEPIA {120, 65, 67, 69, 32, 34, 36, 38, 40, 42, 44, 45, 46, 47, 62, 63}, // SKINCOLOR_BEIGE + { 3, 6, 32, 33, 35, 37, 51, 52, 54, 55, 57, 58, 60, 61, 63, 30}, // SKINCOLOR_WALNUT { 67, 70, 73, 76, 48, 49, 51, 53, 54, 56, 58, 59, 61, 63, 29, 30}, // SKINCOLOR_BROWN { 72, 76, 48, 51, 53, 55, 57, 59, 61, 63, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER {120, 120, 120, 121, 121, 122, 123, 124, 126, 127, 129, 131, 133, 135, 137, 139}, // SKINCOLOR_SALMON {120, 121, 121, 122, 144, 145, 146, 147, 148, 149, 150, 151, 134, 136, 138, 140}, // SKINCOLOR_PINK {144, 145, 146, 147, 148, 149, 150, 151, 134, 135, 136, 137, 138, 139, 140, 141}, // SKINCOLOR_ROSE { 64, 67, 70, 73, 146, 147, 148, 150, 118, 118, 119, 119, 156, 159, 141, 143}, // SKINCOLOR_BRICK + { 68, 75, 48, 50, 52, 94, 152, 136, 137, 138, 139, 140, 141, 142, 143, 31}, // SKINCOLOR_CINNAMON {120, 121, 144, 145, 147, 149, 132, 133, 134, 136, 198, 198, 199, 255, 30, 31}, // SKINCOLOR_RUBY {120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 131, 134, 136, 137, 139, 140}, // SKINCOLOR_RASPBERRY {120, 65, 67, 69, 71, 124, 125, 127, 132, 133, 135, 136, 138, 139, 140, 141}, // SKINCOLOR_CHERRY {122, 123, 124, 126, 129, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142}, // SKINCOLOR_RED {123, 125, 128, 131, 133, 135, 136, 138, 140, 140, 141, 141, 142, 142, 143, 31}, // SKINCOLOR_CRIMSON {123, 124, 126, 128, 132, 135, 137, 27, 28, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_MAROON + {120, 96, 97, 98, 99, 65, 122, 144, 123, 124, 147, 149, 151, 153, 156, 159}, // SKINCOLOR_LEMONADE {120, 97, 112, 113, 113, 85, 87, 126, 149, 150, 151, 252, 253, 254, 255, 29}, // SKINCOLOR_FLAME { 99, 113, 113, 84, 85, 87, 126, 128, 130, 196, 197, 198, 199, 240, 243, 246}, // SKINCOLOR_SCARLET {103, 113, 113, 84, 85, 88, 127, 130, 131, 133, 134, 136, 138, 139, 141, 143}, // SKINCOLOR_KETCHUP - {120, 121, 122, 123, 124, 147, 147, 148, 90, 91, 92, 93, 94, 95, 152, 154}, // SKINCOLOR_DAWN - { 98, 112, 113, 84, 85, 87, 89, 149, 150, 251, 252, 206, 238, 240, 243, 246}, // SKINCOLOR_SUNSET + {120, 121, 122, 123, 124, 147, 148, 91, 93, 95, 152, 154, 156, 159, 141, 143}, // SKINCOLOR_DAWN + { 98, 112, 113, 84, 85, 87, 89, 149, 150, 251, 251, 205, 206, 207, 29, 31}, // SKINCOLOR_SUNSET {120, 120, 80, 80, 81, 82, 83, 83, 84, 85, 86, 88, 89, 91, 93, 95}, // SKINCOLOR_CREAMSICLE { 80, 81, 82, 83, 84, 85, 86, 88, 89, 91, 94, 95, 154, 156, 158, 159}, // SKINCOLOR_ORANGE { 82, 83, 84, 85, 87, 89, 90, 92, 94, 152, 153, 155, 157, 159, 141, 142}, // SKINCOLOR_PUMPKIN @@ -266,17 +294,19 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { { 98, 98, 112, 112, 113, 113, 84, 85, 87, 89, 91, 93, 95, 153, 156, 159}, // SKINCOLOR_TANGERINE {120, 80, 66, 70, 72, 76, 148, 149, 150, 151, 153, 154, 156, 61, 62, 63}, // SKINCOLOR_PEACH { 64, 66, 68, 70, 72, 74, 76, 78, 48, 50, 52, 54, 56, 58, 60, 62}, // SKINCOLOR_CARAMEL - {120, 120, 96, 96, 97, 82, 84, 77, 50, 54, 57, 59, 61, 63, 29, 31}, // SKINCOLOR_CREAM - {112, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119}, // SKINCOLOR_GOLD + {120, 96, 96, 97, 98, 82, 84, 77, 50, 54, 57, 59, 61, 63, 29, 31}, // SKINCOLOR_CREAM + { 96, 97, 98, 112, 113, 114, 115, 116, 117, 151, 118, 119, 157, 159, 140, 143}, // SKINCOLOR_GOLD { 97, 112, 113, 113, 114, 78, 53, 252, 252, 253, 253, 254, 255, 29, 30, 31}, // SKINCOLOR_ROYAL {112, 113, 114, 115, 116, 117, 118, 119, 156, 157, 158, 159, 141, 141, 142, 143}, // SKINCOLOR_BRONZE {120, 99, 113, 114, 116, 117, 119, 61, 63, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_COPPER + { 96, 97, 98, 99, 104, 105, 106, 107, 117, 152, 154, 156, 159, 141, 142, 143}, // SKINCOLOR_QUARRY { 96, 97, 98, 100, 101, 102, 104, 113, 114, 115, 116, 117, 118, 119, 156, 159}, // SKINCOLOR_YELLOW { 96, 98, 99, 112, 113, 114, 114, 106, 106, 107, 107, 108, 108, 109, 110, 111}, // SKINCOLOR_MUSTARD - {105, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 31}, // SKINCOLOR_OLIVE - {121, 144, 145, 72, 73, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT + {120, 96, 97, 98, 176, 113, 114, 106, 115, 107, 108, 109, 110, 174, 175, 31}, // SKINCOLOR_CROCODILE + { 98, 101, 104, 105, 106, 115, 107, 108, 182, 109, 183, 110, 174, 111, 30, 31}, // SKINCOLOR_OLIVE + { 0, 121, 122, 144, 71, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT { 98, 99, 112, 101, 113, 114, 106, 179, 180, 180, 181, 182, 183, 173, 174, 175}, // SKINCOLOR_GARDEN - { 96, 97, 99, 100, 102, 104, 160, 162, 164, 166, 168, 171, 223, 223, 207, 31}, // SKINCOLOR_LIME + {120, 96, 97, 98, 99, 176, 177, 163, 164, 166, 168, 170, 223, 207, 243, 31}, // SKINCOLOR_LIME { 98, 104, 105, 105, 106, 167, 168, 169, 170, 171, 172, 173, 174, 175, 30, 31}, // SKINCOLOR_HANDHELD {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 182, 183}, // SKINCOLOR_TEA {120, 120, 176, 176, 177, 177, 178, 179, 165, 166, 167, 168, 169, 170, 171, 172}, // SKINCOLOR_PISTACHIO @@ -289,9 +319,10 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { {160, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 191, 175}, // SKINCOLOR_EMERALD {160, 184, 185, 186, 187, 188, 189, 190, 191, 191, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_SWAMP {120, 120, 80, 80, 81, 177, 162, 164, 228, 228, 204, 204, 205, 205, 206, 207}, // SKINCOLOR_DREAM - {176, 160, 184, 185, 186, 187, 188, 230, 230, 206, 206, 207, 28, 29, 30, 31}, // SKINCOLOR_PLAGUE + { 97, 176, 160, 184, 185, 186, 187, 229, 229, 205, 206, 207, 28, 29, 30, 31}, // SKINCOLOR_PLAGUE {208, 209, 210, 211, 213, 220, 216, 167, 168, 188, 188, 189, 190, 191, 30, 31}, // SKINCOLOR_ALGAE - {120, 176, 177, 160, 185, 220, 216, 217, 221, 230, 206, 206, 254, 255, 29, 31}, // SKINCOLOR_CARIBBEAN + {120, 176, 177, 160, 185, 220, 216, 217, 229, 229, 204, 205, 206, 254, 255, 31}, // SKINCOLOR_CARIBBEAN + {120, 96, 97, 98, 177, 220, 216, 217, 218, 204, 252, 253, 254, 255, 30, 31}, // SKINCOLOR_AZURE {120, 208, 208, 210, 212, 214, 220, 220, 220, 221, 221, 222, 222, 223, 223, 191}, // SKINCOLOR_AQUA {210, 213, 220, 220, 220, 216, 216, 221, 221, 221, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL {120, 120, 208, 208, 209, 210, 211, 212, 213, 215, 216, 217, 218, 219, 222, 223}, // SKINCOLOR_CYAN @@ -301,7 +332,9 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { {120, 0, 0, 200, 200, 201, 11, 14, 17, 218, 222, 223, 238, 240, 243, 246}, // SKINCOLOR_PLATINUM {120, 120, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 204, 205, 206, 207}, // SKINCOLOR_SLATE {120, 200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 207, 31}, // SKINCOLOR_STEEL + { 96, 97, 98, 112, 113, 114, 11, 203, 204, 205, 205, 237, 239, 241, 243, 246}, // SKINCOLOR_THUNDER { 64, 66, 68, 70, 32, 34, 36, 203, 204, 205, 24, 25, 26, 28, 29, 31}, // SKINCOLOR_RUST + { 81, 72, 76, 48, 51, 55, 252, 205, 205, 206, 240, 241, 242, 243, 244, 246}, // SKINCOLOR_WRISTWATCH {225, 226, 227, 228, 229, 205, 205, 206, 207, 207, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_JET {208, 209, 211, 213, 215, 217, 229, 230, 232, 234, 236, 238, 240, 242, 244, 246}, // SKINCOLOR_SAPPHIRE {120, 120, 224, 225, 226, 202, 227, 228, 229, 230, 231, 233, 235, 237, 239, 241}, // SKINCOLOR_PERIWINKLE @@ -321,6 +354,7 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { {144, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM {144, 145, 146, 147, 148, 149, 150, 251, 251, 252, 252, 253, 254, 255, 29, 30}, // SKINCOLOR_POMEGRANATE {120, 120, 120, 121, 121, 122, 122, 123, 192, 248, 249, 250, 251, 252, 253, 254}, // SKINCOLOR_LILAC + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 96, 100, 104, 113, 116, 119}, // SKINCOLOR_SUPER1 {120, 120, 120, 120, 120, 120, 120, 120, 96, 98, 101, 104, 113, 115, 117, 119}, // SKINCOLOR_SUPER2 {120, 120, 120, 120, 120, 120, 96, 98, 100, 102, 104, 113, 114, 116, 117, 119}, // SKINCOLOR_SUPER3 From b2e12461d9a5d0cb51fd19322f87ec81f3c7a9ee Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 26 Apr 2019 19:26:22 -0500 Subject: [PATCH 299/382] Fix boost -> drift -> release sliptides not showing the effect when turning right --- src/k_kart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.c b/src/k_kart.c index 79cfe8763..c6f028872 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5031,6 +5031,7 @@ static void K_KartDrift(player_t *player, boolean onground) if ((!player->kartstuff[k_sneakertimer]) || (!player->cmd.driftturn) + || (!player->kartstuff[k_aizdriftstrat]) || (player->cmd.driftturn > 0) != (player->kartstuff[k_aizdriftstrat] > 0)) { if (!player->kartstuff[k_drift]) From 359d06f1b4d4f969f367718c16457a5d6fd0c8cd Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 26 Apr 2019 22:32:31 -0400 Subject: [PATCH 300/382] Modify the first shade of Byzantium --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index df65a7c9e..5eeb9a1be 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -351,7 +351,7 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { {120, 120, 176, 176, 177, 6, 8, 10, 249, 250, 196, 197, 198, 199, 143, 31}, // SKINCOLOR_TOXIC { 96, 97, 98, 112, 113, 73, 146, 248, 249, 251, 205, 205, 206, 207, 29, 31}, // SKINCOLOR_MAUVE {121, 145, 192, 248, 249, 250, 251, 252, 252, 253, 253, 254, 254, 255, 30, 31}, // SKINCOLOR_LAVENDER - {144, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM + {201, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM {144, 145, 146, 147, 148, 149, 150, 251, 251, 252, 252, 253, 254, 255, 29, 30}, // SKINCOLOR_POMEGRANATE {120, 120, 120, 121, 121, 122, 122, 123, 192, 248, 249, 250, 251, 252, 253, 254}, // SKINCOLOR_LILAC From fd251ed29f19470313dda1d5d1e9d0d9ba885cf5 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Apr 2019 17:28:29 -0700 Subject: [PATCH 301/382] Move some cvars out of D_ClientServerInit and save them --- src/d_clisrv.c | 12 +++--------- src/d_netcmd.c | 8 ++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f3b07d343..901879ec4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3199,15 +3199,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 +3250,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 diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 08bf33185..574c39d06 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -667,6 +667,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); From 9e24d4aba7c6a17479baf57813674b6251d6722c Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Apr 2019 19:26:11 +0100 Subject: [PATCH 302/382] Completely untested -encore parameter for the map command; inverts cvar value. --- src/d_netcmd.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 08bf33185..bd0d6fb23 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2204,12 +2204,14 @@ static void Command_Map_f(void) const char *mapname; size_t i; INT32 j, newmapnum; - boolean newresetplayers; + boolean newresetplayers, newencoremode; INT32 newgametype = gametype; - // max length of command: map map03 -gametype coop -noresetplayers -force - // 1 2 3 4 5 6 + // max length of command: map map03 -gametype race -noresetplayers -force -encore + // 1 2 3 4 5 6 7 // = 8 arg max + // i don't know whether this is intrinsic to the system or just someone being weird but + // "noresetplayers" is pretty useless for kart if it turns out this is too close to the limit if (COM_Argc() < 2 || COM_Argc() > 8) { CONS_Printf(M_GetText("map [-gametype [-force]: warp to map\n")); @@ -2292,6 +2294,21 @@ static void Command_Map_f(void) } } + // new encoremode value + // use cvar by default + + newencoremode = (boolean)cv_kartencore.value; + + if (COM_CheckParm("-encore")) + { + if (!M_SecretUnlocked(SECRET_ENCORE) && !newencoremode) + { + CONS_Alert(CONS_NOTICE, M_GetText("You haven't unlocked Encore Mode yet!\n")); + return; + } + newencoremode = !newencoremode; + } + if (!(i = COM_CheckParm("-force")) && newgametype == gametype) // SRB2Kart newresetplayers = false; // if not forcing and gametypes is the same @@ -2322,7 +2339,7 @@ static void Command_Map_f(void) } fromlevelselect = false; - D_MapChange(newmapnum, newgametype, (boolean)cv_kartencore.value, newresetplayers, 0, false, false); + D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false); } /** Receives a map command and changes the map. From 353a5b1b6199d4ace1db4bec3d69ec544090f092 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 21 Apr 2019 17:34:59 -0400 Subject: [PATCH 303/382] New -port param --- src/i_tcp.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 11a84ceba..0e5da8ae1 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -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 "); - 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; @@ -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) From db34bcbdbfaa09069180ee4b8d5965efcd7645cc Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 28 Apr 2019 22:02:25 -0400 Subject: [PATCH 304/382] Prettyify code. --- src/i_tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 0e5da8ae1..fb0e5852d 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -909,9 +909,9 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen } if (getsockname(s, (struct sockaddr *)&sin, &len) == -1) - CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); + CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); else - current_port = (UINT16)ntohs(sin.sin_port); + current_port = (UINT16)ntohs(sin.sin_port); return s; } From 70566c808886eb5d0d9406c452ca2b2be3862f32 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 30 Apr 2019 13:03:13 -0700 Subject: [PATCH 305/382] Fix differing signedness compare --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 5d10aa3ca..29aa99fae 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -693,7 +693,7 @@ static INT32 AddToMasterServer(boolean firstadd) UINT32 signature, tmp; const char *insname; - if (socket_fd == ERRSOCKET)/* Woah, our socket was closed! */ + if (socket_fd == (SOCKET_TYPE)ERRSOCKET)/* Woah, our socket was closed! */ { if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) return ConnectionFailedwerrno(errno); From 913d5dd595ef7fe5d132de6bfb1417c4e454c434 Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 30 Apr 2019 23:08:01 +0100 Subject: [PATCH 306/382] OpenGL sprite billboarding Should work on both normal and precipitation sprites. Sprites that are split by lighting should work correctly. --- src/hardware/hw_main.c | 148 +++++++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 27 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index efecac524..272da06d8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4246,10 +4246,43 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } } +// This is expecting a pointer to an array containing 4 wallVerts for a sprite +static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) +{ + if (spr && spr->mobj && wallVerts) + { + float basey = FIXED_TO_FLOAT(spr->mobj->z); + float lowy = wallVerts[0].y; + if (P_MobjFlip(spr->mobj) == -1) + { + basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); + } + // Rotate sprites to fully billboard with the camera + // X, Y, AND Z need to be manipulated for the polys to rotate around the + // origin, because of how the origin setting works I believe that should + // be mobj->z or mobj->z + mobj->height + wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gr_viewludsin + basey; + wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gr_viewludsin + basey; + // translate back to be around 0 before translating back + wallVerts[3].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos; + wallVerts[2].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos; + + wallVerts[0].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos; + wallVerts[1].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos; + + wallVerts[3].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin; + wallVerts[2].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin; + + wallVerts[0].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin; + wallVerts[1].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin; + } +} + static void HWR_SplitSprite(gr_vissprite_t *spr) { float this_scale = 1.0f; FOutVector wallVerts[4]; + FOutVector baseWallVerts[4]; // This is what the verts should end up as GLPatch_t *gpatch; FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); @@ -4262,11 +4295,13 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) float realtop, realbot, top, bot; float towtop, towbot, towmult; float bheight; + float realheight, heightmult; const sector_t *sector = spr->mobj->subsector->sector; const lightlist_t *list = sector->lightlist; #ifdef ESLOPE float endrealtop, endrealbot, endtop, endbot; float endbheight; + float endrealheight; fixed_t temp; fixed_t v1x, v1y, v2x, v2y; #endif @@ -4299,16 +4334,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) HWR_DrawSpriteShadow(spr, gpatch, this_scale); } - wallVerts[0].x = wallVerts[3].x = spr->x1; - wallVerts[2].x = wallVerts[1].x = spr->x2; - wallVerts[0].z = wallVerts[3].z = spr->z1; - wallVerts[1].z = wallVerts[2].z = spr->z2; + baseWallVerts[0].x = baseWallVerts[3].x = spr->x1; + baseWallVerts[2].x = baseWallVerts[1].x = spr->x2; + baseWallVerts[0].z = baseWallVerts[3].z = spr->z1; + baseWallVerts[1].z = baseWallVerts[2].z = spr->z2; - wallVerts[2].y = wallVerts[3].y = spr->ty; + baseWallVerts[2].y = baseWallVerts[3].y = spr->ty; if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale; + baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale; else - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; + baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height; v1x = FLOAT_TO_FIXED(spr->x1); v1y = FLOAT_TO_FIXED(spr->z1); @@ -4317,44 +4352,56 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (spr->flip) { - wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; - wallVerts[2].sow = wallVerts[1].sow = 0; - }else{ - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s; + baseWallVerts[2].sow = baseWallVerts[1].sow = 0; + } + else + { + baseWallVerts[0].sow = baseWallVerts[3].sow = 0; + baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t; - wallVerts[0].tow = wallVerts[1].tow = 0; - }else{ - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t; + baseWallVerts[0].tow = baseWallVerts[1].tow = 0; + } + else + { + baseWallVerts[3].tow = baseWallVerts[2].tow = 0; + baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t; } // if it has a dispoffset, push it a little towards the camera if (spr->dispoffset) { float co = -gr_viewcos*(0.05f*spr->dispoffset); float si = -gr_viewsin*(0.05f*spr->dispoffset); - wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si; - wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si; - wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co; - wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; + baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; + baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; + baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; + baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; } - realtop = top = wallVerts[3].y; - realbot = bot = wallVerts[0].y; - towtop = wallVerts[3].tow; - towbot = wallVerts[0].tow; + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, baseWallVerts); + + realtop = top = baseWallVerts[3].y; + realbot = bot = baseWallVerts[0].y; + towtop = baseWallVerts[3].tow; + towbot = baseWallVerts[0].tow; towmult = (towbot - towtop) / (top - bot); #ifdef ESLOPE - endrealtop = endtop = wallVerts[2].y; - endrealbot = endbot = wallVerts[1].y; + endrealtop = endtop = baseWallVerts[2].y; + endrealbot = endbot = baseWallVerts[1].y; #endif + // copy the contents of baseWallVerts into the drawn wallVerts array + // baseWallVerts is used to know the final shape to easily get the vertex + // co-ordinates + memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts)); + if (!cv_translucency.value) // translucency disabled { Surf.FlatColor.s.alpha = 0xFF; @@ -4481,12 +4528,53 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; + + // The x and y only need to be adjusted in the case that it's not a papersprite + if (spr->mobj) + { + // Get the x and z of the vertices so billboarding draws correctly + realheight = realbot - realtop; + endrealheight = endrealbot - endrealtop; + heightmult = (realtop - top) / realheight; + wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + + heightmult = (endrealtop - endtop) / endrealheight; + wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + + heightmult = (realtop - bot) / realheight; + wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + + heightmult = (endrealtop - endbot) / endrealheight; + wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + } #else wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); wallVerts[2].y = wallVerts[3].y = top; wallVerts[0].y = wallVerts[1].y = bot; + + // The x and y only need to be adjusted in the case that it's not a papersprite + if (spr->mobj) + { + // Get the x and z of the vertices so billboarding draws correctly + realheight = realbot - realtop; + heightmult = (realtop - top) / realheight; + wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + + heightmult = (realtop - bot) / realheight; + wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + } #endif if (colormap) @@ -4655,6 +4743,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; } + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, wallVerts); + // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components /// \todo coloured @@ -4736,6 +4827,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) wallVerts[0].z = wallVerts[3].z = spr->z1; wallVerts[1].z = wallVerts[2].z = spr->z2; + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, wallVerts); + wallVerts[0].sow = wallVerts[3].sow = 0; wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; From 3a707c093b9b587a9153fd4bf0ef496203fe626d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 1 May 2019 23:30:53 -0400 Subject: [PATCH 307/382] Add options for adjusting deadzone, increase default deadzone from 0.25 to 0.5 --- src/d_netcmd.c | 4 ++++ src/g_game.c | 16 +++++++++++----- src/g_game.h | 8 ++++---- src/m_menu.c | 2 +- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b605c9541..21e83d59b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -864,6 +864,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); diff --git a/src/g_game.c b/src/g_game.c index ad25c8ce9..229cf3d47 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -406,6 +406,8 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, #endif #endif +static CV_PossibleValue_t deadzone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; + // don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. // it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on! @@ -476,6 +478,7 @@ consvar_t cv_aimaxis = {"joyaxis_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, consvar_t cv_lookaxis = {"joyaxis_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_driftaxis = {"joyaxis_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_deadzone = {"joy_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_moveaxis2 = {"joyaxis2_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -484,6 +487,7 @@ consvar_t cv_aimaxis2 = {"joyaxis2_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL consvar_t cv_lookaxis2 = {"joyaxis2_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_driftaxis2 = {"joyaxis2_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_deadzone2 = {"joy2_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_turnaxis3 = {"joyaxis3_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_moveaxis3 = {"joyaxis3_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -492,6 +496,7 @@ consvar_t cv_aimaxis3 = {"joyaxis3_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL consvar_t cv_lookaxis3 = {"joyaxis3_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis3 = {"joyaxis3_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_driftaxis3 = {"joyaxis3_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_deadzone3 = {"joy3_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_turnaxis4 = {"joyaxis4_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_moveaxis4 = {"joyaxis4_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -500,6 +505,7 @@ consvar_t cv_aimaxis4 = {"joyaxis4_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL consvar_t cv_lookaxis4 = {"joyaxis4_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis4 = {"joyaxis4_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_driftaxis4 = {"joyaxis4_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_deadzone4 = {"joy4_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #if MAXPLAYERS > 16 @@ -925,8 +931,8 @@ static INT32 Joy1Axis(axis_input_e axissel) retaxis = +JOYAXISRANGE; if (!Joystick.bGamepadStyle && axissel < AXISDEAD) { - const INT32 jdeadzone = JOYAXISRANGE/4; - if (-jdeadzone < retaxis && retaxis < jdeadzone) + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone.value) >> FRACBITS; + if (abs(retaxis) <= jdeadzone) return 0; } if (flp) retaxis = -retaxis; //flip it around @@ -1006,7 +1012,7 @@ static INT32 Joy2Axis(axis_input_e axissel) retaxis = +JOYAXISRANGE; if (!Joystick2.bGamepadStyle && axissel < AXISDEAD) { - const INT32 jdeadzone = JOYAXISRANGE/4; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone2.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } @@ -1087,7 +1093,7 @@ static INT32 Joy3Axis(axis_input_e axissel) retaxis = +JOYAXISRANGE; if (!Joystick3.bGamepadStyle && axissel < AXISDEAD) { - const INT32 jdeadzone = JOYAXISRANGE/4; + const INT32 jdeadzone = jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone3.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } @@ -1167,7 +1173,7 @@ static INT32 Joy4Axis(axis_input_e axissel) retaxis = +JOYAXISRANGE; if (!Joystick4.bGamepadStyle && axissel < AXISDEAD) { - const INT32 jdeadzone = JOYAXISRANGE/4; + const INT32 jdeadzone = jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone4.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } diff --git a/src/g_game.h b/src/g_game.h index eea149c98..9681491b7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -62,10 +62,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 diff --git a/src/m_menu.c b/src/m_menu.c index fefafff31..a5b21b768 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2493,7 +2493,7 @@ boolean M_Responder(event_t *ev) { if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) { - const INT32 jdeadzone = JOYAXISRANGE/4; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone.value) >> FRACBITS; if (ev->data3 != INT32_MAX) { if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone) From 8f336572ef9cd45f5b5d88aeacd9a04e43ec41b5 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 1 May 2019 23:50:18 -0400 Subject: [PATCH 308/382] Slight Grow improvements for public - Using Grow while Shrunk will make you normal-size, instead of giant. - Baked in a Shrink/Grow noise into K_RemoveGrowShrink, whenever you have either --- src/k_kart.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c6f028872..b826d628a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2124,11 +2124,13 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto static void K_RemoveGrowShrink(player_t *player) { - player->kartstuff[k_growshrinktimer] = 0; - player->kartstuff[k_growcancel] = 0; - if (player->mo && !P_MobjWasRemoved(player->mo)) { + if (player->kartstuff[k_growshrinktimer] > 0) // Play Shrink noise + S_StartSound(player->mo, sfx_kc59); + else if (player->kartstuff[k_growshrinktimer] < 0) // Play Grow noise + S_StartSound(player->mo, sfx_kc5a); + if (player->kartstuff[k_invincibilitytimer] == 0) player->mo->color = player->skincolor; @@ -2138,6 +2140,9 @@ static void K_RemoveGrowShrink(player_t *player) player->mo->destscale = (6*player->mo->destscale)/8; } + player->kartstuff[k_growshrinktimer] = 0; + player->kartstuff[k_growcancel] = 0; + P_RestoreMusic(player); } @@ -3544,8 +3549,13 @@ static void K_DoShrink(player_t *user) continue; if (players[i].kartstuff[k_position] < user->kartstuff[k_position]) { + //P_FlashPal(&players[i], PAL_NUKE, 10); + + // Grow should get taken away. + if (players[i].kartstuff[k_growshrinktimer] > 0) + K_RemoveGrowShrink(&players[i]); // Don't hit while invulnerable! - if (!players[i].kartstuff[k_invincibilitytimer] + else if (!players[i].kartstuff[k_invincibilitytimer] && players[i].kartstuff[k_growshrinktimer] <= 0 && !players[i].kartstuff[k_hyudorotimer]) { @@ -3559,15 +3569,9 @@ static void K_DoShrink(player_t *user) players[i].mo->destscale = (6*mapobjectscale)/8; if (cv_kartdebugshrink.value && !modeattacking && !players[i].bot) players[i].mo->destscale = (6*players[i].mo->destscale)/8; + S_StartSound(players[i].mo, sfx_kc59); } } - - // Grow should get taken away. - if (players[i].kartstuff[k_growshrinktimer] > 0) - K_RemoveGrowShrink(&players[i]); - - //P_FlashPal(&players[i], PAL_NUKE, 10); - S_StartSound(players[i].mo, sfx_kc59); } } } @@ -5570,16 +5574,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO && player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage { - K_PlayPowerGloatSound(player->mo); - player->mo->scalespeed = mapobjectscale/TICRATE; - player->mo->destscale = (3*mapobjectscale)/2; - if (cv_kartdebugshrink.value && !modeattacking && !player->bot) - player->mo->destscale = (6*player->mo->destscale)/8; - player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds - P_RestoreMusic(player); - if (!P_IsLocalPlayer(player)) - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); - S_StartSound(player->mo, sfx_kc5a); + if (player->kartstuff[k_growshrinktimer] < 0) // If you're shrunk, then "grow" will just make you normal again. + K_RemoveGrowShrink(player); + else + { + K_PlayPowerGloatSound(player->mo); + player->mo->scalespeed = mapobjectscale/TICRATE; + player->mo->destscale = (3*mapobjectscale)/2; + if (cv_kartdebugshrink.value && !modeattacking && !player->bot) + player->mo->destscale = (6*player->mo->destscale)/8; + player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds + P_RestoreMusic(player); + if (!P_IsLocalPlayer(player)) + S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); + S_StartSound(player->mo, sfx_kc5a); + } player->kartstuff[k_itemamount]--; } break; From f6b698b42039dc30f1ee3de08e8da319061ea4e2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 1 May 2019 23:56:12 -0400 Subject: [PATCH 309/382] Port over double-press Grow cancel from internal --- src/k_kart.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b826d628a..ba15882f9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2141,7 +2141,7 @@ static void K_RemoveGrowShrink(player_t *player) } player->kartstuff[k_growshrinktimer] = 0; - player->kartstuff[k_growcancel] = 0; + player->kartstuff[k_growcancel] = -1; P_RestoreMusic(player); } @@ -5311,14 +5311,24 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Grow Canceling else if (player->kartstuff[k_growshrinktimer] > 0) { - if (cmd->buttons & BT_ATTACK) + if (player->kartstuff[k_growcancel] >= 0) { - player->kartstuff[k_growcancel]++; - if (player->kartstuff[k_growcancel] > 26) - K_RemoveGrowShrink(player); + if (cmd->buttons & BT_ATTACK) + { + player->kartstuff[k_growcancel]++; + if (player->kartstuff[k_growcancel] > 26) + K_RemoveGrowShrink(player); + } + else + player->kartstuff[k_growcancel] = 0; } else - player->kartstuff[k_growcancel] = 0; + { + if ((cmd->buttons & BT_ATTACK) || (player->pflags & PF_ATTACKDOWN)) + player->kartstuff[k_growcancel] = -1; + else + player->kartstuff[k_growcancel] = 0; + } } else if (player->kartstuff[k_itemamount] <= 0) { @@ -5683,7 +5693,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_curshield] = 0; if (player->kartstuff[k_growshrinktimer] <= 0) - player->kartstuff[k_growcancel] = 0; + player->kartstuff[k_growcancel] = -1; if (player->kartstuff[k_itemtype] == KITEM_SPB || player->kartstuff[k_itemtype] == KITEM_SHRINK @@ -6868,7 +6878,7 @@ static void K_drawKartItem(void) } else if (stplyr->kartstuff[k_growshrinktimer] > 0) { - if (stplyr->kartstuff[k_growcancel]) + if (stplyr->kartstuff[k_growcancel] > 0) { itembar = stplyr->kartstuff[k_growcancel]; maxl = 26; From e59a7175be91c0cde11df8dd98a2dae08945e1a7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:39:49 -0400 Subject: [PATCH 310/382] Fix skin shit --- src/b_bot.c | 8 +--- src/d_clisrv.c | 28 -------------- src/d_clisrv.h | 14 ------- src/d_player.h | 48 ----------------------- src/g_game.c | 94 ++++++--------------------------------------- src/lua_playerlib.c | 56 --------------------------- src/p_saveg.c | 28 -------------- src/p_user.c | 36 ++++++++--------- 8 files changed, 31 insertions(+), 281 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index b84db288c..c16976b07 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -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; } diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f3b07d343..d7a8e6528 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index f3a9011eb..8e431dbbf 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -224,21 +224,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; diff --git a/src/d_player.h b/src/d_player.h index decd96552..c6a7f0f34 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -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. // @@ -442,29 +415,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 diff --git a/src/g_game.c b/src/g_game.c index ad25c8ce9..260c88790 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2325,25 +2325,12 @@ void G_PlayerReborn(INT32 player) INT32 score, marescore; INT32 lives; INT32 continues; - UINT8 charability; - UINT8 charability2; // SRB2kart UINT8 kartspeed; UINT8 kartweight; // - fixed_t normalspeed; - fixed_t runspeed; - UINT8 thrustfactor; - UINT8 accelstart; - UINT8 acceleration; INT32 charflags; INT32 pflags; - UINT32 thokitem; - UINT32 spinitem; - UINT32 revitem; - fixed_t actionspd; - fixed_t mindash; - fixed_t maxdash; INT32 ctfteam; INT32 starposttime; INT16 starpostx; @@ -2399,18 +2386,10 @@ void G_PlayerReborn(INT32 player) skincolor = players[player].skincolor; skin = players[player].skin; - charability = players[player].charability; - charability2 = players[player].charability2; // SRB2kart kartspeed = players[player].kartspeed; kartweight = players[player].kartweight; // - normalspeed = players[player].normalspeed; - runspeed = players[player].runspeed; - thrustfactor = players[player].thrustfactor; - accelstart = players[player].accelstart; - acceleration = players[player].acceleration; - charflags = players[player].charflags; starposttime = players[player].starposttime; starpostx = players[player].starpostx; @@ -2419,13 +2398,6 @@ void G_PlayerReborn(INT32 player) starpostnum = players[player].starpostnum; respawnflip = players[player].kartstuff[k_starpostflip]; //SRB2KART starpostangle = players[player].starpostangle; - jumpfactor = players[player].jumpfactor; - thokitem = players[player].thokitem; - spinitem = players[player].spinitem; - revitem = players[player].revitem; - actionspd = players[player].actionspd; - mindash = players[player].mindash; - maxdash = players[player].maxdash; mare = players[player].mare; bot = players[player].bot; @@ -2489,24 +2461,11 @@ void G_PlayerReborn(INT32 player) // save player config truth reborn p->skincolor = skincolor; p->skin = skin; - p->charability = charability; - p->charability2 = charability2; // SRB2kart p->kartspeed = kartspeed; p->kartweight = kartweight; // - p->normalspeed = normalspeed; - p->runspeed = runspeed; - p->thrustfactor = thrustfactor; - p->accelstart = accelstart; - p->acceleration = acceleration; p->charflags = charflags; - p->thokitem = thokitem; - p->spinitem = spinitem; - p->revitem = revitem; - p->actionspd = actionspd; - p->mindash = mindash; - p->maxdash = maxdash; p->starposttime = starposttime; p->starpostx = starpostx; @@ -2514,7 +2473,6 @@ void G_PlayerReborn(INT32 player) p->starpostz = starpostz; p->starpostnum = starpostnum; p->starpostangle = starpostangle; - p->jumpfactor = jumpfactor; p->exiting = exiting; p->numboxes = numboxes; @@ -5531,24 +5489,8 @@ void G_BeginRecording(void) demo_p += 16; // Stats - WRITEUINT8(demo_p,player->charability); - WRITEUINT8(demo_p,player->charability2); - WRITEUINT8(demo_p,player->actionspd>>FRACBITS); - WRITEUINT8(demo_p,player->mindash>>FRACBITS); - WRITEUINT8(demo_p,player->maxdash>>FRACBITS); - // SRB2kart WRITEUINT8(demo_p,player->kartspeed); WRITEUINT8(demo_p,player->kartweight); - // - WRITEUINT8(demo_p,player->normalspeed>>FRACBITS); - WRITEUINT8(demo_p,player->runspeed>>FRACBITS); - WRITEUINT8(demo_p,player->thrustfactor); - WRITEUINT8(demo_p,player->accelstart); - WRITEUINT8(demo_p,player->acceleration); - - // Trying to convert it back to % causes demo desync due to precision loss. - // Don't do it. - WRITEFIXED(demo_p, player->jumpfactor); // Save netvar data (SONICCD, etc) CV_SaveNetVars(&demo_p); @@ -5761,9 +5703,8 @@ void G_DoPlayDemo(char *defdemoname) UINT8 i; lumpnum_t l; char skin[17],color[17],*n,*pdemoname; - UINT8 version,subversion,charability,charability2,kartspeed,kartweight,thrustfactor,accelstart,acceleration; + UINT8 version,subversion,kartspeed,kartweight; UINT32 randseed; - fixed_t actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor; char msg[1024]; #if defined(SKIPERRORS) && !defined(DEVELOP) boolean skiperrors = false; @@ -5900,21 +5841,21 @@ void G_DoPlayDemo(char *defdemoname) M_Memcpy(color,demo_p,16); demo_p += 16; - charability = READUINT8(demo_p); - charability2 = READUINT8(demo_p); - actionspd = (fixed_t)READUINT8(demo_p)<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")) @@ -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")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 0061ee029..fb82ceb23 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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<flags & FF_SHATTER) && !(rover->flags & FF_SPINBUST) && !((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED)) - && (player->charability != CA_GLIDEANDCLIMB && !player->powers[pw_super]) + && (/*player->charability != CA_GLIDEANDCLIMB &&*/ !player->powers[pw_super]) && !(player->pflags & PF_DRILLING) && !metalrecording) continue; // Only Knuckles can break this rock... - if (!(rover->flags & FF_SHATTER) && (rover->flags & FF_ONLYKNUX) && !(player->charability == CA_GLIDEANDCLIMB)) - continue; + /*if (!(rover->flags & FF_SHATTER) && (rover->flags & FF_ONLYKNUX) && !(player->charability == CA_GLIDEANDCLIMB)) + continue;*/ topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); @@ -2468,7 +2468,7 @@ static void P_DoBubbleBreath(player_t *player) return; // Tails stirs up the water while flying in it - if (player->powers[pw_tailsfly] && (leveltime & 1) && player->charability != CA_SWIM) + /*if (player->powers[pw_tailsfly] && (leveltime & 1) && player->charability != CA_SWIM) { fixed_t radius = (3*player->mo->radius)>>1; angle_t fa = ((leveltime%45)*FINEANGLES/8) & FINEMASK; @@ -2494,7 +2494,7 @@ static void P_DoBubbleBreath(player_t *player) stirwaterz, MT_SMALLBUBBLE); bubble->destscale = player->mo->scale; P_SetScale(bubble,bubble->destscale); - } + }*/ } // @@ -3718,13 +3718,13 @@ void P_DoJump(player_t *player, boolean soundandstate) else if (player->mo->eflags & MFE_GOOWATER) { player->mo->momz = 7*FRACUNIT; - if (player->charability == CA_JUMPBOOST && onground) + /*if (player->charability == CA_JUMPBOOST && onground) { if (player->charability2 == CA2_MULTIABILITY) player->mo->momz += FixedMul(FRACUNIT/4, dist6); else player->mo->momz += FixedMul(FRACUNIT/8, dist6); - } + }*/ } else if (maptol & TOL_NIGHTS) player->mo->momz = 24*FRACUNIT; @@ -4029,7 +4029,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) #ifdef HAVE_BLUA if (!LUAh_JumpSpinSpecial(player)) #endif - switch (player->charability) + /*switch (player->charability) { case CA_TELEKINESIS: if (player->pflags & PF_JUMPED) @@ -4054,11 +4054,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; default: break; - } + }*/ } } - if (player->charability == CA_AIRDRILL) + /*if (player->charability == CA_AIRDRILL) { if (player->pflags & PF_JUMPED) { @@ -4076,7 +4076,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_InstaThrust(player->mo, player->mo->angle, ((FixedMul(player->normalspeed - player->actionspd/4, player->mo->scale))*2)/3); } } - } + }*/ if (cmd->buttons & BT_DRIFT && !player->exiting && !P_PlayerInPain(player)) { @@ -4299,7 +4299,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { if (player->secondjump == 1) { - if (player->charability == CA_FLOAT) + /*if (player->charability == CA_FLOAT) player->mo->momz = 0; else if (player->charability == CA_SLOWFALL) { @@ -4310,7 +4310,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (P_MobjFlip(player->mo)*player->mo->momz < -gravity*4) player->mo->momz = P_MobjFlip(player->mo)*-gravity*4; - } + }*/ player->pflags &= ~PF_SPINNING; } } @@ -4320,11 +4320,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_JUMPDOWN; // Repeat abilities, but not double jump! - if ((player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) + /*if ((player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) || (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) player->secondjump = 0; else if (player->charability == CA_FLOAT && player->secondjump == 1) - player->secondjump = 2; + player->secondjump = 2;*/ // If letting go of the jump button while still on ascent, cut the jump height. @@ -6545,7 +6545,7 @@ static void P_MovePlayer(player_t *player) else if (player->dashspeed > 0 && player->dashspeed < FixedMul(player->mindash, player->mo->scale)) player->dashspeed = FixedMul(player->mindash, player->mo->scale); - if (!(player->charability == CA_GLIDEANDCLIMB) || player->gotflag) // If you can't glide, then why the heck would you be gliding? + if (/*!(player->charability == CA_GLIDEANDCLIMB) ||*/ player->gotflag) // If you can't glide, then why the heck would you be gliding? { /* // SRB2kart - ??? if (player->pflags & PF_GLIDING || player->climbing) @@ -6854,7 +6854,7 @@ static void P_MovePlayer(player_t *player) } // Otherwise, face the direction you're travelling. else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_ROLL - || (/*(player->mo->state >= &states[S_PLAY_ABL1] && player->mo->state <= &states[S_PLAY_SPC4]) && */player->charability == CA_FLY)) // SRB2kart - idk + /*|| ((player->mo->state >= &states[S_PLAY_ABL1] && player->mo->state <= &states[S_PLAY_SPC4]) && player->charability == CA_FLY)*/) // SRB2kart - idk player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); // Update the local angle control. @@ -9090,7 +9090,7 @@ void P_PlayerThink(player_t *player) || (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player)))) player->powers[pw_flashing]--; - if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter + if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX /*&& player->charability != CA_SWIM*/ && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter player->powers[pw_tailsfly]--; /* // SRB2kart - Can't drown. From 889ead7840408b378ac512901c4f52b01ddf3ad1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:44:04 -0400 Subject: [PATCH 311/382] Fix wheel animations --- src/g_game.c | 2 +- src/k_kart.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index ad25c8ce9..713eecac1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5283,7 +5283,7 @@ void G_ReadMetalTic(mobj_t *metal) speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS; // Use speed to decide an appropriate state - if (speed > 28) // default skin runspeed + if (speed > 20) // default skin runspeed statetype = 2; else if (speed > 1) // stopspeed statetype = 1; diff --git a/src/k_kart.c b/src/k_kart.c index c6f028872..8d1e9373a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1634,7 +1634,7 @@ void K_KartMoveAnimation(player_t *player) P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_R); } // Run frames - S_KART_RUN1 S_KART_RUN1_L S_KART_RUN1_R - else if (player->speed > FixedMul(player->runspeed, player->mo->scale)) + else if (player->speed > (20*player->mo->scale)) { if (cmd->driftturn < 0 && !(player->mo->state >= &states[S_KART_RUN1_R] && player->mo->state <= &states[S_KART_RUN2_R])) P_SetPlayerMobjState(player->mo, S_KART_RUN1_R); @@ -1644,7 +1644,7 @@ void K_KartMoveAnimation(player_t *player) P_SetPlayerMobjState(player->mo, S_KART_RUN1); } // Walk frames - S_KART_WALK1 S_KART_WALK1_L S_KART_WALK1_R - else if (player->speed <= FixedMul(player->runspeed, player->mo->scale)) + else if (player->speed <= (20*player->mo->scale)) { if (cmd->driftturn < 0 && !(player->mo->state >= &states[S_KART_WALK1_R] && player->mo->state <= &states[S_KART_WALK2_R])) P_SetPlayerMobjState(player->mo, S_KART_WALK1_R); From 804cde886110819a7a8df5213564d8a75f2de009 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:48:01 -0400 Subject: [PATCH 312/382] Fix polyobj angle delta --- src/p_polyobj.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 9967969d3..03fb10d0f 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -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[0] = mo->angle; + localangle[0] += delta; else if (mo->player == &players[displayplayers[1]]) - localangle[1] = mo->angle; + localangle[1] += delta; else if (mo->player == &players[displayplayers[2]]) - localangle[2] = mo->angle; + localangle[2] += delta; else if (mo->player == &players[displayplayers[3]]) - localangle[3] = mo->angle; + localangle[3] += delta; } } } From 8a1ff31d1db6dffd65c7b9f360f5427f7eba9dfc Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:49:05 -0400 Subject: [PATCH 313/382] Remove bad +1 --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index cb62738ad..b2e27f89b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5787,7 +5787,7 @@ static void M_DrawPlaybackMenu(void) if (splitscreen >= i - playback_view1) { - INT32 ply = displayplayers[i - playback_view1 + 1]; + INT32 ply = displayplayers[i - playback_view1]; icon = facerankprefix[players[ply].skin]; if (i != itemOn) From 5a1fc6f9f4f85dafcd3680b58e547933443acbf6 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:49:36 -0400 Subject: [PATCH 314/382] Remove outdated comment --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index f9c8f401c..7d673f66d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1217,7 +1217,7 @@ INT32 JoyAxis(axis_input_e axissel, UINT8 p) // // set secondaryplayer true to build player 2's ticcmd in splitscreen mode // -INT32 localaiming[MAXSPLITSCREENPLAYERS]; // TODO: convert these 3 into MAXSPLITSCREENPLAYERS arrays +INT32 localaiming[MAXSPLITSCREENPLAYERS]; angle_t localangle[MAXSPLITSCREENPLAYERS]; boolean camspin[MAXSPLITSCREENPLAYERS]; From fe28094c0c4ce26b517cb89ee2a929bb15eb23bf Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 01:33:11 -0400 Subject: [PATCH 315/382] Menu fix-up - Use center menu style for the tiny extras menu - Move Screenshot Options, Add-on Options, Replay Options, and Erase Data into Data Options again --- src/m_menu.c | 83 +++++++++++++++++++--------------------------------- 1 file changed, 30 insertions(+), 53 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index b2e27f89b..3d407ec45 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -319,7 +319,7 @@ menu_t OP_SoundOptionsDef; //static void M_RestartAudio(void); //Misc -menu_t /*OP_DataOptionsDef,*/ OP_ScreenshotOptionsDef, OP_EraseDataDef; +menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef; menu_t OP_HUDOptionsDef, OP_ChatOptionsDef; menu_t OP_GameOptionsDef, OP_ServerOptionsDef; #ifndef NONET @@ -338,11 +338,11 @@ static patch_t *addonsp[NUM_EXT+5]; // Replay hut menu_t MISC_ReplayHutDef; +menu_t MISC_ReplayOptionsDef; static void M_HandleReplayHutList(INT32 choice); static void M_DrawReplayHut(void); static void M_DrawReplayStartMenu(void); static boolean M_QuitReplayHut(void); -static void M_EnterReplayOptions(INT32 choice); static void M_HutStartReplay(INT32 choice); static void M_DrawPlaybackMenu(void); @@ -547,10 +547,8 @@ static menuitem_t MISC_AddonsMenu[] = static menuitem_t MISC_ReplayHutMenu[] = { - {IT_CALL |IT_STRING, NULL, "Replay Options...", M_EnterReplayOptions, 0}, - - {IT_KEYHANDLER|IT_NOTHING, NULL, "", M_HandleReplayHutList, 20}, // Dummy menuitem for the replay list - {IT_NOTHING, NULL, "", NULL, 20}, // Dummy for handling wrapping to the top of the menu.. + {IT_KEYHANDLER|IT_NOTHING, NULL, "", M_HandleReplayHutList, 0}, // Dummy menuitem for the replay list + {IT_NOTHING, NULL, "", NULL, 0}, // Dummy for handling wrapping to the top of the menu.. }; static menuitem_t MISC_ReplayStartMenu[] = @@ -778,9 +776,9 @@ static menuitem_t SR_PandorasBox[] = // Sky Room Custom Unlocks static menuitem_t SR_MainMenu[] = { - {IT_STRING|IT_SUBMENU, NULL, "Unlockables", &SR_UnlockChecklistDef, 0}, - {IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 10}, - {IT_CALL|IT_STRING, NULL, "Replay Hut", M_ReplayHut, 20}, + {IT_STRING|IT_SUBMENU, NULL, "Unlockables", &SR_UnlockChecklistDef, 100}, + {IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 108}, + {IT_CALL|IT_STRING, NULL, "Replay Hut", M_ReplayHut, 116}, {IT_DISABLED, NULL, "", NULL, 0}, // Custom1 {IT_DISABLED, NULL, "", NULL, 0}, // Custom2 {IT_DISABLED, NULL, "", NULL, 0}, // Custom3 @@ -1129,15 +1127,13 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, {IT_SUBMENU|IT_STRING, NULL, "HUD Options...", &OP_HUDOptionsDef, 60}, - {IT_STRING|IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 70}, + {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 70}, + {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80}, - {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 90}, - {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 100}, - {IT_STRING|IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 110}, + {IT_SUBMENU|IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 100}, - {IT_CALL|IT_STRING, NULL, "Tricks & Secrets (F1)", M_Manual, 130}, - {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 140}, - {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 150}, + {IT_CALL|IT_STRING, NULL, "Tricks & Secrets (F1)", M_Manual, 120}, + {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 130}, }; static menuitem_t OP_ControlsMenu[] = @@ -1409,12 +1405,14 @@ static menuitem_t OP_SoundOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 135}, }; -/*static menuitem_t OP_DataOptionsMenu[] = +static menuitem_t OP_DataOptionsMenu[] = { - {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10}, + {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10}, + {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 20}, + {IT_STRING | IT_SUBMENU, NULL, "Replay Options...", &MISC_ReplayOptionsDef, 30}, - {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 30}, -};*/ + {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 50}, +}; static menuitem_t OP_ScreenshotOptionsMenu[] = { @@ -1655,7 +1653,7 @@ menu_t MISC_AddonsDef = { NULL, sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), - &MainDef, + &OP_DataOptionsDef, MISC_AddonsMenu, M_DrawAddons, 50, 28, @@ -1671,7 +1669,7 @@ menu_t MISC_ReplayHutDef = MISC_ReplayHutMenu, M_DrawReplayHut, 30, 80, - (sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t)) - 2, // Start on the replay list + 0, M_QuitReplayHut }; @@ -1679,9 +1677,9 @@ menu_t MISC_ReplayOptionsDef = { "M_REPOPT", sizeof (MISC_ReplayOptionsMenu)/sizeof (menuitem_t), - &MISC_ReplayHutDef, + &OP_DataOptionsDef, MISC_ReplayOptionsMenu, - M_DrawGenericBackgroundMenu, + M_DrawGenericMenu, 27, 40, 0, NULL @@ -1808,18 +1806,7 @@ menu_t SR_PandoraDef = 0, M_ExitPandorasBox }; -menu_t SR_MainDef = -{ - "M_SECRET", - sizeof (SR_MainMenu)/sizeof (menuitem_t), - &MainDef, - SR_MainMenu, - M_DrawGenericMenu, - //M_DrawSkyRoom, - 60, 40, - 0, - NULL -}; +menu_t SR_MainDef = CENTERMENUSTYLE(NULL, SR_MainMenu, &MainDef, 72); //menu_t SR_LevelSelectDef = MAPICONMENUSTYLE(NULL, SR_LevelSelectMenu, &SR_MainDef); @@ -2163,10 +2150,10 @@ menu_t OP_OpenGLColorDef = NULL }; #endif -//menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); -menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_MainDef, 30, 30); +menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); +menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); +menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); +menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 30, 30); // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE @@ -5697,15 +5684,6 @@ static boolean M_QuitReplayHut(void) return true; } -static void M_EnterReplayOptions(INT32 choice) -{ - (void)choice; - - // We can't just use M_SetupNextMenu because that'll boot us back to the title screen! - currentMenu = &MISC_ReplayOptionsDef; - itemOn = currentMenu->lastOn; -} - static void M_HutStartReplay(INT32 choice) { (void)choice; @@ -6088,11 +6066,10 @@ static void M_Options(INT32 choice) (void)choice; // if the player is not admin or server, disable gameplay & server options - OP_MainMenu[5].status = OP_MainMenu[6].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_MainMenu[4].status = OP_MainMenu[5].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); - // if the player is playing _at all_, disable the erase data & credits options - OP_MainMenu[9].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); - OP_MainMenu[10].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // Play credits + OP_DataOptionsMenu[3].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); // Erase data OP_GameOptionsMenu[3].status = (M_SecretUnlocked(SECRET_ENCORE)) ? (IT_CVAR|IT_STRING) : IT_SECRET; // cv_kartencore From 032a755ef771bd12abf0b337d8039ac80b3cb67a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 01:34:25 -0400 Subject: [PATCH 316/382] Remove unique version number --- src/doomdef.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 793537f82..8db114fb5 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -151,8 +151,8 @@ extern FILE *logstream; #else #define VERSION 100 // Game version #define SUBVERSION 4 // more precise version number -#define VERSIONSTRING "v1.0.4 Netreplays" -#define VERSIONSTRINGW L"v1.0.4 Netreplays" +#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! #endif From 2d9ae1abfd3aadff827e5e1e3e92f4ca627cf922 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:13:44 -0400 Subject: [PATCH 317/382] Dumbass typo --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 229cf3d47..bfe49fc1a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1093,7 +1093,7 @@ static INT32 Joy3Axis(axis_input_e axissel) retaxis = +JOYAXISRANGE; if (!Joystick3.bGamepadStyle && axissel < AXISDEAD) { - const INT32 jdeadzone = jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone3.value) >> FRACBITS; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone3.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } @@ -1173,7 +1173,7 @@ static INT32 Joy4Axis(axis_input_e axissel) retaxis = +JOYAXISRANGE; if (!Joystick4.bGamepadStyle && axissel < AXISDEAD) { - const INT32 jdeadzone = jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone4.value) >> FRACBITS; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone4.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } From ab7e7476483e75c5f2993d1bc0cc30c583ee5121 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:51:13 -0400 Subject: [PATCH 318/382] Fix warnings Remove entries from dehacked, remove P_DoJump, remove debug stuff --- src/dehacked.c | 21 ----- src/g_game.c | 2 +- src/lua_baselib.c | 12 --- src/p_local.h | 1 - src/p_user.c | 204 +--------------------------------------------- src/st_stuff.c | 16 ++-- 6 files changed, 13 insertions(+), 243 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 1c88fe832..03944640d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8642,27 +8642,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}, diff --git a/src/g_game.c b/src/g_game.c index 260c88790..a1e90822e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2338,7 +2338,6 @@ void G_PlayerReborn(INT32 player) INT16 starpostz; INT32 starpostnum; INT32 starpostangle; - fixed_t jumpfactor; INT32 exiting; INT16 numboxes; INT16 totalring; @@ -2390,6 +2389,7 @@ void G_PlayerReborn(INT32 player) kartspeed = players[player].kartspeed; kartweight = players[player].kartweight; // + charflags = players[player].charflags; starposttime = players[player].starposttime; starpostx = players[player].starpostx; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d9a5fb1d7..481ab89a0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -946,17 +946,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)); @@ -2645,7 +2634,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}, diff --git a/src/p_local.h b/src/p_local.h index 1ac613bdb..a6f6b8aef 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -178,7 +178,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);*/ diff --git a/src/p_user.c b/src/p_user.c index ab0a16edd..d5a4c6944 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3634,195 +3634,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. } */ -// -// P_DoJump -// -// Jump routine for the player -// -void P_DoJump(player_t *player, boolean soundandstate) -{ - fixed_t factor; - const fixed_t dist6 = FixedMul(FixedDiv(player->speed, player->mo->scale), player->actionspd)/20; - - return; - - if (player->pflags & PF_JUMPSTASIS) - return; - - if (!player->jumpfactor) - return; - - if (player->kartstuff[k_spinouttimer]) // SRB2kart - return; - - /* // SRB2kart - climbing in a kart? - if (player->climbing) - { - // Jump this high. - if (player->powers[pw_super]) - player->mo->momz = 5*FRACUNIT; - else if (player->mo->eflags & MFE_UNDERWATER) - player->mo->momz = 2*FRACUNIT; - else - player->mo->momz = 15*(FRACUNIT/4); - - player->mo->angle = player->mo->angle - ANGLE_180; // Turn around from the wall you were climbing. - - if (player == &players[consoleplayer]) - localangle = player->mo->angle; // Adjust the local control 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; - - player->climbing = 0; // Stop climbing, duh! - P_InstaThrust(player->mo, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale)); // Jump off the wall. - } - // Quicksand jumping. - else if (P_InQuicksand(player->mo)) - { - if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1) - return; - player->mo->momz += (39*(FRACUNIT/4))>>1; - if (player->mo->momz >= 6*FRACUNIT) - player->mo->momz = 6*FRACUNIT; //max momz in quicksand - else if (player->mo->momz < 0) // still descending? - player->mo->momz = (39*(FRACUNIT/4))>>1; // just default to the jump height. - } - else*/ if (!(player->pflags & PF_JUMPED)) // Spin Attack - { - if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1) - return; - - // Jump this high. - if (player->pflags & PF_CARRIED) - { - player->mo->momz = 9*FRACUNIT; - player->pflags &= ~PF_CARRIED; - /*if (player-players == consoleplayer && botingame) - CV_SetValue(&cv_analog2, true);*/ - } - else if (player->pflags & PF_ITEMHANG) - { - player->mo->momz = 9*FRACUNIT; - player->pflags &= ~PF_ITEMHANG; - } - else if (player->pflags & PF_ROPEHANG) - { - player->mo->momz = 12*FRACUNIT; - player->pflags &= ~PF_ROPEHANG; - P_SetTarget(&player->mo->tracer, NULL); - } - else if (player->mo->eflags & MFE_GOOWATER) - { - player->mo->momz = 7*FRACUNIT; - /*if (player->charability == CA_JUMPBOOST && onground) - { - if (player->charability2 == CA2_MULTIABILITY) - player->mo->momz += FixedMul(FRACUNIT/4, dist6); - else - player->mo->momz += FixedMul(FRACUNIT/8, dist6); - }*/ - } - else if (maptol & TOL_NIGHTS) - player->mo->momz = 24*FRACUNIT; - else - player->mo->momz = 3*FRACUNIT; // Kart jump momentum. - /* // SRB2kart - Okay enough of that. - else if (player->powers[pw_super]) - { - if (player->charability == CA_FLOAT) - player->mo->momz = 28*FRACUNIT; //Obscene jump height anyone? - else if (player->charability == CA_SLOWFALL) - player->mo->momz = 37*(FRACUNIT/2); //Less obscene because during super, floating propells oneself upward. - else // Default super jump momentum. - player->mo->momz = 13*FRACUNIT; - - // Add a boost for super characters with float/slowfall and multiability. - if (player->charability2 == CA2_MULTIABILITY && - (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)) - player->mo->momz += 2*FRACUNIT; - else if (player->charability == CA_JUMPBOOST) - { - if (player->charability2 == CA2_MULTIABILITY) - player->mo->momz += FixedMul(FRACUNIT/4, dist6); - else - player->mo->momz += FixedMul(FRACUNIT/8, dist6); - } - } - else if (player->charability2 == CA2_MULTIABILITY && - (player->charability == CA_DOUBLEJUMP || player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)) - { - // Multiability exceptions, since some abilities cannot effectively use it and need a boost. - if (player->charability == CA_DOUBLEJUMP) - player->mo->momz = 23*(FRACUNIT/2); // Increased jump height instead of infinite jumps. - else if (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) - player->mo->momz = 12*FRACUNIT; // Increased jump height due to ineffective repeat. - } - else - { - player->mo->momz = 39*(FRACUNIT/4); // Default jump momentum. - if (player->charability == CA_JUMPBOOST && onground) - { - if (player->charability2 == CA2_MULTIABILITY) - player->mo->momz += FixedMul(FRACUNIT/4, dist6); - else - player->mo->momz += FixedMul(FRACUNIT/8, dist6); - } - } - */ - - // Reduce player momz by 58.5% when underwater. - if (player->mo->eflags & MFE_UNDERWATER) - player->mo->momz = FixedMul(player->mo->momz, FixedDiv(117*FRACUNIT, 200*FRACUNIT)); - - player->jumping = 1; - } - - factor = player->jumpfactor; - - if (twodlevel || (player->mo->flags2 & MF2_TWOD)) - factor += player->jumpfactor / 10; - - P_SetObjectMomZ(player->mo, FixedMul(factor, player->mo->momz), false); // Custom height - - // set just an eensy above the ground - if (player->mo->eflags & MFE_VERTICALFLIP) - { - player->mo->z--; - if (player->mo->pmomz < 0) - player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump. - else - player->mo->pmomz = 0; - } - else - { - player->mo->z++; - if (player->mo->pmomz > 0) - player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump. - else - player->mo->pmomz = 0; - } - player->mo->eflags &= ~MFE_APPLYPMOMZ; - - player->pflags |= PF_JUMPED; - - if (soundandstate) - { - if (!player->spectator) - S_StartSound(player->mo, sfx_jump); // Play jump sound! - - /* // SRB2kart - don't need jump frames - if (!(player->charability2 == CA2_SPINDASH)) - P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); - else - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - */ - } -} - // // P_DoSpinDash // @@ -3946,7 +3757,7 @@ void P_DoJumpShield(player_t *player) return; player->pflags &= ~PF_JUMPED; - P_DoJump(player, false); + //P_DoJump(player, false); player->pflags &= ~PF_JUMPED; player->secondjump = 0; player->jumping = 0; @@ -4091,7 +3902,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // Jump S3&K style while in quicksand. if (P_InQuicksand(player->mo)) { - P_DoJump(player, true); + //P_DoJump(player, true); player->secondjump = 0; player->pflags &= ~PF_THOKKED; } @@ -4099,7 +3910,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // can't jump while in air, can't jump while jumping if (onground || player->climbing || player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG)) { - P_DoJump(player, true); + //P_DoJump(player, true); player->secondjump = 0; player->pflags &= ~PF_THOKKED; } @@ -6538,13 +6349,6 @@ static void P_MovePlayer(player_t *player) P_SetPlayerMobjState(player->mo, S_KART_STND1); // SRB2kart - was S_PLAY_STND } - // Cap the speed limit on a spindash - // Up the 60*FRACUNIT number to boost faster, you speed demon you! - if (player->dashspeed > FixedMul(player->maxdash, player->mo->scale)) - player->dashspeed = FixedMul(player->maxdash, player->mo->scale); - else if (player->dashspeed > 0 && player->dashspeed < FixedMul(player->mindash, player->mo->scale)) - player->dashspeed = FixedMul(player->mindash, player->mo->scale); - if (/*!(player->charability == CA_GLIDEANDCLIMB) ||*/ player->gotflag) // If you can't glide, then why the heck would you be gliding? { /* // SRB2kart - ??? @@ -6798,7 +6602,7 @@ static void P_MovePlayer(player_t *player) P_DoSpinDash(player, cmd); */ // jumping - P_DoJumpStuff(player, cmd); + //P_DoJumpStuff(player, cmd); /* // If you're not spinning, you'd better not be spindashing! diff --git a/src/st_stuff.c b/src/st_stuff.c index 36a658aec..cd4ed7e25 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -573,17 +573,17 @@ static void ST_drawDebugInfo(void) if (cv_debug & DBG_DETAILED) { - V_DrawRightAlignedString(320, height - 104, V_MONOSPACE, va("SHIELD: %5x", stplyr->powers[pw_shield])); + //V_DrawRightAlignedString(320, height - 104, V_MONOSPACE, va("SHIELD: %5x", stplyr->powers[pw_shield])); V_DrawRightAlignedString(320, height - 96, V_MONOSPACE, va("SCALE: %5d%%", (stplyr->mo->scale*100)/FRACUNIT)); - V_DrawRightAlignedString(320, height - 88, V_MONOSPACE, va("DASH: %3d/%3d", stplyr->dashspeed>>FRACBITS, FixedMul(stplyr->maxdash,stplyr->mo->scale)>>FRACBITS)); - V_DrawRightAlignedString(320, height - 80, V_MONOSPACE, va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime])); + //V_DrawRightAlignedString(320, height - 88, V_MONOSPACE, va("DASH: %3d/%3d", stplyr->dashspeed>>FRACBITS, FixedMul(stplyr->maxdash,stplyr->mo->scale)>>FRACBITS)); + //V_DrawRightAlignedString(320, height - 80, V_MONOSPACE, va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime])); // Flags - V_DrawRightAlignedString(304-64, height - 72, V_MONOSPACE, "Flags:"); - V_DrawString(304-60, height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM"); - V_DrawString(304-40, height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD"); - V_DrawString(304-20, height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP"); - V_DrawString(304, height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST"); + //V_DrawRightAlignedString(304-64, height - 72, V_MONOSPACE, "Flags:"); + //V_DrawString(304-60, height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM"); + //V_DrawString(304-40, height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD"); + //V_DrawString(304-20, height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP"); + //V_DrawString(304, height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST"); V_DrawRightAlignedString(320, height - 64, V_MONOSPACE, va("CEILZ: %6d", stplyr->mo->ceilingz>>FRACBITS)); V_DrawRightAlignedString(320, height - 56, V_MONOSPACE, va("FLOORZ: %6d", stplyr->mo->floorz>>FRACBITS)); From e954f0b410a09451dc03a1c772061c4537e658e5 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:52:22 -0400 Subject: [PATCH 319/382] Missed a spot --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8d1e9373a..d8028f08a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8291,7 +8291,7 @@ static void K_drawKartFirstPerson(void) } { - if (stplyr->speed < FixedMul(stplyr->runspeed, stplyr->mo->scale) && (leveltime & 1) && !splitscreen) + if (stplyr->speed < (20*stplyr->mo->scale) && (leveltime & 1) && !splitscreen) y++; // the following isn't EXPLICITLY right, it just gets the result we want, but i'm too lazy to look up the right way to do it if (stplyr->mo->flags2 & MF2_SHADOW) From 9314a0d9a9a7a9533f7cd55cdce50a94628c0224 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:58:34 -0400 Subject: [PATCH 320/382] Fix normalspeed Alright fuck this branch it's misery --- src/p_enemy.c | 4 ++-- src/p_mobj.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 31a5a61bf..599d1f2a5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -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)); diff --git a/src/p_mobj.c b/src/p_mobj.c index e1ac3f2db..508acc0b1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1932,7 +1932,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; //} From 833cf980b487086c441677d6fdd9a37744f3d57b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 09:20:49 -0400 Subject: [PATCH 321/382] Finish this Now that I was told that the spinout slowdown bug was caused by this I was 100% convinced that we need to remove all of this bullshit ASAP --- src/g_game.c | 13 ++ src/lua_baselib.c | 25 --- src/p_local.h | 2 - src/p_user.c | 445 +--------------------------------------------- 4 files changed, 18 insertions(+), 467 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e986434a7..9bbe4197c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5489,8 +5489,21 @@ void G_BeginRecording(void) demo_p += 16; // Stats + demo_p++; // charability + demo_p++; // charability2 + demo_p++; // actionspd + demo_p++; // mindash + demo_p++; // maxdash + // SRB2Kart WRITEUINT8(demo_p,player->kartspeed); WRITEUINT8(demo_p,player->kartweight); + // + demo_p++; // normalspeed + demo_p++; // runspeed + demo_p++; // thrustfactor + demo_p++; // accelstart + demo_p++; // acceleration + demo_p += 4; // jumpfactor // Save netvar data (SONICCD, etc) CV_SaveNetVars(&demo_p); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 481ab89a0..541514530 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -946,29 +946,6 @@ static int lib_pHomingAttack(lua_State *L) return 1; }*/ -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)); @@ -2634,8 +2611,6 @@ static luaL_Reg lib[] = { {"P_NukeEnemies",lib_pNukeEnemies}, {"P_HomingAttack",lib_pHomingAttack}, //{"P_SuperReady",lib_pSuperReady}, - {"P_SpawnThokMobj",lib_pSpawnThokMobj}, - {"P_SpawnSpinMobj",lib_pSpawnSpinMobj}, {"P_Telekinesis",lib_pTelekinesis}, // p_map diff --git a/src/p_local.h b/src/p_local.h index a6f6b8aef..2362476dd 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -186,8 +186,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); diff --git a/src/p_user.c b/src/p_user.c index d5a4c6944..9999b5a9d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1653,113 +1653,6 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) return ghost; } -// -// P_SpawnThokMobj -// -// Spawns the appropriate thok object on the player -// -void P_SpawnThokMobj(player_t *player) -{ - mobj_t *mobj; - mobjtype_t type = player->thokitem; - fixed_t zheight; - - if (player->skincolor == 0) - return; - - if (player->spectator) - return; - - if (type == MT_GHOST) - mobj = P_SpawnGhostMobj(player->mo); // virtually does everything here for us - else - { - if (player->mo->eflags & MFE_VERTICALFLIP) - zheight = player->mo->z + player->mo->height + FixedDiv(P_GetPlayerHeight(player) - player->mo->height, 3*FRACUNIT) - FixedMul(mobjinfo[type].height, player->mo->scale); - else - zheight = player->mo->z - FixedDiv(P_GetPlayerHeight(player) - player->mo->height, 3*FRACUNIT); - - if (!(player->mo->eflags & MFE_VERTICALFLIP) && zheight < player->mo->floorz && !(mobjinfo[type].flags & MF_NOCLIPHEIGHT)) - zheight = player->mo->floorz; - else if (player->mo->eflags & MFE_VERTICALFLIP && zheight + FixedMul(mobjinfo[type].height, player->mo->scale) > player->mo->ceilingz && !(mobjinfo[type].flags & MF_NOCLIPHEIGHT)) - zheight = player->mo->ceilingz - FixedMul(mobjinfo[type].height, player->mo->scale); - - mobj = P_SpawnMobj(player->mo->x, player->mo->y, zheight, type); - - // set to player's angle, just in case - mobj->angle = player->mo->angle; - - // color and skin - mobj->color = player->mo->color; - mobj->skin = player->mo->skin; - - // vertical flip - if (player->mo->eflags & MFE_VERTICALFLIP) - mobj->flags2 |= MF2_OBJECTFLIP; - mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); - - // scale - P_SetScale(mobj, player->mo->scale); - mobj->destscale = player->mo->scale; - } - - P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do - if (demorecording) - G_GhostAddThok(); -} - -// -// P_SpawnSpinMobj -// -// Spawns the appropriate spin object on the player -// -void P_SpawnSpinMobj(player_t *player, mobjtype_t type) -{ - mobj_t *mobj; - fixed_t zheight; - - if (player->skincolor == 0) - return; - - if (player->spectator) - return; - - if (type == MT_GHOST) - mobj = P_SpawnGhostMobj(player->mo); // virtually does everything here for us - else - { - if (player->mo->eflags & MFE_VERTICALFLIP) - zheight = player->mo->z + player->mo->height + FixedDiv(P_GetPlayerHeight(player) - player->mo->height, 3*FRACUNIT) - FixedMul(mobjinfo[type].height, player->mo->scale); - else - zheight = player->mo->z - FixedDiv(P_GetPlayerHeight(player) - player->mo->height, 3*FRACUNIT); - - if (!(player->mo->eflags & MFE_VERTICALFLIP) && zheight < player->mo->floorz && !(mobjinfo[type].flags & MF_NOCLIPHEIGHT)) - zheight = player->mo->floorz; - else if (player->mo->eflags & MFE_VERTICALFLIP && zheight + FixedMul(mobjinfo[type].height, player->mo->scale) > player->mo->ceilingz && !(mobjinfo[type].flags & MF_NOCLIPHEIGHT)) - zheight = player->mo->ceilingz - FixedMul(mobjinfo[type].height, player->mo->scale); - - mobj = P_SpawnMobj(player->mo->x, player->mo->y, zheight, type); - - // set to player's angle, just in case - mobj->angle = player->mo->angle; - - // color and skin - mobj->color = player->mo->color; - mobj->skin = player->mo->skin; - - // vertical flip - if (player->mo->eflags & MFE_VERTICALFLIP) - mobj->flags2 |= MF2_OBJECTFLIP; - mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); - - // scale - P_SetScale(mobj, player->mo->scale); - mobj->destscale = player->mo->scale; - } - - P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do -} - // // P_DoPlayerExit // @@ -3815,338 +3708,10 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) } } - P_SpawnThokMobj(player); + //P_SpawnThokMobj(player); player->pflags |= PF_THOKKED; } -// -// P_DoJumpStuff -// -// Handles player jumping -// -static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) -{ - if (player->pflags & PF_JUMPSTASIS) - return; - - if (cmd->buttons & BT_BRAKE && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !P_PlayerInPain(player)) - { - if (onground || player->climbing || player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG)) - {} - else if (player->pflags & PF_MACESPIN && player->mo->tracer) - {} - else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag))) - { -#ifdef HAVE_BLUA - if (!LUAh_JumpSpinSpecial(player)) -#endif - /*switch (player->charability) - { - case CA_TELEKINESIS: - if (player->pflags & PF_JUMPED) - { - if (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY)) - { - P_Telekinesis(player, - -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) - FixedMul(384*FRACUNIT, player->mo->scale)); - } - } - break; - case CA_AIRDRILL: - if (player->pflags & PF_JUMPED) - { - if (player->pflags & PF_THOKKED) // speed up falling down - { - if (player->secondjump < 42) - player->secondjump ++; - } - } - break; - default: - break; - }*/ - } - } - - /*if (player->charability == CA_AIRDRILL) - { - if (player->pflags & PF_JUMPED) - { - if (player->flyangle > 0 && player->pflags & PF_THOKKED) - { - player->flyangle--; - - P_SetObjectMomZ(player->mo, ((player->flyangle-24 - player->secondjump*3)*((player->actionspd>>FRACBITS)/12 + 1)<mo->eflags & MFE_UNDERWATER)) - P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->normalspeed, player->mo->scale)*(80-player->flyangle - (player->actionspd>>FRACBITS)/2)/80); - else - P_InstaThrust(player->mo, player->mo->angle, ((FixedMul(player->normalspeed - player->actionspd/4, player->mo->scale))*2)/3); - } - } - }*/ - - if (cmd->buttons & BT_DRIFT && !player->exiting && !P_PlayerInPain(player)) - { -#ifdef HAVE_BLUA - if (LUAh_JumpSpecial(player)) - ; - else -#endif - if (player->pflags & PF_JUMPDOWN) // all situations below this require jump button not to be pressed already - ; - else - // Jump S3&K style while in quicksand. - if (P_InQuicksand(player->mo)) - { - //P_DoJump(player, true); - player->secondjump = 0; - player->pflags &= ~PF_THOKKED; - } - else - // can't jump while in air, can't jump while jumping - if (onground || player->climbing || player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG)) - { - //P_DoJump(player, true); - player->secondjump = 0; - player->pflags &= ~PF_THOKKED; - } - /* // SRB2kart - no jumpy power things - else if (player->pflags & PF_MACESPIN && player->mo->tracer) - { - player->pflags &= ~PF_MACESPIN; - player->powers[pw_flashing] = TICRATE/4; - } - else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag)) - ; - else if (P_SuperReady(player)) - { - // If you can turn super and aren't already, - // and you don't have a shield, do it! - P_DoSuperTransformation(player, false); - } - else if (player->pflags & PF_JUMPED) - { -#ifdef HAVE_BLUA - if (!LUAh_AbilitySpecial(player)) -#endif - switch (player->charability) - { - case CA_THOK: - case CA_HOMINGTHOK: - case CA_JUMPTHOK: // Credit goes to CZ64 and Sryder13 for the original - // Now it's Sonic's abilities turn! - // THOK! - if (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY)) - { - // Catapult the player - fixed_t actionspd = player->actionspd; - if (player->mo->eflags & MFE_UNDERWATER) - actionspd >>= 1; - if ((player->charability == CA_JUMPTHOK) && !(player->pflags & PF_THOKKED)) - { - player->pflags &= ~PF_JUMPED; - P_DoJump(player, false); - } - P_InstaThrust(player->mo, player->mo->angle, FixedMul(actionspd, player->mo->scale)); - - if (maptol & TOL_2D) - { - player->mo->momx /= 2; - player->mo->momy /= 2; - } - else if (player->charability == CA_HOMINGTHOK) - { - player->mo->momx /= 3; - player->mo->momy /= 3; - } - - if (player->mo->info->attacksound && !player->spectator) - S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound - - P_SpawnThokMobj(player); - - if (player->charability == CA_HOMINGTHOK && !player->homing) - { - if (P_LookForEnemies(player)) - { - if (player->mo->tracer) - player->homing = 3*TICRATE; - } - } - - player->pflags &= ~(PF_SPINNING|PF_STARTDASH); - player->pflags |= PF_THOKKED; - } - break; - - case CA_FLY: - case CA_SWIM: // Swim - // If currently in the air from a jump, and you pressed the - // button again and have the ability to fly, do so! - if (player->charability == CA_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) - ; // Can't do anything if you're a fish out of water! - else if (!(player->pflags & PF_THOKKED) && !(player->powers[pw_tailsfly])) - { - //P_SetPlayerMobjState(player->mo, S_PLAY_ABL1); // Change to the flying animation - - player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer - - player->pflags &= ~(PF_JUMPED|PF_SPINNING|PF_STARTDASH); - player->pflags |= PF_THOKKED; - } - break; - case CA_GLIDEANDCLIMB: - // Now Knuckles-type abilities are checked. - // If you can turn super and aren't already, - // and you don't have a shield, do it! - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) - { - INT32 glidespeed = player->actionspd; - - player->pflags |= PF_GLIDING|PF_THOKKED; - player->glidetime = 0; - - if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - { - // Glide at double speed while super. - glidespeed *= 2; - player->pflags &= ~PF_THOKKED; - } - - //P_SetPlayerMobjState(player->mo, S_PLAY_ABL1); - P_InstaThrust(player->mo, player->mo->angle, FixedMul(glidespeed, player->mo->scale)); - player->pflags &= ~(PF_SPINNING|PF_STARTDASH); - } - break; - case CA_DOUBLEJUMP: // Double-Jump - if (!(player->pflags & PF_THOKKED)) - { - player->pflags &= ~PF_JUMPED; - P_DoJump(player, true); - - // Allow infinite double jumping if super. - if (!player->powers[pw_super]) - player->pflags |= PF_THOKKED; - } - break; - case CA_FLOAT: // Float - case CA_SLOWFALL: // Slow descent hover - if (!player->secondjump) - player->secondjump = 1; - break; - case CA_TELEKINESIS: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) - { - P_Telekinesis(player, - FixedMul(player->actionspd, player->mo->scale), // +ve thrust (pushing away from player) - FixedMul(384*FRACUNIT, player->mo->scale)); - } - break; - case CA_FALLSWITCH: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) - { - player->mo->momz = -player->mo->momz; - P_SpawnThokMobj(player); - player->pflags |= PF_THOKKED; - } - break; - - case CA_AIRDRILL: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) - { - player->flyangle = 56 + (60-(player->actionspd>>FRACBITS))/3; - player->pflags |= PF_THOKKED; - S_StartSound(player->mo, sfx_spndsh); - } - break; - default: - break; - } - } - else if (player->pflags & PF_THOKKED) - { -#ifdef HAVE_BLUA - if (!LUAh_AbilitySpecial(player)) -#endif - switch (player->charability) - { - case CA_FLY: - case CA_SWIM: // Swim - if (player->charability == CA_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) - ; // Can't do anything if you're a fish out of water! - else if (player->powers[pw_tailsfly]) // If currently flying, give an ascend boost. - { - if (!player->fly1) - player->fly1 = 20; - else - player->fly1 = 2; - - if (player->charability == CA_SWIM) - player->fly1 /= 2; - - // Slow down! - if (player->speed > FixedMul(8*FRACUNIT, player->mo->scale) && player->speed > FixedMul(player->normalspeed>>1, player->mo->scale)) - P_Thrust(player->mo, R_PointToAngle2(0,0,player->mo->momx,player->mo->momy), FixedMul(-4*FRACUNIT, player->mo->scale)); - } - break; - default: - break; - } - } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_JUMP && !player->powers[pw_super]) - P_DoJumpShield(player); - */ - } - - if (cmd->buttons & BT_DRIFT) - { - player->pflags |= PF_JUMPDOWN; - - if ((gametype != GT_CTF || !player->gotflag) && !player->exiting) - { - if (player->secondjump == 1) - { - /*if (player->charability == CA_FLOAT) - player->mo->momz = 0; - else if (player->charability == CA_SLOWFALL) - { - if (player->powers[pw_super]) - { - if (P_MobjFlip(player->mo)*player->mo->momz < gravity*16) - player->mo->momz = P_MobjFlip(player->mo)*gravity*16; //Float upward 4x as fast while super. - } - else if (P_MobjFlip(player->mo)*player->mo->momz < -gravity*4) - player->mo->momz = P_MobjFlip(player->mo)*-gravity*4; - }*/ - player->pflags &= ~PF_SPINNING; - } - } - } - else // If not pressing the jump button - { - player->pflags &= ~PF_JUMPDOWN; - - // Repeat abilities, but not double jump! - /*if ((player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) - || (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - player->secondjump = 0; - else if (player->charability == CA_FLOAT && player->secondjump == 1) - player->secondjump = 2;*/ - - - // If letting go of the jump button while still on ascent, cut the jump height. - if (player->pflags & PF_JUMPED && P_MobjFlip(player->mo)*player->mo->momz > 0 && player->jumping == 1) - { - player->mo->momz >>= 1; - player->jumping = 0; - } - } -} - boolean P_AnalogMove(player_t *player) { return player->pflags & PF_ANALOGMODE; @@ -6848,8 +6413,8 @@ static void P_MovePlayer(player_t *player) speed = R_PointToDist2(player->rmomx, player->rmomy, 0, 0); - if (speed > player->normalspeed-5*FRACUNIT) - speed = player->normalspeed-5*FRACUNIT; + if (speed > K_GetKartSpeed(player, false)-(5<= runnyspeed) player->fovadd = speed-runnyspeed; @@ -7404,7 +6969,7 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target dist = 1; if (source->type == MT_DETON && enemy->player) // For Deton Chase (Unused) - ns = FixedDiv(FixedMul(enemy->player->normalspeed, enemy->scale), FixedDiv(20*FRACUNIT,17*FRACUNIT)); + ns = FixedDiv(FixedMul(K_GetKartSpeed(enemy->player, false), enemy->scale), FixedDiv(20*FRACUNIT,17*FRACUNIT)); else if (source->type != MT_PLAYER) { if (source->threshold == 32000) @@ -7413,7 +6978,7 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target ns = FixedMul(source->info->speed, source->scale); } else if (source->player) - ns = FixedDiv(FixedMul(source->player->actionspd, source->scale), 3*FRACUNIT/2); + ns = FixedDiv(FixedMul(K_GetKartSpeed(source->player, false), source->scale), 3*FRACUNIT/2); source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); From 3fdd51736b54406651827bfa764fab42736457ad Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:00:51 -0400 Subject: [PATCH 322/382] HORRID HACK around holding enter in the playback menu having awful, crash-causing side-effects --- src/m_menu.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index b516c8ec4..144b671eb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -354,6 +354,8 @@ static void M_PlaybackSetViews(INT32 choice); static void M_PlaybackAdjustView(INT32 choice); static void M_PlaybackQuit(INT32 choice); +static UINT8 playback_enterheld = 0; // horrid hack to prevent holding the button from being extremely fucked + // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawGenericBackgroundMenu(void); @@ -2837,11 +2839,11 @@ boolean M_Responder(event_t *ev) // Flip left/right with up/down for the playback menu, since it's a horizontal icon row. switch (ch) { - case KEY_LEFTARROW: ch = KEY_UPARROW; break; - case KEY_UPARROW: ch = KEY_RIGHTARROW; break; - case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; - case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; - default: break; + case KEY_LEFTARROW: ch = KEY_UPARROW; break; + case KEY_UPARROW: ch = KEY_RIGHTARROW; break; + case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; + case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; + default: break; } } @@ -2891,6 +2893,15 @@ boolean M_Responder(event_t *ev) case KEY_ENTER: noFurtherInput = true; currentMenu->lastOn = itemOn; + + if (currentMenu == &PlaybackMenuDef) + { + boolean held = (boolean)playback_enterheld; + playback_enterheld = TICRATE/7; + if (held) + return true; + } + if (routine) { if (((currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_CALL @@ -3294,6 +3305,14 @@ void M_Ticker(void) if (--skullAnimCounter <= 0) skullAnimCounter = 8; + if (currentMenu == &PlaybackMenuDef) + { + if (playback_enterheld > 0) + playback_enterheld--; + } + else + playback_enterheld = 0; + //added : 30-01-98 : test mode for five seconds if (vidm_testingmode > 0) { @@ -4349,7 +4368,6 @@ void M_StartMessage(const char *string, void *routine, M_StartControlPanel(); // can't put menuactive to true if (currentMenu == &MessageDef) // Prevent recursion - MessageDef.prevMenu = &MainDef; else MessageDef.prevMenu = currentMenu; From 00a3ea58ee2db2193fcfd96bad5473c37525f5bb Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:03:50 -0400 Subject: [PATCH 323/382] Add message boxes for file add errors --- src/g_game.c | 13 +++++++++---- src/m_menu.c | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 7d673f66d..d29da5ba0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6570,16 +6570,21 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) if (toomany) { - CONS_Printf("Too many files loaded\n"); + CONS_Alert(CONS_WARNING, M_GetText("Too many files loaded to add anymore for demo playback\n")); + if (!CON_Ready()) + M_StartMessage(M_GetText("There are too many files loaded to add this demo's add-ons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); } else if (ncs != FS_FOUND) { if (ncs == FS_NOTFOUND) - CONS_Printf("You do not have a copy of %s\n", filename); + CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename); else if (ncs == FS_MD5SUMBAD) - CONS_Printf("Checksum mismatch on %s\n", filename); + CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename); else - CONS_Printf("Unknown error finding file (%s)\n", filename); + CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename); + + if (!CON_Ready()) + M_StartMessage(M_GetText("There were errors trying to add this demo's add-ons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); } else { diff --git a/src/m_menu.c b/src/m_menu.c index 144b671eb..ed034f93c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4368,6 +4368,7 @@ void M_StartMessage(const char *string, void *routine, M_StartControlPanel(); // can't put menuactive to true if (currentMenu == &MessageDef) // Prevent recursion + MessageDef.prevMenu = ((demo.playback) ? &PlaybackMenuDef : &MainDef); else MessageDef.prevMenu = currentMenu; From 50be0cdbee730bf3ca4db2c61939e80412d62174 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:31:50 -0400 Subject: [PATCH 324/382] Don't keep fast-forward enabled between demos --- src/g_game.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index d29da5ba0..13fb3d61a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -8090,6 +8090,8 @@ void G_StopDemo(void) demo.timing = false; singletics = false; + CV_SetValue(&cv_playbackspeed, 1); + if (gamestate == GS_LEVEL && rendermode != render_none) { V_SetPaletteLump("PLAYPAL"); // Reset the palette From 3fed6b69956a80d5275c364475009b9300014ef0 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:36:11 -0400 Subject: [PATCH 325/382] Disable rewind between demos, too. --- src/g_game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_game.c b/src/g_game.c index 13fb3d61a..a5a623841 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -8091,6 +8091,7 @@ void G_StopDemo(void) singletics = false; CV_SetValue(&cv_playbackspeed, 1); + demo.rewinding = false; if (gamestate == GS_LEVEL && rendermode != render_none) { From 2c49feeb9c4a6f002e64c957e27d2d5742140de8 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:42:29 -0400 Subject: [PATCH 326/382] ENSURE viewcount slider is present for multiplayer demos --- src/m_menu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index ed034f93c..7fb2a1ec4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5758,6 +5758,8 @@ static void M_DrawPlaybackMenu(void) } else { + PlaybackMenu[playback_viewcount].status = IT_ARROWS|IT_STRING; + for (i = 0; i <= splitscreen; i++) PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; for (i = splitscreen+1; i < 4; i++) From b679cfe5c5539c87a929b47c05ce38f32757030d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:50:05 -0400 Subject: [PATCH 327/382] Hide this debug message --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index a5a623841..6e9a60681 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4855,7 +4855,7 @@ static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) { INT32 closest_skin = GetSkinNumClosestToStats(kartspeed, kartweight); - CONS_Printf("Using %s instead...\n", skins[closest_skin].name); + //CONS_Printf("Using %s instead...\n", skins[closest_skin].name); SetPlayerSkinByNum(p, closest_skin); } From 9a1ae859bdb4422c3041e30e25a05c64bea7b07c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:58:02 -0400 Subject: [PATCH 328/382] Don't allow custom gamedata to overwrite kart gamedata or replay folders --- src/dehacked.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b0052c6c6..972fe9591 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2142,11 +2142,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; } From 7301140b10ebe4c7d02381b395201dff0e498d22 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 2 May 2019 18:31:51 -0400 Subject: [PATCH 329/382] Remove MP3 widechar tag searching 1. It's slow, 2. It's incorrect --- src/sdl/mixer_sound.c | 56 ------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index dde62fc7a..7b5a95a45 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -908,15 +908,6 @@ boolean I_LoadSong(char *data, size_t len) const size_t key3len = strlen(key3); const size_t key4len = strlen(key4); - // for mp3 wide chars - const char *key1w = "L\0O\0O\0P\0"; - const char *key2w = "P\0O\0I\0N\0T\0\0\0\xFF\xFE"; - const char *key3w = "M\0S\0\0\0\xFF\xFE"; - const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0\0\0\xFF\xFE"; - const char *wterm = "\0\0"; - char wval[10]; - - size_t wstart, wp; char *p = data; SDL_RWops *rw; @@ -1067,53 +1058,6 @@ boolean I_LoadSong(char *data, size_t len) p += key4len; // skip LENGTHMS song_length = (float)(atoi(p) / 1000.0L); } - // below: search MP3 or other tags that use wide char encoding - else if (fpclassify(loop_point) == FP_ZERO && !memcmp(p, key1w, key1len*2)) // LOOP wide char - { - p += key1len*2; - if (!memcmp(p, key2w, (key2len+1)*2)) // POINT= wide char - { - p += (key2len+1)*2; - wstart = (size_t)p; - wp = 0; - while (wp < 9 && memcmp(p, wterm, 2)) - { - wval[wp] = *p; - p += 2; - wp = ((size_t)(p-wstart))/2; - } - wval[min(wp, 9)] = 0; - loop_point = (float)((44.1L+atoi(wval) / 44100.0L)); - } - else if (!memcmp(p, key3w, (key3len+1)*2)) // MS= wide char - { - p += (key3len+1)*2; - wstart = (size_t)p; - wp = 0; - while (wp < 9 && memcmp(p, wterm, 2)) - { - wval[wp] = *p; - p += 2; - wp = ((size_t)(p-wstart))/2; - } - wval[min(wp, 9)] = 0; - loop_point = (float)(atoi(wval) / 1000.0L); - } - } - else if (fpclassify(song_length) == FP_ZERO && !memcmp(p, key4w, (key4len+1)*2)) // LENGTHMS= wide char - { - p += (key4len+1)*2; - wstart = (size_t)p; - wp = 0; - while (wp < 9 && memcmp(p, wterm, 2)) - { - wval[wp] = *p; - p += 2; - wp = ((size_t)(p-wstart))/2; - } - wval[min(wp, 9)] = 0; - song_length = (float)(atoi(wval) / 1000.0L); - } if (fpclassify(loop_point) != FP_ZERO && fpclassify(song_length) != FP_ZERO && song_length > loop_point) // Got what we needed // the last case is a sanity check, in case the wide char searches were false matches. From d2236a32c38dd834c96866ee1972b42471055b3f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 2 May 2019 19:14:23 -0400 Subject: [PATCH 330/382] Remove song_length tag search Because songs without this tag will skiplag when loading. --- src/sdl/mixer_sound.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 7b5a95a45..045e82b15 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -902,11 +902,9 @@ boolean I_LoadSong(char *data, size_t len) const char *key1 = "LOOP"; const char *key2 = "POINT="; const char *key3 = "MS="; - const char *key4 = "LENGTHMS="; const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); - const size_t key4len = strlen(key4); char *p = data; SDL_RWops *rw; @@ -1053,14 +1051,8 @@ boolean I_LoadSong(char *data, size_t len) // Everything that uses LOOPMS will work perfectly with SDL_Mixer. } } - else if (fpclassify(song_length) == FP_ZERO && !strncmp(p, key4, key4len)) // is it LENGTHMS=? - { - p += key4len; // skip LENGTHMS - song_length = (float)(atoi(p) / 1000.0L); - } - if (fpclassify(loop_point) != FP_ZERO && fpclassify(song_length) != FP_ZERO && song_length > loop_point) // Got what we needed - // the last case is a sanity check, in case the wide char searches were false matches. + if (fpclassify(loop_point) != FP_ZERO) // Got what we needed break; else // continue searching p++; From 5cd8ff01ba29a0b3e6023df4df3b56d22c0463fe Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 3 May 2019 16:38:59 +0100 Subject: [PATCH 331/382] add parentheses around these conditions to fix sloped lights cutting out lights on FOF walls for apparently no reason not making a merge request because this is so laughably stupidly simple --- src/r_segs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index 7495d7889..c82554ac8 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -854,8 +854,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; } From 64fb7f90f0ef7cd3552c2c10734c39bece8dd51c Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 6 May 2019 16:57:32 +0100 Subject: [PATCH 332/382] Add a cvar for sprite billboarding, off by default. --- src/hardware/hw_main.c | 6 +++--- src/hardware/hw_main.h | 1 + src/r_main.c | 1 + src/v_video.c | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 272da06d8..7e0b369eb 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4249,7 +4249,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t // This is expecting a pointer to an array containing 4 wallVerts for a sprite static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) { - if (spr && spr->mobj && wallVerts) + if (cv_grspritebillboarding.value && spr && spr->mobj && wallVerts) { float basey = FIXED_TO_FLOAT(spr->mobj->z); float lowy = wallVerts[0].y; @@ -4530,7 +4530,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].y = endbot; // The x and y only need to be adjusted in the case that it's not a papersprite - if (spr->mobj) + if (cv_grspritebillboarding.value && spr->mobj) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; @@ -4559,7 +4559,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[0].y = wallVerts[1].y = bot; // The x and y only need to be adjusted in the case that it's not a papersprite - if (spr->mobj) + if (cv_grspritebillboarding.value && spr->mobj) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 59042cf3b..f86b198a1 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -95,6 +95,7 @@ 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_baseviewwindowy; diff --git a/src/r_main.c b/src/r_main.c index 94945af5b..08b1ab2f0 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1407,6 +1407,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grcoronasize); #endif CV_RegisterVar(&cv_grmd2); + CV_RegisterVar(&cv_grspritebillboarding); #endif #ifdef HWRENDER diff --git a/src/v_video.c b/src/v_video.c index cfe7d0360..c3b29e157 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -81,6 +81,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0 static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; // console variables in development consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif const UINT8 gammatable[5][256] = From 70ff9be41909b171290c5eadf04ba227046fc966 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 6 May 2019 20:24:26 +0100 Subject: [PATCH 333/382] No sprite billboarding on papersprites --- src/hardware/hw_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 79a46f6b0..0e041ae19 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4249,7 +4249,9 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t // This is expecting a pointer to an array containing 4 wallVerts for a sprite static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) { - if (cv_grspritebillboarding.value && spr && spr->mobj && wallVerts) + if (cv_grspritebillboarding.value + && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) + && wallVerts) { float basey = FIXED_TO_FLOAT(spr->mobj->z); float lowy = wallVerts[0].y; @@ -4530,7 +4532,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].y = endbot; // The x and y only need to be adjusted in the case that it's not a papersprite - if (cv_grspritebillboarding.value && spr->mobj) + if (cv_grspritebillboarding.value + && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; @@ -4559,7 +4562,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[0].y = wallVerts[1].y = bot; // The x and y only need to be adjusted in the case that it's not a papersprite - if (cv_grspritebillboarding.value && spr->mobj) + if (cv_grspritebillboarding.value + && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; From 0958617ecbd5a343b491d0fd17e4bce824f050ee Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 21:17:32 -0400 Subject: [PATCH 334/382] Fix skybox bug --- src/r_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.c b/src/r_main.c index 4d825eef8..b2f511dee 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -852,7 +852,7 @@ void R_SkyboxFrame(player_t *player) { for (i = 1; i <= splitscreen; i++) { - if (player == &players[i]) + if (player == &players[displayplayers[i]]) { thiscam = &camera[i]; break; From 1c1435aea718208993615b56ebc231bf4071c019 Mon Sep 17 00:00:00 2001 From: Sal Date: Mon, 6 May 2019 21:51:35 -0400 Subject: [PATCH 335/382] Merge branch 'version-prep' into 'master' Version prep See merge request KartKrew/Kart!148 (cherry picked from commit dfc4b22c911340e330a0f71fabb4a1461b5747ed) 2e221946 Final v1 colors 359d06f1 Modify the first shade of Byzantium 3a707c09 Add options for adjusting deadzone, increase default deadzone from 0.25 to 0.5 889ead78 Fix wheel animations 2d9ae1ab Dumbass typo e954f0b4 Missed a spot 5316e63a Merge branch 'next-colors' into 'v1' 55db2268 Merge branch 'anim-fix' into 'v1' 26159aae Merge branch 'deadzone-bullshit' into 'v1' 30c19caa Update version number 8f07ed77 Update patch.kart hash --- CMakeLists.txt | 2 +- appveyor.yml | 4 ++-- src/config.h.in | 4 ++-- src/doomdef.h | 15 ++++++++------- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7c4de616..7995034d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) diff --git a/appveyor.yml b/appveyor.yml index 10b658918..3d46cf6de 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -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. diff --git a/src/config.h.in b/src/config.h.in index bd7e78619..f3dd53ee1 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -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 / 03 / 11 - 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 "6461b30bb20754a16a1b582120f55842" #endif #endif diff --git a/src/doomdef.h b/src/doomdef.h index b12c42b49..acd279776 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -149,12 +149,13 @@ 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? @@ -224,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. From 3e93180d3db25cc3e27819ca420035828c048e75 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 22:39:20 -0400 Subject: [PATCH 336/382] Don't cover chat with pause effect --- src/d_main.c | 3 --- src/hu_stuff.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 08ae8af17..c2d1d2869 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -534,9 +534,6 @@ static void D_Display(void) if (demo.rewinding) V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM); - if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1))) - V_DrawVhsEffect(demo.rewinding); - // vid size change is now finished if it was on... vid.recalc = 0; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b7eb1e1f3..f343f12b7 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2292,6 +2292,9 @@ 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) From c8fdc95597e838eb5e1579c2e0fe9ad979cc605f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 22:54:47 -0400 Subject: [PATCH 337/382] Forgot to update date --- src/config.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h.in b/src/config.h.in index f3dd53ee1..338647435 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -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.1.0 - patch.kart + * Last updated 2019 / 05 / 06 - Kart v1.1.0 - patch.kart */ // Base SRB2 hashes From 26adea323461e1148effbd19c97c9542f67011f0 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 7 May 2019 01:34:49 -0500 Subject: [PATCH 338/382] Battle, not Match --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index f2d442149..e73847243 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3095,7 +3095,7 @@ void G_ExitLevel(void) const char *Gametype_Names[NUMGAMETYPES] = { "Race", // GT_RACE - "Match" // GT_MATCH + "Battle" // GT_MATCH /*"Co-op", // GT_COOP "Competition", // GT_COMPETITION From 1b7d7cabdf455b2b32ac0072c7a6a30b91bab1c6 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 7 May 2019 02:06:59 -0500 Subject: [PATCH 339/382] Correct a merge mistake --- src/d_netcmd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d5258646d..e824e0721 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2325,7 +2325,8 @@ static void Command_Map_f(void) ; // The player wants us to trek on anyway. Do so. // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer // Alternatively, bail if the map header is completely missing anyway. - else + else if (!mapheaderinfo[newmapnum-1] + || !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype))) { char gametypestring[32] = "Single Player"; From ed64cd4dace855d9e7f184dbe52331c4244b3741 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 8 May 2019 00:17:21 -0500 Subject: [PATCH 340/382] Default billboarding to "On" --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index afc0fb7e6..c22d7a580 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -80,7 +80,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0 //static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; // console variables in development consvar_t cv_grmdls = {"gr_mdls", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif const UINT8 gammatable[5][256] = From 9163a051924bc9a88bd53f309328e5a501c337de Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 9 May 2019 23:03:32 -0400 Subject: [PATCH 341/382] fix up misleading indentation of a if statement --- src/p_spec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index d25587be6..a23f9f2d7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2472,8 +2472,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) S_SetInternalMusicVolume(fadetarget); else S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); - if (!(line->flags & ML_EFFECT3)) - S_ShowMusicCredit(); + + if (!(line->flags & ML_EFFECT3)) + S_ShowMusicCredit(); if (position) S_SetMusicPosition(position); From d44a5d1013812a1e23cf4bebd75c11749354e62b Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 9 May 2019 23:10:23 -0400 Subject: [PATCH 342/382] fix the array-bounds warning by setting a upper limit --- src/p_inter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 673df055a..2c7324472 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1837,6 +1837,9 @@ void P_CheckTimeLimit(void) } } + if (playercount > MAXPLAYERS) + playercount = MAXPLAYERS; + //Sort 'em. for (i = 1; i < playercount; i++) { From 51312b628d466b7970d32b56ac7b719b47721472 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 9 May 2019 23:10:23 -0400 Subject: [PATCH 343/382] fix the array-bounds warning by setting a upper limit --- src/p_inter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 673df055a..2c7324472 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1837,6 +1837,9 @@ void P_CheckTimeLimit(void) } } + if (playercount > MAXPLAYERS) + playercount = MAXPLAYERS; + //Sort 'em. for (i = 1; i < playercount; i++) { From 5613446b6f7475c8aa8de8c0bedf3616a2e92229 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 03:21:46 -0500 Subject: [PATCH 344/382] Have Look Back reset your color to prefcolor --- src/m_menu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index a345da599..cc6acb34c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9323,6 +9323,9 @@ static void M_HandleSetupMultiPlayer(INT32 choice) size_t l; boolean exitmenu = false; // exit to previous menu and send name change + if ((choice == gamecontrol[gc_lookback][0] || choice == gamecontrol[gc_lookback][1]) && itemOn == 2) + choice == KEY_BACKSPACE // Hack to allow resetting prefcolor on controllers + switch (choice) { case KEY_DOWNARROW: From 08bf9ee1f5edf3192b5898214b29886c594f6621 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 04:22:34 -0500 Subject: [PATCH 345/382] whoops Fixes stupid obvious mistakes and changes the prefcolor reset to item. --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 34c6a6e13..52a73b601 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9318,8 +9318,8 @@ static void M_HandleSetupMultiPlayer(INT32 choice) size_t l; boolean exitmenu = false; // exit to previous menu and send name change - if ((choice == gamecontrol[gc_lookback][0] || choice == gamecontrol[gc_lookback][1]) && itemOn == 2) - choice == KEY_BACKSPACE // Hack to allow resetting prefcolor on controllers + if ((choice == gamecontrol[gc_fire][0] || choice == gamecontrol[gc_fire][1]) && itemOn == 2) + choice = KEY_BACKSPACE; // Hack to allow resetting prefcolor on controllers switch (choice) { From ed55a63b582409caa8377a48f97f034e8d30ae06 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 14:42:39 -0500 Subject: [PATCH 346/382] Fix rewind previews not showing for player 1 --- src/g_game.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 734db9956..bee8246d2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5941,7 +5941,8 @@ void G_StoreRewindInfo(void) void G_PreviewRewind(tic_t previewtime) { - size_t i, j; + SINT8 i; + size_t j; fixed_t tweenvalue = 0; rewindinfo_t *info = rewindhead, *next_info = rewindhead; @@ -6001,13 +6002,14 @@ void G_PreviewRewind(tic_t previewtime) players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j]; } - for (i = splitscreen+1; i > 0; i--) + for (i = splitscreen; i >= 0; i--) P_ResetCamera(&players[displayplayers[i]], &camera[i]); } void G_ConfirmRewind(tic_t rewindtime) { - tic_t i; + SINT8 i; + tic_t j; boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3]; @@ -6027,10 +6029,10 @@ void G_ConfirmRewind(tic_t rewindtime) G_DoPlayDemo(NULL); // Restart the current demo - for (i = 0; i < rewindtime && leveltime < rewindtime; i++) + for (j = 0; j < rewindtime && leveltime < rewindtime; i++) { //TryRunTics(1); - G_Ticker((i % NEWTICRATERATIO) == 0); + G_Ticker((j % NEWTICRATERATIO) == 0); } demo.rewinding = false; @@ -6049,7 +6051,7 @@ void G_ConfirmRewind(tic_t rewindtime) R_ExecuteSetViewSize(); G_ResetViews(); - for (i = splitscreen+1; i > 0; i--) + for (i = splitscreen; i >= 0; i--) P_ResetCamera(&players[displayplayers[i]], &camera[i]); } From 4f3fbb8da56dc581070be2b57f5f8c4e22ae8982 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 16:38:50 -0500 Subject: [PATCH 347/382] Fix viewpoint being reset on boost when spectating --- src/g_game.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index bee8246d2..5aa3edbbd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1249,7 +1249,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (demo.playback) return; - player = &players[displayplayers[ssplayer-1]]; + if (ssplayer == 1) + player = &players[consoleplayer]; + else + player = &players[displayplayers[ssplayer-1]]; + if (ssplayer == 2) thiscam = (player->bot == 2 ? &camera[0] : &camera[ssplayer-1]); else From f3b6b732f8288c433f4d2eecd1d40c4ceccf8af7 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Mon, 13 May 2019 12:49:44 -0500 Subject: [PATCH 348/382] Update bonuschars credits --- src/f_finale.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/f_finale.c b/src/f_finale.c index 29aacb90e..19a7b8c98 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -459,9 +459,13 @@ static const char *credits[] = { "\"ZarroTsu\"", "", "\1External Artists", + "\"1-Up Mason\"", + "\"Chengi\"", "\"Chrispy\"", "\"DirkTheHusky\"", + "\"LJSTAR\"", "\"MotorRoach\"", + "\"Mr. McScrewup\"", "\"Nev3r\"", "\"Ritz\"", "\"Rob\"", @@ -470,6 +474,7 @@ static const char *credits[] = { "\"Spherallic\"", "\"VAdaPEGA\"", "\"Virt\"", + "\"Voltrix\"", "\"zxyspku\"", "", "\1Sound Design", From cd4b9abb7897b03f53caa58b5aa3ae86c9c297a2 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 12 May 2019 14:17:56 +0200 Subject: [PATCH 349/382] SPB intangibility --- src/p_enemy.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index bf1cacdc7..7963286d2 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -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,6 +8385,10 @@ void A_SPBChase(mobj_t *actor) { if (actor->tracer && actor->tracer->health) { + + // we're tailing a player, now's a good time to regain our damage properties + actor->flags &= ~MF_NOCLIPTHING; + fixed_t defspeed = wspeed; fixed_t range = (160*actor->tracer->scale); fixed_t cx = 0, cy =0; @@ -8515,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 @@ -8550,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; From 1c52319d08c758a8c617a464b6702194026d3ab8 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 14 May 2019 22:29:28 -0500 Subject: [PATCH 350/382] More credits updates --- src/f_finale.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 19a7b8c98..2bf5c7438 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -438,6 +438,7 @@ static const char *credits[] = { "", "\1Support Programming", "Colette \"fickleheart\" Bordelon", + "James R.", "\"Lat\'\"", "\"Monster Iestyn\"", "\"Shuffle\"", @@ -501,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", @@ -560,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} }; From 519a2893737b9b6a29f41d71261fd713857b9590 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 17 May 2019 08:06:18 -0500 Subject: [PATCH 351/382] Fix the permanent instashield bug --- src/k_kart.c | 2 +- src/p_user.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 526564a6f..43c6c7cc8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4574,7 +4574,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { player->powers[pw_flashing] = K_GetKartFlashing(player); } - else if (player->powers[pw_flashing] == K_GetKartFlashing(player)) + else if (player->powers[pw_flashing] >= K_GetKartFlashing(player)) { player->powers[pw_flashing]--; } diff --git a/src/p_user.c b/src/p_user.c index 61d8f36f3..a9ea84432 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8495,8 +8495,8 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) - || (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player)))) + if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && + (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player))) player->powers[pw_flashing]--; if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX /*&& player->charability != CA_SWIM*/ && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter From e1451b7a985a42687f00cfc5c38c96a1049fc2cd Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 22 May 2019 22:45:32 -0700 Subject: [PATCH 352/382] Acknowledge fallback models as an OGL option indeed (You may also be able to actually read that code too.) --- src/m_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 52a73b601..cf9f649ac 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1270,6 +1270,7 @@ enum op_video_vsync, #ifdef HWRENDER op_video_md2, + op_video_kartman, op_video_ogl, #endif }; @@ -3334,7 +3335,9 @@ void M_Init(void) #ifdef HWRENDER // Permanently hide some options based on render mode if (rendermode == render_soft) - OP_VideoOptionsMenu[op_video_ogl].status = OP_VideoOptionsMenu[op_video_md2].status = IT_DISABLED; + OP_VideoOptionsMenu[op_video_ogl].status = + OP_VideoOptionsMenu[op_video_kartman].status = + OP_VideoOptionsMenu[op_video_md2] .status = IT_DISABLED; #endif #ifndef NONET From 38360f29ec1bccce2adfbc7b039075e38ac6988f Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 22 May 2019 23:16:20 -0700 Subject: [PATCH 353/382] Move FOV option out of OGL options --- src/m_menu.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cf9f649ac..9b5e98e44 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1244,14 +1244,15 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 55}, //{IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 65}, {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 65}, + {IT_STRING | IT_CVAR, NULL, "Field of View", &cv_fov, 75}, - {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 80}, - {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 90}, + {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90}, + {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmdls, 105}, - {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 115}, - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 125}, + {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmdls, 115}, + {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 125}, + {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 135}, #endif }; @@ -1266,6 +1267,7 @@ enum op_video_wdd, //op_video_wd, op_video_skybox, + op_video_fov, op_video_fps, op_video_vsync, #ifdef HWRENDER @@ -1286,10 +1288,9 @@ static menuitem_t OP_OpenGLOptionsMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 10}, {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 20}, - {IT_STRING|IT_CVAR, NULL, "Field of View", &cv_fov, 35}, - {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 45}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 55}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 65}, + {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 35}, + {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 45}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 55}, /*#ifdef _WINDOWS {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50}, #endif From ccd0ec96a45f6d92bff2db11ca6da2d03ca51b5c Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 13:08:38 +0200 Subject: [PATCH 354/382] let angle be changed while spun out and boosting --- src/d_player.h | 1 + src/g_game.c | 7 +++---- src/k_kart.c | 8 ++++++++ src/p_user.c | 8 +++++--- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index c6a7f0f34..114674ff5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -273,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 diff --git a/src/g_game.c b/src/g_game.c index 5aa3edbbd..f29c97874 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1253,7 +1253,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) player = &players[consoleplayer]; else player = &players[displayplayers[ssplayer-1]]; - + if (ssplayer == 2) thiscam = (player->bot == 2 ? &camera[0] : &camera[ssplayer-1]); else @@ -1558,8 +1558,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (((player->mo && player->speed > 0) // Moving || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (player->kartstuff[k_respawn]) // Respawning - || (player->spectator || objectplacing)) // Not a physical player - && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out turning + || (player->spectator || objectplacing))) // Not a physical player lang += (cmd->angleturn<<16); cmd->angleturn = (INT16)(lang >> 16); @@ -3274,7 +3273,7 @@ const char *Gametype_Names[NUMGAMETYPES] = { "Race", // GT_RACE "Battle" // GT_MATCH - + /*"Co-op", // GT_COOP "Competition", // GT_COMPETITION "Team Match", // GT_TEAMMATCH diff --git a/src/k_kart.c b/src/k_kart.c index 43c6c7cc8..6eeb091c7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3541,6 +3541,9 @@ void K_DoSneaker(player_t *player, INT32 type) player->kartstuff[k_sneakertimer] = sneakertime; + // set angle for spun out players: + player->kartstuff[k_boostangle] = (INT32)player->mo->angle; + if (type != 0) { player->pflags |= PF_ATTACKDOWN; @@ -4469,6 +4472,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_UpdateOffroad(player); K_UpdateEngineSounds(player, cmd); // Thanks, VAda! + + // update boost angle if not spun out + if (!player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) + player->kartstuff[k_boostangle] = (INT32)player->mo->angle; + K_GetKartBoostPower(player); // Speed lines diff --git a/src/p_user.c b/src/p_user.c index a9ea84432..0b938b0b0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4054,6 +4054,8 @@ static void P_3dMovement(player_t *player) { if (player->kartstuff[k_drift] != 0) movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift]; + else if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_wipeoutslow]) // if spun out, use the boost angle + movepushangle = (angle_t)player->kartstuff[k_boostangle]; else movepushangle = player->mo->angle; } @@ -5780,7 +5782,7 @@ static void P_MovePlayer(player_t *player) || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (player->kartstuff[k_respawn]) // Respawning || (player->spectator || objectplacing)) // Not a physical player - && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out turning + ) // ~~Spinning and boosting cancels out turning~~ Not anymore given spinout is more slippery and more prone to get you killed because of boosters. { player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1; player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1; @@ -7377,7 +7379,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_CameraThinker(player, thiscam, resetcalled)) return true; - + if (thiscam == &camera[1]) // Camera 2 { num = 1; @@ -8495,7 +8497,7 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && + if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player))) player->powers[pw_flashing]--; From 8628a543a5910a7c18515bb7157b08b503cba794 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 13:51:19 +0200 Subject: [PATCH 355/382] give friction to brakes --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 43c6c7cc8..d96e092ba 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5778,8 +5778,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) player->mo->friction += 4608; - if (player->speed > 0 && cmd->forwardmove < 0 && player->mo->friction == 59392) - player->mo->friction += 1608; + if (player->speed > 0 && cmd->forwardmove < 0) // change friction while braking no matter what, otherwise it's not any more effective than just letting go off accel + player->mo->friction -= 2048; } // Karma ice physics From cb8af8eb9594ae75d1eaa7528e6133807bc2fcca Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 14:11:26 +0200 Subject: [PATCH 356/382] add k_booostangle to dehacked --- src/dehacked.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dehacked.c b/src/dehacked.c index 7b1b321d7..b311a860c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8391,6 +8391,7 @@ static const char *const KARTSTUFF_LIST[] = { "BOOSTPOWER", "SPEEDBOOST", "ACCELBOOST", + "BOOSTANGLE", "BOOSTCAM", "DESTBOOSTCAM", "TIMEOVERCAM", From d97a0ce2b4e30cdb92714048d61c9427ae1bb695 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 14:13:35 +0200 Subject: [PATCH 357/382] Move the friction change out of the offroad check --- src/k_kart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d96e092ba..e17d45dfb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5778,10 +5778,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) player->mo->friction += 4608; - if (player->speed > 0 && cmd->forwardmove < 0) // change friction while braking no matter what, otherwise it's not any more effective than just letting go off accel - player->mo->friction -= 2048; } + if (player->speed > 0 && cmd->forwardmove < 0) // change friction while braking no matter what, otherwise it's not any more effective than just letting go off accel + player->mo->friction -= 2048; + // Karma ice physics if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) { From ba3e682e0e91a86be557ec6ce0e62345847c2298 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 26 May 2019 11:19:26 +0200 Subject: [PATCH 358/382] fix banana's SpinPlayer using the wrong inflictor --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 2c766349d..fd1047daa 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -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) From 1bcebaadfd8ba5dfb0fc30471de1c2f35f11605b Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 26 May 2019 15:05:10 +0200 Subject: [PATCH 359/382] Lua fixes + new drawOnMinimap function --- src/k_kart.c | 8 +-- src/lua_hudlib.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++ src/p_map.c | 2 +- src/p_user.c | 4 +- 4 files changed, 181 insertions(+), 7 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e32295ad6..fc1552296 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8184,7 +8184,7 @@ static void K_drawBattleFullscreen(void) #ifdef HAVE_BLUA if (!LUA_HudEnabled(hud_battlecomebacktimer)) drawcomebacktimer = false; -#endif +#endif if (splitscreen) { @@ -8796,13 +8796,13 @@ void K_drawKartHUD(void) { #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_battlefullscreen)) - { -#endif + { +#endif K_drawBattleFullscreen(); return; #ifdef HAVE_BLUA } // yes we legit checked if we had lua to close a single bracket. Not my proudest code edit tbh. -#endif +#endif } // Draw the item window diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 3a72a32d3..22c89a234 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -383,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)<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)<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)<height/2)<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; } diff --git a/src/p_user.c b/src/p_user.c index a9ea84432..c43e09291 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7377,7 +7377,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_CameraThinker(player, thiscam, resetcalled)) return true; - + if (thiscam == &camera[1]) // Camera 2 { num = 1; @@ -8495,7 +8495,7 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && + if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player))) player->powers[pw_flashing]--; From 1a9b21c195b3b95fa5889f0b971e1ff0bb82bfd4 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 27 May 2019 22:03:17 +0100 Subject: [PATCH 360/382] Fix Post Processing in 64-bit Software 3P/4P Vid_BlitLinearScreen didn't make sure that it was actually meant to be copying the entire screen rows before doing it properly. --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index 3dfea0418..a624878c6 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -292,7 +292,7 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3 #ifdef HAVE_VIDCOPY VID_BlitLinearScreen_ASM(srcptr,destptr,width,height,srcrowbytes,destrowbytes); #else - if (srcrowbytes == destrowbytes) + if ((srcrowbytes == destrowbytes) && (srcrowbytes == (size_t)width)) M_Memcpy(destptr, srcptr, srcrowbytes * height); else { From 88d5e9b7d22388769cf5d720c521180799af1938 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 27 May 2019 14:20:07 -0700 Subject: [PATCH 361/382] wip --- src/v_video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/v_video.c b/src/v_video.c index a624878c6..2ba28b43c 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2537,8 +2537,10 @@ Unoptimized version UINT8 *srcscr = screens[0]; INT32 y; +#if 0 if (splitscreen > 1) // 3P/4P has trouble supporting this, anyone want to fix it? :p return; +#endif // Make sure table is built if (heatshifter == NULL || lastheight != viewheight) From 392f357b1af90dc4caa7e770ea87aedba78fb2de Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 27 May 2019 14:20:12 -0700 Subject: [PATCH 362/382] Revert "Fix Post Processing in 64-bit Software 3P/4P" This reverts commit 1a9b21c195b3b95fa5889f0b971e1ff0bb82bfd4. --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index 2ba28b43c..5b5e3a063 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -292,7 +292,7 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3 #ifdef HAVE_VIDCOPY VID_BlitLinearScreen_ASM(srcptr,destptr,width,height,srcrowbytes,destrowbytes); #else - if ((srcrowbytes == destrowbytes) && (srcrowbytes == (size_t)width)) + if (srcrowbytes == destrowbytes) M_Memcpy(destptr, srcptr, srcrowbytes * height); else { From 01a0fb1c8f0e43712d4c5e21949c20589a89996a Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 27 May 2019 22:59:58 +0100 Subject: [PATCH 363/382] Fix Heatwave Post-processing Effect in 3P/4P --- src/v_video.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index a624878c6..9233eda42 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2404,7 +2404,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) boolean *heatshifter = NULL; INT32 lastheight = 0; -INT32 heatindex[2] = { 0, 0 }; +INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; // // V_DoPostProcessor @@ -2537,9 +2537,6 @@ Unoptimized version UINT8 *srcscr = screens[0]; INT32 y; - if (splitscreen > 1) // 3P/4P has trouble supporting this, anyone want to fix it? :p - return; - // Make sure table is built if (heatshifter == NULL || lastheight != viewheight) { @@ -2554,7 +2551,7 @@ Unoptimized version heatshifter[y] = true; } - heatindex[0] = heatindex[1] = 0; + heatindex[0] = heatindex[1] = heatindex[2] = heatindex[3] = 0; lastheight = viewheight; } From 96b5a1df43d022095826a9a0123c4545c14f4739 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 28 May 2019 06:33:38 -0500 Subject: [PATCH 364/382] Update patch.kart hash THIS SHOULD BE THE LAST TIME I SWEAR --- src/config.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h.in b/src/config.h.in index 338647435..f3f8339f8 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -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 "6461b30bb20754a16a1b582120f55842" +#define ASSET_HASH_PATCH_KART "7093231f2c3c1cca1a909a708be85d9a" #endif #endif From 1a038ad463624293479de086cb661bc43e073de3 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 28 May 2019 06:56:35 -0500 Subject: [PATCH 365/382] Don't guard the return --- src/k_kart.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index fc1552296..9964140d3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8796,13 +8796,9 @@ void K_drawKartHUD(void) { #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_battlefullscreen)) - { #endif K_drawBattleFullscreen(); - return; -#ifdef HAVE_BLUA - } // yes we legit checked if we had lua to close a single bracket. Not my proudest code edit tbh. -#endif + return; } // Draw the item window From 9ec9c639ddb475aae1a06c7cfe9cb1726db68908 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 15:08:33 -0700 Subject: [PATCH 366/382] Revert "Revert "Fix Post Processing in 64-bit Software 3P/4P"" This reverts commit 392f357b1af90dc4caa7e770ea87aedba78fb2de. --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index 1f8bb6777..9233eda42 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -292,7 +292,7 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3 #ifdef HAVE_VIDCOPY VID_BlitLinearScreen_ASM(srcptr,destptr,width,height,srcrowbytes,destrowbytes); #else - if (srcrowbytes == destrowbytes) + if ((srcrowbytes == destrowbytes) && (srcrowbytes == (size_t)width)) M_Memcpy(destptr, srcptr, srcrowbytes * height); else { From d8967112c604db567dd4c63073849fc4bb8c4818 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 15:11:37 -0700 Subject: [PATCH 367/382] Fix compiler errors The truncation handling in this one spot is okay, but the compiler isn't smart enough for it. I'm leaving it as a warning because I'd like to make a dedicated function for handling snprintf truncation in the future. --- src/Makefile.cfg | 1 + src/p_enemy.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index a0398154a..8402e349f 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -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 diff --git a/src/p_enemy.c b/src/p_enemy.c index 7963286d2..1795a304b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8386,13 +8386,13 @@ void A_SPBChase(mobj_t *actor) if (actor->tracer && actor->tracer->health) { - // we're tailing a player, now's a good time to regain our damage properties - actor->flags &= ~MF_NOCLIPTHING; - 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); From 88ba895d1853998f5a110c7136542fffdd58679c Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 19:00:24 -0700 Subject: [PATCH 368/382] Fix GCC 8 Travis error --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6f8a7aa7..6d2e8cddf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 From 2b795475123167d4417e89906b78b5e01441bec9 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 19:03:02 -0700 Subject: [PATCH 369/382] Fix XCode compiler errors I'm faily certain this also fixes broken logic (g_game.c). --- src/g_game.c | 2 +- src/p_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index f29c97874..10bd76acc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6032,7 +6032,7 @@ void G_ConfirmRewind(tic_t rewindtime) G_DoPlayDemo(NULL); // Restart the current demo - for (j = 0; j < rewindtime && leveltime < rewindtime; i++) + for (j = 0; j < rewindtime && leveltime < rewindtime; j++) { //TryRunTics(1); G_Ticker((j % NEWTICRATERATIO) == 0); diff --git a/src/p_user.c b/src/p_user.c index 0b938b0b0..ced8b2da0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7913,7 +7913,7 @@ boolean P_SpectatorJoinGame(player_t *player) static void P_CalcPostImg(player_t *player) { sector_t *sector = player->mo->subsector->sector; - postimg_t *type = postimg_none; + postimg_t *type = NULL; INT32 *param; fixed_t pviewheight; UINT8 i; From 154ce80a9b8ea9b4d0a350e40ec207a85888415b Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:20:32 -0700 Subject: [PATCH 370/382] Revert "Force of habit" This reverts commit 9f0887fafca1388561c535714c60d84016f2f447. --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 29aa99fae..8ae8c8305 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -701,7 +701,7 @@ static INT32 AddToMasterServer(boolean firstadd) M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == ERRSOCKET) + if (res == -1) return ConnectionFailedwerrno(errno); if (res == 0)/* nothing selected */ { From a8d1ddd1c2d6de4e8476cafc6adf93b8af05cade Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:20:33 -0700 Subject: [PATCH 371/382] Revert "Check error on select" This reverts commit 1d77716d7ebeea2bf279d690a6c0542ff155cb22. --- src/mserv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index 8ae8c8305..21eb44c96 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -701,8 +701,6 @@ static INT32 AddToMasterServer(boolean firstadd) M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == -1) - return ConnectionFailedwerrno(errno); if (res == 0)/* nothing selected */ { /* From 62b957d3482b8c12bcf75a5411e4e6309f832d7d Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:21:04 -0700 Subject: [PATCH 372/382] Revert "Unfuck MS connecting and error reporting" This reverts commit 50ae248b84defb4d399fa9794783fd51ab32f696. --- src/mserv.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index 21eb44c96..f5c4fa889 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -661,19 +661,11 @@ FUNCMATH static const char *int2str(INT32 n) #ifndef NONET static INT32 ConnectionFailed(void) { - time(&MSLastPing); con_state = MSCS_FAILED; CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n")); CloseConnection(); return MS_CONNECT_ERROR; } - -static INT32 ConnectionFailedwerrno(int no) -{ - CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error: %s\n"), - strerror(no)); - return ConnectionFailed(); -} #endif /** Tries to register the local game server on the master server. @@ -690,41 +682,44 @@ static INT32 AddToMasterServer(boolean firstadd) msg_server_t *info = (msg_server_t *)msg.buffer; INT32 room = -1; fd_set tset; + time_t timestamp = time(NULL); UINT32 signature, tmp; const char *insname; - if (socket_fd == (SOCKET_TYPE)ERRSOCKET)/* Woah, our socket was closed! */ - { - if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) - return ConnectionFailedwerrno(errno); - } - M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == 0)/* nothing selected */ + if (res != ERRSOCKET && !res) { - /* - Timeout next call because SendPingToMasterServer - (our calling function) already calls this once - every two minutes. - */ - if (retry++ == 1) + if (retry++ > 30) // an about 30 second timeout { retry = 0; CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n")); + MSLastPing = timestamp; return ConnectionFailed(); } return MS_CONNECT_ERROR; } retry = 0; + if (res == ERRSOCKET) + { + if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) + { + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); + MSLastPing = timestamp; + return ConnectionFailed(); + } + } // so, the socket is writable, but what does that mean, that the connection is // ok, or bad... let see that! j = (socklen_t)sizeof (i); - if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j) == ERRSOCKET) - return ConnectionFailedwerrno(errno); + getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j); if (i) // it was bad - return ConnectionFailedwerrno(i); + { + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); + MSLastPing = timestamp; + return ConnectionFailed(); + } #ifdef PARANOIA if (ms_RoomId <= 0) @@ -757,12 +752,15 @@ static INT32 AddToMasterServer(boolean firstadd) msg.length = (UINT32)sizeof (msg_server_t); msg.room = 0; if (MS_Write(&msg) < 0) + { + MSLastPing = timestamp; return ConnectionFailed(); + } if(con_state != MSCS_REGISTERED) CONS_Printf(M_GetText("Master Server update successful.\n")); - time(&MSLastPing); + MSLastPing = timestamp; con_state = MSCS_REGISTERED; CloseConnection(); #endif From 8faff03f31e514ce0bd814ecfba83c44d3a0e00e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 Jun 2019 14:24:11 -0700 Subject: [PATCH 373/382] Index displayplayers correctly --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0bb87556d..7dff12317 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2040,7 +2040,7 @@ static void Command_View_f(void) return; } - displayplayerp = &displayplayers[viewnum]; + displayplayerp = &displayplayers[viewnum-1]; if (COM_Argc() > 1)/* switch to player */ { From 3d6161c7ca80647801580b7d18f374ebe10c35f2 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 17 Jun 2019 20:57:31 +0100 Subject: [PATCH 374/382] Fix compatibility with the MS (Specifically Doomseeker) Send back 32 players worth of playerinfo regardless of MAXPLAYERS. Fill the extra with unconnected nodes. --- src/d_clisrv.c | 10 ++++++++-- src/d_clisrv.h | 2 +- src/doomdef.h | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1dc2c1420..213f5dde0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1428,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. @@ -1477,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 diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e7879d582..66d9e73ea 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -468,7 +468,7 @@ 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(?) INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes diff --git a/src/doomdef.h b/src/doomdef.h index 4ab40853a..24b52e8d2 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -252,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, From 636724aeb64301eca639295bfafc68cda6e9219d Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 19 Jun 2019 20:05:20 +0100 Subject: [PATCH 375/382] Stop OpenGL having infinite precipitation draw distance --- src/hardware/hw_main.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 63cde0ca0..8863de931 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5470,7 +5470,7 @@ static void HWR_AddSprites(sector_t *sec) } #ifdef HWPRECIP - // Someone seriously wants infinite draw distance for precipitation? + // No to infinite precipitation draw distance. if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) @@ -5486,13 +5486,6 @@ static void HWR_AddSprites(sector_t *sec) HWR_ProjectPrecipitationSprite(precipthing); } } - else - { - // Draw everything in sector, no checks - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) - if (!(precipthing->precipflags & PCF_INVISIBLE)) - HWR_ProjectPrecipitationSprite(precipthing); - } #endif } From 3ee34f751869b462773df507ec947e6921ab5ae4 Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 19 Jun 2019 21:54:11 +0100 Subject: [PATCH 376/382] Integer comparison warning --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 064f8d41c..c7344b16a 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -706,7 +706,7 @@ static INT32 AddToMasterServer(boolean firstadd) haven't open a socket, and actually open it! */ /*if (res == ERRSOCKET)*//* wtf? no! */ - if (socket_fd == ERRSOCKET) + if (socket_fd == (SOCKET_TYPE)ERRSOCKET) { if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) { From a6b7c0a99637464db1bbdbc762ef630ba852513d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 19 Jun 2019 14:32:11 -0700 Subject: [PATCH 377/382] Don't get stuck in room menu in a modified game --- src/m_menu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 9b5e98e44..46f7bc5b7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8432,7 +8432,11 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; if (ms_RoomId < 0) + { M_RoomMenu(0); // Select a room instead of staring at an empty list + // This prevents us from returning to the modified game alert. + currentMenu->prevMenu = &MP_MainDef; + } else M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; From b5aff9f6e77a9b19770a602cebb6e3eae9f3be72 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:16:23 -0700 Subject: [PATCH 378/382] Also count terminating byte in fileneeded filename --- src/d_netfil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 4dcd3da4a..989d20db9 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -130,7 +130,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); - if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED) + if (p + 1 + 4 + strlen(wadfilename) + 1 + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once if (netbuffer->packettype == PT_MOREFILESNEEDED) From fa8999c0df7489e5b8b68fe19a33405893d3627c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:24:50 -0700 Subject: [PATCH 379/382] Add a comment by Sryder's request --- src/d_netfil.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_netfil.c b/src/d_netfil.c index 989d20db9..a321fb788 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -130,6 +130,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); + // Look below at the WRITE macros to understand what these numbers mean. if (p + 1 + 4 + strlen(wadfilename) + 1 + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once From aa5857211ca1431013f0c4f9368062a1e2d7904c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:29:55 -0700 Subject: [PATCH 380/382] Cover edge case of WRITESTRINGN --- src/d_netfil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index a321fb788..76b66836b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -131,7 +131,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); // Look below at the WRITE macros to understand what these numbers mean. - if (p + 1 + 4 + strlen(wadfilename) + 1 + 16 > p_start + MAXFILENEEDED) + 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) From 76c5e3d6feb21e4a0b5e2e3180e5edc7b1e9c27d Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 22 Jun 2019 21:39:31 -0700 Subject: [PATCH 381/382] Spell it "forward" --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 9b5e98e44..ccb717c29 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -522,7 +522,7 @@ static menuitem_t PlaybackMenu[] = {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward", M_PlaybackFastForward, 52}, {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, From 78bd39acd53e5b3eeead72f79bf7b3cc032bf645 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 25 Jun 2019 00:44:12 -0700 Subject: [PATCH 382/382] Someone doesn't know how pointers or WRITE macros work... Fixes SIGSEGV when saving a replay. --- src/g_game.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 10bd76acc..b8a1a3bfa 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6477,10 +6477,10 @@ void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT { char temp[16]; - if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) { WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - WRITEUINT32(demoinfo_p, demo_p - demobuffer); + *(UINT32 *)demoinfo_p = demo_p - demobuffer; } WRITEUINT8(demo_p, DW_STANDING); @@ -8172,16 +8172,17 @@ boolean G_CheckDemoStatus(void) void G_SaveDemo(void) { - UINT8 *p = demobuffer+16; // checksum position + UINT8 *p = demobuffer+16; // after version + UINT32 length; #ifdef NOMD5 UINT8 i; #endif // Ensure extrainfo pointer is always available, even if no info is present. - if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) { WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - WRITEUINT32(demoinfo_p, (UINT32)(demo_p - demobuffer)); + *(UINT32 *)demoinfo_p = demo_p - demobuffer; } WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data. @@ -8227,12 +8228,14 @@ void G_SaveDemo(void) sprintf(writepoint, "%s.lmp", demo_slug); } + length = *(UINT32 *)demoinfo_p; + WRITEUINT32(demoinfo_p, length); #ifdef NOMD5 for (i = 0; i < 16; i++, p++) *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. #else // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. - md5_buffer((char *)p+16, (demobuffer + (UINT32)*demoinfo_p) - (p+16), p); + md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p); #endif