//============================================================================= // KFMapObjective_HoldZone //============================================================================= // Objective type for the hold objective. While this is active, players // have to keep zeds out of an area while standing in the area themselves. // They must do this for a certain period of time to complete the objective. //============================================================================= // Killing Floor 2 // Copyright (C) 2017 Tripwire Interactive LLC //============================================================================= class KFMapObjective_HoldZone extends KFMapObjective_AreaDefense; var() float RequiredTime; // in seconds var float ProgressCheckInterval; var float CurrentProgressTime; var transient int TrackProgressTimerIdx; var transient repnotify int ZoneProgressEnabledIdx, ZoneProgressIdx; /** 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; replication { if (bNetDirty) CurrentProgressTime, ZoneProgressEnabledIdx, ZoneProgressIdx; } simulated function ReplicatedEvent(name VarName) { switch (VarName) { case nameof(ZoneProgressEnabledIdx): TriggerZoneProgressEvent(ZoneProgressEnabledIdx); break; case nameof(ZoneProgressIdx): TriggerZoneProgressEvent(ZoneProgressIdx); break; default: super.ReplicatedEvent(VarName); }; } simulated function ActivateObjective() { local int PlayerCount; super.ActivateObjective(); if (Role == ROLE_AUTHORITY) { CurrentProgressTime = 0.0f; SetTimer(ProgressCheckInterval, true, nameof(Timer_CheckProgress)); SetTimer(RequiredTime, false, nameof(Timer_TrackProgress)); SetTimer(RemindPlayersTime, false, nameof(Timer_TooFewPlayersReminderCooldown)); TrackProgressTimerIdx = Timers.Find('FuncName', nameof(Timer_TrackProgress)); PlayerCount = Clamp(KFGameInfo(WorldInfo.Game).GetLivingPlayerCount(), 1, 6) - 1; if (TouchingHumans.Length < PlayerThresholds[PlayerCount] && TouchingZeds.Length >= ZedThresholds[PlayerCount]) { PauseTimer(true, nameof(Timer_TrackProgress)); } bActive = true; bForceNetUpdate = true; } } simulated function DeactivateObjective() { local KFPawn_Human KFPH; super.DeactivateObjective(); if (Role == ROLE_AUTHORITY) { ClearTimer(nameof(Timer_CheckProgress)); ClearTimer(nameof(Timer_TrackProgress)); if (GetProgress() < 1.0f) { if (FailureSoundEvent != none) { PlaySoundBase(FailureSoundEvent, false, WorldInfo.NetMode == NM_DedicatedServer); } } else { foreach WorldInfo.AllPawns(class'KFPawn_Human', KFPH) { GrantReward(KFPlayerReplicationInfo(KFPH.PlayerReplicationInfo), KFPlayerController(KFPH.Controller)); } } bActive = false; bForceNetUpdate = true; } } simulated function Timer_TrackProgress(); simulated function Timer_TooFewPlayersReminderCooldown(); simulated function Timer_TooManyZedsReminderCooldown(); simulated function Timer_CheckProgress() { local int PlayerCount, i, PrevZoneProgressIdx, GenEvtIdx; local float PrevProgress, CurrProgress; local KFSeqEvent_HoldZoneProgress GenEvt; local KFGameReplicationInfo KFGRI; PrevProgress = GetProgress(); if (bActive) { 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 (TouchingHumans.Length >= PlayerThresholds[PlayerCount] && TouchingZeds.Length <= ZedThresholds[PlayerCount]) { if (Timers[TrackProgressTimerIdx].bPaused) { ZoneProgressEnabledIdx = EHoldZoneProgressEvent_ZoneEnabled; TriggerZoneProgressEvent(ZoneProgressEnabledIdx); } PauseTimer(false, nameof(Timer_TrackProgress)); CurrentProgressTime = GetTimerCount(nameof(Timer_TrackProgress)); bDangerState=false; if (IsComplete()) { KFGRI = KFGameReplicationInfo(WorldInfo.GRI); if (KFGRI != none) { KFGRI.DeactivateObjective(); } } } else { if (Role == ROLE_Authority) { 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)); } } } if (!Timers[TrackProgressTimerIdx].bPaused) { ZoneProgressEnabledIdx = EHoldZoneProgressEvent_ZoneDisabled; TriggerZoneProgressEvent(ZoneProgressEnabledIdx); } PauseTimer(true, nameof(Timer_TrackProgress)); bDangerState=true; } UpdateMeshArrayState(); bTooFewPlayers = TouchingHumans.Length < PlayerThresholds[PlayerCount]; bTooManyZeds = TouchingZeds.Length > ZedThresholds[PlayerCount]; } CurrProgress = GetProgress(); if (Role == ROLE_Authority) { PrevZoneProgressIdx = ZoneProgressIdx; // check the first applicable generated event (assumes all applicable events are identical) for (GenEvtIdx = 0; GenEvtIdx < GeneratedEvents.Length; GenEvtIdx++) { GenEvt = KFSeqEvent_HoldZoneProgress(GeneratedEvents[GenEvtIdx]); if (GenEvt != None) { for (i = 0; i < GenEvt.ProgressThresholds.Length; i++) { if (PrevProgress < GenEvt.ProgressThresholds[i] && CurrProgress >= GenEvt.ProgressThresholds[i]) { ZoneProgressIdx = GenEvt.ProgressOutputStartIndex + i; break; } } break; } } if (ZoneProgressIdx != PrevZoneProgressIdx) { TriggerZoneProgressEvent(ZoneProgressIdx); } } } simulated function TriggerZoneProgressEvent(int Idx) { local int GenEvtIdx; local KFSeqEvent_HoldZoneProgress GenEvt; local array ActivateIndices; ActivateIndices.AddItem(Idx); // notify all applicable generated events (assumes all applicable events are identical) for (GenEvtIdx = 0; GenEvtIdx < GeneratedEvents.Length; GenEvtIdx++) { GenEvt = KFSeqEvent_HoldZoneProgress(GeneratedEvents[GenEvtIdx]); if (GenEvt != None) { GenEvt.Reset(); GenEvt.CheckActivate(self, self,, ActivateIndices); } } } simulated function float GetProgress() { if (CurrentProgressTime == -1.0f) { return 1.0f; } return FClamp(CurrentProgressTime / RequiredTime, 0.0f, 1.0f); } simulated function bool IsComplete() { return GetProgress() >= 1.f; } simulated function bool IsActive() { return bActive; } simulated function bool ShouldDrawIcon() { return true; } simulated function Vector GetIconLocation() { return Location; } simulated function string GetProgressText() { local float TotalTime; local int MinutesRemaining, SecondsRemaining; local string TimeString; if (!bActive || RequiredTime <= 0.0f || CurrentProgressTime < 0.0f) { return ""; } TotalTime = FMax(RequiredTime - CurrentProgressTime, 0.0f); MinutesRemaining = int(TotalTime / 60); SecondsRemaining = int(TotalTime % 60); if (MinutesRemaining < 10) { TimeString $= "0"; } TimeString $= MinutesRemaining; TimeString $= ":"; if (SecondsRemaining < 10) { TimeString $= "0"; } TimeString $= SecondsRemaining; return TimeString; } simulated function string GetLocalizedRequirements() { return Localize("Objectives", default.RequirementsLocKey, "KFGame") @ GetProgressText(); } defaultproperties { bAlwaysRelevant = true RemoteRole = ROLE_SimulatedProxy LocalizationPackageName = "KFGame" LocalizationKey = "HoldZoneObjective" DescriptionLocKey = "HoldZoneDescription" NameShortLocKey = "HoldZoneObjective" DescriptionShortLocKey = "HoldZoneDescriptionShort" RequirementsLocKey = "HoldZoneRequired" RequiredTime = 300.f; ProgressCheckInterval = .25f; CurrentProgressTime = 0.0f; PlayerThresholds[0]=1 PlayerThresholds[1]=1 PlayerThresholds[2]=2 PlayerThresholds[3]=2 PlayerThresholds[4]=3 PlayerThresholds[5]=3 ZedThresholds[0]=4 ZedThresholds[1]=4 ZedThresholds[2]=4 ZedThresholds[3]=3 ZedThresholds[4]=2 ZedThresholds[5]=2 ZoneProgressEnabledIdx=EHoldZoneProgressEvent_ZoneDisabled ZoneProgressIdx=-1 SupportedEvents.Add(class'KFSeqEvent_HoldZoneProgress') RemindPlayersTime=30.f }