From 578e386e40ec0281990aa3b16876b71780a29184 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sat, 25 Aug 2018 15:56:34 -0400
Subject: [PATCH] Add MUSICPOSITION level header and mapmusposition variable to
 instantly jump to position

* Cutscene support too!
---
 src/d_netcmd.c | 14 +++++++-------
 src/dehacked.c |  9 +++++++++
 src/doomstat.h |  3 +++
 src/f_finale.c | 10 ++++++----
 src/g_game.c   |  1 +
 src/p_setup.c  |  1 +
 src/p_user.c   |  4 ++--
 src/s_sound.c  |  3 ++-
 8 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 41b8ace60..35a750fec 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -3979,6 +3979,7 @@ 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 ...
@@ -4030,10 +4031,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_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
 
 	if (argc > 3)
 	{
@@ -4041,12 +4047,6 @@ static void Command_Tunes_f(void)
 		if (speed > 0.0f)
 			S_SpeedMusic(speed);
 	}
-
-	if (argc > 4)
-	{
-		UINT32 position = (UINT32)atoi(COM_Argv(4));
-		S_SetMusicPosition(position);
-	}
 }
 
 static void Command_RestartAudio_f(void)
diff --git a/src/dehacked.c b/src/dehacked.c
index 52b1623d2..3786a805a 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1151,6 +1151,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, "MUSICPOSITION"))
+				mapheaderinfo[num-1]->musposition = (UINT32)get_number(word2);
 			else if (fastcmp(word, "FORCECHARACTER"))
 			{
 				strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
@@ -1447,6 +1449,10 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
 			{
 				cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
 			}
+			else if (fastcmp(word, "MUSICPOSITION"))
+			{
+				cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2);
+			}
 			else if (fastcmp(word, "MUSICLOOP"))
 			{
 				cutscenes[num]->scene[scenenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
@@ -8742,6 +8748,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/doomstat.h b/src/doomstat.h
index 092fce418..610c21941 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -33,6 +33,7 @@
 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 // -*--------------
@@ -153,6 +154,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
@@ -223,6 +225,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 musposition;    ///< 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/f_finale.c b/src/f_finale.c
index 151889c4c..3b3ae8a91 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -1831,9 +1831,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_ChangeMusicAdvanced(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;
@@ -1904,9 +1905,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_ChangeMusicAdvanced(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 58bee0141..c679a9057 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;
diff --git a/src/p_setup.c b/src/p_setup.c
index c62f281b3..a579f65dd 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -208,6 +208,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
 	mapheaderinfo[num]->musname[6] = 0;
 	mapheaderinfo[num]->mustrack = 0;
+	mapheaderinfo[num]->musposition = 0;
 	mapheaderinfo[num]->forcecharacter[0] = '\0';
 	mapheaderinfo[num]->weather = 0;
 	mapheaderinfo[num]->skynum = 1;
diff --git a/src/p_user.c b/src/p_user.c
index fd09b0847..04c0c3f98 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1247,13 +1247,13 @@ void P_RestoreMusic(player_t *player)
 		if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
 		{
 			S_SpeedMusic(1.4f);
-			S_ChangeMusic(mapmusname, mapmusflags, true);
+			S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
 		}
 		else
 			S_ChangeMusicInternal("_shoes", true);
 	}
 	else
-		S_ChangeMusic(mapmusname, mapmusflags, true);
+		S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
 }
 
 //
diff --git a/src/s_sound.c b/src/s_sound.c
index 6ab68b2ec..604b710ee 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -1741,9 +1741,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]->musposition;
 	}
 
 	if (cv_resetmusic.value)
 		S_StopMusic();
-	S_ChangeMusic(mapmusname, mapmusflags, true);
+	S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
 }