//Controller class for Patriarch ✓ class ControllerBossOS extends KFMonsterControllerOS; var NavigationPoint HidingSpots; var float WaitAnimTimeout; var int AnimWaitChannel; var name AnimWaitingFor; var bool bAlreadyFoundEnemy; function bool CanKillMeYet() { return false; } function TimedFireWeaponAtEnemy() { if ( (Enemy == none) || FireWeaponAt(Enemy) ) SetCombatTimer(); else SetTimer(0.01, true); } function FightEnemy(bool bCanCharge) { if( KFM.bShotAnim ) { GoToState('WaitForAnim'); return; } if (KFM.MeleeRange != KFM.default.MeleeRange) KFM.MeleeRange = KFM.default.MeleeRange; if ( Enemy == none || Enemy.Health <= 0 ) FindNewEnemy(); if ( (Enemy == FailedHuntEnemy) && (Level.TimeSeconds == FailedHuntTime) ) { if ( Enemy == FailedHuntEnemy ) { GoalString = "FAILED HUNT - HANG OUT"; if ( EnemyVisible() ) bCanCharge = false; } } if ( !EnemyVisible() ) { if( bAlreadyFoundEnemy || ZombieBossOS(Pawn).SneakCount > 2 ) { bAlreadyFoundEnemy = true; GoalString = "Hunt"; GotoState('ZombieHunt'); } else { ZombieBossOS(Pawn).SneakCount++; GoalString = "InitialHunt"; GotoState('InitialHunting'); } return; } Target = Enemy; GoalString = "Charge"; PathFindState = 2; DoCharge(); } state InitialHunting extends Hunting { event SeePlayer(Pawn SeenPlayer) { super.SeePlayer(SeenPlayer); bAlreadyFoundEnemy = true; GoalString = "Hunt"; GotoState('ZombieHunt'); } function BeginState() { local float ZDif; ZombieBossOS(Pawn).SneakCount++; if( Pawn.CollisionRadius>27 || Pawn.CollisionHeight>46 ) { ZDif = Pawn.CollisionHeight-44; Pawn.SetCollisionSize(24,44); Pawn.MoveSmooth(vect(0,0,-1)*ZDif); } super.BeginState(); } function EndState() { local float ZDif; if( Pawn.CollisionRadius!=Pawn.default.CollisionRadius || Pawn.CollisionHeight!=Pawn.default.CollisionHeight ) { ZDif = Pawn.default.CollisionRadius-44; Pawn.MoveSmooth(vect(0,0,1)*ZDif); Pawn.SetCollisionSize(Pawn.default.CollisionRadius,Pawn.default.CollisionHeight); } super.EndState(); } } state ZombieCharge { function bool StrafeFromDamage(float Damage, class DamageType, bool bFindDest) { return false; } function bool TryStrafe(vector sideDir) { return false; } function Timer() { Disable('NotifyBump'); Target = Enemy; TimedFireWeaponAtEnemy(); } WaitForAnim: if ( Monster(Pawn).bShotAnim ) { Goto('Moving'); } if ( !FindBestPathToward(Enemy, false,true) ) GotoState('ZombieRestFormation'); Moving: MoveToward(Enemy); WhatToDoNext(17); if ( bSoaking ) SoakStop("STUCK IN CHARGING!"); } state RunSomewhere { Ignores HearNoise,DamageAttitudeTo,Tick,EnemyChanged,Startle; function BeginState() { HidingSpots = none; Enemy = none; SetTimer(0.1,true); } event SeePlayer(Pawn SeenPlayer) { SetEnemy(SeenPlayer); } function Timer() { if( Enemy==none ) return; Target = Enemy; KFM.RangedAttack(Target); } Begin: if( Pawn.Physics==PHYS_Falling ) WaitForLanding(); While( KFM.bShotAnim ) Sleep(0.25); if( HidingSpots==none ) HidingSpots = FindRandomDest(); if( HidingSpots==none ) ZombieBossOS(Pawn).BeginHealing(); if( ActorReachable(HidingSpots) ) { MoveTarget = HidingSpots; HidingSpots = none; } else FindBestPathToward(HidingSpots,true,false); if( MoveTarget==none ) ZombieBossOS(Pawn).BeginHealing(); if( Enemy!=none && VSize(Enemy.Location-Pawn.Location)<100 ) MoveToward(MoveTarget,Enemy,,false); else MoveToward(MoveTarget,MoveTarget,,false); if( HidingSpots==none || !PlayerSeesMe() ) ZombieBossOS(Pawn).BeginHealing(); GoTo'Begin'; } State SyrRetreat { Ignores HearNoise,DamageAttitudeTo,Tick,EnemyChanged,Startle; function BeginState() { HidingSpots = none; Enemy = none; SetTimer(0.1,true); } event SeePlayer(Pawn SeenPlayer) { SetEnemy(SeenPlayer); } function Timer() { if( Enemy==none ) return; Target = Enemy; KFM.RangedAttack(Target); } function FindHideSpot() { local NavigationPoint N,BN; local float Dist,BDist,MDist; local vector EnemyDir; if( Enemy==none ) { HidingSpots = FindRandomDest(); return; } EnemyDir = Normal(Enemy.Location-Pawn.Location); For( N=Level.NavigationPointList; N!=none; N=N.NextNavigationPoint ) { MDist = VSize(N.Location-Pawn.Location); if( MDist<2500 && !FastTrace(N.Location,Enemy.Location) && FindPathToward(N)!=none ) { Dist = VSize(N.Location-Enemy.Location)/FMax(MDist/800.f,1.5); if( (EnemyDir Dot Normal(Enemy.Location-N.Location))<0.2 ) Dist/=10; if( BN==none || BDist 0 ) { WaitAnimTimeout -= Delta; if( WaitAnimTimeout <= 0 ) { WaitAnimTimeout = 0; WaitTimeout(); } } if( bUseFreezeHack ) { MoveTarget = none; MoveTimer = -1; Pawn.Acceleration = vect(0,0,0); Pawn.GroundSpeed = 1; Pawn.AccelRate = 0; } } function EndState() { super.EndState(); AnimWaitingFor = ''; } } defaultproperties { }