Change Temperature

#Kismet

A custom Kismet node that can change the world temperature at runtime.

This node also has a Duration property, that allows smoothly interpolating the heat overlay effect.

NOTE: You may want to edit the value of ObjCategory to something unique, so you can tell it apart from other copies of this script.

Drew_SeqAct_ChangeTemperature.uc

[RAW] [Download]

class Drew_SeqAct_ChangeTemperature extends SequenceAction;
 
/**
 * The new temperature the map should use. A MapInfo needs to exist for this to work.
 */
var() float NewTemperature;
 
/**
 * If > 0, how long should it take to interpolate the heat overlay.
 */
var() float Duration;
 
event Activated()
{
    local WorldInfo WI;
    local Hat_MapInfo MI;
    local Engine E;
    local LocalPlayer LP;
 
    WI = GetWorldInfo();
    MI = Hat_MapInfo(WI.GetMapInfo());
    if (MI == None)
        return;
 
    MI.Temperature = NewTemperature;
 
    // Update any usage of temperature in materials.
    WI.UpdateGenericSceneProxyParameters();
 
    // Also update the heat overlay(s).
    E = class'Engine'.static.GetEngine();
    foreach E.GamePlayers(LP)
    {
        UpdateHeatOverlayEffect(LP);
    }
}
 
function UpdateHeatOverlayEffect(LocalPlayer LP)
{
    local Hat_HUD H;
    local MaterialEffect m;
    local MaterialInstance MatInst;
    local InterpCurveFloat Curve;
    local float Temp, PrevTemp;
 
    H = Hat_HUD(LP.Actor.MyHUD);
    if (H == None) return;
 
    m = MaterialEffect(LP.PlayerPostProcess.FindPostProcessEffect('HeatOverlay'));
    if (m == None) return;
 
    MatInst = MaterialInstance(m.GetMaterial(true));
    if (MatInst == None && Duration <= 0.f)  // Wasn't initialized (overridden) yet?
    {
        // Let Hat_HUD initialize it and handle the temperature effect.
        H.InitPostProcessMaterialInstance();
        return;
    }
 
    // We got here, so we need to update the parameter manually.
 
    Temp = H.GetSceneTemperature();
 
    if (Duration > 0.f)
    {
        PrevTemp = 0.f;
        if (MatInst != None)
            MatInst.GetScalarParameterValue('Scale', PrevTemp);
        // We need to interpolate, so we need a time-varying material.
        if (MaterialInstanceTimeVarying(MatInst) == None)
        {
            // That won't do - recreate it as time-varying.
            MatInst = new(m) class'MaterialInstanceTimeVarying';
            MatInst.SetParent(m.GetMaterial(false));
            m.SetMaterial(MatInst);
        }
        Curve = H.GenerateCurveFloat(PrevTemp, Temp, Duration);
        MaterialInstanceTimeVarying(MatInst).SetScalarCurveParameterValue('Scale', Curve);
        MaterialInstanceTimeVarying(MatInst).SetScalarStartTime('Scale', 0.0);
    }
    else if (MaterialInstanceTimeVarying(MatInst) != None)
    {
        // For whatever reason, calling SetScalarParameterValue doesn't work anymore once we've done our time-varying conversion.
        // Create a dummy curve that just sets the value instantly, I guess.
        Curve = H.GenerateCurveFloat(Temp, Temp, 0.f);
        MaterialInstanceTimeVarying(MatInst).SetScalarCurveParameterValue('Scale', Curve);
        MaterialInstanceTimeVarying(MatInst).SetScalarStartTime('Scale', 0.0);
    }
    else
    {
        MatInst.SetScalarParameterValue('Scale', Temp);
    }
 
    if (Temp <= 0.f && Duration > 0.f && H.WorldInfo.TimeDilation > 0.f)
    {
        // We gotta wait for the interpolation to end before we can hide the effect completely.
        // Set the timer on the archetype so its correctly reset, even when using multiple nodes.
        H.SetTimer(Duration / H.WorldInfo.TimeDilation, false, NameOf(DelayedUpdateShowInGame), ObjectArchetype, LP);
    }
    else
    {
        m.bShowInGame = (Temp > 0.f);
    }
}
 
function DelayedUpdateShowInGame(LocalPlayer LP)
{
    local Hat_HUD H;
    local MaterialEffect m;
 
    H = Hat_HUD(LP.Actor.MyHUD);
    if (H == None) return;
 
    m = MaterialEffect(LP.PlayerPostProcess.FindPostProcessEffect('HeatOverlay'));
    if (m == None) return;
 
    m.bShowInGame = (H.GetSceneTemperature() > 0.f);
}
 
defaultproperties
{
    ObjName = "Change Temperature"
    ObjCategory = "Give me a custom category!"
    bCallHandler = false
 
    VariableLinks.Empty
}