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

161 lines
3.3 KiB
Ucode

//-----------------------------------------------------------
//
//-----------------------------------------------------------
class HardPatController extends BossZombieController;
var NavigationPoint MidGoals[2];
var byte ReachOffset;
var Actor OldPathsCheck[3];
function Debugf( string S )
{
Level.GetLocalPlayerController().ClientMessage(S);
Log(S);
}
final function FindPathAround()
{
local Actor Res;
local NavigationPoint N;
local NavigationPoint OldPts[12];
local byte i;
local bool bResult;
if( Enemy==None || VSizeSquared(Enemy.Location-Pawn.Location)<360000 )
return; // No can do this.
// Attempt to find an alternative path to enemy.
/* This works by:
- finding shortest path to enemy
- block middle path point
- if the path is still about same to enemy, try block the new path and repeat up to 6 times.
*/
for( i=0; i<ArrayCount(OldPts); ++i )
{
Res = FindPathToward(Enemy);
if( Res==None )
break;
if( i>0 && CompareOldPaths() )
{
bResult = true;
break;
}
N = GetMidPoint();
if( N==None )
break;
N.bBlocked = true;
OldPts[i] = N;
if( i==0 )
SetOldPaths();
}
// Unblock temp blocked paths.
for( i=0; i<ArrayCount(OldPts); ++i )
if( OldPts[i]!=None )
OldPts[i].bBlocked = false;
if( !bResult )
return;
// Fetch results and switch state.
GetMidGoals();
if( ReachOffset<2 )
GoToState('PatFindWay');
}
final function NavigationPoint GetMidPoint()
{
local byte n;
for( n=0; n<ArrayCount(RouteCache); ++n )
if( RouteCache[n]==None )
break;
if( n==0 )
return None;
return NavigationPoint(RouteCache[(n-1)*0.5]);
}
final function bool CompareOldPaths()
{
local byte n,i;
for( i=0; i<6; ++i )
{
if( RouteCache[i]==None )
break;
for( n=0; n<ArrayCount(OldPathsCheck); ++n )
if( RouteCache[i]==OldPathsCheck[n] )
return false;
}
return true;
}
final function SetOldPaths()
{
local byte n;
for( n=0; n<ArrayCount(OldPathsCheck); ++n )
OldPathsCheck[n] = RouteCache[n+1];
if( RouteCache[1]==None )
OldPathsCheck[0] = RouteCache[0];
}
final function GetMidGoals()
{
local byte n;
for( n=0; n<ArrayCount(RouteCache); ++n )
if( RouteCache[n]==None )
break;
if( n==0 )
{
ReachOffset = 2;
return;
}
--n;
MidGoals[0] = NavigationPoint(RouteCache[n*0.5]);
MidGoals[1] = NavigationPoint(RouteCache[n]);
if( MidGoals[0]==MidGoals[1] )
ReachOffset = 1;
else ReachOffset = 0;
}
function bool CanKillMeYet()
{
return false;
}
state PatFindWay
{
Ignores Timer,SeePlayer,HearNoise,DamageAttitudeTo,EnemyChanged,Startle,Tick;
final function PickDestination()
{
if( ReachOffset>=2 )
{
GotoState('ZombieHunt');
return;
}
if( ActorReachable(MidGoals[ReachOffset]) )
{
MoveTarget = MidGoals[ReachOffset];
++ReachOffset;
}
else
{
MoveTarget = FindPathToward(MidGoals[ReachOffset]);
if( MoveTarget==None )
++ReachOffset;
}
}
function BreakUpDoor( KFDoorMover Other, bool bTryDistanceAttack )
{
Global.BreakUpDoor(Other,bTryDistanceAttack);
Pawn.GoToState('');
}
Begin:
PickDestination();
if( MoveTarget==None )
Sleep(0.5f);
else MoveToward(MoveTarget,MoveTarget,,False);
GoTo'Begin';
}
defaultproperties
{
}