//============================================================================= // KFPawn_ZedBloatKing //============================================================================= // Boss king variant of the bloat. //============================================================================= // Killing Floor 2 // Copyright (C) 2017 Tripwire Interactive LLC //============================================================================= class KFPawn_ZedBloatKing extends KFPawn_ZedBloat implements(KFInterface_MonsterBoss); //Localization var localized array BossCaptionStrings; //Intro Camera var bool bUseAnimatedCamera; var vector AnimatedBossCameraOffset; //List of things that are getting pulled, 0-5 players, 6-10 zeds var KFPawn PullVictims[11]; //Explosion template for fart attack var protected const KFGameExplosion FartExplosionTemplate; var const ParticleSystem FartFXTemplate; var const name FartFXSocket; var repnotify byte FartFXNotify; //Note: Fart attack happens on a timer without any special move // It uses a base timer, then a variance to +/- it a bit at random var Vector2D BaseFartAttackTimer; var Vector2D VarianceFartAttackTimer; var Vector2D RageFartAttackTimer; var Vector2D RageVarianceFartAttackTimer; var array DifficultyFartAttackTimers; var array DifficultyVarianceFartTimers; var array DifficultyRageFartTimers; var array DifficultyVarianceRageFartTimers; //Trigger used to track pawns that are within range of the KB var KFTrigger_BloatKingGorge GorgeTrigger; //Poop Monster spawn offset var const float PoopMonsterOffset; var ParticleSystem PoopMonsterFXTemplate; var AkEvent PoopMonsterSFXTemplate; var const name PoopMonsterFXSocket; var repnotify byte PoopMonsterFXNotify; //Delayed spawn tracking of poop monsters var const float PoopMonsterSpawnDelay; var int CurrentDelayedSpawns; //Sprint speed specific to enrage var const float RageSprintSpeedMultiplier; //Health thresholds for triggering enrage var array EnrageHealthThresholds; /** Footstep camera shake */ var protected const float FootstepCameraShakePitchAmplitude; var protected const float FootstepCameraShakeRollAmplitude; replication { if (Role == ROLE_Authority) PullVictims, FartFXNotify, PoopMonsterFXNotify; } simulated event ReplicatedEvent(name VarName) { if (VarName == 'bIsEnraged') { SetEnraged(bIsEnraged); } else if (VarName == 'FartFXNotify') { PlayFartSpawnFX(); } else if (VarName == 'PoopMonsterFXNotify') { PlayPoopSpawnFX(); } else { super.ReplicatedEvent(VarName); } } //----------------------------------------------------------------------------- // Boss interface //----------------------------------------------------------------------------- simulated function KFPawn_Monster GetMonsterPawn() { return self; } simulated function string GetRandomBossCaption() { if (default.BossCaptionStrings.Length <= 0) { return ""; } return default.BossCaptionStrings[Rand(default.BossCaptionStrings.Length)]; } static simulated event bool IsABoss() { return true; } simulated function float GetHealthPercent() { return float(Health) / float(HealthMax); } /** Turn on the boss camera animation mode */ simulated function SetAnimatedBossCamera(bool bEnable, optional vector CameraOffset) { bUseAnimatedCamera = bEnable; if (bUseAnimatedCamera) { AnimatedBossCameraOffset = CameraOffset; } else { AnimatedBossCameraOffset = vect(0, 0, 0); } } /** Whether this pawn is in theatric camera mode */ simulated function bool UseAnimatedBossCamera() { return bUseAnimatedCamera; } /** The name of the socket to use as a camera base for theatric sequences */ simulated function name GetBossCameraSocket() { return 'TheatricCameraRootSocket'; } /** The relative offset to use for the cinematic camera */ simulated function vector GetBossCameraOffset() { return AnimatedBossCameraOffset; } function OnZedDied(Controller Killer) { super.OnZedDied(Killer); KFGameInfo(WorldInfo.Game).BossDied(Killer); ClearFartTimer(); ClearTimer('AllowNextPoopMonster'); } function KFAIWaveInfo GetWaveInfo(int BattlePhase, int Difficulty) { //@TODO: King Bloat boss wave functionality return none; } function byte GetNumMinionsToSpawn() { //@TODO: King Bloat boss wave functionality return 0; } //----------------------------------------------------------------------------- // Pawn //----------------------------------------------------------------------------- function PossessedBy(Controller C, bool bVehicleTransition) { Super.PossessedBy(C, bVehicleTransition); if(DifficultyFartAttackTimers.length > 0) { BaseFartAttackTimer = DifficultyFartAttackTimers[Min(WorldInfo.Game.GetModifiedGameDifficulty(), DifficultyFartAttackTimers.length)]; } if (DifficultyVarianceFartTimers.length > 0) { VarianceFartAttackTimer = DifficultyVarianceFartTimers[Min(WorldInfo.Game.GetModifiedGameDifficulty(), DifficultyVarianceFartTimers.length)]; } if (DifficultyRageFartTimers.length > 0) { RageFartAttackTimer = DifficultyRageFartTimers[Min(WorldInfo.Game.GetModifiedGameDifficulty(), DifficultyRageFartTimers.length)]; } if (DifficultyVarianceRageFartTimers.length > 0) { RageVarianceFartAttackTimer = DifficultyVarianceRageFartTimers[Min(WorldInfo.Game.GetModifiedGameDifficulty(), DifficultyVarianceRageFartTimers.length)]; } PlayBossMusic(); class'KFPawn_MonsterBoss'.static.PlayBossEntranceTheatrics(self); SetFartAttackTimer(); GorgeTrigger = Spawn(class'KFTrigger_BloatKingGorge', self, , Location, Rotation); GorgeTrigger.SetBase(self); GorgeTrigger.SetRelativeLocation(vect(0, 0, 0)); GorgeTrigger.CylinderComponent.SetCylinderSize(Sqrt(class'KFSM_BloatKing_Gorge'.default.GorgeAttackRangeSq), CylinderComponent.CollisionHeight); } /** Play music for this boss (overridden for each boss) */ function PlayBossMusic() { if (KFGameInfo(WorldInfo.Game) != none) { KFGameInfo(WorldInfo.Game).ForceAbominationMusicTrack(); } } function bool CanObliterateDoors() { //King Bloat will always obliterate doors return true; } event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector Momentum, class DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser) { Super.TakeDamage(Damage, InstigatedBy, HitLocation, Momentum, DamageType, HitInfo, DamageCauser); if (EnrageHealthThresholds.Length > 0 && (float(Health) / float(HealthMax)) < EnrageHealthThresholds[0]) { if (IsCombatCapable()) { EnrageHealthThresholds.Remove(0, 1); KFAIController_ZedBloatKing(Controller).StartArmorEnrage(); } } } function int GetHitZoneIndex(name BoneName) { if (BoneName == 'KBArmor') { //Known arbitrary, hacking some things in place return OverrideArmorFXIndex; } return super.GetHitZoneIndex(BoneName); } simulated function KFSkinTypeEffects GetHitZoneSkinTypeEffects(int HitZoneIdx) { if (HitZoneIdx == OverrideArmorFXIndex) { return CharacterArch.ImpactSkins[2]; } return super.GetHitZoneSkinTypeEffects(HitZoneIdx); } function ZedExplodeArmor(int ArmorZoneIdx, name ArmorZoneName) { super.ZedExplodeArmor(ArmorZoneIdx, ArmorZoneName); Knockdown( Velocity != vect(0,0,0) ? -Velocity*2 : 3*(-vector(Rotation) * GroundSpeed), vect(1,1,1),,,,, Location ); //KFAIController_ZedBloatKing(Controller).StartArmorEnrage(); } simulated event bool CanDoSpecialMove(ESpecialMove AMove, optional bool bForceCheck) { if (bIsEnraged && AMove == SM_Block) { return false; } return super.CanDoSpecialMove(AMove, bForceCheck); } /** Called by PawnAnimInfo when determining whether an attack with bSpecializedMode TRUE can be performed. This makes the FleshPound use attacks from his PawnAnimInfo that are configured as "specialized" only if he's enraged. */ function bool ShouldPlaySpecialMeleeAnims() { return IsEnraged(); } /** Return current rage status */ simulated event bool IsEnraged() { return bIsEnraged; } /** Enrage this FleshPound! */ simulated function bool SetEnraged(bool bNewEnraged) { local bool bSuccess; bSuccess = super.SetEnraged(bNewEnraged); if (bSuccess && Role == ROLE_Authority) { if (bIsEnraged) { DoSpecialMove(SM_Custom1, true, , SpecialMoveHandler.SpecialMoveClasses[SM_Custom1].static.PackFlagsBase(self)); //If we're higher then the average rage fart attack timer, reset it here to the new lower rage time if (GetTimerCount(nameof(TimerFartAttack)) > Lerp(RageFartAttackTimer.X, RageFartAttackTimer.Y, GetHealthPercentage())) { ClearFartTimer(); SetFartAttackTimer(); } if (KFAIController_ZedBloatKing(Controller) != None) { KFAIController_ZedBloatKing(Controller).SetEnrageTimer(); } } } return bSuccess; } function AdjustMovementSpeed(float SpeedAdjust) { //Redo calculation here to account for the multiplier on sprint speed if (bIsEnraged) { DesiredAdjustedGroundSpeed = default.GroundSpeed * SpeedAdjust * InitialGroundSpeedModifier; if (IsDoingSpecialMove()) { DesiredAdjustedSprintSpeed = fMax(default.SprintSpeed * SpeedAdjust * InitialGroundSpeedModifier * SpecialMoves[SpecialMove].GetSprintSpeedModifier() * default.RageSprintSpeedMultiplier, DesiredAdjustedGroundSpeed); } else { DesiredAdjustedSprintSpeed = fMax(default.SprintSpeed * SpeedAdjust * InitialGroundSpeedModifier * default.RageSprintSpeedMultiplier, DesiredAdjustedGroundSpeed); } NormalGroundSpeed = DesiredAdjustedGroundSpeed; NormalSprintSpeed = DesiredAdjustedSprintSpeed; } else { super.AdjustMovementSpeed(SpeedAdjust); } } /** Overridden to cause slight camera shakes when walking. */ simulated event PlayFootStepSound(int FootDown) { if (WorldInfo.NetMode != NM_DedicatedServer) { if (IsHumanControlled() && IsLocallyControlled()) { FootstepCameraShake.RotOscillation.Pitch.Amplitude = 0; FootstepCameraShake.RotOscillation.Roll.Amplitude = 0; } else { FootstepCameraShake.RotOscillation.Pitch.Amplitude = FootstepCameraShakePitchAmplitude; FootstepCameraShake.RotOscillation.Roll.Amplitude = FootstepCameraShakeRollAmplitude; FootstepCameraShakeInnerRadius = default.FootstepCameraShakeInnerRadius; FootstepCameraShakeOuterRadius = default.FootstepCameraShakeOuterRadius; if (!bIsSprinting || VSizeSQ(Velocity) < 10000.f) { FootstepCameraShake.RotOscillation.Pitch.Amplitude *= 0.75f; FootstepCameraShake.RotOscillation.Roll.Amplitude *= 0.75f; } } } super.PlayFootStepSound(FootDown); } /** Spawn a puke mine */ simulated function ANIMNOTIFY_PukeMineAttack() { local vector SpawnLocation; local rotator SpawnRotation; if (Role == ROLE_Authority) { Mesh.GetSocketWorldLocationAndRotation('PukeSocket', SpawnLocation, SpawnRotation); SpawnPukeMine(SpawnLocation, SpawnRotation); } } function SetFartAttackTimer() { local float HealthPct, TimerValue; HealthPct = GetHealthPercentage(); if (bIsEnraged) { TimerValue = Lerp(RageFartAttackTimer.X, RageFartAttackTimer.Y, HealthPct) + ((FRand() - 0.5) * 2.0f) * Lerp(RageVarianceFartAttackTimer.X, RageVarianceFartAttackTimer.Y, HealthPct); } else { TimerValue = Lerp(BaseFartAttackTimer.X, BaseFartAttackTimer.Y, HealthPct) + ((FRand() - 0.5) * 2.0f) * Lerp(VarianceFartAttackTimer.X, VarianceFartAttackTimer.Y, HealthPct); } SetTimer(TimerValue, false, nameof(TimerFartAttack)); } function ClearFartTimer() { ClearTimer(nameof(TimerFartAttack)); } simulated function TimerFartAttack() { local Vector FartLocation; local Rotator FartRotation; if (!IsAliveAndWell()) { ClearTimer(nameof(TimerFartAttack)); return; } // Explode using the given template Mesh.GetSocketWorldLocationAndRotation(default.FartFXSocket, FartLocation, FartRotation); // Notify to trigger client spawn ++FartFXNotify; // Explosion, fart visual FX PlayFartSpawnFX(); // Puke mine using the same tech for the standard puke mines if (bIsEnraged) { SpawnPukeMine(FartLocation, FartRotation); } //Reset timer for next attack SetFartAttackTimer(); } simulated function PlayFartSpawnFX() { local Vector SocketLocation; local Rotator SocketRotation; local KFExplosion_BloatKingFart ExploActor; if (Role == ROLE_Authority) { SpawnPoopMonster(); } ExploActor = Spawn(class'KFExplosion_BloatKingFart', self, , Location, Rotation); if (ExploActor != none) { ExploActor.InstigatorController = Controller; ExploActor.Instigator = self; ExploActor.Explode(FartExplosionTemplate); } if (WorldInfo.NetMode != NM_DedicatedServer) { Mesh.GetSocketWorldLocationAndRotation(default.FartFXSocket, SocketLocation, SocketRotation); WorldInfo.MyEmitterPool.SpawnEmitter(default.FartFXTemplate, SocketLocation, SocketRotation); } } function AddGorgeVictim(KFPawn NewPawn) { local bool bHuman; local int i; bHuman = KFPawn_Human(NewPawn) != none; NewPawn.SetCollision(true, false); NewPawn.setPhysics(PHYS_Interpolating); for (i = bHuman ? 0 : 6; i < bHuman ? 6 : 11; ++i) { if (PullVictims[i] == none) { PullVictims[i] = NewPawn; return; } } } function RemoveGorgeVictim(KFPawn OldPawn) { local int i; OldPawn.SetCollision(true, true); OldPawn.SetPhysics(PHYS_Walking); for (i = 0; i < 11; ++i) { if (PullVictims[i] == OldPawn) { PullVictims[i] = none; return; } } } function AllowNextPoopMonster() { if (CurrentDelayedSpawns > 0) { //Clear timer to force it to be out of the way when the call to spawn next monster checks for active timer ClearTimer(NameOf(AllowNextPoopMonster)); CurrentDelayedSpawns--; SpawnPoopMonster(); } } function SpawnPoopMonster() { local KFPawn_Monster NewZed; local Vector X,Y,Z; if (IsDoingSpecialMove(SM_BossTheatrics)) { return; } if (IsTimerActive(NameOf(AllowNextPoopMonster))) { ++CurrentDelayedSpawns; return; } GetAxes(Rotation, X, Y, Z); NewZed = Spawn(class'KFPawn_ZedBloatKingSubspawn', , , Location + (X * PoopMonsterOffset), Rotation, , true); if (NewZed != None) { NewZed.SetPhysics(PHYS_Falling); KFGameInfo(WorldInfo.Game).SetMonsterDefaults(NewZed); NewZed.SpawnDefaultController(); NewZed.Knockdown(, vect(1, 1, 1), NewZed.Location, 1000, 100); if (KFAIController(NewZed.Controller) != None) { KFGameInfo(WorldInfo.Game).GetAIDirector().AIList.AddItem(KFAIController(NewZed.Controller)); KFAIController(NewZed.Controller).SetTeam(1); } ++PoopMonsterFXNotify; PlayPoopSpawnFX(); } SetTimer(PoopMonsterSpawnDelay, false, NameOf(AllowNextPoopMonster)); } simulated function PlayPoopSpawnFX() { local Vector SocketLocation; local Rotator SocketRotation; if (WorldInfo.NetMode != NM_DedicatedServer) { Mesh.GetSocketWorldLocationAndRotation(default.PoopMonsterFXSocket, SocketLocation, SocketRotation); WorldInfo.MyEmitterPool.SpawnEmitter(default.PoopMonsterFXTemplate, SocketLocation, SocketRotation); PlaySoundBase(default.PoopMonsterSFXTemplate, true, true, true, SocketLocation, true, SocketRotation); } } //----------------------------------------------------------------------------- // Pawn Removals //----------------------------------------------------------------------------- function CauseHeadTrauma(float BleedOutTime = 5.f) { return; } simulated function bool PlayDismemberment(int InHitZoneIndex, class InDmgType, optional vector HitDirection) { return false; } simulated function PlayHeadAsplode() { return; } simulated function ApplyHeadChunkGore(class DmgType, vector HitLocation, vector HitDirection) { return; } simulated function string GetIconPath() { return "ZED_Patriarch_UI.ZED-VS_Icon_Boss"; } defaultproperties { LocalizationKey=KFPawn_ZedBloatKing //----------------------------------------------------- // Gameplay ArmorZoneStatus=7 // 0b00000111 PreviousArmorZoneStatus=7 bCanRage=true //There can be as many thresholds here as you want. Just do them in order from highest -> lowest EnrageHealthThresholds=(0.8,0.6,0.4,0.2) //Fart is base timer +/- some random amount of the variance, giving you a range of say 25-35 seconds with a base of 30 and variance of 5 // These values are X = 0 health, Y = 100% health DifficultyFartAttackTimers(0)=(X=4.0,Y=7.0) // Normal //(X=5.0,Y=9.0) DifficultyFartAttackTimers(1)=(X=3.5,Y=6.0) // Hard //(X=4.5,Y=8.5) DifficultyFartAttackTimers(2)=(X=3.0,Y=5.5) // Suicidal //(X=4.0,Y=8.0) DifficultyFartAttackTimers(3)=(X=3.0,Y=5.0) // Hell On Earth //(X=4.0,Y=7.0) DifficultyVarianceFartTimers(0)=(X=2.5,Y=3.5) // Normal //(X=3.0,Y=4.0) DifficultyVarianceFartTimers(1)=(X=2.0,Y=3.0) // Hard //(X=2.5,Y=3.5) DifficultyVarianceFartTimers(2)=(X=1.5,Y=2.5) // Suicidal //(X=2.0,Y=3.0) DifficultyVarianceFartTimers(3)=(X=1.5,Y=2.5) // Hell On Earth //(X=2.0,Y=3.0) DifficultyRageFartTimers(0)=(X=1.5,Y=2.25) // Normal //(X=1.75,Y=2.5) DifficultyRageFartTimers(1)=(X=1.0,Y=1.75) // Hard //(X=1.25,Y=2.0) DifficultyRageFartTimers(2)=(X=0.5,Y=1.25) // Suicidal //(X=0.75,Y=1.5) DifficultyRageFartTimers(3)=(X=0.5,Y=1.25) // Hell On Earth //(X=0.75,Y=1.5) DifficultyVarianceRageFartTimers(0)=(X=1.65,Y=2.1) // Normal //(X=1.65,Y=2.1) DifficultyVarianceRageFartTimers(1)=(X=1.15,Y=1.6) // Hard //(X=1.15,Y=1.6) DifficultyVarianceRageFartTimers(2)=(X=0.65,Y=1.1) // Suicidal //(X=0.65,Y=1.1) DifficultyVarianceRageFartTimers(3)=(X=0.65,Y=1.1) // Hell On Earth //(X=0.65,Y=1.1) //Offset from center of the BK to spawn the poop monster PoopMonsterOffset=-100 PoopMonsterFXTemplate=ParticleSystem'CHR_Bile_EMIT.FX_Bile_Birth_01' PoopMonsterSFXTemplate=AkEvent'WW_ZED_Abomination.Play_Abomination_Bile_Spawn' PoopMonsterFXSocket=Poop_Attach //Amount of time between spawns PoopMonsterSpawnDelay=1.5 //2.f // Used for special crawler gas AOE attack "explosion" template FART ATTACK Begin Object Class=KFGameExplosion Name=ExploTemplate0 Damage=5 DamageRadius=450 //600 DamageFalloffExponent=0.f DamageDelay=0.f MyDamageType=class'KFDT_Toxic_BloatKingFart' // Damage Effects KnockDownStrength=0 KnockDownRadius=0 FractureMeshRadius=0 FracturePartVel=0 ExplosionEffects=KFImpactEffectInfo'ZED_BloatKing_ARCH.FX_GasAoE_Explosion_01' ExplosionSound=AkEvent'WW_ZED_Abomination.Play_Abomination_AOE_Explo' MomentumTransferScale=100 // Dynamic Light ExploLight=none // Camera Shake CamShake=CameraShake'FX_CameraShake_Arch.Grenades.Default_Grenade' CamShakeInnerRadius=350 //450 CamShakeOuterRadius=600 //900 CamShakeFalloff=1.f bOrientCameraShakeTowardsEpicenter=true End Object FartExplosionTemplate =ExploTemplate0 FartFXTemplate=ParticleSystem'ZED_BloatKing_EMIT.FX_Bloatking_Fart_01' FartFXSocket=Poop_Attach // --------------------------------------------- // effects Begin Object Class=CameraShake Name=FootstepCameraShake0 bSingleInstance=true OscillationDuration=0.25f RotOscillation={(Pitch=(Amplitude=120.f,Frequency=60.f),Roll=(Amplitude=60.f,Frequency=40.f))} End Object FootstepCameraShake=FootstepCameraShake0 FootstepCameraShakePitchAmplitude=120.f FootstepCameraShakeRollAmplitude=60.f FootstepCameraShakeInnerRadius=200 FootstepCameraShakeOuterRadius=900 // --------------------------------------------- // Special Moves Begin Object Name=SpecialMoveHandler_0 SpecialMoveClasses(SM_GrappleAttack)=class'KFSM_BloatKing_Gorge' SpecialMoveClasses(SM_Custom1)=class'KFSM_BloatKing_Enrage' End Object //----------------------------------------------------- // Content MonsterArchPath="ZED_ARCH.ZED_BloatKing_Archetype" PawnAnimInfo=KFPawnAnimInfo'ZED_BloatKing_ANIM.BloatKing_AnimGroup' DifficultySettings=class'KFDifficulty_BloatKing' OverrideArmorFXIndex=200 PukeMineProjectileClass=class'KFGameContent.KFProj_BloatKingPukeMine' //----------------------------------------------------- // AI / Nav ControllerClass=class'KFAIController_ZedBloatKing' Begin Object Name=MeleeHelper_0 BaseDamage=55.f MaxHitRange=375.f MomentumTransfer=40000.f MyDamageType=class'KFDT_Bludgeon_BloatKing' End Object // Stats XPValues(0)=1291 XPValues(1)=1694 XPValues(2)=1790 XPValues(3)=1843 Health=9000 //11250 DoshValue=500 Mass=400.f RotationRate=(Pitch=50000,Yaw=20000,Roll=50000) GroundSpeed=450.0f //160 //210 //231 //255 SprintSpeed=450.0f //260 //210 410 //315 //330 //345 //380 RageSprintSpeedMultiplier=1.5f //1.3f //1.25 1.45 //1.55 VomitRange=440.f //400.f VomitDamage=20 ArmorInfoClass=class'KFZedArmorInfo_BloatKing' RepArmorPct[0]=255 RepArmorPct[1]=255 RepArmorPct[2]=255 HitZones[HZI_HEAD]=(ZoneName=head, BoneName=Head, Limb=BP_Head, GoreHealth=MaxInt, DmgScale=1.2, SkinID=1) HitZones[2]=(ZoneName=chest, BoneName=Spine2, Limb=BP_Torso, GoreHealth=150, DmgScale=1.2) HitZones[10]=(ZoneName=stomach, BoneName=Spine1, Limb=BP_Torso, GoreHealth=150, DmgScale=1.2) HitZones[11]=(ZoneName=abdomen, BoneName=Hips, Limb=BP_Torso, GoreHealth=150, DmgScale=1.2) // for reference: Vulnerability=(default, head, legs, arms, special) // cutting everything in half to make it harder to stumble except the head. IncapSettings(AF_Stun)= (Vulnerability=(0.1, 0.55, 0.1, 0.1, 0.55), Cooldown=17.0, Duration=1.25) IncapSettings(AF_Knockdown)=(Vulnerability=(0.1, 0.4, 0.1, 0.1, 0.25), Cooldown=20.0) IncapSettings(AF_Stumble)= (Vulnerability=(0.1, 0.3, 0.1, 0.1, 0.4), Cooldown=10.0) IncapSettings(AF_GunHit)= (Vulnerability=(0.1, 0.1, 0.1, 0.1, 0.5), Cooldown=1.7) IncapSettings(AF_MeleeHit)= (Vulnerability=(0.1, 0.95, 0.1, 0.1, 0.75), Cooldown=2.0) IncapSettings(AF_Poison)= (Vulnerability=(0)) IncapSettings(AF_Microwave)=(Vulnerability=(0.08), Cooldown=10.0, Duration=3.0) IncapSettings(AF_FirePanic)=(Vulnerability=(0.65), Cooldown=15.0, Duration=1.2) IncapSettings(AF_EMP)= (Vulnerability=(0.5), Cooldown=10.0, Duration=2.2) IncapSettings(AF_Freeze)= (Vulnerability=(0.3), Cooldown=15.0, Duration=1.0) IncapSettings(AF_Snare)= (Vulnerability=(1.0, 2.0, 1.0, 1.0, 2.0), Cooldown=10.5, Duration=3.0) IncapSettings(AF_Bleed)= (Vulnerability=(0.15), Cooldown=10.0) // Resistant damage types DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Submachinegun', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_AssaultRifle', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Shotgun', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Handgun', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Rifle', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Slashing', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Bludgeon', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Microwave', DamageScale=(0.9))) DamageTypeModifiers.Add((DamageType=class'KFDT_Explosive', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic', DamageScale=(0.05)) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_BloatKingFart', DamageScale=(0.00))) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_BloatKingPukeMine', DamageScale=(0.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_BloatKingSubspawnExplosion', DamageScale=(0.75))) //Special cases DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_HRGHealthrower', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_MicrowaveRifle', DamageScale=(0.7))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGTeslauncher', DamageScale=(0.6))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Minigun', DamageScale=(0.6))) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_MineReconstructorExplosion', DamageScale=(1.2))) DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGenerator_Beam', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGeneratorSphereImpact', DamageScale=(2))) DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGenerator_DefaultFiremodeZapDamage', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGenerator_AltFiremodeZapDamage', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGScorcherLightingImpact', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire_HRGScorcherDoT', DamageScale=(0.4))) //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.3))) //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.3))) //DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.25))) //DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.3))) DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) ParryResistance=4 // Penetration PenetrationResistance=10.0 bCanBePinned=false }