1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFTrigger_MinigameGenerator.uc
2020-12-13 18:01:13 +03:00

517 lines
16 KiB
Ucode

//=============================================================================
// KFTrigger_MinigameGenerator
//=============================================================================
// Trigger used to activate all minigames in a level
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// - Dan Weiss
//=============================================================================
class KFTrigger_MinigameGenerator extends Trigger_PawnsOnly
config(Game)
implements(KFInterface_Usable);
/** Amount of time (in seconds) that the generator should remain running */
var() float ActiveTime;
/** Amount of time until the generator can be reactivated */
var() float ReactivationTime;
var bool bActiveGenerator;
var bool bCanBeActivated;
var array<KFTrigger_MinigameButton> LevelButtons;
/** Objective index for the event this is tied to */
var() int ObjectiveIndex;
/** Index of the event this is tied to */
var() int EventIndex;
/** Amount of time remaining until the generator shuts off */
var repnotify byte GeneratorTimeRemaining;
var float PreviousTimeRemaining;
/** Actor reference showing status indicator */
var() array<StaticMeshActor> GeneratorStatusIndicators;
/** Material slot to use for the status modification */
var() int GlowIndex;
struct GeneratorStatus
{
var() float MinTimeRemaining;
var() LinearColor StatusColor;
};
var() array<GeneratorStatus> StatusIndicator;
var int CurrentStatusIndex;
struct EmissiveActor
{
var() Actor EmissiveActor;
var float GeneratorOnValue;
var float GeneratorOffValue;
structdefaultproperties
{
GeneratorOnValue=0.f
GeneratorOffValue=0.f
}
};
struct EmissiveUpdateActorList
{
var() float ActivationDelay;
var() array<Actor> ActorList;
var array<EmissiveActor> CachedActorList;
};
var() array<EmissiveUpdateActorList> MapEmissiveActorList;
var int CurrentEmissiveActorListIndex;
replication
{
if (bNetDirty)
GeneratorTimeRemaining;
}
simulated event ReplicatedEvent(name VarName)
{
if (VarName == 'GeneratorTimeRemaining')
{
UpdateGeneratorStatus();
}
else
{
super.ReplicatedEvent(VarName);
}
}
function Tick(float DeltaTime)
{
super.Tick(DeltaTime);
if (bActiveGenerator)
{
GeneratorTimeRemaining = FloatToByte(GetRemainingTimeForTimer('DeactivateMinigames') / ActiveTime);
UpdateGeneratorStatus();
}
}
simulated function UpdateGeneratorStatus()
{
local float CurrentTimeRemaining;
local LinearColor ParamColor;
local bool bStatusChange;
local int CurIndex;
local int i;
if (WorldInfo.NetMode != NM_DedicatedServer && StatusIndicator.Length > 0)
{
CurIndex = CurrentStatusIndex;
CurrentTimeRemaining = ByteToFloat(GeneratorTimeRemaining);
//Reset or first startup
if (PreviousTimeRemaining < CurrentTimeRemaining)
{
CurrentStatusIndex = 0;
if (CurrentTimeRemaining > 0)
{
EnableEmissiveActors();
}
}
//Update if we've gone past the time required for current color
if (StatusIndicator[CurrentStatusIndex].MinTimeRemaining > CurrentTimeRemaining)
{
for (CurrentStatusIndex = 0; CurrentStatusIndex < StatusIndicator.Length; ++CurrentStatusIndex)
{
if (StatusIndicator[CurrentStatusIndex].MinTimeRemaining < CurrentTimeRemaining)
{
break;
}
}
}
CurrentStatusIndex = Min(CurrentStatusIndex, StatusIndicator.Length - 1);
//Check for change and update color if necessary
bStatusChange = CurrentStatusIndex != CurIndex;
if (bStatusChange && GeneratorStatusIndicators.Length > 0 )
{
ParamColor = StatusIndicator[CurrentStatusIndex].StatusColor;
for (i = 0; i < GeneratorStatusIndicators.Length; ++i)
{
if (MaterialInstance(GeneratorStatusIndicators[i].StaticMeshComponent.GetMaterial(GlowIndex)) != none)
{
MaterialInstance(GeneratorStatusIndicators[i].StaticMeshComponent.GetMaterial(GlowIndex)).SetVectorParameterValue('Scalar_Glow_color', ParamColor);
}
}
}
PreviousTimeRemaining = CurrentTimeRemaining;
if (CurrentTimeRemaining <= 0)
{
DisableEmissiveActors();
}
}
}
simulated function EnableEmissiveActors()
{
CurrentEmissiveActorListIndex = 0;
if (MapEmissiveActorList.Length > 0)
{
if (MapEmissiveActorList[0].ActivationDelay > 0.f)
{
SetTimer(MapEmissiveActorList[0].ActivationDelay, false, nameof(EnableNextEmissiveList));
}
else
{
EnableNextEmissiveList();
}
}
}
simulated function EnableNextEmissiveList()
{
local EmissiveActor CurrentActor;
local int i;
local StaticMeshActor Smesh;
local SkeletalMeshActor Skmesh;
local MaterialInstance MatInst;
if (MapEmissiveActorList[CurrentEmissiveActorListIndex].ActorList.Length > 0)
{
foreach MapEmissiveActorList[CurrentEmissiveActorListIndex].CachedActorList(CurrentActor)
{
Smesh = StaticMeshActor(CurrentActor.EmissiveActor);
Skmesh = SkeletalMeshActor(CurrentActor.EmissiveActor);
if (Smesh != none)
{
for (i = 0; i < Smesh.StaticMeshComponent.Materials.Length; ++i)
{
MatInst = MaterialInstance(Smesh.StaticMeshComponent.GetMaterial(i));
if (MatInst != None)
{
MatInst.SetScalarParameterValue('Scalar_Emissive_Intensity', CurrentActor.GeneratorOnValue);
}
}
}
else if (Skmesh != none)
{
for (i = 0; i < Skmesh.SkeletalMeshComponent.Materials.Length; ++i)
{
MatInst = MaterialInstance(Skmesh.SkeletalMeshComponent.GetMaterial(i));
if (MatInst != None)
{
MatInst.SetScalarParameterValue('Scalar_Emissive_Intensity', CurrentActor.GeneratorOnValue);
}
}
}
}
}
CurrentEmissiveActorListIndex++;
if (CurrentEmissiveActorListIndex < MapEmissiveActorList.Length)
{
if (MapEmissiveActorList[CurrentEmissiveActorListIndex].ActivationDelay > 0.f)
{
SetTimer(MapEmissiveActorList[CurrentEmissiveActorListIndex].ActivationDelay - MapEmissiveActorList[CurrentEmissiveActorListIndex - 1].ActivationDelay, false, nameof(EnableNextEmissiveList));
}
else
{
EnableNextEmissiveList();
}
}
}
simulated function DisableEmissiveActors()
{
local EmissiveUpdateActorList CurrentList;
local EmissiveActor CurrentActor;
local int i;
local StaticMeshActor Smesh;
local SkeletalMeshActor Skmesh;
local MaterialInstance MatInst;
foreach MapEmissiveActorList(CurrentList)
{
foreach CurrentList.CachedActorList(CurrentActor)
{
Smesh = StaticMeshActor(CurrentActor.EmissiveActor);
Skmesh = SkeletalMeshActor(CurrentActor.EmissiveActor);
if (Smesh != none)
{
for (i = 0; i < Smesh.StaticMeshComponent.Materials.Length; ++i)
{
MatInst = MaterialInstance(Smesh.StaticMeshComponent.GetMaterial(i));
if (MatInst != None)
{
MatInst.SetScalarParameterValue('Scalar_Emissive_Intensity', CurrentActor.GeneratorOffValue);
}
}
}
else if (Skmesh != none)
{
for (i = 0; i < Skmesh.SkeletalMeshComponent.Materials.Length; ++i)
{
MatInst = MaterialInstance(Skmesh.SkeletalMeshComponent.GetMaterial(i));
if (MatInst != None)
{
MatInst.SetScalarParameterValue('Scalar_Emissive_Intensity', CurrentActor.GeneratorOffValue);
}
}
}
}
}
}
simulated function InitEmissiveActors()
{
local EmissiveActor NewActor;
local int i, j, k;
local StaticMeshActor Smesh;
local SkeletalMeshActor Skmesh;
local float CurValue;
for (i = 0; i < MapEmissiveActorList.Length; ++i)
{
for (j = 0; j < MapEmissiveActorList[i].ActorList.Length; ++j)
{
Smesh = StaticMeshActor(MapEmissiveActorList[i].ActorList[j]);
Skmesh = SkeletalMeshActor(MapEmissiveActorList[i].ActorList[j]);
NewActor.EmissiveActor = MapEmissiveActorList[i].ActorList[j];
k = 0;
if (Smesh != none)
{
while (Smesh.StaticMeshComponent.GetMaterial(k) != none)
{
Smesh.StaticMeshComponent.CreateAndSetMaterialInstanceConstant(k);
MaterialInstance(Smesh.StaticMeshComponent.GetMaterial(k)).Parent.GetScalarParameterValue('Scalar_Emissive_Intensity', CurValue);
++k;
NewActor.GeneratorOnValue = Max(CurValue, NewActor.GeneratorOnValue);
}
}
else if (Skmesh != none)
{
while (Skmesh.SkeletalMeshComponent.GetMaterial(k) != none)
{
Skmesh.SkeletalMeshComponent.CreateAndSetMaterialInstanceConstant(k);
MaterialInstance(Skmesh.SkeletalMeshComponent.GetMaterial(k)).Parent.GetScalarParameterValue('Scalar_Emissive_Intensity', NewActor.GeneratorOnValue);
++k;
NewActor.GeneratorOnValue = Max(CurValue, NewActor.GeneratorOnValue);
}
}
MapEmissiveActorList[i].CachedActorList.AddItem(NewActor);
}
}
}
/** KFInterface_Usable */
simulated function bool GetIsUsable(Pawn User)
{
return true;
}
/** KFInterface_Usable */
simulated function int GetInteractionIndex(Pawn User)
{
return IMT_UseMinigameGenerator;
}
/** HUD */
event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
{
super.Touch(Other, OtherComp, HitLocation, HitNormal);
class'KFPlayerController'.static.UpdateInteractionMessages(Other);
}
/** HUD */
event UnTouch(Actor Other)
{
super.UnTouch(Other);
class'KFPlayerController'.static.UpdateInteractionMessages(Other);
}
/** Cache all minigame triggers at startup so we don't have to do all actors every activation */
simulated function PostBeginPlay()
{
local KFTrigger_MinigameButton MinigameTrigger;
local int i;
super.PostBeginPlay();
if (Role == ROLE_Authority)
{
foreach WorldInfo.AllActors(class'KFTrigger_MinigameButton', MinigameTrigger)
{
LevelButtons.AddItem(MinigameTrigger);
}
}
if (WorldInfo.NetMode != NM_DedicatedServer)
{
if (GeneratorStatusIndicators.Length > 0 && GlowIndex >= 0)
{
for (i = 0; i < GeneratorStatusIndicators.Length; ++i)
{
if (GlowIndex < GeneratorStatusIndicators[i].StaticMeshComponent.Materials.Length)
{
GeneratorStatusIndicators[i].StaticMeshComponent.CreateAndSetMaterialInstanceConstant(GlowIndex);
}
}
}
InitEmissiveActors();
UpdateGeneratorStatus();
}
}
/** Handles trigger interaction */
function bool UsedBy(Pawn User)
{
if (bCanBeActivated)
{
//Clear any timer that was already started, treat this as a full reactivation of minigames
ClearTimer('DeactivateMinigames');
SetTimer(ActiveTime, false, 'DeactivateMinigames');
//Set reactivation timer to prevent button spam
bCanBeActivated = false;
SetTimer(ReactivationTime, false, 'AllowActivation');
ActivateMinigames();
//Activate objective completion for turning on generator
TriggerObjectiveCompletion();
}
return true;
}
function TriggerObjectiveCompletion()
{
local KFPlayercontroller KFPC;
local bool bIsObjectiveDataValid;
bIsObjectiveDataValid = ObjectiveIndex >= 0 && ObjectiveIndex < 5 && EventIndex > SEI_None && EventIndex < SEI_MAX;
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
{
KFPC.ClientOnTriggerUsed(class'KFTrigger_MinigameGenerator');
if(bIsObjectiveDataValid)
{
KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, EventIndex);
}
}
}
function AllowActivation()
{
local int i;
bCanBeActivated = true;
for (i = 0; i < Touching.Length; ++i)
{
class'KFPlayerController'.static.UpdateInteractionMessages(Touching[i]);
}
}
/** Handle activation of the generator and minigames in the level */
function ActivateMinigames()
{
local KFTrigger_MinigameButton MinigameButton;
//Don't activate if we're simply updating the timer
if (!bActiveGenerator)
{
foreach LevelButtons(MinigameButton)
{
MinigameButton.SetMinigameActive();
}
bActiveGenerator = true;
UpdateGeneratorState();
}
else
{
GeneratorReactivated();
}
}
/** Handle deactivation of the generator and minigames in the level */
function DeactivateMinigames()
{
local KFTrigger_MinigameButton MinigameButton;
//Don't deactivate if we're already inactive
if (bActiveGenerator)
{
foreach LevelButtons(MinigameButton)
{
MinigameButton.SetMinigameInactive();
}
bActiveGenerator = false;
UpdateGeneratorState();
GeneratorTimeRemaining = 0;
UpdateGeneratorStatus();
}
}
function GeneratorReactivated()
{
local KFSeqEvent_MinigameGeneratorStateChanged StateChangeEvent;
local int i;
//Notify Kismet that minigame state has been changed
for (i = 0; i < GeneratedEvents.Length; i++)
{
StateChangeEvent = KFSeqEvent_MinigameGeneratorStateChanged(GeneratedEvents[i]);
if (StateChangeEvent != none)
{
StateChangeEvent.StateChanged(self, self, bActiveGenerator, true);
}
}
}
function UpdateGeneratorState()
{
local KFSeqEvent_MinigameGeneratorStateChanged StateChangeEvent;
local int i;
//Notify Kismet that minigame state has been changed
for (i = 0; i < GeneratedEvents.Length; i++)
{
StateChangeEvent = KFSeqEvent_MinigameGeneratorStateChanged(GeneratedEvents[i]);
if (StateChangeEvent != none)
{
StateChangeEvent.StateChanged(self, self, bActiveGenerator, false);
}
}
}
defaultproperties
{
SupportedEvents.Empty
SupportedEvents.Add(class'KFSeqEvent_MinigameGeneratorStateChanged')
RemoteRole=ROLE_SimulatedProxy
NetPriority=+00002.500000
bAlwaysRelevant=true
ActiveTime=300.0f
ReactivationTime=10.0f
bCanBeActivated=true
CurrentStatusIndex=-1
GlowIndex=1
PreviousTimeRemaining=-1.f
CurrentEmissiveActorListIndex=-1
EventIndex=-1
ObjectiveIndex=-1
}