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

351 lines
9.1 KiB
Ucode

//=============================================================================
// KFMapObjective_ExterminateWave
//=============================================================================
// Objective type for exterminating zeds, including bosses. This objective
// simulates a typical Killing Floor "survival" wave.
//=============================================================================
// Killing Floor 2
// Copyright (C) 2018 Tripwire Interactive LLC
//=============================================================================
class KFMapObjective_ExterminateWave extends KFMapObjective_ActorBase;
//=============================================================================
// KFMapObjective_ExterminateWave variables
//=============================================================================
var() bool bBossWave;
var() EBossAIType BossType<EditCondition=bBossWave>;
var() bool bShowBossSpawnTheatrics<EditCondition=bBossWave>;
var() bool bRandomBoss<EditCondition=bBossWave>;
var repnotify float BossHealthPct;
var transient repnotify int WaveProgressIdx, BossProgressIdx;
replication
{
if (bNetInitial)
bBossWave, bShowBossSpawnTheatrics;
if (bNetDirty && !bBossWave)
WaveProgressIdx;
if (bNetDirty && bBossWave)
BossProgressIdx, BossHealthPct;
}
simulated event ReplicatedEvent(name VarName)
{
switch (VarName)
{
case nameof(WaveProgressIdx):
TriggerWavePctProgress();
break;
case nameof(BossProgressIdx):
TriggerBossHealthPctProgress();
break;
default:
super.ReplicatedEvent(VarName);
}
}
//=============================================================================
// KFMapObjective_ExterminateWave functions
//=============================================================================
function NotifyZedKilled(Controller Killer, Pawn KilledPawn, bool bIsBoss)
{
local float OldWavePct, NewWavePct;
local KFGameReplicationInfo KFGRI;
local int PrevWaveProgressIdx, GenEvtIdx, i;
local KFSeqEvent_ExterminateWavePct GenEvt;
PrevWaveProgressIdx = WaveProgressIdx;
// the killed zed is a boss, so set the boss health to zero
// if this isn't done, the objective won't know that it was successfully completed when deactivated
if (bIsBoss)
{
BossHealthPct = 0.0f;
}
// check the first applicable generated event (assumes all applicable events are identical)
for (GenEvtIdx = 0; GenEvtIdx < GeneratedEvents.Length; GenEvtIdx++)
{
GenEvt = KFSeqEvent_ExterminateWavePct(GeneratedEvents[GenEvtIdx]);
if (GenEvt != None)
{
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
OldWavePct = float(KFGRI.WaveTotalAICount - (KFGRI.AIRemaining + 1)) / float(KFGRI.WaveTotalAICount);
NewWavePct = float(KFGRI.WaveTotalAICount - KFGRI.AIRemaining) / float(KFGRI.WaveTotalAICount);
for (i = 0; i < GenEvt.ProgressThresholds.Length; i++)
{
if (OldWavePct < GenEvt.ProgressThresholds[i] &&
NewWavePct >= GenEvt.ProgressThresholds[i])
{
WaveProgressIdx = GenEvt.ProgressOutputStartIndex + i;
break;
}
}
break;
}
}
if (WaveProgressIdx != PrevWaveProgressIdx)
{
TriggerWavePctProgress();
}
}
simulated function TriggerWavePctProgress()
{
local int GenEvtIdx;
local KFSeqEvent_ExterminateWavePct GenEvt;
local array<int> ActivateIndices;
ActivateIndices.AddItem(WaveProgressIdx);
// notify all applicable generated events (assumes all applicable events are identical)
for (GenEvtIdx = 0; GenEvtIdx < GeneratedEvents.Length; GenEvtIdx++)
{
GenEvt = KFSeqEvent_ExterminateWavePct(GeneratedEvents[GenEvtIdx]);
if (GenEvt != None)
{
GenEvt.Reset();
GenEvt.CheckActivate(self, self,, ActivateIndices);
}
}
}
function NotifyBossDamaged(KFPawn_Monster Boss, int Damage)
{
local float OldHealthPct, NewHealthPct;
local int PrevBossProgressIdx, GenEvtIdx, i;
local KFSeqEvent_ExterminateBossHealthPct GenEvt;
PrevBossProgressIdx = BossProgressIdx;
OldHealthPct = float(Boss.Health + Damage) / float(Boss.HealthMax);
NewHealthPct = float(Boss.Health) / float(Boss.HealthMax);
BossHealthPct = NewHealthPct;
// check the first applicable generated event (assumes all applicable events are identical)
for(GenEvtIdx = 0; GenEvtIdx < GeneratedEvents.Length; GenEvtIdx++)
{
GenEvt = KFSeqEvent_ExterminateBossHealthPct(GeneratedEvents[GenEvtIdx]);
if(GenEvt != None)
{
for (i = 0; i < GenEvt.ProgressThresholds.Length; i++)
{
if (OldHealthPct >= GenEvt.ProgressThresholds[i] &&
NewHealthPct < GenEvt.ProgressThresholds[i])
{
BossProgressIdx = GenEvt.ProgressOutputStartIndex + i;
break;
}
}
break;
}
}
if (BossProgressIdx != PrevBossProgressIdx)
{
TriggerBossHealthPctProgress();
}
}
simulated function TriggerBossHealthPctProgress()
{
local int GenEvtIdx;
local KFSeqEvent_ExterminateBossHealthPct GenEvt;
local array<int> ActivateIndices;
ActivateIndices.AddItem(BossProgressIdx);
// notify all applicable generated events (assumes all applicable events are identical)
for(GenEvtIdx = 0; GenEvtIdx < GeneratedEvents.Length; GenEvtIdx++)
{
GenEvt = KFSeqEvent_ExterminateBossHealthPct(GeneratedEvents[GenEvtIdx]);
if(GenEvt != None)
{
GenEvt.Reset();
GenEvt.CheckActivate(self, self,, ActivateIndices);
}
}
}
//=============================================================================
// KFInterface_MapObjective functions
//=============================================================================
// Status
simulated function ActivateObjective()
{
super.ActivateObjective();
if (Role == ROLE_Authority)
{
BossHealthPct = 1.0f;
bIsActive = true;
if (bBossWave)
{
if (KFGameInfo_Objective(WorldInfo.Game) != none)
{
KFGameInfo_Objective(WorldInfo.Game).SetBossIndex();
}
}
}
}
simulated function DeactivateObjective()
{
local KFPawn_Human KFPH;
super.DeactivateObjective();
if (Role == ROLE_Authority)
{
// failed the objective
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));
}
}
bIsActive = false;
}
}
simulated function bool IsActive()
{
return bIsActive;
}
simulated function bool UsesProgress()
{
return true;
}
simulated function bool IsBonus();
function bool CanActivateObjective()
{
return !IsCurrentGameModeBlacklisted();
}
function bool IsCurrentGameModeBlacklisted()
{
local class<KFGameInfo> CurrGameClass;
foreach GameModeBlacklist(CurrGameClass)
{
if (CurrGameClass == WorldInfo.GRI.GameClass)
{
return true;
}
}
return false;
}
simulated function float GetProgress()
{
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (bBossWave)
{
return FClamp(1.0f - BossHealthPct, 0.0f, 1.0f);
}
return FClamp(float(KFGRI.WaveTotalAICount - KFGRI.AIRemaining) / float(KFGRI.WaveTotalAICount), 0.0f, 1.0f);
}
simulated function bool IsComplete()
{
return false;
}
simulated function float GetActivationPctChance()
{
return 1.f;
}
simulated function string GetProgressText()
{
return int(GetProgress() * 100) $ "%";
}
simulated function string GetLocalizedRequirements()
{
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
return Localize("Objectives", default.RequirementsLocKey, "KFGame") @ KFGRI.WaveTotalAICount;
}
simulated function bool GetIsMissionCritical()
{
return bIsMissionCriticalObjective;
}
// HUD
simulated function bool ShouldDrawIcon()
{
return false;
}
simulated function Vector GetIconLocation();
simulated function DrawHUD(KFHUDBase hud, Canvas drawCanvas);
defaultproperties
{
Begin Object Class=SpriteComponent Name=Sprite
Sprite=Texture2D'EditorResources.S_Actor'
HiddenGame=True
AlwaysLoadOnClient=False
AlwaysLoadOnServer=False
End Object
Components.Add(Sprite)
GameModeBlacklist.Add(class'KFGameInfo_Survival')
GameModeBlacklist.Add(class'KFGameInfo_VersusSurvival')
GameModeBlacklist.Add(class'KFGameInfo_Endless')
GameModeBlacklist.Add(class'KFGameInfo_WeeklySurvival')
LocalizationPackageName="KFGame"
LocalizationKey="ExterminateWaveObjective"
DescriptionLocKey="ExterminateWaveDescription"
NameShortLocKey="ExterminateWaveObjective"
DescriptionShortLocKey="ExterminateWaveDescriptionShort"
RequirementsLocKey="ExterminateWaveRequired"
//DefaultIcon=Texture2D'Objectives_UI.UI_Objectives_ObjectiveMode'
ObjectiveIcon=Texture2D'Objectives_UI.UI_Objectives_ObjectiveMode'
PerPlayerSpawnRateMod = (1.f, 1.f, 1.f, 1.f, 1.f, 1.f)
bAlwaysRelevant=true
RemoteRole=ROLE_SimulatedProxy
SupportedEvents.Add(class'KFSeqEvent_ExterminateWavePct')
SupportedEvents.Add(class'KFSeqEvent_ExterminateBossHealthPct')
WaveProgressIdx=-1
BossProgressIdx=-1
BossHealthPct=1.0f
}