• Please make sure you are familiar with the forum rules. You can find them here: https://forums.tripwireinteractive.com/index.php?threads/forum-rules.2334636/

Code [Code] Base Music Replacement System

forrestmark9

Grizzled Veteran
Nov 29, 2011
1,110
42
A basic system for replacing and overriding music within KF2. I do not know if this is fully compilable because the workshop upload tool is now broken and I'm too lazy to setup everything to run via KFEditor Make but I did leave comments for most everything.

BaseMusicGRI.uc
Code:
class BaseMusicGRI extends KFGameReplicationInfo;

/************************************
*  Music Manager
************************************/

/** Class that is spawned, replace this from a mutator to update or change the music system. */
var class<KFMusicManager> MusicManagerClass; 

/** The spawned manager everything music related goes through this */
var KFMusicManager MusicManager;

/** Spawn and setup the manager class for music */
simulated function ReceivedGameClass()
{
    MusicManager = Spawn(MusicManagerClass, Self);
    MusicManager.GRIOwner = Self;

    Super.ReceivedGameClass();
}

/** Redirect the default music system through the music manager but else fallback to the default behavior */
simulated function PlayNewMusicTrack( optional bool bGameStateChanged, optional bool bForceAmbient )
{
    if( MusicManager != None )
    {
        MusicManager.SelectMusicTrack(bGameStateChanged, bForceAmbient);
    }
    else 
    {
        Super.PlayNewMusicTrack(bGameStateChanged, bForceAmbient);
    }
}

simulated function ForceNewMusicTrack( KFMusicTrackInfo ForcedTrackInfo )
{
    if( MusicManager != None )
    {
        MusicManager.ForceMusicTrack(ForcedTrackInfo);
    }
    else 
    {
        Super.ForceNewMusicTrack(ForcedTrackInfo);
    }
}

defaultproperties
{
    MusicManagerClass=class'KFMusicManager'
}

KFMusicManager.uc
Code:
//=============================================================================
// KFMusicManager
//=============================================================================
// A class spawned by the GameReplicationInfo to handle playing music.
//=============================================================================
class KFMusicManager extends Info;

/** The KFGameReplicationInfo that owns this class */
var KFGameReplicationInfo GRIOwner;

/** Current SoundCue component that is used when SoundCue music is playing */
var AudioComponent MusicComp;

simulated function SetupMusicTrack( KFMusicTrackInfo NextMusicTrackInfo, bool bPlayStandardTrack )
{
    local KFMusicTrackInfo_Custom CustomInfo;
    local SoundCue CurrentTrack;
    local KFPlayerController KFPC;

    CustomInfo = KFMusicTrackInfo_Custom(NextMusicTrackInfo);

    /** If the selected track is not a custom track or is AkEvent music */
    if( CustomInfo == None || CustomInfo.StandardTrack != None )
    {
        GRIOwner.UpdateMusicTrack(NextMusicTrackInfo, bPlayStandardTrack);
        return;
    }

    /** The sound track was a SoundCue so lets select the correct version then play it */
    if( bPlayStandardTrack )
    {
        CurrentTrack = SoundCue(CustomInfo.StandardSong);
    }
    else 
    {
        CurrentTrack = SoundCue(CustomInfo.InstrumentalSong);
    }

    /** Set the music track info in the GRI */
    GRIOwner.CurrentMusicTrackInfo = CustomInfo;

    /** Force the SoundCue to the Music type so that the music volume slider changes the volume of the played Cue */
    CurrentTrack.SoundClass = 'Music';

    /** Stop the original system from spamming songs */
    GRIOwner.bPendingMusicTrackChange = false;
    GRIOwner.MusicComp = None;

    /** Play the SoundCue */
    PlayMusicSoundCue(CurrentTrack);

    /** Display the music ScaleForm GUI and assign the music name and artist */
    foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
    {
        KFPC.TeamMessage(KFPC.PlayerReplicationInfo, CustomInfo.TrackName$" -- "$CustomInfo.ArtistName, 'Music');
    }
}

simulated function PlayMusicSoundCue(SoundCue MusicTrack)
{
    local AudioComponent A;

    /** Fadeout any currently playing SoundCue music */
    if( MusicComp != None )
    {
        MusicComp.FadeOut(5.0f, 0.0);
        MusicComp = None;
    }

    /** Create a AudioComponent */
    A = WorldInfo.CreateAudioComponent(MusicTrack, false, false, false,, false);
    if( A != None )
    {
        /** Basic settings to tell the AudioComponent that this is music */
        A.bAutoDestroy = true;
        A.bShouldRemainActiveIfDropped = true;
        A.bIsMusic = true;

        /** Play the music by fading it in and then setting the MusicComp var to the AudioComponent */
        A.FadeIn(5.0f, 1.0f);
        MusicComp = A;
    }
}

/** A basic delegate function that you can replace to override what happens when a music track is selected and wants to be played */
delegate OnMusicTrackSelected(KFMusicTrackInfo Track)
{
    SetupMusicTrack( Track, KFGameEngine(Class'Engine'.static.GetEngine()).bMusicVocalsEnabled );
}

simulated function SelectMusicTrack( optional bool bGameStateChanged, optional bool bForceAmbient )
{
    local KFMapInfo             KFMI;
    local class<KFGameInfo>     KFGameClass;
    local KFMusicTrackInfo      NextMusicTrackInfo;
    local bool                  bLoop;
    local bool                  bPlayActionTrack;

    if ( class'KFGameEngine'.static.CheckNoMusic() )
    {
        return;
    }

    KFGameClass = class<KFGameInfo>(GRIOwner.GameClass);
    if ( KFGameClass == None )
    {
        return;
    }

    // @todo: consider using music intensity (255?) for ambient music to simplify this logic
    bPlayActionTrack = (!bForceAmbient && KFGameClass.static.ShouldPlayActionMusicTrack(GRIOwner));

    // if we've just transitioned into the "action" phase of the game,
    // check if we need to delay the action music
    if( bGameStateChanged )
    {
        if( bPlayActionTrack )
        {
            if( KFGameClass.default.ActionMusicDelay > 0 )
            {
                SetTimer( KFGameClass.default.ActionMusicDelay, false, nameof(SelectMusicTrack) );
                return;
            }
        }
    }
    else if( GRIOwner.CurrentMusicTrackInfo != none )
    {
        bLoop = GRIOwner.CurrentMusicTrackInfo.bLoop;
    }

    // loop if we're designated to loop or this is the boss wave
    if( bLoop || GRIOwner.IsFinalWave() )
    {
        NextMusicTrackInfo = GRIOwner.CurrentMusicTrackInfo;
    }
    else
    {
        KFMI = KFMapInfo(WorldInfo.GetMapInfo());
        if ( KFMI != none )
        {
            NextMusicTrackInfo = KFMI.GetNextMusicTrackByGameIntensity(bPlayActionTrack, GRIOwner.MusicIntensity);
        }
        else
        {
            // Some maps might not be setup correctly, let's just grab a random default song
            NextMusicTrackInfo = class'KFMapInfo'.static.StaticGetRandomTrack(bPlayActionTrack);
        }
    }

    OnMusicTrackSelected(NextMusicTrackInfo);
}

simulated function SelectBossMusicTrack( KFMusicTrackInfo BossTrack )
{
    OnMusicTrackSelected(BossTrack);
}

simulated function ForceMusicTrack( KFMusicTrackInfo ForcedTrackInfo )
{
    local int Index;
    local class<KFGameInfo> KFGameClass;

    /** Check if the music being forced is boss music */
    KFGameClass = class<KFGameInfo>(GRIOwner.GameClass);
    if( KFGameClass != None )
    {
        /** Look for the track inside of ForcedMusicTracks inside the GameInfo and if it's not the main menu music then call SelectBossMusicTrack */
        Index = KFGameClass.default.ForcedMusicTracks.Find(ForcedTrackInfo);
        if( Index != INDEX_NONE && KFGameClass.default.ForcedMusicTracks[Index].Name != 'TrackInfo' )
        {
            SelectBossMusicTrack(ForcedTrackInfo);
            return;
        }
    }

    OnMusicTrackSelected(ForcedTrackInfo);
}

defaultproperties
{
    bAlwaysRelevant=True
    RemoteRole=ROLE_SimulatedProxy
}

KFMusicTrackInfo_Custom.uc
Code:
class KFMusicTrackInfo_Custom extends KFMusicTrackInfo;

var() AkBaseSoundObject StandardSong;
var() AkBaseSoundObject InstrumentalSong;

defaultproperties
{
}
 
Last edited: