diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a7ae75db4..a4d384d77 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -5577,6 +5577,15 @@ static void Follower2_OnChange(void) strlwr(str); if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright... { + + if (stricmp(cpy, "None") == 0) + { + CV_StealthSet(&cv_follower2, "-1"); + SendNameAndColor2(); + return; + } + + INT32 num = R_FollowerAvailable(str); char set[10]; if (num == -1) // that's an error. @@ -5599,6 +5608,14 @@ static void Follower3_OnChange(void) strlwr(str); if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright... { + + if (stricmp(cpy, "None") == 0) + { + CV_StealthSet(&cv_follower3, "-1"); + SendNameAndColor3(); + return; + } + INT32 num = R_FollowerAvailable(str); char set[10]; if (num == -1) // that's an error. @@ -5621,6 +5638,14 @@ static void Follower4_OnChange(void) strlwr(str); if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright... { + + if (stricmp(cpy, "None") == 0) + { + CV_StealthSet(&cv_follower4, "-1"); + SendNameAndColor4(); + return; + } + INT32 num = R_FollowerAvailable(str); char set[10]; if (num == -1) // that's an error. diff --git a/src/g_game.c b/src/g_game.c index 0831f7855..74e4b1906 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3251,7 +3251,7 @@ 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 + demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything } void G_ExitLevel(void) @@ -3284,7 +3284,7 @@ const char *Gametype_Names[NUMGAMETYPES] = { "Race", // GT_RACE "Battle" // GT_MATCH - + /*"Co-op", // GT_COOP "Competition", // GT_COMPETITION "Team Match", // GT_TEAMMATCH @@ -4926,6 +4926,13 @@ void G_ReadDemoExtraData(void) M_Memcpy(player_names[p],demo_p,16); demo_p += 16; } + if (extradata & DXD_FOLLOWER) + { + // Set our follower + M_Memcpy(name, demo_p, 16); + demo_p += 16; + SetPlayerFollower(p, name); + } if (extradata & DXD_PLAYSTATE) { extradata = READUINT8(demo_p); @@ -5028,6 +5035,7 @@ void G_WriteDemoExtraData(void) WRITEUINT8(demo_p, skins[players[i].skin].kartspeed); WRITEUINT8(demo_p, skins[players[i].skin].kartweight); + } if (demo_extradata[i] & DXD_COLOR) { @@ -5045,6 +5053,15 @@ void G_WriteDemoExtraData(void) M_Memcpy(demo_p,name,16); demo_p += 16; } + if (demo_extradata[i] & DXD_FOLLOWER) + { + // write follower + memset(name, 0, 16); + strncpy(name, followers[players[i].followerskin].skinname, 16); + CONS_Printf("%s\n", name); + M_Memcpy(demo_p, name, 16); + demo_p += 16; + } if (demo_extradata[i] & DXD_PLAYSTATE) { demo_writerng = 1; @@ -5668,6 +5685,8 @@ void G_GhostTicker(void) g->p += 16; // Same tbh if (ziptic & DXD_NAME) g->p += 16; // yea + if (ziptic & DXD_FOLLOWER) + g->p += 16; // ok 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 } @@ -6396,6 +6415,12 @@ void G_BeginRecording(void) CV_SaveNetVars(&demo_p, true); // Now store some info for each in-game player + + // Lat' 12/05/19: Do note that for the first game you load, everything that gets saved here is total garbage; + // The name will always be Player , the skin sonic, the color None and the follower 0. This is only correct on subsequent games. + // In the case of said first game, the skin and the likes are updated with Got_NameAndColor, which are then saved in extradata for the demo with DXD_SKIN in r_things.c for instance. + + for (p = 0; p < MAXPLAYERS; p++) { if (playeringame[p]) { player = &players[p]; @@ -6420,6 +6445,12 @@ void G_BeginRecording(void) M_Memcpy(demo_p,name,16); demo_p += 16; + // Save follower's skin name + memset(name, 0, 16); + strncpy(name, followers[player->followerskin].skinname, 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); @@ -7031,7 +7062,7 @@ void G_DoPlayDemo(char *defdemoname) { UINT8 i, p; lumpnum_t l; - char skin[17],color[17],*n,*pdemoname; + char skin[17],color[17],follower[17],*n,*pdemoname; UINT8 version,subversion; UINT32 randseed; char msg[1024]; @@ -7045,6 +7076,7 @@ void G_DoPlayDemo(char *defdemoname) skin[16] = '\0'; color[16] = '\0'; + follower[16] = '\0'; // No demo name means we're restarting the current demo if (defdemoname == NULL) @@ -7280,6 +7312,10 @@ void G_DoPlayDemo(char *defdemoname) M_Memcpy(color,demo_p,16); demo_p += 16; + // Follower + M_Memcpy(follower,demo_p,16); + demo_p += 16; + demo_p += 5; // Backwards compat - some stats // SRB2kart kartspeed[0] = READUINT8(demo_p); @@ -7321,6 +7357,19 @@ void G_DoPlayDemo(char *defdemoname) break; } + // Follower + if (!SetPlayerFollower(0, follower)) + { + snprintf(msg, 1024, M_GetText("%s features a follower that is not currently loaded.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + // net var data CV_LoadNetVars(&demo_p); @@ -7474,6 +7523,11 @@ void G_DoPlayDemo(char *defdemoname) break; } + // Follower + M_Memcpy(follower, demo_p, 16); + demo_p += 16; + SetPlayerFollower(p, follower); + // Score, since Kart uses this to determine where you start on the map players[p].score = READUINT32(demo_p); @@ -7679,6 +7733,9 @@ void G_AddGhost(char *defdemoname) M_Memcpy(color, p,16); p += 16; + // Follower data was here, doesn't matter for ghosts + p += 16; + // Ghosts do not have a player structure to put this in. p++; // charability p++; // charability2 @@ -7741,6 +7798,9 @@ void G_AddGhost(char *defdemoname) M_Memcpy(color, p, 16); p += 16; + // Follower data was here, skip it, we don't care about it for ghosts. + p += 16; + p += 4; // score kartspeed = READUINT8(p); diff --git a/src/g_game.h b/src/g_game.h index a69f91421..06b9ef829 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -214,6 +214,7 @@ extern UINT8 demo_writerng; #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_FOLLOWER 0x20 // follower was changed #define DXD_PST_PLAYING 0x01 #define DXD_PST_SPECTATING 0x02 diff --git a/src/m_menu.c b/src/m_menu.c index 0bedf62c6..e07abff9d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9428,8 +9428,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) { diff --git a/src/p_user.c b/src/p_user.c index ea99cdcf9..8b59fd22c 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; diff --git a/src/r_things.c b/src/r_things.c index 75d2d4349..d0b34eddd 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2719,6 +2719,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) P_SetScale(player->mo, player->mo->scale); + // for replays: We have changed our skin mid-game; let the game know so it can do the same in the replay! demo_extradata[playernum] |= DXD_SKIN; return; @@ -2751,6 +2752,9 @@ void SetFollower(INT32 playernum, INT32 skinnum) player->follower = NULL; } + // for replays: We have changed our follower mid-game; let the game know so it can do the same in the replay! + demo_extradata[playernum] |= DXD_FOLLOWER; + return; }