rott/kf_sources/KFOldSchoolZeds/Classes/ControllerBossOS.uc
2026-07-14 20:27:09 +07:00

346 lines
8.3 KiB
Ucode

//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> 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<Dist )
{
BN = N;
BDist = Dist;
}
}
}
if( BN==none )
HidingSpots = FindRandomDest();
else HidingSpots = BN;
}
Begin:
if( Pawn.Physics==PHYS_Falling )
WaitForLanding();
While( KFM.bShotAnim )
Sleep(0.25);
if( HidingSpots==none )
FindHideSpot();
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 )
ZombieBossOS(Pawn).BeginHealing();
GoTo'Begin';
}
function bool PlayerSeesMe()
{
local Controller C;
For( C=Level.ControllerList; C!=none; C=C.NextController )
{
if( C.bIsPlayer && C.Pawn!=none && C.Pawn!=Pawn && LineOfSightTo(C.Pawn) )
return true;
}
return false;
}
function SetWaitForAnimTimout(float NewWaitAnimTimeout, name AnimToWaitFor)
{
WaitAnimTimeout = NewWaitAnimTimeout;
AnimWaitingFor = AnimToWaitFor;
}
state WaitForAnim
{
Ignores SeePlayer,HearNoise,Timer,EnemyNotVisible,NotifyBump,Startle;
function WaitTimeout()
{
if( bUseFreezeHack )
{
if( Pawn!=none )
{
Pawn.AccelRate = Pawn.default.AccelRate;
Pawn.GroundSpeed = Pawn.default.GroundSpeed;
}
bUseFreezeHack = false;
}
AnimEnd(AnimWaitChannel);
}
event AnimEnd(int Channel)
{
Pawn.AnimEnd(Channel);
if ( !Monster(Pawn).bShotAnim )
WhatToDoNext(99);
}
function Tick( float Delta )
{
Global.Tick(Delta);
if( WaitAnimTimeout > 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
{
}