UE2 - UT2kX Mutator to Play Specified Music

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.
Apr 11, 2006
738
0
16
I've been wanting to write a simple mutator to help players get more in the Christmas spirit. Unfortunately I've been running into a problem getting this mutator to function correctly on a dedicated server.

Here is my current code.
This works very simply:
There's two arrays, one array of strings (song names), another array of ints (song durations).
Every 5 seconds the timer runs. It checks if the last song has ended (or it hasn't played a song at all). If so, it chooses a string in the array, starting from 0 and moving up until reaching the end of the array or defined songs.

Then it looks through the ControllerList and checks for PlayerControllers. For every PlayerController it sets the client's song to the specified string. (If the client doesn't have the song they won't hear anything, but that's ok.)


Code:
//=============================================================================
// Mutator_HolidayMusic - Plays specified songs for clients
//=============================================================================

class Mutator_HolidayMusic extends Mutator;

var(Action) Actor.EMusicTransition  Transition;

var string MySongNames[32];
var int MySongTimes[32];
var int LastSongIndex;
var float LastSongStart;


event PreBeginPlay()
{
   SetTimer(5.0,true);
}

function Timer()
{
   local Controller C;
   local string TempString;

   if (Level.TimeSeconds > LastSongStart + MySongTimes[LastSongIndex] || LastSongStart == 0)
   {
      if (LastSongIndex < 30)  //That's 31 including 0. Array.Length - 1
         LastSongIndex++;
      else
         LastSongIndex = 0;

      if (MySongNames[LastSongIndex] == "")
      {
         TempString = MySongNames[0];
         LastSongIndex = 0;
         LastSongStart = Level.TimeSeconds + 1;
         Level.Game.Broadcast(self, "*Now Playing: "$TempString$". If you don't hear this music, please check out SomeLink for the download!");
      }
      else
      {
         TempString = MySongNames[LastSongIndex];
         LastSongStart = Level.TimeSeconds + 1;
         Level.Game.Broadcast(self, "Now Playing: "$TempString$". If you don't hear this music, please check out SomeLink for the download!");
      }


      for ( C = Level.ControllerList; C != None; C = C.nextController )
      {
         if ( C.IsA('PlayerController') )
            PlayerController(C).ClientSetMusic( TempString, Transition );
      }
   }
}


defaultproperties
{
   GroupName="Music"
   Friendlyname="Holiday Music"
   Description="Change players' music to play through a list of special tunes that you configure!"

   Transition=MTRAN_Fade
   
   MySongNames(0)="UT3-18 Frozen Babylon"
   MySongNames(1)="UT3-03 Tactical Agenda"
   MySongNames(2)="UT3-04 ONS01 (UT3 Remix)"
   MySongNames(3)="UT3-05 Mekalopolis"
   MySongNames(4)="UT3-06 Skyward Fire (UT3 Remix)"
   MySongNames(5)="UT3-08 Go Down (UT3 Remix)"
   MySongNames(6)="UT3-10 Foregone Destruction (UT3 Remix)"
   MySongNames(7)="UT3-15 Firestorm"
   MySongNames(8)="UT3-14 Defector"
   MySongNames(9)="UT3-09 Quantum Velocity"

   MySongTimes(0)=195
   MySongTimes(1)=277
   MySongTimes(2)=257
   MySongTimes(3)=337
   MySongTimes(4)=260
   MySongTimes(5)=188
   MySongTimes(6)=291
   MySongTimes(7)=303
   MySongTimes(8)=283
   MySongTimes(9)=272
}


So right now this code is based on the ScriptedTrigger's action - Gameplay.ACTION_PlayMusic. The PlayMusic action does the exact same thing as my code does, looking through the ControllerList and setting the client's music for all PlayerControllers.

Let me know if you have any ideas on what I need to do to get this to function on a dedicated server.
 
Apr 11, 2006
738
0
16
Testing with Action_PlayMusic reveals that spaces in file names are accepted.

Current line of thinking is to spawn a ReplicationInfo in PreBeginPlay and let that handle the Timer functions.
 
Apr 11, 2006
738
0
16
Tried a couple more approaches to this where I spawned a ReplicationInfo/Actor that would handle the timer functions, but not having any luck unfortunately.
 

rejecht

Attention Micronians
Jun 15, 2009
511
0
16
.no
sites.google.com
I recently had a look at MutServerLogo, so I'm guessing it's because RemoteRole == None (see Info which Mutator inherits from), thus ignoring any replicated function calls. (So, the script is executing server-side (NM_*Server instance), but since it has no relationship with the other side (RemoteRole == None), it will ignore replication.)
 

rejecht

Attention Micronians
Jun 15, 2009
511
0
16
.no
sites.google.com
@Wormbo: Yeah, my thinking was überflawed. The execution context obviously doesn't matter when the call is initiated through PlayerController.ClientSetMusic, in which case GameInfo derivatives couldn't do much either. :] I should test things myself before building on assumptions. *30 lashes*


There's nothing wrong with the replicated function call, though.
PlayerController does get called from the mutator timer function on a dedicated server, and it works, as long as it's an ogg file.

PlayerController.ClientSetMusic (Whatever, 3) NM_Client (3) ROLE_AutonomousProxy (3) ROLE_Authority (4)


Tested on a locally hosted dedicated server.

Conclusion so far:
it doesn't play mp3 files,
it does play ogg files.

+Edit+
// only used for level music - will be stopped when level changes
// Song parameter should not include extension (assumes .ogg)
native final function int PlayMusic( string Song, optional float FadeInTime );
 
Last edited: