class ZombieBossOS extends KFMonsterOS; var BossHPNeedle CurrentNeedle; var bool bChargingPlayer,bClientCharg,bFireAtWill,bMinigunning,bIsBossView; var float RageStartTime,LastChainGunTime,LastMissileTime,LastSneakedTime; var bool bClientMiniGunning; var name ChargingAnim; var byte SyringeCount,ClientSyrCount; var int MGFireCounter; var vector TraceHitPos; var Emitter mTracer,mMuzzleFlash; var bool bClientCloaked; var float LastCheckTimes; var int HealingLevels[3],HealingAmount; var float MGFireDuration; var float MGLostSightTimeout; var() float MGDamage; var() float ClawMeleeDamageRange; var() float ImpaleMeleeDamageRange; var float LastChargeTime; var float LastForceChargeTime; var int NumChargeAttacks; var float ChargeDamage; var float LastDamageTime; var float SneakStartTime; var int SneakCount; var() float PipeBombDamageScale; replication { reliable if( Role==ROLE_Authority ) bChargingPlayer,SyringeCount,TraceHitPos,bMinigunning,bIsBossView; } simulated function CalcAmbientRelevancyScale() { CustomAmbientRelevancyScale = 5000/(100 * SoundRadius); } function vector ComputeTrajectoryByTime( vector StartPosition, vector EndPosition, float fTimeEnd ) { local vector NewVelocity; NewVelocity = super.ComputeTrajectoryByTime( StartPosition, EndPosition, fTimeEnd ); if( PhysicsVolume.IsA( 'KFPhysicsVolume' ) && StartPosition.Z < EndPosition.Z ) { if( PhysicsVolume.Gravity.Z < class'PhysicsVolume'.default.Gravity.Z ) { if( Mass > 900 ) { NewVelocity.Z += 90; } } } return NewVelocity; } function ZombieMoan() { if( !bShotAnim ) super.ZombieMoan(); } simulated function SetBurningBehavior(){} simulated function UnSetBurningBehavior(){} function bool CanGetOutOfWay() { return false; } simulated function Tick(float DeltaTime) { local KFHumanPawn HP; super.Tick(DeltaTime); if( Role == ROLE_Authority ) { PipeBombDamageScale -= DeltaTime * 0.33; if( PipeBombDamageScale < 0 ) { PipeBombDamageScale = 0; } } if( Level.NetMode==NM_DedicatedServer ) return; bSpecialCalcView = bIsBossView; if( bZapped ) { LastCheckTimes = Level.TimeSeconds; } else if( bCloaked && Level.TimeSeconds>LastCheckTimes ) { LastCheckTimes = Level.TimeSeconds+0.8; ForEach VisibleCollidingActors(class'KFHumanPawn',HP,1000,Location) { if( HP.Health <= 0 || !HP.ShowStalkers() ) continue; if( !bSpotted ) { bSpotted = true; CloakBoss(); } return; } if( bSpotted ) { bSpotted = false; bUnlit = false; CloakBoss(); } } } simulated function CloakBoss() { local Controller C; local int Index; if( bZapped ) { return; } if( bSpotted ) { Visibility = 120; if( Level.NetMode==NM_DedicatedServer ) return; Skins[0] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; Skins[1] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; Skins[2] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; Skins[3] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; Skins[4] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; Skins[5] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; Skins[6] = Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'; bUnlit = true; return; } Visibility = 1; bCloaked = true; if( Level.NetMode!=NM_Client ) { For( C=Level.ControllerList; C!=none; C=C.NextController ) { if( C.bIsPlayer && C.Enemy==self ) C.Enemy = none; } } if( Level.NetMode==NM_DedicatedServer ) return; Skins[0] = Shader'KFOldSchoolZeds_Textures.BossCloakShader'; Skins[1] = Shader'KFOldSchoolZeds_Textures.BossCloakShader'; Skins[2] = Shader'KFOldSchoolZeds_Textures.BossCloakShader'; Skins[3] = Shader'KFOldSchoolZeds_Textures.BossCloakShader'; Skins[4] = Shader'KFOldSchoolZeds_Textures.BossCloakShader'; Skins[5] = Shader'KFOldSchoolZeds_Textures.BossCloakShader'; Skins[6] = Texture'KillingFloorLabTextures.LabCommon.voidtex'; if(PlayerShadow != none) PlayerShadow.bShadowActive = false; Projectors.Remove(0, Projectors.Length); bAcceptsProjectors = false; SetOverlayMaterial(FinalBlend'KFOldSchoolZeds_Textures.Patriarch.BossCloakFizzleFB', 1.0, true); if ( FRand() < 0.10 ) { Index = Rand(Level.Game.NumPlayers); for ( C = Level.ControllerList; C != none; C = C.NextController ) { if ( PlayerController(C) != none ) { if ( Index == 0 ) { PlayerController(C).Speech('AUTO', 8, ""); break; } Index--; } } } } simulated function UnCloakBoss() { if( bZapped ) { return; } Visibility = default.Visibility; bCloaked = false; bSpotted = false; bUnlit = false; if( Level.NetMode==NM_DedicatedServer ) return; Skins = default.Skins; if (PlayerShadow != none) PlayerShadow.bShadowActive = true; bAcceptsProjectors = true; SetOverlayMaterial( none, 0.0, true ); } simulated function SetZappedBehavior() { super.SetZappedBehavior(); if( Level.Netmode != NM_DedicatedServer ) { bUnlit = false; Skins = default.Skins; if (PlayerShadow != none) PlayerShadow.bShadowActive = true; bAcceptsProjectors = true; SetOverlayMaterial(Material'KFZED_FX_T.Energy.ZED_overlay_Hit_Shdr', 999, true); } } simulated function UnSetZappedBehavior() { super.UnSetZappedBehavior(); if( Level.Netmode != NM_DedicatedServer ) { LastCheckTimes = Level.TimeSeconds; SetOverlayMaterial(none, 0.0f, true); } } function SetZapped(float ZapAmount, Pawn Instigator) { LastZapTime = Level.TimeSeconds; if( bZapped ) { TotalZap = ZapThreshold; RemainingZap = ZapDuration; } else { TotalZap += ZapAmount; if( TotalZap >= ZapThreshold ) { RemainingZap = ZapDuration; bZapped = true; } } ZappedBy = Instigator; } simulated function PostBeginPlay() { super.PostBeginPlay(); if( Role < ROLE_Authority ) { return; } if (Level.Game != none) { if( Level.Game.NumPlayers == 1 ) { if( Level.Game.GameDifficulty < 2.0 ) { MGDamage = default.MGDamage * 0.375; } else if( Level.Game.GameDifficulty < 4.0 ) { MGDamage = default.MGDamage * 0.75; } else if( Level.Game.GameDifficulty < 5.0 ) { MGDamage = default.MGDamage * 1.15; } else { MGDamage = default.MGDamage * 1.3; } } else { if( Level.Game.GameDifficulty < 2.0 ) { MGDamage = default.MGDamage * 0.375; } else if( Level.Game.GameDifficulty < 4.0 ) { MGDamage = default.MGDamage * 1.0; } else if( Level.Game.GameDifficulty < 5.0 ) { MGDamage = default.MGDamage * 1.15; } else { MGDamage = default.MGDamage * 1.3; } } } HealingLevels[0] = Health/1.25; HealingLevels[1] = Health/2.f; HealingLevels[2] = Health/3.2; HealingAmount = Health/4; } function bool MakeGrandEntry() { bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('Entrance'); HandleWaitForAnim('Entrance'); GotoState('MakingEntrance'); return true; } state MakingEntrance { Ignores RangedAttack; function Tick( float Delta ) { Acceleration = vect(0,0,0); global.Tick(Delta); } Begin: Sleep(GetAnimDuration('Entrance')); GotoState('InitialSneak'); } simulated function Destroyed() { if( mTracer!=none ) mTracer.Destroy(); if( mMuzzleFlash!=none ) mMuzzleFlash.Destroy(); super.Destroyed(); } simulated Function PostNetBeginPlay() { EnableChannelNotify ( 1,1); AnimBlendParams(1, 1.0, 0.0,, 'Bip01 Spine1'); super.PostNetBeginPlay(); TraceHitPos = vect(0,0,0); bNetNotify = true; } function PlayTakeHit(vector HitLocation, int Damage, class DamageType) { if( Level.TimeSeconds - LastPainAnim < MinTimeBetweenPainAnims ) return; if( Damage>=150 || (DamageType.name=='DamTypeStunNade' && rand(5)>3) || (DamageType.name=='DamTypeCrossbowHeadshot' && Damage>=200) ) PlayDirectionalHit(HitLocation); LastPainAnim = Level.TimeSeconds; if( Level.TimeSeconds - LastPainSound < MinTimeBetweenPainSounds ) return; LastPainSound = Level.TimeSeconds; PlaySound(HitSound[0], SLOT_Pain,2*TransientSoundVolume,,400); } function bool OnlyEnemyAround( Pawn Other ) { local Controller C; For( C=Level.ControllerList; C!=none; C=C.NextController ) { if( C.bIsPlayer && C.Pawn!=none && C.Pawn!=Other && ((VSize(C.Pawn.Location-Location)<1500 && FastTrace(C.Pawn.Location,Location)) || (VSize(C.Pawn.Location-Other.Location)<1000 && FastTrace(C.Pawn.Location,Other.Location))) ) return false; } return true; } function bool IsCloseEnuf( Actor A ) { local vector V; if( A==none ) return false; V = A.Location-Location; if( Abs(V.Z)>(CollisionHeight+A.CollisionHeight) ) return false; V.Z = 0; return (VSize(V)<(CollisionRadius+A.CollisionRadius+25)); } function RangedAttack(Actor A) { local float D; local bool bOnlyE; local bool bDesireChainGun; if( Controller.LineOfSightTo(A) && FRand() < 0.15 && LastChainGunTime1500 && Pawn(A)!=none && FRand() < 0.5 ) { SetAnimAction('MeleeImpale'); } else { SetAnimAction('MeleeClaw'); PlaySound(sound'Claw2s', SLOT_None); } } else if( Level.TimeSeconds - LastSneakedTime > 20.0 ) { if( FRand() < 0.3 ) { LastSneakedTime = Level.TimeSeconds; return; } SetAnimAction('BossHitF'); GoToState('SneakAround'); } else if( bChargingPlayer && (bOnlyE || D<200) ) return; else if( !bDesireChainGun && !bChargingPlayer && (D<300 || (D<700 && bOnlyE)) && (Level.TimeSeconds - LastChargeTime > (5.0 + 5.0 * FRand())) ) { SetAnimAction('BossHitF'); GoToState('Charging'); } else if( LastMissileTime 500 ) { if( !Controller.LineOfSightTo(A) || FRand() > 0.75 ) { LastMissileTime = Level.TimeSeconds+FRand() * 5; return; } LastMissileTime = Level.TimeSeconds + 10 + FRand() * 15; bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('PreFireMG'); HandleWaitForAnim('PreFireMG'); GoToState('FireMissile'); } else if ( !bWaitForAnim && !bShotAnim && LastChainGunTime 0.85 ) { LastChainGunTime = Level.TimeSeconds+FRand()*4; return; } LastChainGunTime = Level.TimeSeconds + 5 + FRand() * 10; bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('PreFireMG'); HandleWaitForAnim('PreFireMG'); MGFireCounter = Rand(60) + 35; GoToState('FireChaingun'); } } event Bump(actor Other) { super(Monster).Bump(Other); if( Other==none ) return; if( Other.IsA('NetKActor') && Physics != PHYS_Falling && !bShotAnim && Abs(Other.Location.Z-Location.Z)<(CollisionHeight+Other.CollisionHeight) ) { Controller.Target = Other; Controller.Focus = Other; bShotAnim = true; Acceleration = (Other.Location-Location); SetAnimAction('MeleeClaw'); PlaySound(sound'Claw2s', SLOT_None); HandleWaitForAnim('MeleeClaw'); } } simulated function AddTraceHitFX( vector HitPos ) { local vector Start,SpawnVel,SpawnDir; local float hitDist; PlaySound(sound'KFOldSchoolZeds_Sounds.MinigunFire',SLOT_Misc,2,,1400,0.9+FRand()*0.2); Start = GetBoneCoords('tip').Origin; if( mTracer==none ) mTracer = Spawn(class'KFMod.KFNewTracer',,,Start); else mTracer.SetLocation(Start); if( mMuzzleFlash==none ) { mMuzzleFlash = Spawn(class'NewMinigunMFlashOS'); AttachToBone(mMuzzleFlash, 'tip'); } else mMuzzleFlash.SpawnParticle(1); hitDist = VSize(HitPos - Start) - 50.f; if( hitDist>10 ) { SpawnDir = Normal(HitPos - Start); SpawnVel = SpawnDir * 10000.f; mTracer.Emitters[0].StartVelocityRange.X.Min = SpawnVel.X; mTracer.Emitters[0].StartVelocityRange.X.Max = SpawnVel.X; mTracer.Emitters[0].StartVelocityRange.Y.Min = SpawnVel.Y; mTracer.Emitters[0].StartVelocityRange.Y.Max = SpawnVel.Y; mTracer.Emitters[0].StartVelocityRange.Z.Min = SpawnVel.Z; mTracer.Emitters[0].StartVelocityRange.Z.Max = SpawnVel.Z; mTracer.Emitters[0].LifetimeRange.Min = hitDist / 10000.f; mTracer.Emitters[0].LifetimeRange.Max = mTracer.Emitters[0].LifetimeRange.Min; mTracer.SpawnParticle(1); } Instigator = self; if( HitPos != vect(0,0,0) ) { Spawn(class'ROBulletHitEffect',,, HitPos, Rotator(Normal(HitPos - Start))); } } simulated function AnimEnd( int Channel ) { local name Sequence; local float Frame, Rate; if( Level.NetMode==NM_Client && bMinigunning ) { GetAnimParams( Channel, Sequence, Frame, Rate ); if( Sequence != 'PreFireMG' && Sequence != 'FireMG' ) { super.AnimEnd(Channel); return; } PlayAnim('FireMG'); bWaitForAnim = true; bShotAnim = true; IdleTime = Level.TimeSeconds; } else super.AnimEnd(Channel); } state FireChaingun { function RangedAttack(Actor A) { Controller.Target = A; Controller.Focus = A; } function bool ShouldChargeFromDamage() { return false; } function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class damageType, optional int HitIndex) { local float EnemyDistSq, DamagerDistSq; global.TakeDamage(Damage,instigatedBy,hitlocation,Momentum,damageType); if( InstigatedBy != none ) { DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location); if( (ChargeDamage > 200 && DamagerDistSq < (500 * 500)) || DamagerDistSq < (100 * 100) ) { SetAnimAction('BossHitF'); GoToState('Charging'); return; } } if( Controller.Enemy != none && InstigatedBy != none && InstigatedBy != Controller.Enemy ) { EnemyDistSq = VSizeSquared(Location - Controller.Enemy.Location); DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location); } if( InstigatedBy != none && (DamagerDistSq < EnemyDistSq || Controller.Enemy == none) ) { MonsterController(Controller).ChangeEnemy(InstigatedBy,Controller.CanSee(InstigatedBy)); Controller.Target = InstigatedBy; Controller.Focus = InstigatedBy; if( DamagerDistSq < (500 * 500) ) { SetAnimAction('BossHitF'); GoToState('Charging'); } } } function EndState() { TraceHitPos = vect(0,0,0); bMinigunning = false; AmbientSound = default.AmbientSound; SoundVolume=default.SoundVolume; SoundRadius=default.SoundRadius; MGFireCounter=0; LastChainGunTime = Level.TimeSeconds + 5 + (FRand()*10); } function BeginState() { OnlineHeadshotOffset=default.OnlineHeadshotOffset; bFireAtWill = false; Acceleration = vect(0,0,0); MGLostSightTimeout = 0.0; bMinigunning = true; } function AnimEnd( int Channel ) { if( MGFireCounter <= 0 ) { bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('FireEndMG'); HandleWaitForAnim('FireEndMG'); GoToState(''); } else { if ( Controller.Enemy != none ) { if ( Controller.LineOfSightTo(Controller.Enemy) && FastTrace(GetBoneCoords('tip').Origin,Controller.Enemy.Location)) { MGLostSightTimeout = 0.0; Controller.Focus = Controller.Enemy; Controller.FocalPoint = Controller.Enemy.Location; } else { MGLostSightTimeout = Level.TimeSeconds + (0.25 + FRand() * 0.35); Controller.Focus = none; } Controller.Target = Controller.Enemy; } else { MGLostSightTimeout = Level.TimeSeconds + (0.25 + FRand() * 0.35); Controller.Focus = none; } if( !bFireAtWill ) { MGFireDuration = Level.TimeSeconds + (0.75 + FRand() * 0.5); } else if ( FRand() < 0.03 && Controller.Enemy != none && PlayerController(Controller.Enemy.Controller) != none ) { PlayerController(Controller.Enemy.Controller).Speech('AUTO', 9, ""); } bFireAtWill = true; bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('FireMG'); bWaitForAnim = true; } } function FireMGShot() { local vector Start,End,HL,HN,Dir; local rotator R; local Actor A; MGFireCounter--; Start = GetBoneCoords('tip').Origin; if( Controller.Focus!=none ) R = rotator(Controller.Focus.Location-Start); else R = rotator(Controller.FocalPoint-Start); if( NeedToTurnFor(R) ) R = Rotation; Dir = Normal(vector(R)+VRand()*0.06); //*0.04 End = Start+Dir*10000; bBlockHitPointTraces = false; A = Trace(HL,HN,End,Start,true); bBlockHitPointTraces = true; if( A==none ) return; TraceHitPos = HL; if( Level.NetMode!=NM_DedicatedServer ) AddTraceHitFX(HL); if( A!=Level ) { A.TakeDamage(MGDamage+Rand(3),self,HL,Dir*500,class'DamageType'); } } function bool NeedToTurnFor( rotator targ ) { local int YawErr; targ.Yaw = DesiredRotation.Yaw & 65535; YawErr = (targ.Yaw - (Rotation.Yaw & 65535)) & 65535; return !((YawErr < 2000) || (YawErr > 64535)); } Begin: While( true ) { Acceleration = vect(0,0,0); if( MGLostSightTimeout > 0 && Level.TimeSeconds > MGLostSightTimeout ) { bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('FireEndMG'); HandleWaitForAnim('FireEndMG'); GoToState(''); } if( MGFireCounter <= 0 ) { bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('FireEndMG'); HandleWaitForAnim('FireEndMG'); GoToState(''); } if( bFireAtWill ) FireMGShot(); Sleep(0.05); } } state FireMissile { Ignores RangedAttack; function bool ShouldChargeFromDamage() { return false; } function BeginState() { OnlineHeadshotOffset=default.OnlineHeadshotOffset; Acceleration = vect(0,0,0); } function AnimEnd( int Channel ) { local vector Start; local Rotator R; Start = GetBoneCoords('tip').Origin; if ( !SavedFireProperties.bInitialized ) { SavedFireProperties.AmmoClass = MyAmmo.class; SavedFireProperties.ProjectileClass = MyAmmo.ProjectileClass; SavedFireProperties.WarnTargetPct = 0.15; SavedFireProperties.MaxRange = 10000; SavedFireProperties.bTossed = false; SavedFireProperties.bTrySplash = false; SavedFireProperties.bLeadTarget = true; SavedFireProperties.bInstantHit = true; SavedFireProperties.bInitialized = true; } R = AdjustAim(SavedFireProperties,Start,100); PlaySound(Sound'KFOldSchoolZeds_Sounds.Shared.LAWFire'); Spawn(class'BossLAWProjOS',,,Start,R); bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('FireEndMG'); HandleWaitForAnim('FireEndMG'); if ( FRand() < 0.05 && Controller.Enemy != none && PlayerController(Controller.Enemy.Controller) != none ) { PlayerController(Controller.Enemy.Controller).Speech('AUTO', 10, ""); } GoToState(''); } Begin: while ( true ) { Acceleration = vect(0,0,0); Sleep(0.1); } } function bool MeleeDamageTarget(int hitdamage, vector pushdir) { if( Controller.Target!=none && Controller.Target.IsA('NetKActor') ) pushdir = Normal(Controller.Target.Location-Location)*100000; return super.MeleeDamageTarget(hitdamage, pushdir); } state Charging { function bool CanSpeedAdjust() { return false; } function bool ShouldChargeFromDamage() { return false; } //Dont play hit anims while charging so people don't complain about broken head hitboxes :) function OldPlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class damageType, vector Momentum, optional int HitIndex){} function BeginState() { bChargingPlayer = true; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); NumChargeAttacks = Rand(2) + 1; OnlineHeadshotOffset.Z=60; OnlineHeadshotOffset.X=30; } function EndState() { SetGroundSpeed(GetOriginalGroundSpeed()); bChargingPlayer = false; ChargeDamage = 0; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); OnlineHeadshotOffset=default.OnlineHeadshotOffset; LastChargeTime = Level.TimeSeconds; } function Tick( float Delta ) { if( NumChargeAttacks <= 0 ) { GoToState(''); } if( Role == ROLE_Authority && bShotAnim) { if( bChargingPlayer ) { bChargingPlayer = false; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } SetGroundSpeed(OriginalGroundSpeed * 1.25); if( LookTarget!=none ) { Acceleration = AccelRate * Normal(LookTarget.Location - Location); } } else { if( !bChargingPlayer ) { bChargingPlayer = true; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } if( bZapped ) { SetGroundSpeed(OriginalGroundSpeed * 1.5); } else { SetGroundSpeed(OriginalGroundSpeed * 2.5); } } Global.Tick(Delta); } function bool MeleeDamageTarget(int hitdamage, vector pushdir) { local bool RetVal; NumChargeAttacks--; RetVal = Global.MeleeDamageTarget(hitdamage, pushdir*1.5); if( RetVal ) GoToState(''); return RetVal; } function RangedAttack(Actor A) { if( VSize(A.Location-Location)>700 && Level.TimeSeconds - LastForceChargeTime > 3.0 ) GoToState(''); Global.RangedAttack(A); } Begin: Sleep(6); GoToState(''); } function BeginHealing() { MonsterController(Controller).WhatToDoNext(55); } state Healing // Healing { function bool ShouldChargeFromDamage() { return false; } Begin: Sleep(GetAnimDuration('Heal')); GoToState(''); } state KnockDown // Knocked { function bool ShouldChargeFromDamage() { return false; } Begin: if( Health > 0 ) { Sleep(GetAnimDuration('KnockDown')); CloakBoss(); if( KFGameType(Level.Game).FinalSquadNum == SyringeCount ) { KFGameType(Level.Game).AddBossBuddySquad(); } GotoState('Escaping'); } else { GotoState(''); } } State Escaping extends Charging // Got hurt and running away... { function BeginHealing() { bShotAnim = true; Acceleration = vect(0,0,0); SetAnimAction('Heal'); HandleWaitForAnim('Heal'); GoToState('Healing'); } function RangedAttack(Actor A) { if ( bShotAnim ) return; else if ( IsCloseEnuf(A) ) { if( bCloaked ) UnCloakBoss(); bShotAnim = true; Acceleration = vect(0,0,0); Acceleration = (A.Location-Location); SetAnimAction('MeleeClaw'); PlaySound(sound'Claw2s', SLOT_None); } } function bool MeleeDamageTarget(int hitdamage, vector pushdir) { return Global.MeleeDamageTarget(hitdamage, pushdir*1.5); } function Tick( float Delta ) { if( Role == ROLE_Authority && bShotAnim) { if( bChargingPlayer ) { bChargingPlayer = false; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } SetGroundSpeed(GetOriginalGroundSpeed()); } else { if( !bChargingPlayer ) { bChargingPlayer = true; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } if( bZapped ) { SetGroundSpeed(OriginalGroundSpeed * 1.5); } else { SetGroundSpeed(OriginalGroundSpeed * 2.5); } } Global.Tick(Delta); } function EndState() { SetGroundSpeed(GetOriginalGroundSpeed()); bChargingPlayer = false; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); if( bCloaked ) UnCloakBoss(); } Begin: While( true ) { Sleep(0.5); if( !bCloaked && !bShotAnim ) CloakBoss(); if( !Controller.IsInState('SyrRetreat') && !Controller.IsInState('WaitForAnim')) Controller.GoToState('SyrRetreat'); } } State SneakAround extends Escaping // Attempt to sneak around. { function BeginHealing() { MonsterController(Controller).WhatToDoNext(56); GoToState(''); } function bool MeleeDamageTarget(int hitdamage, vector pushdir) { local bool RetVal; RetVal = super.MeleeDamageTarget(hitdamage, pushdir); GoToState(''); return RetVal; } function BeginState() { super.BeginState(); SneakStartTime = Level.TimeSeconds; } function EndState() { super.EndState(); LastSneakedTime = Level.TimeSeconds; } Begin: CloakBoss(); While( true ) { Sleep(0.5); if( Level.TimeSeconds - SneakStartTime > 10.0 ) { GoToState(''); } if( !bCloaked && !bShotAnim ) CloakBoss(); if( !Controller.IsInState('ZombieHunt') && !Controller.IsInState('WaitForAnim') ) { Controller.GoToState('ZombieHunt'); } } } State InitialSneak extends SneakAround // Sneak attack the players straight off the bat. { Begin: CloakBoss(); While( true ) { Sleep(0.5); SneakCount++; if( SneakCount > 1000 || (Controller != none && ControllerBossOS(Controller).bAlreadyFoundEnemy) ) //BossZombieController to ControllerBossOS { GoToState(''); } if( !bCloaked && !bShotAnim ) CloakBoss(); if( !Controller.IsInState('InitialHunting') && !Controller.IsInState('WaitForAnim') ) { Controller.GoToState('InitialHunting'); } } } simulated function DropNeedle() { if( CurrentNeedle!=none ) { DetachFromBone(CurrentNeedle); CurrentNeedle.SetLocation(GetBoneCoords('Bip01 R Finger0').Origin); CurrentNeedle.DroppedNow(); CurrentNeedle = none; } } simulated function NotifySyringeA() { if( Level.NetMode!=NM_Client ) { if( SyringeCount<3 ) SyringeCount++; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } if( Level.NetMode!=NM_DedicatedServer ) { DropNeedle(); CurrentNeedle = Spawn(class'BossHPNeedle'); AttachToBone(CurrentNeedle,'Bip01 R Finger0'); } } function NotifySyringeB() { if( Level.NetMode != NM_Client ) { Health += HealingAmount; bHealed = true; } } simulated function NotifySyringeC() { if( Level.NetMode!=NM_DedicatedServer && CurrentNeedle!=none ) { CurrentNeedle.Velocity = vect(-45,300,-90) >> Rotation; DropNeedle(); } } simulated function PostNetReceive() { if( bClientMiniGunning != bMinigunning ) { bClientMiniGunning = bMinigunning; if( bMinigunning ) { IdleHeavyAnim='FireMG'; IdleRifleAnim='FireMG'; IdleCrouchAnim='FireMG'; IdleWeaponAnim='FireMG'; IdleRestAnim='FireMG'; } else { IdleHeavyAnim='BossIdle'; IdleRifleAnim='BossIdle'; IdleCrouchAnim='BossIdle'; IdleWeaponAnim='BossIdle'; IdleRestAnim='BossIdle'; } } if( bClientCharg!=bChargingPlayer ) { bClientCharg = bChargingPlayer; if (bChargingPlayer) { MovementAnims[0] = ChargingAnim; MovementAnims[1] = ChargingAnim; MovementAnims[2] = ChargingAnim; MovementAnims[3] = ChargingAnim; } else if( !bChargingPlayer ) { MovementAnims[0] = default.MovementAnims[0]; MovementAnims[1] = default.MovementAnims[1]; MovementAnims[2] = default.MovementAnims[2]; MovementAnims[3] = default.MovementAnims[3]; } } else if( ClientSyrCount!=SyringeCount ) { ClientSyrCount = SyringeCount; Switch( SyringeCount ) { Case 1: SetBoneScale(3,0,'SyringeBoneOne'); Break; Case 2: SetBoneScale(3,0,'SyringeBoneOne'); SetBoneScale(4,0,'SyringeBoneTwo'); Break; Case 3: SetBoneScale(3,0,'SyringeBoneOne'); SetBoneScale(4,0,'SyringeBoneTwo'); SetBoneScale(5,0,'SyringeBoneThree'); Break; default: SetBoneScale(3,1,'SyringeBoneOne'); SetBoneScale(4,1,'SyringeBoneTwo'); SetBoneScale(5,1,'SyringeBoneThree'); Break; } } else if( TraceHitPos!=vect(0,0,0) ) { AddTraceHitFX(TraceHitPos); TraceHitPos = vect(0,0,0); } else if( bClientCloaked!=bCloaked ) { bClientCloaked = bCloaked; bCloaked = !bCloaked; if( bCloaked ) UnCloakBoss(); else CloakBoss(); bCloaked = bClientCloaked; } } simulated function int DoAnimAction( name AnimName ) { if(AnimName=='MeleeImpale' || AnimName=='MeleeClaw' || AnimName=='BossHitF') { AnimBlendParams(1, 1.0, 0.0,, 'Bip01 Spine1'); PlayAnim(AnimName,, 0.0, 1); return 1; } return super.DoAnimAction(AnimName); } simulated event SetAnimAction(name NewAction) { local int meleeAnimIndex; if( NewAction=='' ) return; if(NewAction == 'Claw') { meleeAnimIndex = Rand(3); NewAction = meleeAnims[meleeAnimIndex]; CurrentDamtype = ZombieDamType[meleeAnimIndex]; } ExpectingChannel = DoAnimAction(NewAction); if( Controller != none ) { ControllerBossOS(Controller).AnimWaitChannel = ExpectingChannel; } if( AnimNeedsWait(NewAction) ) { bWaitForAnim = true; } else { bWaitForAnim = false; } if( Level.NetMode!=NM_Client ) { AnimAction = NewAction; bResetAnimAct = true; ResetAnimActTime = Level.TimeSeconds+0.3; } } simulated function HandleWaitForAnim( name NewAnim ) { local float RageAnimDur; Controller.GoToState('WaitForAnim'); RageAnimDur = GetAnimDuration(NewAnim); ControllerBossOS(Controller).SetWaitForAnimTimout(RageAnimDur,NewAnim); //BossZombieController to ControllerBossOS } simulated function bool AnimNeedsWait(name TestAnim) { if(TestAnim == 'FireMG' ||TestAnim == 'PreFireMG' || TestAnim == 'FireEndMG' || TestAnim == 'Heal' || TestAnim == 'KnockDown' || TestAnim == 'Entrance' || TestAnim == 'VictoryLaugh' ) { return true; } return false; } simulated function HandleBumpGlass() { } function bool FlipOver() { return false; } function bool ShouldChargeFromDamage() { if( (SyringeCount==0 && Health (5.0 + 5.0 * FRand()) ) { return true; } return false; } function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class damageType, optional int HitIndex) { local float DamagerDistSq; local float UsedPipeBombDamScale; if ( class(damageType) == none && class(damageType) == none ) { bOnlyDamagedByCrossbow = false; } if ( class(damageType) != none ) { UsedPipeBombDamScale = FMax(0,(1.0 - PipeBombDamageScale)); PipeBombDamageScale += 0.075; if( PipeBombDamageScale > 1.0 ) { PipeBombDamageScale = 1.0; } Damage *= UsedPipeBombDamScale; } super.TakeDamage(Damage,instigatedBy,hitlocation,Momentum,damageType); if( Level.TimeSeconds - LastDamageTime > 10 ) { ChargeDamage = 0; } else { LastDamageTime = Level.TimeSeconds; ChargeDamage += Damage; } if( ShouldChargeFromDamage() && ChargeDamage > 200 ) { if( InstigatedBy != none ) { DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location); if( DamagerDistSq < (700 * 700) ) { SetAnimAction('BossHitF'); ChargeDamage=0; LastForceChargeTime = Level.TimeSeconds; GoToState('Charging'); return; } } } if( Health<=0 || SyringeCount==3 || IsInState('Escaping') || IsInState('KnockDown')) return; if( ((SyringeCount==0 && Health damageType, vector Momentum, optional int HitIndex) { if(LastChainGunTime> Rotation); return true; } function Died(Controller Killer, class damageType, vector HitLocation) { local Controller C; super.Died(Killer,damageType,HitLocation); KFGameType(Level.Game).DoBossDeath(); For( C=Level.ControllerList; C!=none; C=C.NextController ) { if( PlayerController(C)!=none ) { PlayerController(C).SetViewTarget(self); PlayerController(C).ClientSetViewTarget(self); PlayerController(C).bBehindView = true; PlayerController(C).ClientSetBehindView(true); } } } function ClawDamageTarget() { local vector PushDir; local name Anim; local float frame,rate; local float UsedMeleeDamage; local bool bDamagedSomeone; local KFHumanPawn P; local Actor OldTarget; if( MeleeDamage > 1 ) { UsedMeleeDamage = (MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1)); } else { UsedMeleeDamage = MeleeDamage; } GetAnimParams(1, Anim,frame,rate); if( Anim == 'MeleeImpale' ) { MeleeRange = ImpaleMeleeDamageRange; } else { MeleeRange = ClawMeleeDamageRange; } if(Controller!=none && Controller.Target!=none) PushDir = (damageForce * Normal(Controller.Target.Location - Location)); else PushDir = damageForce * vector(Rotation); if( Anim == 'MeleeImpale' ) { bDamagedSomeone = MeleeDamageTarget(UsedMeleeDamage, PushDir); } else { OldTarget = Controller.Target; foreach DynamicActors(class'KFHumanPawn', P) { if ( (P.Location - Location) dot PushDir > 0.0 ) { Controller.Target = P; bDamagedSomeone = bDamagedSomeone || MeleeDamageTarget(UsedMeleeDamage, damageForce * Normal(P.Location - Location)); } } Controller.Target = OldTarget; } MeleeRange = default.MeleeRange; } static simulated function PreCacheMaterials(LevelInfo myLevel) { myLevel.AddPrecacheMaterial(FinalBlend'KFPatch2.BossHairFB'); myLevel.AddPrecacheMaterial(FinalBlend'KFOldSchoolZeds_Textures.Patriarch.BossCloakFizzleFB'); myLevel.AddPrecacheMaterial(Finalblend'KFOldSchoolZeds_Textures.Patriarch.BossGlowFB'); myLevel.AddPrecacheMaterial(Texture'KFPatch2.BossBits'); myLevel.AddPrecacheMaterial(Texture'KFPatch2.GunPoundSkin'); myLevel.AddPrecacheMaterial(Texture'KFPatch2.BossGun'); myLevel.AddPrecacheMaterial(Texture'KillingFloorLabTextures.LabCommon.voidtex'); myLevel.AddPrecacheMaterial(Shader'KFPatch2.LaserShader'); myLevel.AddPrecacheMaterial(Shader'KFOldSchoolZeds_Textures.BossCloakShader'); } defaultproperties { ChargingAnim="RunF" HealingLevels(0)=5600 HealingLevels(1)=3500 HealingLevels(2)=2187 HealingAmount=1750 MGDamage=6.000000 ClawMeleeDamageRange=85.000000 ImpaleMeleeDamageRange=45.000000 MoanVoice=SoundGroup'KFOldSchoolZeds_Sounds.Patriarch.Patriarch_Speech' ZapThreshold=5.000000 ZappedDamageMod=1.250000 ZapResistanceScale=1.000000 bHarpoonToHeadStuns=False bHarpoonToBodyStuns=False DamageToMonsterScale=5.000000 ZombieFlag=3 MeleeDamage=100 damageForce=170000 bFatAss=True KFRagdollName="FleshPoundRag" JumpSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieJump' bMeleeStunImmune=True CrispUpThreshhold=1 bCanDistanceAttackDoors=True bUseExtendedCollision=True ColOffset=(Z=65.000000) ColRadius=27.000000 ColHeight=25.000000 PlayerCountHealthScale=0.750000 BurningWalkFAnims(0)="WalkF" BurningWalkFAnims(1)="WalkF" BurningWalkFAnims(2)="WalkF" BurningWalkAnims(0)="WalkF" BurningWalkAnims(1)="WalkF" BurningWalkAnims(2)="WalkF" OnlineHeadshotOffset=(X=2.000000,Y=-6.000000,Z=74.000000) OnlineHeadshotScale=1.100000 MotionDetectorThreat=10.000000 bBoss=True HitSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Patriarch.Patriarch_Pain' DeathSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombieDeath' ScoringValue=500 IdleHeavyAnim="BossIdle" IdleRifleAnim="BossIdle" RagDeathVel=80.000000 RagDeathUpKick=100.000000 MeleeRange=10.000000 GroundSpeed=120.000000 WaterSpeed=120.000000 HealthMax=4000.000000 Health=4000 HeadRadius=8.200000 HeadHeight=8.500000 MenuName="Patriarch 2.5" ControllerClass=Class'KFOldSchoolZeds.ControllerBossOS' MovementAnims(0)="WalkF" MovementAnims(1)="WalkF" MovementAnims(2)="WalkF" MovementAnims(3)="WalkF" TurnLeftAnim="BossHitF" TurnRightAnim="BossHitF" AirAnims(0)="JumpInAir" AirAnims(1)="JumpInAir" AirAnims(2)="JumpInAir" AirAnims(3)="JumpInAir" TakeoffAnims(0)="JumpTakeOff" TakeoffAnims(1)="JumpTakeOff" TakeoffAnims(2)="JumpTakeOff" TakeoffAnims(3)="JumpTakeOff" LandAnims(0)="JumpLanded" LandAnims(1)="JumpLanded" LandAnims(2)="JumpLanded" LandAnims(3)="JumpLanded" AirStillAnim="JumpInAir" TakeoffStillAnim="JumpTakeOff" IdleCrouchAnim="BossIdle" IdleWeaponAnim="BossIdle" IdleRestAnim="BossIdle" AmbientSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieBreath' Mesh=SkeletalMesh'KFBossOld.Boss' PrePivot=(Z=3.000000) Skins(0)=FinalBlend'KFPatch2.BossHairFB' Skins(1)=Texture'KFPatch2.BossBits' Skins(2)=Texture'KFPatch2.GunPoundSkin' Skins(3)=Texture'KFPatch2.BossGun' Skins(4)=Texture'KFPatch2.BossBits' Skins(5)=Texture'KFPatch2.BossBits' Skins(6)=Shader'KFPatch2.LaserShader' bNetNotify=False Mass=1000.000000 RotationRate=(Yaw=36000,Roll=0) }