1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFMapObjective_ActivateTrigger.uc

547 lines
15 KiB
Ucode
Raw Normal View History

2020-12-13 15:01:13 +00:00
//=============================================================================
// KFMapObjective_ActivateTrigger
//=============================================================================
// Objective for Biodome for Airship. The player has to activate a trigger n
// times for the objective to be complete. Zeds in the volume will stop the
// trigger from being activated.
//=============================================================================
// Killing Floor 2
// Copyright (C) 2018 Tripwire Interactive LLC
//=============================================================================
class KFMapObjective_ActivateTrigger extends KFMapObjective_AreaDefense;
/** How many times the players have pulled the trigger. */
var repnotify int TriggerPulls;
/** How many times a trigger has to be pulled until the objective is complete, per number of players */
var() const int TriggerPullsRequiredForPlayerCount[6];
/** How many times a trigger has to be pulled until the objective is complete. */
var int TriggerPullsRequired;
/** Reference to the trigger that we may need to override. */
var() KFTrigger_ObjectiveLever ObjectiveLever;
/** A delay from the the start of an objective, so the player can't automatically pull the lever. */
var() float ActivationDelay;
/** A sound to play when the trigger is ready to be triggered (e.g. after activation delay or trigger reset delay) */
var() array<AkEvent> TriggerReadySoundEvents;
/** A sound to play when the trigger is pulled */
var() array<AkEvent> TriggerPulledSoundEvents;
/** A sound to play when the objective is fully complete */
var() AkEvent SuccessSoundEvent100pct;
/** A sound to play when the objective is mostly complete */
var() AkEvent SuccessSoundEvent85pct;
/** A sound to play when the objective is adequately complete */
var() AkEvent SuccessSoundEvent50pct;
/** A sound to play when the objective is barely complete */
var() AkEvent SuccessSoundEvent25pct;
/** Sound event to play when players are engaged with too many zeds in the zone */
var() AkEvent TooManyZedsSoundEvent;
/** Sound event to play when too few players are in the zone */
var() AkEvent TooFewPlayersSoundEvent;
/** How often to remind players about the objective if they aren't engaged in completing it */
var() float RemindPlayersTime;
/** A sound to play when enough players are in the zone, few enough zeds are in the zone, and players are still not pulling the readied trigger */
var() array<AkEvent> TriggerReminderSoundEvents;
/** How often to remind players that the trigger is ready to be pulled */
var() float ReadyTriggerReminderTime;
var transient bool bObjectiveLeverActiveBefore;
var transient bool bObjectiveLeverBlessedBefore;
/** Incremented whenever the lever gets activated, used to kick off a kismet node */
var repnotify int nNumLeversActivated;
/** Set to true whenever the lever is ready to be pulled */
var bool bLeverReady;
/** Whether any players are on the objective */
var repnotify bool bNoPlayers;
/** Color for the objective progress icon when it is ready/not ready */
var const color ReadyIconColor;
var const color NotReadyIconColor;
/** Whether the trigger is allowed to be interacted with */
var bool bInteractable;
replication
{
if(bNetDirty)
TriggerPulls, TriggerPullsRequired, nNumLeversActivated, bNoPlayers, bInteractable;
}
simulated event ReplicatedEvent(name VarName)
{
if (VarName == nameof(TriggerPulls))
{
if (TriggerPulls != 0)
{
TriggerObjectiveProgressEvent(EActivateTriggerProgressEvent_TriggerPulled, float(TriggerPulls)/float(TriggerPullsRequired));
bLeverReady = false;
}
}
else if (VarName == nameof(nNumLeversActivated))
{
TriggerObjectiveProgressEvent(EActivateTriggerProgressEvent_TriggerReady);
bLeverReady = true;
}
else
{
super.ReplicatedEvent(VarName);
}
}
simulated function ActivateObjective()
{
local int PlayerCount;
if (ObjectiveLever != none)
{
ObjectiveLever.OwningObjective = self;
}
super.ActivateObjective();
if (Role == ROLE_Authority)
{
TriggerPulls = 0;
PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1;
TriggerPullsRequired = TriggerPullsRequiredForPlayerCount[PlayerCount];
`log(self @ "-" @ GetFuncName() @ "- ActivationDelay:" @ ActivationDelay);
if (ObjectiveLever != none)
{
ObjectiveLever.SetFathersBlessing(false);
}
bInteractable = false;
if (ActivationDelay > 0.f)
{
SetTimer(ActivationDelay, false, 'ActivateTrigger');
}
else
{
ActivateTrigger();
}
CurrentRewardAmount = 0;
bObjectiveLeverActiveBefore = false;
bObjectiveLeverBlessedBefore = false;
// don't allow "too few players" reminder to be played right away
SetTimer(RemindPlayersTime, false, nameof(Timer_TooFewPlayersReminderCooldown));
}
if (WorldInfo.NetMode != NM_DedicatedServer)
{
CheckTriggerActivation();
}
}
simulated function DeactivateObjective()
{
local KFPlayerController KFPC;
local KFPawn_Human KFPH;
super.DeactivateObjective();
if (Role == ROLE_Authority)
{
ClearTimer('Timer_CheckObjective');
bInteractable = false;
if (ObjectiveLever != none)
{
// Lever should work as trap outside of objective.
ObjectiveLever.SetFathersBlessing(true);
}
if (CurrentRewardAmount > 0)
{
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFPH)
{
GrantReward(KFPlayerReplicationInfo(KFPH.PlayerReplicationInfo), KFPlayerController(KFPH.Controller));
}
}
PlayDeactivationDialog();
}
KFPC = KFPlayerController(GetALocalPlayerController());
if (KFPC != none && KFPC.MyGFxHUD != none)
{
KFPC.MyGFxHUD.WaveInfoWidget.ObjectiveContainer.SetFailState(CurrentRewardAmount <= 0);
}
}
function PlayDeactivationDialog()
{
if (CurrentRewardAmount <= 0)
{
PlaySoundBase(FailureSoundEvent, false, WorldInfo.NetMode == NM_DedicatedServer);
BroadcastLocalizedMessage(class'KFLocalMessage_Priority', GMT_ObjectiveLost);
}
else
{
if (GetProgress() <= JustWinThreshold)
{
PlaySoundBase(SuccessSoundEvent25pct, false, WorldInfo.NetMode == NM_DedicatedServer);
}
else if (GetProgress() <= StandardWinThreshold)
{
PlaySoundBase(SuccessSoundEvent50pct, false, WorldInfo.NetMode == NM_DedicatedServer);
}
else if (GetProgress() <= GoodWinThreshold)
{
PlaySoundBase(SuccessSoundEvent85pct, false, WorldInfo.NetMode == NM_DedicatedServer);
}
else
{
PlaySoundBase(SuccessSoundEvent100pct, false, WorldInfo.NetMode == NM_DedicatedServer);
}
}
}
simulated function ActivateTrigger()
{
local int PlayerCount;
`log(self @ "-" @ GetFuncName());
bInteractable = true;
if (ObjectiveLever != none)
{
PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1;
ObjectiveLever.SetFathersBlessing(TouchingZeds.length < ZedThresholds[PlayerCount] && TouchingHumans.Length >= PlayerThresholds[PlayerCount]);
}
nNumLeversActivated++;
TriggerObjectiveProgressEvent(EActivateTriggerProgressEvent_TriggerReady);
SetTimer(0.25f, true, 'Timer_CheckObjective');
// don't allow "trigger ready" reminder to play right away
SetTimer(ReadyTriggerReminderTime, false, nameof(Timer_TriggerReadyReminderCooldown));
}
//-----------------------------------------------------------------------------
// Volume
//-----------------------------------------------------------------------------
event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
{
local int PlayerCount;
super.Touch(Other, OtherComp, HitLocation, HitNormal);
PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1;
if (TouchingZeds.Length >= ZedThresholds[PlayerCount])
{
if (ObjectiveLever != none && bActive && bInteractable)
{
ObjectiveLever.SetFathersBlessing(false);
CheckTriggerActivation();
}
}
else if (TouchingHumans.Length >= PlayerThresholds[PlayerCount])
{
if (ObjectiveLever != none && bActive && bInteractable)
{
ObjectiveLever.SetFathersBlessing(true);
CheckTriggerActivation();
}
}
}
event UnTouch(Actor Other)
{
local int PlayerCount;
super.UnTouch(Other);
PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1;
if (TouchingHumans.Length < PlayerThresholds[PlayerCount])
{
if (ObjectiveLever != none && bActive && bInteractable)
{
ObjectiveLever.SetFathersBlessing(false);
CheckTriggerActivation();
}
}
else if (TouchingZeds.Length < ZedThresholds[PlayerCount])
{
if (ObjectiveLever != none && bActive && bInteractable)
{
ObjectiveLever.SetFathersBlessing(true);
CheckTriggerActivation();
}
}
}
simulated function Timer_CheckObjective()
{
local int i, PlayerCount;
for (i = 0; i < TouchingZeds.length; i++)
{
if (!IsValidZed(TouchingZeds[i]))
{
TouchingZeds.Remove(i, 1);
}
}
PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1;
if (bActive && bInteractable && ObjectiveLever != none)
{
ObjectiveLever.SetFathersBlessing(TouchingZeds.length < ZedThresholds[PlayerCount] && TouchingHumans.Length >= PlayerThresholds[PlayerCount]);
CheckTriggerActivation();
}
if(ObjectiveLever != none && ObjectiveLever.bAllowActivation && !bObjectiveLeverActiveBefore)
{
// reset reminder when the lever becomes ready again
SetTimer(ReadyTriggerReminderTime, false, nameof(Timer_TriggerReadyReminderCooldown));
if (TriggerReadySoundEvents.Length > TriggerPulls)
{
PlaySoundBase(TriggerReadySoundEvents[TriggerPulls], , WorldInfo.NetMode == NM_DedicatedServer);
}
}
bObjectiveLeverActiveBefore = ObjectiveLever.bAllowActivation;
if (Role == ROLE_Authority)
{
bNoPlayers = TouchingHumans.Length <= 0;
if (bActive && bInteractable)
{
PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1;
if (TouchingHumans.Length < PlayerThresholds[PlayerCount])
{
if (!IsTimerActive(nameof(Timer_TooFewPlayersReminderCooldown)))
{
// trigger sound event
if (TooFewPlayersSoundEvent != none)
{
PlaySoundBase(TooFewPlayersSoundEvent, , WorldInfo.NetMode == NM_DedicatedServer);
}
SetTimer(RemindPlayersTime, false, nameof(Timer_TooFewPlayersReminderCooldown));
}
}
if (TouchingZeds.Length > ZedThresholds[PlayerCount])
{
if (!IsTimerActive(nameof(Timer_TooManyZedsReminderCooldown)))
{
if (TooManyZedsSoundEvent != none)
{
PlaySoundBase(TooManyZedsSoundEvent, , WorldInfo.NetMode == NM_DedicatedServer);
}
SetTimer(RemindPlayersTime, false, nameof(Timer_TooManyZedsReminderCooldown));
}
}
bTooFewPlayers = TouchingHumans.Length < PlayerThresholds[PlayerCount];
bTooManyZeds = TouchingZeds.Length > ZedThresholds[PlayerCount];
if (ObjectiveLever != none && ObjectiveLever.bAllowActivation)
{
if (TriggerPulls < TriggerReminderSoundEvents.Length && TriggerReminderSoundEvents[TriggerPulls] != none && !IsTimerActive(nameof(Timer_TriggerReadyReminderCooldown)))
{
if (TriggerReminderSoundEvents[TriggerPulls] != none)
{
PlaySoundBase(TriggerReminderSoundEvents[TriggerPulls], , WorldInfo.NetMode == NM_DedicatedServer);
}
SetTimer(ReadyTriggerReminderTime, false, nameof(Timer_TriggerReadyReminderCooldown));
}
}
}
}
}
// These timer functions don't definitions, they just need to exist for SetTimer
simulated function Timer_TooFewPlayersReminderCooldown();
simulated function Timer_TooManyZedsReminderCooldown();
simulated function Timer_TriggerReadyReminderCooldown();
simulated function OnTriggerActivated()
{
local KFGameReplicationInfo KFGRI;
if (!bActive || !bInteractable)
{
return;
}
TriggerPulls++;
TriggerObjectiveProgressEvent(EActivateTriggerProgressEvent_TriggerPulled, float(TriggerPulls) / float(TriggerPullsRequired));
if (Role == ROLE_Authority)
{
CurrentRewardAmount = GetMaxDoshReward() * GetProgress();
if (TriggerPulls <= TriggerPulledSoundEvents.Length)
{
PlaySoundBase(TriggerPulledSoundEvents[TriggerPulls-1],, WorldInfo.NetMode == NM_DedicatedServer);
}
}
if (GetProgress() >= 1.f)
{
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
KFGRI.DeactivateObjective();
}
}
}
simulated function OnTriggerReactivated()
{
CheckTriggerActivation();
nNumLeversActivated++;
TriggerObjectiveProgressEvent(EActivateTriggerProgressEvent_TriggerReady);
}
simulated function CheckTriggerActivation()
{
bDangerState = false;
if (ObjectiveLever != none)
{
bDangerState = !ObjectiveLever.bFathersBlessing;
UpdateMeshArrayState();
ObjectiveLever.BroadcastInteractionMessages();
}
}
simulated function float GetProgress()
{
if (TriggerPullsRequired == 0)
{
return 0;
}
return float(TriggerPulls) / float(TriggerPullsRequired);
}
simulated function bool IsComplete()
{
return GetProgress() >= 1.f;
}
simulated function string GetLocalizedRequirements()
{
return Localize("Objectives", default.RequirementsLocKey, "KFGame") @ TriggerPullsRequired;
}
simulated function string GetProgressText()
{
if (!bActive)
{
return "";
}
return TriggerPulls $ "/" $ TriggerPullsRequired;
}
simulated function GetLocalizedStatus(out string statusMessage, out int bWarning, out int bNotification)
{
statusMessage = "";
super.GetLocalizedStatus(statusMessage, bWarning, bNotification);
if (statusMessage == "")
{
if (ObjectiveLever.ReadyToActivate() || bLeverReady)
{
statusMessage = Localize("Objectives", "Ready", LocalizationPackageName);
bNotification = 1;
bWarning = 0;
return;
}
else
{
statusMessage = Localize("Objectives", "NotReady", LocalizationPackageName);
bNotification = 0;
bWarning = 1;
return;
}
}
}
simulated function color GetIconColor()
{
// want to show the not ready color if stopped for some reason
if (bTooManyZeds || (bTooFewPlayers && !bNoPlayers))
{
return NotReadyIconColor;
}
// but want to show the normal color if exactly zero players on the objective
if ((ROLE == ROLE_Authority && TouchingHumans.Length <= 0) || bNoPlayers)
{
return ObjectiveIconColor;
}
//otherwise if the lever is ready, choose that color
if (ObjectiveLever.ReadyToActivate() || bLeverReady)
{
return ReadyIconColor;
}
return ObjectiveIconColor;
}
defaultproperties
{
DescriptionLocKey="DescriptionActivateTrigger"
DescriptionShortLocKey = "DescriptionActivateTriggerShort"
RequirementsLocKey="RequiredActivateTrigger"
LocalizationKey="ActivateTrigger"
NameShortLocKey="ActivateTrigger"
GameModeBlacklist.Add(class'KFGameInfo_Endless')
GameModeBlacklist.Add(class'KFGameInfo_WeeklySurvival')
SupportedEvents.Add(class'KFSeqEvent_ActivateTriggerProgress')
TriggerPullsRequired=6
ActivationDelay=5.f
PlayerThresholds[0]=1
PlayerThresholds[1]=1
PlayerThresholds[2]=2
PlayerThresholds[3]=2
PlayerThresholds[4]=3
PlayerThresholds[5]=3
ZedThresholds[0]=6
ZedThresholds[1]=5
ZedThresholds[2]=4
ZedThresholds[3]=3
ZedThresholds[4]=2
ZedThresholds[5]=1
RemindPlayersTime=30.f
ObjectiveIcon=Texture2D'Objectives_UI.UI_Objectives_ObjectiveMode'
ReadyIconColor=(R=0, G=255, B=0, A=255);
NotReadyIconColor=(R=255, G=0, B=0, A=255);
}