From 54e92a96b35dedce8cbbd4ab597da1d2ef52973c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 11 Jun 2018 19:36:47 +0100 Subject: [PATCH 001/390] 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 1352209d..fa0316bf 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/390] 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 1d16e4df..d7a7973d 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 a58aff3f..5211b31e 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 b7e874b1..e2df1114 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 5403aef1..00e0f8c9 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 7f641558..9cde20f9 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 27bd3fa1..d6fd046b 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 4bace7a4..89c40063 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 a8b27bb8..2499931a 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 4f1c49b4..6be4cf96 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 1be970d2..3c260809 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 e8e8fd02..f7a0a599 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 53e0a7d8..74a6b5e7 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 eadd0153..dff2b8f4 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 208aebe3..a1d7994b 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 17a6797f..6c6b9153 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 c62c3b20..afc3c053 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 7abf8534..03b037fe 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 ea129a10..3da594fe 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 a2d51a59..538707ff 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 87f8fd67..9b09ffe8 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 e29ac080..25c21a07 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 36a5904a..85cae2ed 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 66283ce36a233c82135f3bfb204f231af189336f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 10:32:38 -0400 Subject: [PATCH 003/390] 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 f7a0a599..6a878425 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 74a6b5e7..53e0a7d8 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 dff2b8f4..eadd0153 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 1a935eabd53ed4b1aceb64592cfb24811f4a4ec0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 12:51:42 -0400 Subject: [PATCH 004/390] 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 9b09ffe8..fbd58732 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 b71996106be2bbefc085d0f8e4277ecd4dbc6ddf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 13:23:08 -0400 Subject: [PATCH 005/390] 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 25c21a07..d3b51b15 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 e4f48cfb71bbc24c173346e5290689765db30e6d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 14:08:31 -0400 Subject: [PATCH 006/390] 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 85cae2ed..543de323 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 0cfe0824b6c003afce5bca0d4495a09312ea155f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 15:10:42 -0400 Subject: [PATCH 007/390] 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 6a878425..09368366 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 2e0e0a3856cda84dd867ed3dc5ca30701e2233f8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 15:28:57 -0400 Subject: [PATCH 008/390] 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 6c6b9153..f504ffb5 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 afc3c053..7832ff03 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 00bbb60e69a4df5892b339cbbc985c9a337b2d5f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 22:15:53 -0400 Subject: [PATCH 009/390] 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 fbd58732..f966f531 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 db9528f6e4b6a95b4b4ccb0ba730cba3e489c49a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 23:29:18 -0400 Subject: [PATCH 010/390] 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 6c6b9153..4ca6c97c 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 974b1d340aa81c4358b0cd8a138dea55db2d564e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 18:26:33 -0400 Subject: [PATCH 011/390] 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 f966f531..644a667b 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 ade637798b5458c59c8de7ad9c8490ed7efb4797 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:06:24 -0400 Subject: [PATCH 012/390] 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 644a667b..e5552b0a 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 96fa8996dbd174a9552b73fb37aa8387273357bb Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:18:35 -0400 Subject: [PATCH 013/390] 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 e5552b0a..fc6ccf50 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 164be3056f96f33d3d32aab0324a0a7d50d0f0da Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:19:18 -0400 Subject: [PATCH 014/390] 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 3da594fe..4a9500e7 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 2644180b7e5f2316cd64752b3424338efc03ede8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 19:46:57 -0400 Subject: [PATCH 015/390] 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 4a9500e7..4a52ead5 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 54f94b80db6b16908b29f6c9d131c39ac3b95d20 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Sep 2018 08:41:40 -0400 Subject: [PATCH 016/390] 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 543de323..6fed59a9 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 7916e020d2c21091209a23d3b37c262b39338d8c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 1 Jan 2019 10:47:16 -0500 Subject: [PATCH 017/390] 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 4a87712f..04e82ea3 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 e2e345988aa2567abb9ff6de11ad0e2b7f946278 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 04:58:03 -0500 Subject: [PATCH 018/390] 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 00b30902..f5f3aeb7 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 827461cc36e1d7aa73174c7f437ca2366e640935 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 21 Oct 2018 14:51:49 -0400 Subject: [PATCH 019/390] 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 871fa0a4..01193668 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 ad989f36..716c4d65 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 e63ea34d..d77e636b 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 db7379fb..4409ec35 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 4b340cab..e6e5a1d2 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 2bd794c0069d8320c7978dd7bb4e95bc9cf76eef Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 06:26:18 -0500 Subject: [PATCH 020/390] 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 f5f3aeb7..d3443312 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 2e4c1395511a0e6427742ef8d9c115e6cec55aa1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 06:48:06 -0500 Subject: [PATCH 021/390] 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 4507c27f..f3e3bbed 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 1c1331199d98a8de6cd0a6a3cb12114ce3723c4c Mon Sep 17 00:00:00 2001 From: Digiku Date: Mon, 7 Jan 2019 03:41:25 -0500 Subject: [PATCH 022/390] 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 64e37121..b177212c 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 9d5622c0bccddb294411f058d0a0249472dd5a3c Mon Sep 17 00:00:00 2001 From: Arthur Date: Sat, 15 Dec 2018 08:46:08 -0500 Subject: [PATCH 023/390] 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 d45bb70b..5e789673 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 4609913b..8145a691 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 295ca251710cde302487c47bf107e2b2d40c3812 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sat, 15 Dec 2018 20:57:11 -0500 Subject: [PATCH 024/390] 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 e2fa90eb..0afd6d27 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 2856cada..5d865c5a 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 ca43c7b4..57d8026b 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 00000000..3b083fee --- /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 00000000..1662d647 --- /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 00000000..bac799cd --- /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 00000000..c0e0522f --- /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 00000000..73b2b484 --- /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 00000000..ed7e41a5 --- /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 91578e7f..f8b324ed 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 00000000..dc49a74e --- /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 00000000..7e9a3cab --- /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 df582865..a5166138 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 09287436..d789a61f 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 05ac6450..7962e01b 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 78dfc820..336a709d 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 5bfa29b8..3056b975 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 d20dd672..1a2a7f80 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 71eda043..bc67f04a 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 9f0b121b15d9517aca50786db4bbab564f8b4de1 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 16 Dec 2018 12:04:10 -0500 Subject: [PATCH 025/390] 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 0afd6d27..7b45b097 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 5d865c5a..10517b7e 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 3b083fee..998dc70b 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 bac799cd..87a2f6ed 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 f8b324ed..dbf9649d 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 11be1746037bffd207e64cfe10e07d1596ddfff4 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 16 Dec 2018 15:24:17 -0500 Subject: [PATCH 026/390] 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 73b2b484..495c8c10 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 30c7ad3928e52e817ac67e135e700d1e1cfebdfb Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 17:57:39 -0500 Subject: [PATCH 027/390] 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 a2279a94..753bfab4 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 2e22b069f1f5fe77a5794fa678427c6e7b4b7211 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 19:17:33 -0500 Subject: [PATCH 028/390] 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 10517b7e..b9ff2957 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 87a2f6ed..1f1763eb 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 495c8c10..f0c6f283 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 ed7e41a5..34e83731 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 dbf9649d..a36563ef 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 f0b20e302a9b84e386090f89e0301eec764e3db4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 19:31:30 -0500 Subject: [PATCH 029/390] 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 998dc70b..1fdfefb9 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 1f1763eb..35c6abf2 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 f0c6f283..82833956 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 34e83731..1803f4c5 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 a36563ef..e29c6a38 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 2a24854903d9f5496cb147b5402a1b838e7016a3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 20:36:39 -0500 Subject: [PATCH 030/390] 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 faa860d4..97360b4f 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 34afceaa3b44387f956f6f4660c85935030c2f19 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 20:41:08 -0500 Subject: [PATCH 031/390] 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 1fdfefb9..ff195dda 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 35c6abf2..53f6034c 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 ab99f19dd1b023d8dcc77d439438813d0aaff63a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 21:53:30 -0500 Subject: [PATCH 032/390] 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 958cd7d0..9c550a09 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 039cf894f25fb50eb8d4d27bd8865c791e11715f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 22:50:00 -0500 Subject: [PATCH 033/390] 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 b9ff2957..c29bfe17 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 bbc3d27cee6bccc0979e9c519a7c5c6bb8a8bb2b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Dec 2018 23:44:38 -0500 Subject: [PATCH 034/390] 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 c29bfe17..6cba468e 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 6653b9697f6de62a06eeb3a7809076499f2f7c6a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 00:17:51 -0500 Subject: [PATCH 035/390] 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 ece627d3..fc6ae348 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 6cba468e..10e2847f 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 e29c6a38..5f21ec7e 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 c13d3ff1dd75e3e90dc2365f548fda373391c645 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 00:38:00 -0500 Subject: [PATCH 036/390] 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 10e2847f..f58de224 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 6ed896d46233cd2bcd0bbda2cd9e4277eefa41f0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 01:57:54 -0500 Subject: [PATCH 037/390] 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 5f21ec7e..7bb8442e 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 09629f092f97c059a34b1d7043819dd59e5ffd4c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 10:33:13 -0500 Subject: [PATCH 038/390] 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 fc6ae348..04f63af7 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 f58de224..33cd8b8a 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 4806dadd886f1af9728cbf487f12d74aa2fc299a Mon Sep 17 00:00:00 2001 From: AJ Freda Date: Wed, 19 Dec 2018 20:52:47 -0500 Subject: [PATCH 039/390] 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 ff195dda..49fdbf8a 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 7bb8442e..c0b6d2a7 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 2f930f126227845f29472f2def9ab2ebf9c949f0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Dec 2018 20:56:58 -0500 Subject: [PATCH 040/390] 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 c0b6d2a7..fec8c33a 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 1249f37fc56f050299a9b96198f6de5bd3af3d06 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 23 Dec 2018 17:00:11 -0500 Subject: [PATCH 041/390] 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 7b45b097..c1ece091 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 e4c9e833..fc70492c 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 49fdbf8a..d29414b0 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 fec8c33a..4f77680d 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 7962e01b..9f844c62 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 336a709d..11ad2be9 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 1a2a7f80..8f607796 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 1654aa34c50f9cf64223f21031da5520a9420858 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 26 Dec 2018 23:15:28 -0500 Subject: [PATCH 042/390] 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 82833956..394b0f89 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 4f77680d..22a4d7df 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 c5c799006ab72c937c5a52952c6c75e023097bad Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 26 Dec 2018 23:31:55 -0500 Subject: [PATCH 043/390] 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 d29414b0..1d0e4f36 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 22a4d7df..3410ed3e 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/390] 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 1d0e4f36..84b1bc53 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 d5a0b2df4d6d1a817b2bc5fd8226acca243aae35 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 26 Dec 2018 23:50:35 -0500 Subject: [PATCH 045/390] 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 84b1bc53..ddf89f8d 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 3410ed3e..f7f9dd5b 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 72c2b2832828bd7c8b3f0607d7e21b070c92b7da Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 00:01:51 -0500 Subject: [PATCH 046/390] 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 ddf89f8d..3805deff 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 cf6af71d338c0db58ef4e1af17b0d1c874dc7544 Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 24 Dec 2018 12:08:00 -0500 Subject: [PATCH 047/390] 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 f7f9dd5b..6813b956 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 00792f8dab06cc94afde50c6e4fd9d3fb530336b Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 25 Dec 2018 21:28:51 -0500 Subject: [PATCH 048/390] 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 04f63af7..767eac0b 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 6813b956..fc6c21f1 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/390] 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 31781cba..5352ce6e 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 5d643484..67491abb 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 78fc31af..d49531bd 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 767eac0b..a1e4ad19 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 c1ece091..e1d050cf 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 fc70492c..2f5f6c48 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 f74814f0..b8b3e3ed 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 33cd8b8a..b70d0d6a 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 394b0f89..2c36f974 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 fc6c21f1..ce149197 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 00000000..ca1a974d --- /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 12e3e03b..a61324dc 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 9f844c62..4e083b4c 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 11ad2be9..1db1e27b 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 90411d4e..dd06d04c 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 512320c2..fb2b84b6 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 62596bed38f53b7a8085a4e0f25c9aad716fac77 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 00:47:43 -0500 Subject: [PATCH 050/390] 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 ce149197..b7562171 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 08579d9447c86cb6e6c73420231e9e448d823d60 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 00:54:27 -0500 Subject: [PATCH 051/390] 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 b7562171..d24e4bc6 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 8741a174..ce834c12 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 25ef570a81590a5bdc9e6d319f1cb53b8df41fe4 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 27 Dec 2018 14:58:07 -0500 Subject: [PATCH 052/390] 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 d24e4bc6..0e7d7a8c 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 531d42c1bdfed37797f795ce60d2be7649d08d41 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 27 Dec 2018 15:23:33 -0500 Subject: [PATCH 053/390] 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 6d120efe..4bdc753e 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 e1d050cf..54bd9e78 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 2f5f6c48..133e43c3 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 eb9a31a7..562afe99 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 0e7d7a8c..e17ee32f 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 ce834c12..baf5c7b2 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 cc3b57a96cc317e60aa05d14873e1b786834897a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 27 Dec 2018 22:25:13 -0500 Subject: [PATCH 054/390] 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 e17ee32f..4a26aa0e 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 391d001929fbf6fc239cc10f563e4270cac718a8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 2 Jan 2019 23:31:29 -0500 Subject: [PATCH 055/390] 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 fb2b84b6..512320c2 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 8504b000bbf92bba0e1c93139f3436884e9605f0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 3 Jan 2019 00:57:14 -0500 Subject: [PATCH 056/390] 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 4a26aa0e..91c48ccd 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 05a1a7e24a28f61e7b2263d19a75706494fe7058 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 7 Jan 2019 04:38:17 -0500 Subject: [PATCH 057/390] 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 a1e4ad19..b37850bb 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 d34e1fd4e99860cd9e07af1a47e7ae80281c5589 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 7 Jan 2019 04:40:19 -0500 Subject: [PATCH 058/390] Add floating point epsilons --- src/doomdef.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/doomdef.h b/src/doomdef.h index a35f3291..8b3bdee6 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 4f0be1b064dfe14373b51e92b0dcf4cce243f21c Mon Sep 17 00:00:00 2001 From: Digiku Date: Mon, 7 Jan 2019 16:50:59 -0500 Subject: [PATCH 059/390] 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 b177212c..7708642e 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 090ecdb6e58bd197c684f84c44bf0c921f178ea1 Mon Sep 17 00:00:00 2001 From: Digiku Date: Tue, 8 Jan 2019 11:22:33 -0500 Subject: [PATCH 060/390] 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 b70d0d6a..fb5b201f 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 3cd4b253b154c0277539b565818eefccea4c1ed3 Mon Sep 17 00:00:00 2001 From: Digiku Date: Tue, 8 Jan 2019 11:30:04 -0500 Subject: [PATCH 061/390] 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 fb5b201f..74301a85 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 fad341b0e9c3a315e870a62478f7b01128f804ee Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 15 Jan 2019 14:29:43 -0500 Subject: [PATCH 062/390] 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 67a45a76..0382596f 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 6614e0aa..2823c389 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 0d1c5016641a3b18f9e05213c382fc6f1412afe7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Jan 2019 20:09:55 -0500 Subject: [PATCH 063/390] 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 a726ecbc..5161bf24 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 266bc251..c2768950 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 eb770c19..7e2cce20 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 bce093fd06b8b8441d897553ae1058a7df5e4cf2 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 26 Jan 2019 23:16:49 -0500 Subject: [PATCH 064/390] 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 dd2cfe0e..1782e94f 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 c2768950..333cdaa7 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 7e2cce20..fcde5b7d 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 0aa965c59f5fc4191d7d6402a3de567410729089 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 26 Jan 2019 23:22:30 -0500 Subject: [PATCH 065/390] 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 5161bf24..82d630a5 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 1f72df4edb632379ca60e8e210578b8481aeac9d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 14:33:38 -0600 Subject: [PATCH 066/390] 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 d8022e08..ba926c57 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 dee45fdf62e343f0977fdcfc7f803af11e5df5e7 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 01:26:14 -0600 Subject: [PATCH 067/390] 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 ba926c57..20e79692 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 c9444116dd281d65a8a7876b4e586b9764155e01 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 01:26:43 -0600 Subject: [PATCH 068/390] 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 20e79692..c0e10f23 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/390] 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 41f88ab9..b9384eec 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 712dfdc3d1266122e744321318c34674c5ea56d1 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:06:16 -0600 Subject: [PATCH 070/390] 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 c0e10f23..09c0060b 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 74c37ed06ccbb96acf6525cad4fd18142956d541 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:06:40 -0600 Subject: [PATCH 071/390] 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 b46b248b..e1262a77 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 6dcc4de97938f06db0f6379fc15409004bffb85b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:06:56 -0600 Subject: [PATCH 072/390] 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 09c0060b..abc5857b 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 83738a20b79fd6c40a850cf5f32ad324ad8115c0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 12 Jan 2019 02:48:18 -0600 Subject: [PATCH 073/390] 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 abc5857b..2e8c5b48 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 894db0c6fdfb8f4315c378afe635e7903bc39811 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 15:09:58 -0600 Subject: [PATCH 074/390] 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 2e8c5b48..e548399b 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 ab226c1e39760009696b5d51b7abbb959cc4ab8e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 15:45:08 -0600 Subject: [PATCH 075/390] 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 b9384eec..41f88ab9 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 49b22184..764ad211 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 26770c5103dc0be80bf9a3ae383ad6ad63bfd1dc Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 15:45:42 -0600 Subject: [PATCH 076/390] [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 bb2ea86e..164b0988 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 82dfaf8a..70bf74a9 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 c84faa72..5369ff2c 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 e548399b..d429ccd8 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 975a4a5d..52a35c37 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 3cec3d96580c8e766d34125ff85afbf4f4a15c31 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 16:23:34 -0600 Subject: [PATCH 077/390] 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 d429ccd8..da21d269 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 e1262a77..8814d440 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 cf6e3a45d7beb050ba458a57f36d36f3550ab4ab Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 17:09:25 -0600 Subject: [PATCH 078/390] 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 da21d269..2866624d 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 3a467889aec0cf15cae1d39bc4f6aa3e88b53800 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 17:48:39 -0600 Subject: [PATCH 079/390] 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 f71ff209..3eae4cae 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 8814d440..471b38ec 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 314b2769a90d1b78314f54656266d8c8dbbda693 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 17:58:13 -0600 Subject: [PATCH 080/390] 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 164b0988..50692c67 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 c6248faa30cca421584cf9f7add8f87d28fa7a24 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:07:30 -0600 Subject: [PATCH 081/390] 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 41f88ab9..d6cf4904 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 2866624d..ced20e5b 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 6d11a4a0..f97aecd1 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 471b38ec..4f882958 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 d6234d4b..0f3bf3a8 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 49caebd2db066705f3c2f76ad3e20bfa25262426 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:09:29 -0600 Subject: [PATCH 082/390] 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 ced20e5b..40475c02 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 f7e12165baec6dcea35094f8906ee58b99fb9e08 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:10:25 -0600 Subject: [PATCH 083/390] 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 4f882958..8b99c5aa 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 d05a3a59c4f70bd8628fe8100f47c1e7158da65e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 19:30:20 -0600 Subject: [PATCH 084/390] 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 d6cf4904..982b75d4 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 40475c02..1f43faa3 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 e13e6c5c9b901f2d93ed93ede167947a7388b5ec Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 27 Jan 2019 20:36:13 -0600 Subject: [PATCH 085/390] 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 1f43faa3..a082abe1 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 0c11562209d26c9eaaeefba1340119134f4c9fcb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 31 Jan 2019 00:00:28 -0600 Subject: [PATCH 086/390] 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 a082abe1..55646212 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 6a131f368f555011581c21f5aab965ee50d43385 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 31 Jan 2019 23:03:44 -0600 Subject: [PATCH 087/390] 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 55646212..ab4a6b8e 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 e5be5e80baa31bcb1e1a8b2d490f20457647c9cf Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 00:44:35 -0600 Subject: [PATCH 088/390] 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 5369ff2c..3c8865d6 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 39cb8c4d..e59e4419 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 982b75d4..7b3925e9 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 ab4a6b8e..25a70b3e 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 43c4917e9687641a3b36d074d28cf5c77a05eb40 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 01:01:14 -0600 Subject: [PATCH 089/390] 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 764ad211..3b5659c8 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 7f7dd0097b4c25ccfffada927fd26bcb13895e5f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 01:32:35 -0600 Subject: [PATCH 090/390] 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 25a70b3e..9125a131 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 09eef5f6b1efa269bb6e9ed198505767ca81ce4e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 07:50:42 -0600 Subject: [PATCH 091/390] 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 9125a131..992a38d2 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 0ab690bc60f0b07bb1413d90eefbefaecb442757 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 19:28:05 -0600 Subject: [PATCH 092/390] 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 8ebd2132..c4947891 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 dd95efe3..2a16ee47 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 4a904f79..bc2549d9 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 4de79f13af59d81e9abf008da25f7116d61b528c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 19:46:58 -0600 Subject: [PATCH 093/390] 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 3c8865d6..ff15489a 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 992a38d2..9d3b442f 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 f97aecd1..84ba6c51 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 3724d02e3b2864a535c95bd3efd8b66afe674ae3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 19:53:52 -0600 Subject: [PATCH 094/390] 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 9d3b442f..f17df4f7 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 f0831a17..6b357cd6 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 ba07224a8fc7933ceb584b20403439cbe7de7676 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 20:19:52 -0600 Subject: [PATCH 095/390] 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 f17df4f7..76a799c2 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 84ba6c51..256dd2cf 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 28b9c5fc7dfda879043beb58310804e52d794989 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 20:20:14 -0600 Subject: [PATCH 096/390] 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 ee50cfdd..0ecb60d5 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 e76e3f22811bad35141bb5c036f34ffc091a55ce Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 20:50:33 -0600 Subject: [PATCH 097/390] 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 ff15489a..2e3648ee 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 71d1d10ef6ca99f86f5f32d2d44d5a2c3bfad763 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 21:06:52 -0600 Subject: [PATCH 098/390] 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 2e3648ee..7806fdc2 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 76a799c2..a6afbb14 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 021519e3..d6f89bdc 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 c407f811af5f4a166be496d887dbcf079d90a0e3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 2 Feb 2019 00:24:15 -0600 Subject: [PATCH 099/390] 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 a6afbb14..78111f25 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 ce59b705a48682d9830c5dd3a26bcd4a9c43241e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 2 Feb 2019 10:54:24 -0600 Subject: [PATCH 100/390] 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 78111f25..205773d7 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 d7423d80..f20c57b8 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 fe7c6c7f83166a0e6c0511831271736c4ba13920 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Feb 2019 13:55:29 -0600 Subject: [PATCH 101/390] 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 205773d7..171f0a44 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 7aa83635ae156206c2aac87c3936cd499a6e4254 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Feb 2019 14:29:54 -0600 Subject: [PATCH 102/390] 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 171f0a44..63e5fb72 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 3b5659c8..a5e585cf 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 ee8948d62769801db07e85aa22789e73d0f7ff48 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 4 Feb 2019 03:09:40 -0800 Subject: [PATCH 103/390] 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 7b3925e9..9bbb73ef 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 63e5fb72..c6c091fc 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 256dd2cf..b64fcabb 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 cf1387fe..46afc75e 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 f20c57b8..ce8e3f07 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 67d6ee3b12bea10d3ff4edbddaef2eb6214037db Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 17:54:41 -0800 Subject: [PATCH 104/390] 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 9bbb73ef..5788eb65 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 ac9356a02b2d7e7bb0455cc84abe8bd163628efb Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 17:58:55 -0800 Subject: [PATCH 105/390] 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 c6c091fc..8fbcec0c 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 e52641d15aba18645c367870764bd38895bf6765 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:09:36 -0800 Subject: [PATCH 106/390] 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 7806fdc2..72f0dd2b 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 5788eb65..84741c05 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 8fbcec0c..ca003248 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 b64fcabb..a28a709e 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 8f47b55d29b0b3392e2d9db053d338b23b783520 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:16:54 -0800 Subject: [PATCH 107/390] 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 84741c05..22353701 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 6dc04ab9577fcf4828d6069ace001b3572b16670 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:29:52 -0800 Subject: [PATCH 108/390] 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 22353701..36275305 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 3a8d7af7123730183e7d656bdae6fd41c7931f9f Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 20:48:48 -0800 Subject: [PATCH 109/390] 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 36275305..ab0f4bf3 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 bbd2d84642040e4f82754188f2ab86feffa15a58 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 4 Feb 2019 21:23:48 -0800 Subject: [PATCH 110/390] 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 a308dfc2..2c5bf153 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 61bb44463fb80e7859f2c3608f8d0cae0fe55cb3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 6 Feb 2019 20:25:27 -0600 Subject: [PATCH 111/390] 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 ca003248..a69d76ee 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 e140127180cc4af9f75e9ed49050e2051312b854 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 6 Feb 2019 20:25:45 -0600 Subject: [PATCH 112/390] 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 ab0f4bf3..6fb8aa70 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 a69d76ee..c100ce92 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 a28a709e..cf7dda09 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 46afc75e..12d582aa 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 ce8e3f07..803f1c13 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 dd75c1621cd3193b007975e2f5d798525fb6e5b4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 6 Feb 2019 21:03:05 -0600 Subject: [PATCH 113/390] 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 2bdaaf11..8a8b021c 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 ce162af6..08bcfd2f 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 55430e30688f0c114d3e2c78091554b09c4b76bc Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Feb 2019 07:50:26 +0000 Subject: [PATCH 114/390] 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 f5c4fa88..064f8d41 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 76724c9c130f3e99506fd8ed9b475acccc021646 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 11 Feb 2019 16:39:58 -0500 Subject: [PATCH 115/390] 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 68767b50..4e12b104 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 4a2d1874729a13a1e12e034e4a5512c6e34ca331 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 12 Feb 2019 19:16:36 -0800 Subject: [PATCH 116/390] 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 80203789..c1a92f5b 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 fb4cd26aed5f77ad82a5dfe4e45727b1baec9dc0 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 16:17:48 -0800 Subject: [PATCH 117/390] 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 c1a92f5b..54267d99 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 8a8b021c..bd1f3df9 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 9d9a4755..9a485ffe 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 97aeb27eda5f78e7f385ade7c001f8c50eef4eae Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 20:20:31 -0800 Subject: [PATCH 118/390] 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 5e86a092..93e7a0f3 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 1b604273d44a54cf4b60085747f7b8aed6f8b3c0 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 20:21:09 -0800 Subject: [PATCH 119/390] 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 8a8b021c..fabb6657 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 462e4fb863b87f869c9e94cc3c77b8e0fd6e4cd9 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 14 Feb 2019 00:17:29 -0800 Subject: [PATCH 120/390] 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 8a8b021c..731354af 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 c95928b46fc592f72160596ac15750d60d3ea1f4 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 15 Feb 2019 17:30:27 -0800 Subject: [PATCH 121/390] 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 9cc1bbd2..e58aa8b2 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 1fa32a4b9d5caef00b98884745f92a0d14371b95 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 11:52:35 -0600 Subject: [PATCH 122/390] 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 8a8b021c..47bb8ac9 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 78adae109a926a3d52de64fe075e4a7117147559 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 12:42:24 -0600 Subject: [PATCH 123/390] [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 47bb8ac9..0f5c832f 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 9d9a4755..6e4f6408 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 9d3aa951..b01f9be6 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 dd27858f..425461d5 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 302f50a1..4be4afd9 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 0c1fb11a..73caa211 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 08296d372daff746afa21e16e2e9d02383645977 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:10:58 -0600 Subject: [PATCH 124/390] ??? --- 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 8b99c5aa..7e048af5 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 4bea570143578bf875e81d7e894e9c3b5d5e9d6b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:42:21 -0600 Subject: [PATCH 125/390] 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 0f5c832f..cf40d568 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 e7488f8d768f68370b659fb9490e0b86b9b56a9d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:49:31 -0600 Subject: [PATCH 126/390] 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 cf40d568..e0f9e7fb 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 b006ac447f3d49c7ebc7a37e6189bedbdaef9bb0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 13:58:32 -0600 Subject: [PATCH 127/390] 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 e0f9e7fb..063e9a60 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 ca401aac8acf05e32cee0df54d3a70a2ce1623d5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 14:24:00 -0600 Subject: [PATCH 128/390] 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 063e9a60..c455b3c9 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 6e4f6408..73dcb1ce 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 78f972f8..36becc56 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 fcfce0bd4980a0e2b51cbb6b3fc2e0c5cf6589c2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 15:49:54 -0600 Subject: [PATCH 129/390] 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 c455b3c9..434be94e 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 35be2e0be606d02fb8662811a2c6931ff9f95416 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 16:16:35 -0600 Subject: [PATCH 130/390] 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 93e7a0f3..59274e85 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 276373123e97b2e05a6b2bd2a7e81b804b0ebe65 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 18:29:51 -0600 Subject: [PATCH 131/390] 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 80203789..71adfdf0 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 864c7f43..84b5f1ca 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 73dcb1ce..458f166b 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 7e048af5..f5d5d5b2 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 73caa211..d51c18af 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 0ca17507..995cddfe 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 6e44952d50f7d28839cb524f280a27538896c0c0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 20:53:15 -0600 Subject: [PATCH 132/390] 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 5d854bea..bdc149f0 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 be353c9260da9dcdad88811fc458f2365b9655fb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 21:07:11 -0600 Subject: [PATCH 133/390] 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 bdc149f0..7dccdaf2 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 3bd47b3bebd6bb03dd9b2a64525d5236054b0f1b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 21:55:08 -0600 Subject: [PATCH 134/390] 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 7dccdaf2..d7b2c4d5 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 32c314ff..10a0280b 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 f5d5d5b2..b422e9d2 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 1c5e525db1983d2a1378a15be5de56a21e8135d8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:06:47 -0600 Subject: [PATCH 135/390] 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 d7b2c4d5..490b55bd 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 10a0280b..20edb333 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 b6cc96ad687e994304d2dcc7212da3a981794d11 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:19:05 -0600 Subject: [PATCH 136/390] 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 490b55bd..6dca67fb 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 c00abd1683fe4bea9a583bccfb5a225dcf4970d8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:19:17 -0600 Subject: [PATCH 137/390] 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 8ed33d52..8d8bfca6 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 a6bc581520354ea0e6b9d4cc4aab57fa9b9c89e5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 16 Feb 2019 22:24:37 -0600 Subject: [PATCH 138/390] 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 6dca67fb..7a81aea5 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 20edb333..0042e4bf 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 ed7afc42675ad0dfa2dac8fcda46b083c586f099 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 10:03:34 -0600 Subject: [PATCH 139/390] 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 6d781724..65e3c036 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 d1d270c09d92648d91f49ec3e0ae5b9af4a535f2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 10:04:48 -0600 Subject: [PATCH 140/390] 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 65e3c036..7376bc8c 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 b863ea74..45f9dc1a 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 c31514ae..4cbf4360 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 0042e4bf..4549044b 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 59274e85..9776b2f5 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 a6dff0a324ed016783be4038042d039bfa14afaa Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 11:52:23 -0600 Subject: [PATCH 141/390] 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 4cbf4360..efea0605 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 c260e27cd9fea17fde10c4733e67b201f08074e6 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 17 Feb 2019 13:13:45 -0600 Subject: [PATCH 142/390] 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 ab863c6f..3126a7ca 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 45f9dc1a..9872fa45 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 efea0605..fe6df091 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 e5cbc9c5..5d99d314 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 ef40fae2..73700e1a 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 54ae277bff20522dab31a43f02098e488bc00877 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 17 Feb 2019 23:39:00 +0100 Subject: [PATCH 143/390] 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 b006ae3b..39da4a22 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 4fbbbace..88d7fd6b 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 cd8e0392..e0a360ad 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 3a3b623e341a6d103637d2941af51babe4931441 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:51:02 -0600 Subject: [PATCH 144/390] 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 fe6df091..e65b6571 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 a2b5b76b98a7dec506bc2886dddc4829c7c79034 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:51:28 -0600 Subject: [PATCH 145/390] 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 d51c18af..6b23f67f 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 0d31981dc297bbdf227e6df7e6309db1610706ce Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:52:21 -0600 Subject: [PATCH 146/390] 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 9872fa45..1426e50d 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 96972c9ae9cf321115b7df23054e954d474bf9bb Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 20:54:37 -0600 Subject: [PATCH 147/390] 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 e65b6571..19c40a19 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 9da5b9ae6aa4fd831bdfa6bf88b4cc67985d4831 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 21:08:11 -0600 Subject: [PATCH 148/390] 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 c1a847a1..84ca4a1a 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 188552e0698acf1ecf149b7b0348d0b524a88ea0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 21:23:05 -0600 Subject: [PATCH 149/390] 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 19c40a19..22daab23 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 324108d1203f9980c1b304d512c9ece76a87e79f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 18 Feb 2019 21:33:15 -0600 Subject: [PATCH 150/390] 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 995cddfe..24c4f93e 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 7a80195ed7ecce31db780bf4eba4361b0680f682 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Feb 2019 17:33:02 -0600 Subject: [PATCH 151/390] 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 22daab23..452c5505 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 766ceabf91d10bf272a8575da28f5edeec5a7afc Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Feb 2019 19:26:32 -0600 Subject: [PATCH 152/390] 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 84ca4a1a..9816ca22 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 0e1d7ec6c6f9dd662daf0938d375bd8d76a6d78d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 20 Feb 2019 18:58:17 -0800 Subject: [PATCH 153/390] 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 7376bc8c..c18379aa 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 fc8dc63f95884490b298cd87613a643d20d9807e Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 16:33:45 -0800 Subject: [PATCH 154/390] 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 7376bc8c..bb10afd9 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 c32d7f674548b1697438eb8bc7befb2e9bede1fb Mon Sep 17 00:00:00 2001 From: james Date: Wed, 13 Feb 2019 16:30:50 -0800 Subject: [PATCH 155/390] 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 c18379aa..cc75822d 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 1b2813b9d55e04bf2204eff837c11e4ef413cc0d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 20 Feb 2019 19:25:56 -0800 Subject: [PATCH 156/390] 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 7376bc8c..7ec02eda 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 c9d90f7688aa7804316e99649bd85765cf7942df Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 21 Feb 2019 19:44:18 -0500 Subject: [PATCH 157/390] 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 2529b05d..8ba356b6 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 bf2f6ebc098e4089b30b4e3fd65110890cbac64c Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 18 Feb 2019 01:03:39 -0500 Subject: [PATCH 158/390] 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 8ba356b6..f3b1451a 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 dae9ed16..5413bfdb 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 10fbc50e..e9b29244 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 77a21f7f..8b7adf7c 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 bfbb83df23323ff0a57e952e48721db8e417e26a Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 18 Feb 2019 02:04:58 -0500 Subject: [PATCH 159/390] 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 5413bfdb..dae9ed16 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 e9b29244..10fbc50e 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 230faf15de9f3ab6f043b5711f32930adad4225d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 19 Feb 2019 21:22:35 -0500 Subject: [PATCH 160/390] Some small changes. From 04980044a1924057ba6110947eb314703f0be052 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 21 Feb 2019 22:54:09 -0800 Subject: [PATCH 161/390] 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 7376bc8c..4bfb6f2e 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 e35f65eee292592728e100e14f4e6035e7382457 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 24 Feb 2019 17:47:33 -0800 Subject: [PATCH 162/390] 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 50692c67..886fc85f 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 70bf74a9..71cef9d9 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 47bb8ac9..24804458 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 53a1506e..b9046abd 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 286866d2b6659d36f860a97d01615bb22ea2d110 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 24 Feb 2019 17:59:13 -0800 Subject: [PATCH 163/390] 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 24804458..53a48a9b 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 a25f4b81944230fe28e88c7d959923cc8339a5a1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 26 Feb 2019 21:14:22 +0000 Subject: [PATCH 164/390] 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 e4cb01f6..285d36ca 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 15b27bb7d7fbeff916fc4142ba287e7a3508d8f7 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 27 Feb 2019 15:55:39 -0500 Subject: [PATCH 165/390] 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 61c669db..8e8afcff 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 fa990e8603f45a551b7980ea7211fcdc7f87cc51 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 27 Feb 2019 16:05:43 -0500 Subject: [PATCH 166/390] 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 8e8afcff..3d105870 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 d560fef93014d07245d950f86ecaa363445ca304 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:24:35 -0600 Subject: [PATCH 167/390] 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 11aed24d..4c3b35a3 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 452c5505..219bc815 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 ebd688f32fd83de1760f9b09a775cee92b664a98 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:25:22 -0600 Subject: [PATCH 168/390] 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 219bc815..d1252d58 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 272ba600e2734f39b950cf37bb839b114688d3d6 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:33:59 -0600 Subject: [PATCH 169/390] 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 84f4b589..80d1fcea 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 61893c613c2fbf90fa246fc0419fcb3481debe77 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 3 Mar 2019 20:41:20 -0600 Subject: [PATCH 170/390] 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 d1252d58..10774621 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 89ea7f548eacb0c198146944f235e342fc78dfcb Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 3 Mar 2019 20:02:49 -0800 Subject: [PATCH 171/390] 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 10774621..29a598ac 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 d93b9b5eba8eb69223998cccb2a11b32264f5cc9 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 3 Mar 2019 20:08:28 -0800 Subject: [PATCH 172/390] 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 29a598ac..04897896 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 db3d8eee5060313ed28a9f1a5e4dd75a70234914 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 19:07:34 -0500 Subject: [PATCH 173/390] 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 10774621..29a598ac 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 1bdd1506d96d0105619cdd75fe5fbad8d77ce9d4 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 19:10:43 -0500 Subject: [PATCH 174/390] 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 29a598ac..04897896 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 3a4ed07e02d7375534aa86ff0a772a7b011f8b2b Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 19:16:46 -0500 Subject: [PATCH 175/390] 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 50692c67..886fc85f 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 489ca12bd34bbc8503d807b77ad7439ae256dca7 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:09:20 -0500 Subject: [PATCH 176/390] =?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 04897896..e3a1f3cd 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 dff82fffffac4c7f34d8487c72faeaa67156a0fb Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:26:44 -0500 Subject: [PATCH 177/390] 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 e3a1f3cd..62bc4d8d 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 71d0dfb046901653b72949769bcf00d62948f776 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:27:01 -0500 Subject: [PATCH 178/390] 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 62bc4d8d..4671b4da 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 6b5f00eadeccf2a0754edf5391815ce3a44ff21d Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Mon, 4 Mar 2019 20:35:13 -0500 Subject: [PATCH 179/390] 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 4671b4da..19b062da 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 af19a2c29dc1b68861b78f8f94f37d129e5858e7 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 4 Mar 2019 22:26:05 -0800 Subject: [PATCH 180/390] 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 de250b1f..0c9ea8c7 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 b9abd8b9bc403a34513ff2f8ec53ab3b8e50c7d1 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Tue, 5 Mar 2019 11:29:00 -0500 Subject: [PATCH 181/390] 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 1732f69c..7a5b7787 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 ab4669978a8bacf3041fbe11e075fbafc726a73b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 5 Mar 2019 19:04:15 -0500 Subject: [PATCH 182/390] 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 a8efd306..d8412d3c 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 59a904cb..4b3eee87 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 01d8fc07..0a92b3c2 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 a858967762fb31ea17abd72177d26340c5369d2f Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 6 Mar 2019 18:06:16 -0800 Subject: [PATCH 183/390] 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 19b062da..82800346 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 d6046088a0c93ff517acdaac69b0aee16dfce833 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 11 Mar 2019 22:11:36 -0400 Subject: [PATCH 184/390] 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 26743b73..98e9c6e5 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 f0acaae5..3ea5ebad 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 aea18f36baea9d68f3252e5b7c2723f6f632afed Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 19:42:29 -0400 Subject: [PATCH 185/390] 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 04e82ea3..dde62fc7 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 2c75d4da696fd85567559215af14a602e376f93b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 19:44:24 -0400 Subject: [PATCH 186/390] 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 e8dc80a7..f3be86ee 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 c021e298357c2fd96d2992394c4bd53a49f8d6a0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 21:18:23 -0400 Subject: [PATCH 187/390] 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 0992d55a..c0cb469a 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 67e28573030210350f99f18a6e70fd0265eeb3cf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 23:17:35 -0400 Subject: [PATCH 188/390] 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 89eb697c..f3e33084 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 fdde5f13c59e8a55278ab128ce6b295d5dd600c3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 13 Mar 2019 23:55:30 -0400 Subject: [PATCH 189/390] 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 f3e33084..acb7dcbb 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 6cf05a46132d642eaa3761a9c9a285822006f3b4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 15 Mar 2019 01:00:50 -0400 Subject: [PATCH 190/390] 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 6978dd16..bda0c38f 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 716c4d65..d9132798 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 d77e636b..35542fdc 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 4409ec35..033e99f1 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 e6e5a1d2..1b7796ef 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 6b93ca92211024713fc12ca066e2d712b6088fb6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 15 Mar 2019 01:26:13 -0400 Subject: [PATCH 191/390] 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 1b7796ef..ed4972d2 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 2fb569857a75571c27b02ffe0230da43cb456312 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 18 Mar 2019 22:00:23 +0000 Subject: [PATCH 192/390] 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 a0f9f40a..31fec14f 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 1782e94f..527031fa 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 11b9413a..71ec55de 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 d9132798..8050a1be 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 c0cb469a..f9477f91 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 5259eacb..87ddb310 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 e34e5c35..f624e39d 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 65647d2a..a833ace2 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 438cabcd24a1019f6a7f296fd152f1e3dba3f9c0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 22:59:27 -0500 Subject: [PATCH 193/390] 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 313156d3..02f70316 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 d676dd5a1ed82982086f992ae4b98c7485f0edb5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:02:17 -0500 Subject: [PATCH 194/390] 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 02f70316..54cd3f0c 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 65ac9b7b0b1fdcd96983db609ab95b5bcdf69006 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:08:32 -0500 Subject: [PATCH 195/390] 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 54cd3f0c..916b6ce1 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 64ceb441e3172399689db80a50b795f0548ca4d4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:38:26 -0500 Subject: [PATCH 196/390] 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 916b6ce1..0b52c528 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 29c6dae77623a6384cbacd777ed2547e93edf1ae Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:39:04 -0500 Subject: [PATCH 197/390] 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 0522fd71..b13df51e 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 0b52c528..7335939c 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 e5f94793..f78a06d0 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 4f8d1383b0108b4320fcb53988676acce677d4ed Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 19 Mar 2019 23:45:45 -0500 Subject: [PATCH 198/390] 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 b891bc76..07a72e7f 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 7911fa24d0c222f967297e2a7677146f10e53e03 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Thu, 21 Mar 2019 00:32:27 -0500 Subject: [PATCH 199/390] 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 cb2b6ae4..9fcc8d15 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 7af0554abaa8e35303f8b5f4b54bea1858690411 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 17:47:24 -0500 Subject: [PATCH 200/390] 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 a4a8ff22..793537f8 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 5ea653e4..f4110b2a 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 c7109c0ae4d894d96e894ab73916a96377fe72f0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 18:48:14 -0500 Subject: [PATCH 201/390] 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 79ed85d7..8e5fad28 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 f195fcc9..2387754a 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 834b3a7c..c2da75c8 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 f4110b2a..13027e5d 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 12633ed4..a8cf35eb 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 b135c46d60f90b3e74502c28841a9f0af7771641 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:14:34 -0500 Subject: [PATCH 202/390] 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 13027e5d..c82c368e 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 402796b3c69eb8646efd6b313575c94dfdd34b04 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:19:57 -0500 Subject: [PATCH 203/390] 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 c82c368e..608ab33a 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 8906718fb8148d0c89eda5e733fa8fb88bc2e6f3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:41:25 -0500 Subject: [PATCH 204/390] 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 608ab33a..319c4a00 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 0940be16334dbf0ef1d0e49579c63ffa59057b9e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 19:57:11 -0500 Subject: [PATCH 205/390] 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 3899864f..d87a805d 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 24c4f93e..778ab5ad 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 ccefc48af365da13c05bdefe55161b69c61e9af8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 20:36:22 -0500 Subject: [PATCH 206/390] 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 84d5a6f3..674cf365 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 319c4a00..8e58c975 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 0fc62233..fa88d601 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 4b7d2aea84ef513b7405f9eb00fdad456868ca12 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 21:32:15 -0500 Subject: [PATCH 207/390] 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 8e5fad28..d8ce0f96 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 674cf365..6edb1cf4 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 b13df51e..d4ffe27a 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 4f41ac0c..20c2964b 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 c2da75c8..834b3a7c 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 cdde54f3..d184a283 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 8e58c975..ef8a4196 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 f78a06d0..ffe98d73 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 a8cf35eb..9affc72f 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 8a68cafe..3918e8f9 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 2fc2e85c..e7e877ad 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 fa88d601..39231034 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 90e7a06f..f70bcf3e 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 256c9cef..9b0db658 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 484d34fb..f31075f3 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 07a72e7f..f73aef99 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 67bb7472..6b5f09f6 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 6fd2e09f..a9f78662 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 72949c92..18b14f42 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 1a74f733..7fb11855 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 36182d0e..b4dcd918 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 baba4211..efc5dd46 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 2ddffa3f..9653d8ff 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 f92f1f14..c0fca64d 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 d87a805d..2dd045c1 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 47250334..a98aa861 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 778ab5ad..5a8791d4 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 b2cbe3ed6dfb1a915f237c4dd4b8e36c2bbc0588 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 21:55:08 -0500 Subject: [PATCH 208/390] 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 d4ffe27a..50f0a2e8 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 ef8a4196..fc636537 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 ffe98d73..c9bcaf01 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 a9f78662..03ce05c3 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 2dd045c1..dec7ee0c 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 5a8791d4..1e6d945c 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 2a9dd8e1f9066199cc89cbd9ba0d28d5f396adff Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 24 Mar 2019 22:40:52 -0500 Subject: [PATCH 209/390] 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 6edb1cf4..16a70519 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 fc636537..ca2f0208 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 c9bcaf01..d97752b2 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 03ce05c3..177f3b65 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 dec7ee0c..acb01fb6 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 f96aee93..16f7b881 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 1e6d945c..256a8566 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 587586f4bb9ecab7cc1e67513451ac1251c84c1d Mon Sep 17 00:00:00 2001 From: jameds Date: Mon, 19 Mar 2018 23:15:16 -0700 Subject: [PATCH 210/390] 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 5c173e45..fbb9ac43 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 b9b36a44a8a4c13ac5702abf45260094370ec20c Mon Sep 17 00:00:00 2001 From: jameds Date: Wed, 21 Mar 2018 21:12:48 -0700 Subject: [PATCH 211/390] 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 fbb9ac43..032615e1 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 e8071e66e49b383c2893b901e3a9a2ede5dab08a Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 12:30:02 -0700 Subject: [PATCH 212/390] 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 032615e1..9718bb48 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 69d7e98f34795c12639cdef991007278f5bb678d Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 12:59:13 -0700 Subject: [PATCH 213/390] 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 dd2cfe0e..6933ee1a 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 11b9413a..ed4be044 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 bcdac295..d4a468c5 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 9a350eb8799de64efc3e50e37cc3d6b2da4b95a6 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 13:04:11 -0700 Subject: [PATCH 214/390] 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 dd2cfe0e..5b29cb41 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 11b9413a..bee6b409 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 917edf720d833917b76e032bbf0507d7483c354e Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 26 Mar 2019 13:05:19 -0700 Subject: [PATCH 215/390] 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 5b29cb41..1b2d73d7 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 a4722aded80b6ee1b0dd1bdb95f10d4d6aa44c8c Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Wed, 27 Mar 2019 03:23:32 -0400 Subject: [PATCH 216/390] Add missing entry for SKINCOLOR_BUBBLEGUM in ColorOpposite() --- src/k_kart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.c b/src/k_kart.c index 70075858..0421f625 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -219,6 +219,7 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_SUNSET,10, // SKINCOLOR_MOONSLAM SKINCOLOR_MAUVE,10, // SKINCOLOR_ULTRAVIOLET SKINCOLOR_DAWN,6, // SKINCOLOR_DUSK + SKINCOLOR_POPCORN,11, // SKINCOLOR_BUBBLEGUM SKINCOLOR_EMERALD,8, // SKINCOLOR_PURPLE SKINCOLOR_PASTEL,11, // SKINCOLOR_FUCHSIA SKINCOLOR_MAROON,8, // SKINCOLOR_TOXIC From ff15a9896cbd663d2d9f8caafa48a94d4a829b73 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 29 Mar 2019 22:00:47 -0700 Subject: [PATCH 217/390] 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 9fbe57b3..74f78980 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 6cc875bb502f6a551309eceb6909fbaba02f2f88 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 30 Mar 2019 17:25:54 -0500 Subject: [PATCH 218/390] 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 39231034..18bf0d41 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 1602b0e3d96b4ae7fa32bf443f3c90c7d78e3ab0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 30 Mar 2019 20:57:53 -0500 Subject: [PATCH 219/390] 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 0276e1c9..69a6c5c7 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 01a52848..dbcc5fc3 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 18bf0d41..a6957f3a 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 48dcfab7f645b1b032ab32be0af056723dbe6cd0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 01:22:41 -0500 Subject: [PATCH 220/390] 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 69a6c5c7..6827dc57 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 ca2f0208..09a3db52 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 d97752b2..5b07d053 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 a6957f3a..a5f51f2a 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 cbcb288296f68aad78bff5d7900a2d8bbef0826a Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 02:54:09 -0500 Subject: [PATCH 221/390] 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 09a3db52..94f8bd8d 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 5b07d053..af85bd02 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 a5f51f2a..db31a4a5 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 2fbb0ca5f4e1311106cca02ec5bdb642ecda2874 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 12:49:42 -0500 Subject: [PATCH 222/390] 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 d184a283..5d57d34a 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 223/390] 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 db31a4a5..203531ea 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 940d2b98035ba5df69570701777c3ed378fc3438 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 13:50:29 -0500 Subject: [PATCH 224/390] 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 203531ea..d6436ffa 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 f54f08e6b5901a8c6111fe0b0ba1739b14c9c492 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 16:28:18 -0500 Subject: [PATCH 225/390] 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 94f8bd8d..e56362b6 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 d6436ffa..013eb354 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 a8023adfdf31d5ee036c7bb65e8c3ba1e65d3eb8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 16:28:29 -0500 Subject: [PATCH 226/390] 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 18b14f42..509cc4d7 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 704ce59761fde3e13980085ddac7603fe37db9f3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 17:29:41 -0500 Subject: [PATCH 227/390] 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 013eb354..7e8c3638 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 266a590a14c410b6fa83cbb87192b930fd0d198d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 19:26:53 -0500 Subject: [PATCH 228/390] 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 e56362b6..bf28425c 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 af85bd02..324af06b 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 7e8c3638..0942f1ee 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 33dc1e40..f49c6ca6 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 b177673195c53faa7acca9c05036fe3b13ff7fbc Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 31 Mar 2019 19:29:05 -0500 Subject: [PATCH 229/390] 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 0942f1ee..551a5c89 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 2fcb087d50f60f2c014fab6ca8c57f572fa9bb4b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 12:25:12 -0500 Subject: [PATCH 230/390] 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 551a5c89..5d4e0731 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 4b9562f72f93e563ebc7b7e16863a5dbce14754b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 12:28:01 -0500 Subject: [PATCH 231/390] 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 bf28425c..ca27ec5a 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 b3ef039d871b4ece4c3f2a272012ecbd485f5f4e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 12:56:23 -0500 Subject: [PATCH 232/390] 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 ca27ec5a..723d2b5e 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 324af06b..aa20dee4 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 5d4e0731..37902310 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 11586a10911fcbf4912c0b40ff38d8c9e845db5e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 13:10:35 -0500 Subject: [PATCH 233/390] [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 723d2b5e..f2463832 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 944838dc7d86e07d2676daf39931e7c052c954b7 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 15:07:27 -0500 Subject: [PATCH 234/390] 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 f2463832..0a20b104 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 aa20dee4..c44691e8 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 37902310..4d334a47 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 256a8566..4fce58cc 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 a01a3544f574f8b20c1a775cc833ba3fdf9bb705 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 17:14:45 -0500 Subject: [PATCH 235/390] 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 0a20b104..5aa28a07 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 03653ef85eb7b7259f2d8beca7196d9859b77f02 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 20:17:36 -0500 Subject: [PATCH 236/390] 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 4d334a47..5e18e7e8 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 237/390] 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 5e18e7e8..7a9f83b5 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 6a92335e1c753a1708872f38bfb1efbf54e7df9a Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 1 Apr 2019 23:34:53 -0500 Subject: [PATCH 238/390] 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 7a9f83b5..c841d50e 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 e948b8ba48180d7028d9c5c9fe1f8e8e68008e97 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 5 Apr 2019 02:38:48 -0500 Subject: [PATCH 239/390] 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 16a70519..a86a4f97 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 50f0a2e8..21a8e2a3 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 5aa28a07..df1c8235 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 c44691e8..42623dfa 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 c841d50e..96e4075d 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 16091bcae9d37f5c8d509cc40098130f5b1da2d3 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 02:17:30 -0500 Subject: [PATCH 240/390] 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 96e4075d..730eba0d 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 d9bcb43d0b72967814a6af136cd2278b9b474297 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 11:16:19 -0500 Subject: [PATCH 241/390] 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 730eba0d..a9c91724 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 1f5020dd..29acc12b 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 6267986c726df9e65775ede2a9fb8c79fbeb8d28 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 14:51:00 -0500 Subject: [PATCH 242/390] 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 a86a4f97..d1a820c8 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 df1c8235..d3f8d798 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 42623dfa..19060809 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 a9c91724..0213847d 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 f73aef99..8c1c9ae7 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 177f3b65..9b4f7a21 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 9653d8ff..1585753f 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 29acc12b..dfad4c3a 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 243/390] 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 0213847d..915643ac 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 aaa6418981c68161b460841774c7dff2dcce665f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 18:06:02 -0500 Subject: [PATCH 244/390] 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 d3f8d798..701f0673 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 915643ac..c3d2397f 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 1eff7bfbe80db88b96e5b0619a34bcac7b2e67a1 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 18:17:56 -0500 Subject: [PATCH 245/390] 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 c3d2397f..7c82bc31 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 f38d56d4a613b26f60d97c09e93d930bfacdb380 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 6 Apr 2019 18:59:11 -0500 Subject: [PATCH 246/390] 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 701f0673..f7f0457a 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 7c82bc31..d8d8f4a1 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 f49c6ca6..ef0381d1 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 f8fec8e6250eaee1b17ff13968a762fa29a12f46 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 6 Apr 2019 21:59:58 -0400 Subject: [PATCH 247/390] Lua: fix K_PlayPowerGloatSound mistype --- 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 dde57c2d..d9a5fb1d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2752,7 +2752,7 @@ static luaL_Reg lib[] = { // k_kart {"K_PlayAttackTaunt", lib_kAttackSound}, {"K_PlayBoostTaunt", lib_kBoostSound}, - {"K_PlayPowerGloatSund", lib_kGloatSound}, + {"K_PlayPowerGloatSound", lib_kGloatSound}, {"K_PlayOvertakeSound", lib_kOvertakeSound}, {"K_PlayLossSound", lib_kLossSound}, {"K_PlayHitEmSound", lib_kHitEmSound}, From d59fb7f80c35c498140f92920c099a760b7c98b0 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 6 Apr 2019 23:42:02 -0400 Subject: [PATCH 248/390] 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 1c88fe83..3fcfd50b 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 ac3b1516cdbdac69c9f1ce37bf8c683a744393de Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 7 Apr 2019 17:59:32 -0500 Subject: [PATCH 249/390] 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 f7f0457a..2f4f8531 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 19060809..148a5e52 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 9b4f7a21..a5f6313b 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 45390f2c35d0b0fd19247be8697cc9756b4303a2 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 7 Apr 2019 18:51:42 -0500 Subject: [PATCH 250/390] 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 2f4f8531..2bf89a9e 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 c0af0fb59edf6a722f400001aa87f7f1ec07d13e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 8 Apr 2019 00:30:04 -0500 Subject: [PATCH 251/390] 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 2bf89a9e..6233fb99 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 9a049f5a0d8850a0a739fadeb3b97d3720185457 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 8 Apr 2019 00:45:19 -0500 Subject: [PATCH 252/390] 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 6233fb99..6284ea66 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 42d47a10f3008e74b70944474864f5c6dd9c8c7e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 8 Apr 2019 15:48:20 -0700 Subject: [PATCH 253/390] "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 e227ce2e..4f5e762d 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 f3a9011e..f4db8512 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 9f719967..9cff9278 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 08bf3318..0173b5db 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 166c5e00..e6c327ab 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 6664ff51..51052a0b 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 834b3a7c..4b0c2e3e 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 3ad076ff..afb085c4 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 e746e540757ab4d77734bfdc585c19baecc81803 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 8 Apr 2019 15:57:23 -0700 Subject: [PATCH 254/390] 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 9cff9278..94b11d51 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 ae473585b7849e72c8debc4e66d6896f4f2b438f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Mon, 8 Apr 2019 23:21:11 -0500 Subject: [PATCH 255/390] 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 d1a820c8..6feedb18 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 21a8e2a3..36774a80 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 4de2abd0..4cb8bac5 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 5b4a8e58..2e4d29b9 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 dfad4c3a..16d784f4 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 c48c7a11..c8485c17 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 56c1f05217edc1b634ffdeb8673326418b6c2588 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 01:09:13 -0500 Subject: [PATCH 256/390] 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 16d784f4..646e6015 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 fe3cd967d197584d0dae77146a01d781791ba3cf Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 01:18:10 -0500 Subject: [PATCH 257/390] 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 646e6015..83bfff73 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 258/390] 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 d8d8f4a1..c7461426 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 83bfff73..2d8ca812 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 259/390] 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 6284ea66..37aa4a5e 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 15bb586c572fd4186137144002e44778ea925154 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 23:00:39 -0500 Subject: [PATCH 260/390] 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 83bfff73..59522cb3 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 40d065a024d0326278c88d73a338582a1fdeed56 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Tue, 9 Apr 2019 23:55:25 -0500 Subject: [PATCH 261/390] 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 37aa4a5e..0dd24ecb 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 a5f6313b..038d00a2 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 509cc4d7..26ee9f8c 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 4f1a329ef24423258ea23d2b2a67484944f5bf9d Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Wed, 10 Apr 2019 03:16:46 -0400 Subject: [PATCH 262/390] Update k_kart.c --- 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 0421f625..9d928a2a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -219,7 +219,7 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_SUNSET,10, // SKINCOLOR_MOONSLAM SKINCOLOR_MAUVE,10, // SKINCOLOR_ULTRAVIOLET SKINCOLOR_DAWN,6, // SKINCOLOR_DUSK - SKINCOLOR_POPCORN,11, // SKINCOLOR_BUBBLEGUM + SKINCOLOR_POPCORN,12, // SKINCOLOR_BUBBLEGUM SKINCOLOR_EMERALD,8, // SKINCOLOR_PURPLE SKINCOLOR_PASTEL,11, // SKINCOLOR_FUCHSIA SKINCOLOR_MAROON,8, // SKINCOLOR_TOXIC From 5fcafb643b59cd9e267dc726ae7fb3fcbb747e4b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 10 Apr 2019 09:10:09 -0500 Subject: [PATCH 263/390] 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 c7461426..7a4ea678 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 052104999f1bdf538e398a42fcd735d94f73857b Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 12 Apr 2019 00:35:35 -0500 Subject: [PATCH 264/390] 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 5c09a0bc..af0546dc 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 8c9590e9..335240c5 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 07ccd3d8..d217f409 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 3ad076ff..9a98bb73 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 1a72d616..9e355a09 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 16d39e1d..bac0faea 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 fe7220bb20132092a44fcb79f3ed68de5c9348d1 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 12 Apr 2019 00:46:52 -0500 Subject: [PATCH 265/390] 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 a5d45bc1..543df6ce 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 3286d9ac9384556b515db327439ac05dc75b8db4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 10:16:54 -0500 Subject: [PATCH 266/390] Use strchr? --- src/command.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/command.c b/src/command.c index 543df6ce..8e2d0037 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 451ff30a7a0e7a004547d2e81467974a15004b6c Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 10:25:56 -0500 Subject: [PATCH 267/390] 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 8e2d0037..7d7a357a 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 eb9c9885a9664fafef52210db485c525cf7bd218 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 14:22:48 -0500 Subject: [PATCH 268/390] 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 0dd24ecb..53939213 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 7a4ea678..cbbff403 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 10d70f54472fa95d58eb75f9398bc061bc62db86 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 14:42:15 -0500 Subject: [PATCH 269/390] 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 cbbff403..970630a5 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 295b53801d81c23331951f0e0c943267ad313d7a Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 15:23:23 -0500 Subject: [PATCH 270/390] 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 970630a5..484c653c 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 5ec6517a545c94efcd24d690681053d2e54073d8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 13 Apr 2019 15:23:31 -0500 Subject: [PATCH 271/390] 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 484c653c..c6a93bc4 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 b1001d18088a59f511142f478b3862cbe4e54bb4 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 17:08:04 -0500 Subject: [PATCH 272/390] 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 53939213..85077c7b 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 4fce58cc..f3708428 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 36e678b292a947393cdaa259aaac4d6eef3cefc1 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 14 Apr 2019 15:17:47 -0700 Subject: [PATCH 273/390] 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 ba0095e0..edc04bed 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 e6767825..4682ba4a 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 a0f9f40a..1b0cb523 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 ad52f80627327a8164fbcfb447eff8cd9171f1e0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 23:17:12 -0500 Subject: [PATCH 274/390] 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 c6a93bc4..6d9ccaf1 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 9e3ee274fb8c4bed8555c230bab57c0bb17c86d9 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 23:22:24 -0500 Subject: [PATCH 275/390] 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 6d9ccaf1..4eb18446 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 c67c598df0309dece70a38c3e9eb16daeeef9965 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 14 Apr 2019 23:52:03 -0500 Subject: [PATCH 276/390] 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 acb01fb6..bbfa4c04 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 26fdee82173b8a13d3cc62f967dea7d4c1ff8acc Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 16 Apr 2019 15:05:09 -0400 Subject: [PATCH 277/390] 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 def2fe68..1880abf1 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 430831423ca42c7369e573dddabc634a86a7714d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:09:10 -0500 Subject: [PATCH 278/390] 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 84d5a6f3..636356f7 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 08bf3318..7ac14667 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 99a05840..4e6e76a1 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 0276e1c9..78917f73 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 01a52848..1a94aaa1 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 3ad076ff..7ecf8cd4 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 91570184..da82a276 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 6c5ac8e9427813fb1e301cfb64c92c447aac0347 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:29:27 -0500 Subject: [PATCH 279/390] 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 e227ce2e..86ebb345 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 f3a9011e..a4324d69 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 4e6e76a1..efb0fb81 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 3d7c2ed5..3a40c13a 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 a36700e176fe512f57da12a228cd4026563bc3f5 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:42:49 -0500 Subject: [PATCH 280/390] 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 86ebb345..1543bf68 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 efb0fb81..7e8fe0b8 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 3a40c13a..97a0d0fe 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 0e2bef3f1a8843a03e9946059b2e4b8089a4f4ac Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 17 Apr 2019 23:51:15 -0500 Subject: [PATCH 281/390] 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 1543bf68..1ce6256b 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 a4324d69..dff15f35 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 7e8fe0b8..42f7621c 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 97a0d0fe..2f033331 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 b59645e1b193a58f1a47e0e1d6f6f7e120308c65 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 18 Apr 2019 00:30:28 -0500 Subject: [PATCH 282/390] 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 1ce6256b..08f28d17 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 dff15f35..5b68def2 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 014f916040999340ec932dc6719a8205a56f9a94 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 18 Apr 2019 00:37:08 -0500 Subject: [PATCH 283/390] 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 42f7621c..4dcd3da4 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 ac53d4bbb3e33b4b53d63ac56d01e86a9d156bbe Mon Sep 17 00:00:00 2001 From: fickleheart Date: Thu, 18 Apr 2019 00:39:54 -0500 Subject: [PATCH 284/390] 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 08f28d17..f534a60b 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 1f61397545b68ce7f7fc4448b3cc1d5f854fd7f5 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 18 Apr 2019 03:08:11 -0400 Subject: [PATCH 285/390] 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 d8ce0f96..b79d2ba0 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 6feedb18..b3ae0ade 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 36774a80..76f72dd9 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 20c2964b..b0052c6c 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 834b3a7c..4c4270be 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 85077c7b..109c2baa 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 148a5e52..dd6eefca 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 d7020e8c..2368d1f2 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 3918e8f9..1237a592 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 0ea0c809..299870e0 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 fb6814b2..31beecf0 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 b56538d0..dfb344e3 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 73d5ecbc..4921ba7a 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 4eb18446..cb62738a 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 c95aa392..f4a4ec29 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 6d5137c4..f5073dea 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 e11fe403..ccbfd6ea 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 f70bcf3e..e6cb1999 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 21fb3ddb..5f7c4ef9 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 9b0db658..3c2aad44 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 c5a593d3..355c58db 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 f31075f3..102af9dc 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 34402f1a..9967969d 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 c1a34b2a..2eb0d7ed 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 8c1c9ae7..c85e9530 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 6b5f09f6..eaa7fa3d 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 24e201fc..74f9d462 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 038d00a2..2502c721 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 26ee9f8c..8d840026 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 b819735e..296cbbe8 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 7810c9b5..e3662e2e 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 b4dcd918..12206243 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 0ff97fcc..db5bfbda 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 d6d123e9..6e21e447 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 efc5dd46..71957bb5 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 6f48cc5b..499d8041 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 1585753f..8e649d08 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 bbfa4c04..3b35907b 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 f3708428..f7f4845b 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 a187656a8fffe11fb6e755d49722d1cd20f4add3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 18 Apr 2019 12:20:13 -0400 Subject: [PATCH 286/390] 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 b3ae0ade..31398039 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 8e518e40..eb657eec 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 4c4270be..f80efe63 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 109c2baa..f9c8f401 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 f7c6e1da..2594a5df 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 4fcef218..54395ab4 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 1237a592..17885b71 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 5f7c4ef9..bfb78cef 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 102af9dc..9d583d13 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 eaa7fa3d..9ed17eaa 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 8d840026..df93eaac 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 12206243..2a7d2be9 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 6e21e447..e37bdf52 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 71957bb5..6af42310 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 8e649d08..a89946a5 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 4b05199b9fadc4a6931db91e9437df54e6bfb434 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 18 Apr 2019 22:41:50 -0700 Subject: [PATCH 287/390] 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 3ad076ff..fefafff3 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 3db1244849dc4cd941d39695c718555c44136b9f Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 18 Apr 2019 23:42:28 -0700 Subject: [PATCH 288/390] 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 a5d45bc1..74b9ef51 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 387a701db52260389758727e428dc6567053b855 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 18 Apr 2019 23:50:29 -0700 Subject: [PATCH 289/390] 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 84d5a6f3..82f3721a 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 2ddffa3f..58cc0592 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 d987c8ba07abe22b886a8c0742423d71596eb77b Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 21 Apr 2019 07:52:01 -0500 Subject: [PATCH 290/390] 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 9d928a2a..17790bf0 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 445bb0b99b9bd35b7a9092bb8a6bfdf608f39669 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 22 Apr 2019 00:29:47 -0400 Subject: [PATCH 291/390] 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 126e7e40..e61acdf1 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 5a95877e..c15d13a0 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 095b4ad3..18c6ab33 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 0f43546ada315d3d7509d79b378af5f4d020e013 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 22 Apr 2019 11:29:44 +0200 Subject: [PATCH 292/390] 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 4fcef218..47148a9d 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 6978856e..4d639faf 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 3ad076ff..ddee9874 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 36182d0e..92c029b9 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 473adeed..08ec8d3c 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 e62fcc8148aceb94290963717f329caa0d9d7c5b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 22 Apr 2019 19:27:42 -0400 Subject: [PATCH 293/390] 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 18c6ab33..61f17626 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 85a15847e54026f4ecda2bbe24d5a3c7e46b95bf Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Mon, 22 Apr 2019 04:24:07 -0500 Subject: [PATCH 294/390] 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 9d928a2a..79cfe876 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 256c9cef..07f8abbd 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 5619e63e397b4215180d9f73c4b374138bd54ed7 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 22 Apr 2019 10:39:42 +0200 Subject: [PATCH 295/390] 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 d62ec7ef..31a5a61b 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 2350405ad34ac0fb014cea9485d3a62b8aca9d3a Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 23 Apr 2019 23:49:46 +0200 Subject: [PATCH 296/390] 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 47148a9d..3bb0627e 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 4d639faf..720e82ee 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 ddee9874..10f8eae0 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 92c029b9..a3328084 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 08ec8d3c..ae478394 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 21e8a2c537f7a45fe8ef68265b5686cbc6777694 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 25 Apr 2019 23:13:09 -0400 Subject: [PATCH 297/390] 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 e227ce2e..0c440c17 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 4d739fe7a5bab34d9e6b7477cdb990841eae5643 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 26 Apr 2019 12:59:21 -0700 Subject: [PATCH 298/390] 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 f5c4fa88..eb1e6302 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 aa4ce2b2d12abb7b2f4e6a52fcde35e39a8278af Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 26 Apr 2019 13:06:26 -0700 Subject: [PATCH 299/390] Check error on select --- src/mserv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mserv.c b/src/mserv.c index eb1e6302..1b0b41be 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 fc8ebe83fcb7642a09e06d84c6e506812643cb70 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 26 Apr 2019 13:08:35 -0700 Subject: [PATCH 300/390] 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 1b0b41be..5d10aa3c 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 183e75ff53ce92e606fe35d561d2fb320dec5586 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 26 Apr 2019 18:18:53 -0400 Subject: [PATCH 301/390] 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 1c88fe83..0431eb0c 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 6664ff51..07761c60 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 b4357073..cb9499c6 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 79cfe876..df65a7c9 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 db2935d45a9f2f0fe945cd5c3b3b9822349e4479 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 26 Apr 2019 19:26:22 -0500 Subject: [PATCH 302/390] 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 79cfe876..c6f02887 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 9629fb32163ec2eb7435bae30aea2f028ba09436 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 26 Apr 2019 22:32:31 -0400 Subject: [PATCH 303/390] 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 df65a7c9..5eeb9a1b 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 848bb10c364735677266e94a86ed5b0031ae92d6 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Apr 2019 17:28:29 -0700 Subject: [PATCH 304/390] 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 f3b07d34..901879ec 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 08bf3318..574c39d0 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 031ffbf304256dc79a581547af41a11fc334ddee Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Apr 2019 19:26:11 +0100 Subject: [PATCH 305/390] 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 08bf3318..bd0d6fb2 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 1c21a4ed6f21552f91b0730364c9861958d85c6d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 21 Apr 2019 17:34:59 -0400 Subject: [PATCH 306/390] 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 11a84ceb..0e5da8ae 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 0128643043ac1f0d4f87c4dbbcef37179b18fa55 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 28 Apr 2019 22:02:25 -0400 Subject: [PATCH 307/390] 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 0e5da8ae..fb0e5852 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 103e67bbaaad22100f4d5bbd314813ff9e514a77 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 30 Apr 2019 13:03:13 -0700 Subject: [PATCH 308/390] 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 5d10aa3c..29aa99fa 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 4d77ed925e469ecf12b5c69f5144efc0f7d47f29 Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 30 Apr 2019 23:08:01 +0100 Subject: [PATCH 309/390] 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 efecac52..272da06d 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 39bea80b9ec980cd73a9f5347a34cf741033dbff Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 1 May 2019 23:30:53 -0400 Subject: [PATCH 310/390] 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 b605c954..21e83d59 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 ad25c8ce..229cf3d4 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 eea149c9..9681491b 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 fefafff3..a5b21b76 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 54af8f5fc029acd600347108d885debec7728d52 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 1 May 2019 23:50:18 -0400 Subject: [PATCH 311/390] 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 c6f02887..b826d628 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 2d8461a59d0cfca0b2bd4a9c39a43ab6a42f1557 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 1 May 2019 23:56:12 -0400 Subject: [PATCH 312/390] 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 b826d628..ba15882f 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 5dc30cdac8e7b858f8fff1b468aa2974c818734b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:39:49 -0400 Subject: [PATCH 313/390] 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 b84db288..c16976b0 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 f3b07d34..d7a8e652 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 f3a9011e..8e431dbb 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 decd9655..c6a7f0f3 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 ad25c8ce..260c8879 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 0061ee02..fb82ceb2 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 f99a5a6a8b12d2f77ed9d4f6d10a3ea68f20bb6b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:44:04 -0400 Subject: [PATCH 314/390] 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 ad25c8ce..713eecac 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 c6f02887..8d1e9373 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 913fc8660f96dd0ce26a5a27cd47413ba31ae4b7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:48:01 -0400 Subject: [PATCH 315/390] 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 9967969d..03fb10d0 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 17de62894a7da7f56bfe35b49652a1f97b865a80 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:49:05 -0400 Subject: [PATCH 316/390] 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 cb62738a..b2e27f89 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 37de59cdfd1fdc3603cabcb104f2fd130cbcd80d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 00:49:36 -0400 Subject: [PATCH 317/390] 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 f9c8f401..7d673f66 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 285ab9c9b973e04465a49bf9392033427c46327b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 01:33:11 -0400 Subject: [PATCH 318/390] 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 b2e27f89..3d407ec4 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 46387226324dce106f08710079e5dc8aabe2fe80 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 01:34:25 -0400 Subject: [PATCH 319/390] 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 793537f8..8db114fb 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 fd148ec2078dc249913c57157a3c3515056292bd Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:13:44 -0400 Subject: [PATCH 320/390] 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 229cf3d4..bfe49fc1 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 9e1548692636bcd119adc9b4c6c80213ecc5b87f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:51:13 -0400 Subject: [PATCH 321/390] 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 1c88fe83..03944640 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 260c8879..a1e90822 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 d9a5fb1d..481ab89a 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 1ac613bd..a6f6b8ae 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 ab0a16ed..d5a4c694 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 36a658ae..cd4ed7e2 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 e772a750a897aaa1f9246fb4314c863ea0ec69d4 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:52:22 -0400 Subject: [PATCH 322/390] 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 8d1e9373..d8028f08 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 7bfc39479278fdb8091b714973923a94c7e44a95 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 02:58:34 -0400 Subject: [PATCH 323/390] 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 31a5a61b..599d1f2a 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 e1ac3f2d..508acc0b 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 4d967bcc8e85705dc24bfb4ed7a64b3432546d03 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 09:20:49 -0400 Subject: [PATCH 324/390] 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 e986434a..9bbe4197 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 481ab89a..54151453 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 a6f6b8ae..2362476d 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 d5a4c694..9999b5a9 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 73e152a01cfe18c4aa54cec662b1dff7702791f1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:00:51 -0400 Subject: [PATCH 325/390] 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 b516c8ec..144b671e 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 86dfd70c6fbb84d3a7c239d703476c65e7b6a208 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:03:50 -0400 Subject: [PATCH 326/390] 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 7d673f66..d29da5ba 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 144b671e..ed034f93 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 34eb4bd14dbd213220c60d008d0aba1b9fc527aa Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:31:50 -0400 Subject: [PATCH 327/390] 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 d29da5ba..13fb3d61 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 3f730e03ecd9142a4d1c0f264c02d87d141d7222 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:36:11 -0400 Subject: [PATCH 328/390] 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 13fb3d61..a5a62384 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 25f277e185aac1099a8d689f09b4d17ce3ff3f48 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:42:29 -0400 Subject: [PATCH 329/390] 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 ed034f93..7fb2a1ec 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 489032f7343a7fc1cefcf2d989a7be92747576c1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:50:05 -0400 Subject: [PATCH 330/390] 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 a5a62384..6e9a6068 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 98dbdd7db5407f77fb3f3af4d54f3279f5730aa2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 12:58:02 -0400 Subject: [PATCH 331/390] 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 b0052c6c..972fe959 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 3e5b0c45318d77f594d4ae71596c5d0fcc5752e8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 2 May 2019 18:31:51 -0400 Subject: [PATCH 332/390] 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 dde62fc7..7b5a95a4 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 904b00e9211c310a5e191b8dc3f89b006abb0504 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 2 May 2019 19:14:23 -0400 Subject: [PATCH 333/390] 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 7b5a95a4..045e82b1 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 a5dfbe7eff806cf4efa03b9cb159907f38233214 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 3 May 2019 16:38:59 +0100 Subject: [PATCH 334/390] 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 7495d788..c82554ac 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 8273534967272444d3fb79b1260ca14c05933ce1 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 6 May 2019 16:57:32 +0100 Subject: [PATCH 335/390] 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 272da06d..7e0b369e 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 59042cf3..f86b198a 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 94945af5..08b1ab2f 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 cfe7d036..c3b29e15 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 b304b268c8c4ffe933b78d66eb221216907fa893 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 6 May 2019 20:24:26 +0100 Subject: [PATCH 336/390] 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 79a46f6b..0e041ae1 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 a7df73a35fca958ec3a188dfbe6d7a78a4ec5132 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 21:17:32 -0400 Subject: [PATCH 337/390] 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 4d825eef..b2f511de 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 5022cde44323fd135d71483bbadae4ca155cd646 Mon Sep 17 00:00:00 2001 From: Sal Date: Mon, 6 May 2019 21:51:35 -0400 Subject: [PATCH 338/390] Merge branch 'version-prep' into 'master' Version prep See merge request KartKrew/Kart!148 (cherry picked from commit dfc4b22c911340e330a0f71fabb4a1461b5747ed) 183e75ff Final v1 colors 9629fb32 Modify the first shade of Byzantium 39bea80b Add options for adjusting deadzone, increase default deadzone from 0.25 to 0.5 f99a5a6a Fix wheel animations fd148ec2 Dumbass typo e772a750 Missed a spot 3d71a0aa Merge branch 'next-colors' into 'v1' 071b335d Merge branch 'anim-fix' into 'v1' 0cd815cb 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 e7c4de61..7995034d 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 10b65891..3d46cf6d 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 bd7e7861..f3dd53ee 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 b12c42b4..acd27977 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 4308d3b6817a0d4ac26efd1b3e4f2cbf8cd54b44 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 22:39:20 -0400 Subject: [PATCH 339/390] 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 08ae8af1..c2d1d286 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 b7eb1e1f..f343f12b 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 167f0bfe8b1e114cf1a7944e53cb7bf10063ce40 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 22:54:47 -0400 Subject: [PATCH 340/390] 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 f3dd53ee..33864743 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 b98f8f75048a414741caf74c86da658c7bced6bf Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 7 May 2019 01:34:49 -0500 Subject: [PATCH 341/390] 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 f2d44214..e7384724 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 777f1675fcf4a2d50e159c00277c9683388d2a43 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 7 May 2019 02:06:59 -0500 Subject: [PATCH 342/390] 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 d5258646..e824e072 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 9df84082e920d2d943a618f740a1317585770fa5 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 8 May 2019 00:17:21 -0500 Subject: [PATCH 343/390] 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 afc0fb7e..c22d7a58 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 571e9be7d8e2d214b4bf84c2b2c47abc14344d6f Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 9 May 2019 23:03:32 -0400 Subject: [PATCH 344/390] 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 d25587be..a23f9f2d 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 38f33027a0b6d36bfbb137599e3fe6c8f4d5a855 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 9 May 2019 23:10:23 -0400 Subject: [PATCH 345/390] 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 673df055..2c732447 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 2f31dd3ab7bd2d9918c33c87ca629a9b46b0d919 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 9 May 2019 23:10:23 -0400 Subject: [PATCH 346/390] 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 673df055..2c732447 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 90e4a45aa4b99ee7267f5d92a7dfaba3516143a4 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 03:21:46 -0500 Subject: [PATCH 347/390] 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 a345da59..cc6acb34 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 334056a77d0479dfaeebfe4df4a615dbc5375b60 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 04:22:34 -0500 Subject: [PATCH 348/390] 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 34c6a6e1..52a73b60 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 68ad2a9932a6a6fa0be3536bc99d958525eeea30 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 14:42:39 -0500 Subject: [PATCH 349/390] 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 734db995..bee8246d 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 7cc5fddbd83dd5b016c72b2ebae7cf315e3a0815 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 12 May 2019 16:38:50 -0500 Subject: [PATCH 350/390] 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 bee8246d..5aa3edbb 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 66439fe812df70d084305c4774fd46959440b6ff Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Mon, 13 May 2019 12:49:44 -0500 Subject: [PATCH 351/390] 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 29aacb90..19a7b8c9 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 a40ff7502599f39cb9842dd3a27f4d8f5cd2af33 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 12 May 2019 14:17:56 +0200 Subject: [PATCH 352/390] 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 bf1cacdc..7963286d 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 ea90778c32cf201df1a25e87f4c56ee9a6f7089b Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 14 May 2019 22:29:28 -0500 Subject: [PATCH 353/390] 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 19a7b8c9..2bf5c743 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 59ca91a825d4ca74c0863523a538399640503020 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 17 May 2019 08:06:18 -0500 Subject: [PATCH 354/390] 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 526564a6..43c6c7cc 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 61d8f36f..a9ea8443 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 05dde43423f994e16c2287ff41b02cb2d359c5b3 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 22 May 2019 22:45:32 -0700 Subject: [PATCH 355/390] 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 52a73b60..cf9f649a 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 2fb4dd73fc6475fca0cb2a8cf10d7fa27a2b56e3 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 22 May 2019 23:16:20 -0700 Subject: [PATCH 356/390] 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 cf9f649a..9b5e98e4 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 78c2c54a8708a46b4d8d983728a409594acfc425 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 13:08:38 +0200 Subject: [PATCH 357/390] 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 c6a7f0f3..114674ff 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 5aa3edbb..f29c9787 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 43c6c7cc..6eeb091c 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 a9ea8443..0b938b0b 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 d4d794ceac90d3df472e25a407b9339f76448bff Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 13:51:19 +0200 Subject: [PATCH 358/390] 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 43c6c7cc..d96e092b 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 93740dc8547502039d98b9dae794d2fc2a0f0b2e Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 14:11:26 +0200 Subject: [PATCH 359/390] 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 7b1b321d..b311a860 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 e42e567489f3398d200a124338feb3d053340ba1 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 25 May 2019 14:13:35 +0200 Subject: [PATCH 360/390] 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 d96e092b..e17d45df 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 cb742284695707c49cee8684978d0a81a0f170df Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 26 May 2019 11:19:26 +0200 Subject: [PATCH 361/390] 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 2c766349..fd1047da 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 a7917cb4b9e62ff73c0ae327d973d19e9f077df4 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 26 May 2019 15:05:10 +0200 Subject: [PATCH 362/390] 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 e32295ad..fc155229 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 3a72a32d..22c89a23 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 a9ea8443..c43e0929 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 a2a63c5e7f03a16b84a2a705b026d996c0bae38b Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 27 May 2019 22:03:17 +0100 Subject: [PATCH 363/390] 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 3dfea041..a624878c 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 06ddf557092fbe460c9d7649bafc781e03ac4228 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 27 May 2019 14:20:07 -0700 Subject: [PATCH 364/390] wip --- src/v_video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/v_video.c b/src/v_video.c index a624878c..2ba28b43 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 995edfb1e8c1c67b6aa9334a1fb9093500253910 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 27 May 2019 14:20:12 -0700 Subject: [PATCH 365/390] Revert "Fix Post Processing in 64-bit Software 3P/4P" This reverts commit a2a63c5e7f03a16b84a2a705b026d996c0bae38b. --- 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 2ba28b43..5b5e3a06 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 ab7246d1f7d539c352b3d67305e088ebadffdca0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 27 May 2019 22:59:58 +0100 Subject: [PATCH 366/390] 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 a624878c..9233eda4 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 e266f72a1c7cc53eb7a0eee5daf253cf67c2acef Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 28 May 2019 06:33:38 -0500 Subject: [PATCH 367/390] 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 33864743..f3f8339f 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 c28e1702eb8d8df83245a901bd1b028b46e86758 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Tue, 28 May 2019 06:56:35 -0500 Subject: [PATCH 368/390] 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 fc155229..9964140d 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 71e3ec55bf1c942febe486f478a37ea45243d1aa Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 15:08:33 -0700 Subject: [PATCH 369/390] Revert "Revert "Fix Post Processing in 64-bit Software 3P/4P"" This reverts commit 995edfb1e8c1c67b6aa9334a1fb9093500253910. --- 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 1f8bb677..9233eda4 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 6d4cdfaab71161708ba4c613b9cbdb7926fbfcb4 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 15:11:37 -0700 Subject: [PATCH 370/390] 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 a0398154..8402e349 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 7963286d..1795a304 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 f070bd2d4dd31b3d0c045b90aa42a4b884d9e43c Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 19:00:24 -0700 Subject: [PATCH 371/390] Fix GCC 8 Travis error --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6f8a7aa..6d2e8cdd 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 b15cea53e6c1cd4147e31a3cdb4e555ebc7b73bb Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 19:03:02 -0700 Subject: [PATCH 372/390] 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 f29c9787..10bd76ac 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 0b938b0b..ced8b2da 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 33b7459c1b855b6b14a816359609e85fba52a8e0 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:20:32 -0700 Subject: [PATCH 373/390] Revert "Force of habit" This reverts commit fc8ebe83fcb7642a09e06d84c6e506812643cb70. --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 29aa99fa..8ae8c830 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 0561a5374cf535422edeb621b12af2334197a734 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:20:33 -0700 Subject: [PATCH 374/390] Revert "Check error on select" This reverts commit aa4ce2b2d12abb7b2f4e6a52fcde35e39a8278af. --- src/mserv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index 8ae8c830..21eb44c9 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 8589a1ec07b0781f9fe3d694e2e8374adb1b549f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:21:04 -0700 Subject: [PATCH 375/390] Revert "Unfuck MS connecting and error reporting" This reverts commit 4d739fe7a5bab34d9e6b7477cdb990841eae5643. --- src/mserv.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index 21eb44c9..f5c4fa88 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 91c707d6fdc2dc1a24e266ca1633fcc070a6615e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 Jun 2019 14:24:11 -0700 Subject: [PATCH 376/390] 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 0bb87556..7dff1231 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 935fec1e1519ee3e1706fb5991fb9dc6e92f6de5 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 17 Jun 2019 20:57:31 +0100 Subject: [PATCH 377/390] 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 1dc2c142..213f5dde 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 e7879d58..66d9e73e 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 4ab40853..24b52e8d 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 11c94d33121ae9e8b148b7d19adb57114c95998f Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 19 Jun 2019 20:05:20 +0100 Subject: [PATCH 378/390] 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 63cde0ca..8863de93 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 1b46553d430c54576682fcd2028193ca23119a2b Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 19 Jun 2019 21:54:11 +0100 Subject: [PATCH 379/390] 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 064f8d41..c7344b16 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 ec369e8d21bed3060c7ab407069d7ae3faf40626 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 19 Jun 2019 14:32:11 -0700 Subject: [PATCH 380/390] 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 9b5e98e4..46f7bc5b 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 7f99ebc6928c7e01aa067cbb8a811b161598e27f Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:16:23 -0700 Subject: [PATCH 381/390] 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 4dcd3da4..989d20db 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 d5e1c1af425dec36676da9f7009c0d8e41048268 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:24:50 -0700 Subject: [PATCH 382/390] 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 989d20db..a321fb78 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 bbee4a2554d62880747cfc343e4a6947719b010d Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:29:55 -0700 Subject: [PATCH 383/390] 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 a321fb78..76b66836 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 5f4f10fdbe311d19be2ffefba1267262e5cec900 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 22 Jun 2019 21:39:31 -0700 Subject: [PATCH 384/390] 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 9b5e98e4..ccb717c2 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 d67ea859e3a680c5f5a0d1028cbacacfe980369a Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 24 Jun 2019 20:06:53 +0100 Subject: [PATCH 385/390] Match CheckClip to software's clipping check in R_AddLine Has the added benefit of fixing noclip camera for opengl Unfortunately SkyWalls are kinda broken with this. I'll be looking into them shortly. --- src/hardware/hw_main.c | 85 +++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8863de93..ef623d9b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2421,62 +2421,47 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks backc1 = backc2 = abacksector->ceilingheight; } - // now check for closed sectors! - if (backc1 <= frontf1 && backc2 <= frontf2) + if (viewsector != abacksector && viewsector != afrontsector) { - checkforemptylines = false; - if (!seg->sidedef->toptexture) - return false; + boolean mydoorclosed = false; // My door? Closed!? (doorclosed is actually otherwise unused in openGL) - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - return true; - } - - if (backf1 >= frontc1 && backf2 >= frontc2) - { - checkforemptylines = false; - if (!seg->sidedef->bottomtexture) - return false; - - // properly render skies (consider door "open" if both floors are sky): - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - return true; - } - - if (backc1 <= backf1 && backc2 <= backf2) - { - checkforemptylines = false; - // preserve a kind of transparent door/lift special effect: - if (backc1 < frontc1 || backc2 < frontc2) - { - if (!seg->sidedef->toptexture) - return false; - } - if (backf1 > frontf1 || backf2 > frontf2) - { - if (!seg->sidedef->bottomtexture) - return false; - } - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum) - return false; - - return true; - } - - if (backc1 != frontc1 || backc2 != frontc2 - || backf1 != frontf1 || backf2 != frontf2) + // If the sector behind the line blocks all kinds of view past it + // (back ceiling is lower than close floor, or back floor is higher than close ceiling) + if ((backc1 <= frontf1 && backc2 <= frontf2) + || (backf1 >= frontc1 && backf2 >= frontc2)) { checkforemptylines = false; - return false; + return true; } + // The door is closed if: + // backsector is 0 height or less and + // back ceiling is higher than close ceiling or we need to render a top texture and + // back floor is lower than close floor or we need to render a bottom texture and + // neither front or back sectors are using the sky ceiling + mydoorclosed = (backc1 <= backf1 && backc2 <= backf2 + && ((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture) + && ((backf1 <= frontf1 && backf2 >= frontf2) || seg->sidedef->bottomtexture) + && (abacksector->ceilingpic != skyflatnum || afrontsector->ceilingpic != skyflatnum)); + + if (mydoorclosed) + { + checkforemptylines = false; + return true; + } + } + + // Window. + // We know it's a window when the above isn't true and the back and front sectors don't match + if (backc1 != frontc1 || backc2 != frontc2 + || backf1 != frontf1 || backf2 != frontf2) + { + checkforemptylines = false; + return false; + } + + // In this case we just need to check whether there is actually a need to render any lines, so checkforempty lines + // stays true return false; } #else From 414eee58baeee8a20b569235a838a44e64ad702a Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 24 Jun 2019 20:50:37 +0100 Subject: [PATCH 386/390] checkforemptylines can be static --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ef623d9b..244d7699 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2381,7 +2381,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // e6y: Check whether the player can look beyond this line // #ifdef NEWCLIP -boolean checkforemptylines = true; +static boolean checkforemptylines = true; // Don't modify anything here, just check // Kalaron: Modified for sloped linedefs static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector) From 59bbab1fff7637ffd385b2a1a84aecde81b1a817 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 25 Jun 2019 00:44:12 -0700 Subject: [PATCH 387/390] 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 10bd76ac..b8a1a3bf 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 From c3f6f263d4bbd60afd411e1761afce7315c4dabe Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 26 Jun 2019 23:17:45 +0100 Subject: [PATCH 388/390] Update Skywall handling I've tried to make this so it almost never under-compensates, and over-compensates very little where possible. I don't think it's 1:1 to software's current behaviour, and probably never will be due to software being very strange. --- src/hardware/hw_main.c | 232 ++++++++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 85 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 244d7699..6a08b1c7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1319,7 +1319,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, // HWR_DrawSkyWalls // Draw walls into the depth buffer so that anything behind is culled properly -static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top) +static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) { HWD.pfnSetTexture(NULL); // no texture @@ -1327,9 +1327,6 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(top); // No real way to find the correct height of this - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(bottom); // worldlow/bottom because it needs to cover up the lower thok barrier wall HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); // PF_Invisible so it's not drawn into the colour buffer // PF_NoTexture for no texture @@ -1462,6 +1459,111 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) worldlow = gr_backsector->floorheight; #endif + // Sky culling + if (!gr_curline->polyseg) // Don't do it for polyobjects + { + // Sky Ceilings + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); + + if (gr_frontsector->ceilingpic == skyflatnum) + { + if (gr_backsector->ceilingpic == skyflatnum) + { + // Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the + // backsector is lower + if ((worldhigh <= worldtop) +#ifdef ESLOPE + && (worldhighslope <= worldtopslope) +#endif + ) + { +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); + wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else + { + // Only the frontsector is sky, just draw a skywall from the front ceiling +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else if (gr_backsector->ceilingpic == skyflatnum) + { + // Only the backsector is sky, just draw a skywall from the front ceiling +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + + + // Sky Floors + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); + + if (gr_frontsector->floorpic == skyflatnum) + { + if (gr_backsector->floorpic == skyflatnum) + { + // Both front and back sectors are sky, needs skywall from the backsector's floor, but only if the + // it's higher, also needs to check for bottomtexture as the floors don't usually move down + // when both sides are sky floors + if ((worldlow >= worldbottom) +#ifdef ESLOPE + && (worldlowslope >= worldbottomslope) +#endif + && !(gr_sidedef->bottomtexture)) + { +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else + { + // Only the backsector has sky, just draw a skywall from the back floor +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else if ((gr_backsector->floorpic == skyflatnum) && !(gr_sidedef->bottomtexture)) + { + // Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky if (gr_frontsector->ceilingpic == skyflatnum && @@ -1914,85 +2016,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) Surf.FlatColor.rgba = 0xffffffff; }*/ } - - // Isn't this just the most lovely mess - if (!gr_curline->polyseg) // Don't do it for polyobjects - { - if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn - depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - else - depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - { - if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); - else - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); - } - // behind sector is not a thok barrier - else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height - || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height - || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower - || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - } - // And now for sky floors! - if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->bottomtexture) - depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; - else - depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - { - if (!gr_sidedef->toptexture) // Only extend up if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); - else - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); - } - // behind sector is not a thok barrier - else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height - || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height - || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher - || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - } - } } else { @@ -2060,13 +2083,52 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } } + else + { +#ifdef ESLOPE + //Set textures properly on single sided walls that are sloped + wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); + wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); +#else + // set top/bottom coords + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); +#endif + // When there's no midtexture, draw a skywall to prevent rendering behind it + HWR_DrawSkyWall(wallVerts, &Surf); + } + + + // Single sided lines are simple for skywalls, just need to draw from the top or bottom of the sector if there's + // a sky flat if (!gr_curline->polyseg) { if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector - HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX); + { + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } if (gr_frontsector->floorpic == skyflatnum) - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom); + { +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); +#endif + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); + + HWR_DrawSkyWall(wallVerts, &Surf); + } } } From 0a2eac682bbcf65f97f4ad1fc7b376646b17609c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 4 Jul 2019 16:38:00 -0700 Subject: [PATCH 389/390] Don't use client port as default peer port --- src/i_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index fb0e5852..f58aa22b 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1311,7 +1311,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) int gaie; if (!port || !port[0]) - port = port_name; + port = DEFAULTPORT; DEBFILE(va("Creating new node: %s@%s\n", address, port)); From 14be24dfb63156b100420a68de86aa0c2ac32552 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 4 Jul 2019 17:48:17 -0700 Subject: [PATCH 390/390] Support adding to CV_FLOAT cvars with the Add command --- src/command.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 3eebe32d..6d9c86d3 100644 --- a/src/command.c +++ b/src/command.c @@ -902,7 +902,10 @@ static void COM_Add_f(void) return; } - CV_AddValue(cvar, atoi(COM_Argv(2))); + if (( cvar->flags & CV_FLOAT )) + CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2)))); + else + CV_AddValue(cvar, atoi(COM_Argv(2))); } // =========================================================================