DXOgg playing across level transitions

A refuge for those migrating from the fallen DXEditing.com and a place for general discussion relating to Deus Ex editing (coding, mapping, etc).
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

DXOgg playing across level transitions

Post by bjorn98009_91 »

Hi.

I need some help with figuring out if it's possible to have DXOgg play across level transitions, basically picking up where it left off in the ambient track from the previous level. So far I'm having the ogg player save the position where it's at in PreTravel and then in the Tick function for the DXOggMusicManager it reads from the flags and checks the position. Problem with this is that there is quite a noticable delay after the new map has been loaded and the Tick call in DXOggMusicManager. I tried putting the code in PostBeginPlay instead but that function is run before the player has logged into the map, so I can't access flags from there.

And to top it all off the music continues going after the PreTravel call, so when the music resumes it's not really where it left off before.

Basically I need to save the time and the file-name of the current track somewhere right before the old maps assets are destroyed, and then immedietly on the new map's load I need to read those saved things so I can start the music. Any tips on where to have the code? G-Flex, DDL, Hanfling, anyone?
Last edited by bjorn98009_91 on Tue Feb 04, 2014 11:04 am, edited 1 time in total.
Producer and Quality Assurance Manager for Deus Ex: Revision.
Hanfling
MJ12
Posts: 406
Joined: Sun Oct 04, 2009 6:54 pm

Re: DXOgg playing across level transitions

Post by Hanfling »

Option #1:
Try to spawn the Ogg player inside the Entry level. Worth a try, but i'm not sure if it will work.
http://hyper.dnsalias.net/infobase/arch ... stentEntry

Option #2:
Maybe override Engine's Browse() or LoadMap(). (But LoadMap() seems to call the BeginPlay() stuff anyway.

Option #3:
Wrap it inside a class'Inventory' and put it in the players inventory to make it travel.
I demand my DXE User ID back. Launcher for DeusEx, Rune, Nerf, Unreal & Botpack. HX on Mod DB. Revision on Steam.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Alright I'll look into those. Right now option 3 seems like the best one. I also must mention that altering DeusEx.u is off-limits.
Producer and Quality Assurance Manager for Deus Ex: Revision.
G-Flex
Silhouette
Posts: 621
Joined: Mon Jul 11, 2011 10:16 pm

Re: DXOgg playing across level transitions

Post by G-Flex »

bjorn98009_91 wrote:Basically I need to save the time and the file-name of the current track somewhere right before the old maps assets are destroyed, and then immedietly on the new maps load I need to read those saved things so I can start the music.
Unfortunately, even if you did this there would be at least a small but noticeable delay. I don't think there's a way for you to make it particularly seamless, although I don't know much about DXOgg. Is whoever developed it on these forums?
Hanfling
MJ12
Posts: 406
Joined: Sun Oct 04, 2009 6:54 pm

Re: DXOgg playing across level transitions

Post by Hanfling »

Option #1 might be seemless if it's working.
I demand my DXE User ID back. Launcher for DeusEx, Rune, Nerf, Unreal & Botpack. HX on Mod DB. Revision on Steam.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Nope, I don't think Jim is on here anymore. The UScript class is just a class that takes the song names, and then some logic to make it play the correct song based on PlayerState and so on. On spawn a native constructor is run that hooks into the game's SetInstantMusicVolume function. On each tick the DxOggMusicManager tries to create a new OggStream (based on an open ogg lib), if it's waiting to play a song (some DirectSound subsystems must be initialized first, so we have to wait until that's done before music can be played).

The UScript class calls the native function SetCurrentOgg (when we want to change the song) and that causes the native class to either delete the current oggStream and creating a new one, or it sets a transition time and fading into the new song. Depending upon if we want an instant switch or a fade.

So after a level is discarded after a new one loads the old musicmanager is destroyed, and the native oggStream that is playing along with it.
Producer and Quality Assurance Manager for Deus Ex: Revision.
Hanfling
MJ12
Posts: 406
Joined: Sun Oct 04, 2009 6:54 pm

Re: DXOgg playing across level transitions

Post by Hanfling »

That sounds so fucking dirty. But still sounds like you can spawn (a probably modified) DxOggMusicManager inside the Entry level.
I demand my DXE User ID back. Launcher for DeusEx, Rune, Nerf, Unreal & Botpack. HX on Mod DB. Revision on Steam.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Well my explanation was somewhat crappy, but still that's sort of what it does.
dx-revision.com/files/hosting/random/DXOgg.cpp

Yep, I'll just add an boolean called "Enabled" and set it to false for all the music mangers that we already have in the maps. If Enabled = false it won't run the initialization code to start the music. That way I can use the music managers to hold all the track information so after a load I'll look for the music manager that's in the current map and check what the tracks are, and if they are different from the ones we already have in the music manager in the entry map I'll just replace the tracks in the entry map's manager. That might work.
Producer and Quality Assurance Manager for Deus Ex: Revision.
G-Flex
Silhouette
Posts: 621
Joined: Mon Jul 11, 2011 10:16 pm

Re: DXOgg playing across level transitions

Post by G-Flex »

Just make sure, for the love of God, that the object in the entry map doesn't hold any object references across map transitions. That would be bad.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Hah! Don't worry, it won't.
Producer and Quality Assurance Manager for Deus Ex: Revision.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Done with my seamless player. Placed it in the Entry map and all was fine! Thanks for the help! :D
Producer and Quality Assurance Manager for Deus Ex: Revision.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Although I'm having issues with the "check if ogg file is present and if not default to vanilla music" code. What I'm doing is basically this:

Code: Select all

function CheckPaths()
{
	local DXOggMusicManager testingmgr;
	
	testingmgr = Spawn(class'DXOggMusicManager',None, 'TestingMgr',vect(0,0,-40));
	
	if (testingmgr == None)
		log("Bjorn: TESTING MGR IS NONE! DAFUCK!?");
	
	//Just set the current ogg to a file and the function will return false if the file can't be opened and true if it can.
	
	testingmgr.SetCurrentOgg("Blank.ogg", "Blank.ogg", 0.0, MTran_Instant);
	
	if(Len(AmbientOggFile) > 0)
		bAmbientExists = testingmgr.SetCurrentOgg(AmbientIntroOggFile, AmbientOggFile, 0.0, MTran_Instant);
	else
		bAmbientExists = true;
	
	if(Len(CombatOggFile) > 0)
		bCombatExists = testingmgr.SetCurrentOgg(CombatIntroOggFile, CombatOggFile, 0.0, MTran_Instant);
	else
		bCombatExists = true;
	
	if(Len(ConversationOggFile) > 0)
		bConversationExists = testingmgr.SetCurrentOgg(ConversationIntroOggFile, ConversationOggFile, 0.0, MTran_Instant);
	else
		bConversationExists = true;
	
	if(Len(OutroOggFile) > 0)
		bOutroExists = testingmgr.SetCurrentOgg("", OutroOggFile, 0.0, MTran_Instant);
	else
		bOutroExists = true;
	
	if(Len(DeathOggFile) > 0)
		bDeathExists = testingmgr.SetCurrentOgg("", DeathOggFile, 0.0, MTran_Instant);
	else
		bDeathExists = true;
	
	testingmgr.Destroy();
}
I'm spawning a new music manager and using that managers native SetCurrentOgg function (to prevent my currently playing music to get altered). What I expected was that the entry map's music manager will continue to play music, call the function above and spawn a new music manager to check if the tracks works. But for some reason when I'm making the testingmgr.SetCurrentOgg call I'm messing up the music that's playing from the entry map's manager. Anyone know why I can't have two managers living at once and each of them being able to play music at the same time?

I know it's sort of hacky to do what I'm doing above, but that saves me from having to implement my own C++ code for checking if the track works (not just if the file is there, but if it's actually playable, seekable etc.). It worked perfectly before since I could just call CheckPaths() from PostBeginPlay when each map had it's own music manager, since then there was already a "gap" in the music.
Producer and Quality Assurance Manager for Deus Ex: Revision.
Hanfling
MJ12
Posts: 406
Joined: Sun Oct 04, 2009 6:54 pm

Re: DXOgg playing across level transitions

Post by Hanfling »

Maybe set up a Mutator which replaces the non Entry MusicManagers with wrappers which call the entry levels music managers functions?
I demand my DXE User ID back. Launcher for DeusEx, Rune, Nerf, Unreal & Botpack. HX on Mod DB. Revision on Steam.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Huh?

I have this in my GameInfo:

Code: Select all

event playerpawn Login
(
	string Portal,
	string Options,
	out string Error,
	class<playerpawn> SpawnClass
)
{
	local DeusExPlayer player;
	local DXOggMusicManager entrydxogg, localdxogg;
	
	player = DeusExPlayer(Super.Login(Portal, Options, Error, SpawnClass));
	
	//Find the music manager in the Entry map.
	foreach player.GetEntryLevel().AllActors(class'DXOggMusicManager', entrydxogg)
		break;
	
	//Find the music manager in our current map.
	foreach AllActors(class'DXOggMusicManager', localdxogg)
		break;
		
	//Set the tracks for the Entry music manager to the tracks in the music manager in the map.
	entrydxogg.SetTracks(localdxogg);
	
	return player;
}
This is the code in the MusicManger:

Code: Select all

function SetTracks(DXOggMusicManager dxogg)
{	
	local string savedAmbientOggFile;

	//Save the ambient file we have right now, so we don't lose it.
	savedAmbientOggFile = AmbientOggFile;
	
	log ("Bjorn: We are setting local songs in the Entry player..");
	
	if (dxogg == None)
		log("Bjorn: DXOggMusicManager.SetTracks: Local in-param dxogg is None!");
	
	//Copy over the paths from the map's music manger.
	AmbientIntroOggFile = dxogg.AmbientIntroOggFile;
	AmbientOggFile = dxogg.AmbientOggFile;
	CombatIntroOggFile = dxogg.CombatIntroOggFile;
	CombatOggFile = dxogg.CombatOggFile;
	ConversationIntroOggFile = dxogg.ConversationIntroOggFile;
	ConversationOggFile = dxogg.ConversationOggFile;
	OutroOggFile = dxogg.OutroOggFile;
	DeathOggFile = dxogg.DeathOggFile;

	//Check if the paths we just copied are valid.
	CheckPaths();
	
	// If our ambient track isn't the same as the one we should have for this map.
	if (savedAmbientOggFile != AmbientOggFile)
	{
		log("Bjorn: The current ambient didn't match the ambient we should play. Restart music.");
	
		if (bAmbientExists == true)		
			bAmbientExists = SetCurrentOgg(AmbientIntroOggFile, AmbientOggFile, 0.0, MTran_FastFade);
		else
			SetCurrentOgg("Blank.ogg", "Blank.ogg", 0.0, MTran_Instant);
			
		musicMode = MUS_Ambient;
	}	
}
The music mangers in the maps are disabled (I have a variable called Enabled that is false by default), so those managers will do nothing more than just hold the info to the files (I plan on refactoring this later, it's sort of silly to have the Enabled-variable). So really, when I run the testingmgr.SetCurrentOgg (in CheckPaths) I should be creating a new oggstream in native code and set that oggstream to play my files for testing, it shouldn't mess with the oggstream that I already have for the Entry manager. I'm essentially creating a new object and calling that objects functions, and that shouldn't interfere with the current object's state.
Producer and Quality Assurance Manager for Deus Ex: Revision.
User avatar
bjorn98009_91
Silhouette
Posts: 688
Joined: Thu May 08, 2008 8:17 am
Location: Hufvudstaden, Sweden
Contact:

Re: DXOgg playing across level transitions

Post by bjorn98009_91 »

Or does those two separate ogg managers only exist on the UnrealScript side of things and they are in fact modifying the same underlying native object? That would explain why setting the music on one of them will stop the music on the other one.
Producer and Quality Assurance Manager for Deus Ex: Revision.
Post Reply