155 lines
4.0 KiB
Ucode
155 lines
4.0 KiB
Ucode
class Ext_AICommandBasePet extends AICommand_Base_Zed;
|
|
|
|
var transient Pawn OwnerPawn;
|
|
var transient float NextSightCheckTime;
|
|
|
|
final function vector PickPointNearOwner()
|
|
{
|
|
local byte i;
|
|
local vector V,HL,HN,Start;
|
|
|
|
Start = OwnerPawn.Location;
|
|
if( OwnerPawn.Physics==PHYS_Falling )
|
|
{
|
|
if( Pawn.Trace(HL,HN,OwnerPawn.Location-vect(0,0,5000),OwnerPawn.Location,false,vect(20,20,60))!=None )
|
|
Start = HL;
|
|
}
|
|
while( true )
|
|
{
|
|
++i;
|
|
V.X = FRand()-0.5;
|
|
V.Y = FRand()-0.5;
|
|
V = Start + Normal2D(V) * (100.f+FRand()*500.f);
|
|
|
|
if( i<20 && !FastTrace(V,Start) ) // Destination is inside a wall.
|
|
continue;
|
|
|
|
if( i<20 && FastTrace(V-vect(0,0,100),V) ) // Destination is above a pit.
|
|
continue;
|
|
break;
|
|
}
|
|
OwnerPawn = None;
|
|
return V;
|
|
}
|
|
final function bool CanSeeOwner()
|
|
{
|
|
local Pawn P;
|
|
|
|
NextSightCheckTime = WorldInfo.TimeSeconds+1.f + FRand();
|
|
P = Ext_T_MonsterPRI(PlayerReplicationInfo)!=None ? Ext_T_MonsterPRI(PlayerReplicationInfo).OwnerController.Pawn : None;
|
|
if( P!=None && !LineOfSightTo(P) )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
state ZedBaseCommand
|
|
{
|
|
Begin:
|
|
if( Pawn.Physics == PHYS_Falling )
|
|
{
|
|
DisableMeleeRangeEventProbing();
|
|
WaitForLanding();
|
|
}
|
|
EnableMeleeRangeEventProbing();
|
|
// Check for any interrupt transitions
|
|
CheckInterruptCombatTransitions();
|
|
|
|
// Select nearest enemy if current enemy is invalid
|
|
if( Enemy == none || Enemy.Health <= 0 || !IsValidAttackTarget(KFPawn(Enemy)) )
|
|
SelectEnemy();
|
|
|
|
// Handle special case if I'm supposed to be attacking a door
|
|
if( DoorEnemy != none && DoorEnemy.Health > 0 && VSizeSq( DoorEnemy.Location - Pawn.Location ) < (DoorMeleeDistance * DoorMeleeDistance) ) //200UU
|
|
{
|
|
`AILog( self$" DoorEnemy: "$DoorEnemy$" starting melee attack", 'Command_Base' );
|
|
UpdateHistoryString( "[Attacking : "$DoorEnemy$" at "$WorldInfo.TimeSeconds$"]" );
|
|
class'AICommand_Attack_Melee'.static.Melee( Outer, DoorEnemy );
|
|
}
|
|
|
|
// See if we are close to our owner
|
|
RecheckOwner:
|
|
OwnerPawn = Ext_T_MonsterPRI(PlayerReplicationInfo)!=None ? Ext_T_MonsterPRI(PlayerReplicationInfo).OwnerController.Pawn : None;
|
|
if( OwnerPawn!=None )
|
|
{
|
|
if( Enemy!=None && LineOfSightTo(OwnerPawn) && LineOfSightTo(Enemy) ) // We have sight to our owner and can see enemy, go for it!
|
|
{
|
|
OwnerPawn = None;
|
|
|
|
bWaitingOnMovementPlugIn = true;
|
|
SetEnemyMoveGoal(self, true,,, ShouldAttackWhileMoving() );
|
|
NextSightCheckTime = WorldInfo.TimeSeconds+2.f;
|
|
while( bWaitingOnMovementPlugIn && bUsePluginsForMovement )
|
|
{
|
|
if( NextSightCheckTime<WorldInfo.TimeSeconds && !CanSeeOwner() )
|
|
{
|
|
ClearMovementInfo();
|
|
GoTo'RecheckOwner';
|
|
}
|
|
Sleep(0.03);
|
|
}
|
|
}
|
|
else if( VSizeSq(OwnerPawn.Location-Pawn.Location)>640000.f || !LineOfSightTo(OwnerPawn) ) // 800.f - Need to move closer to our owner.
|
|
{
|
|
bWaitingOnMovementPlugIn = true;
|
|
SetMovePoint(PickPointNearOwner(),OwnerPawn,,300.f);
|
|
|
|
while( bWaitingOnMovementPlugIn && bUsePluginsForMovement )
|
|
{
|
|
Sleep(0.03);
|
|
}
|
|
}
|
|
else // Standing next to our owner.
|
|
{
|
|
OwnerPawn = None;
|
|
Sleep(0.2+FRand()*0.5);
|
|
}
|
|
}
|
|
else if( IsValidAttackTarget(KFPawn(Enemy)) )
|
|
{
|
|
`AILog( "Calling SetEnemyMoveGoal [Dist:"$VSize(Enemy.Location - Pawn.Location)$"] using offset of "$AttackRange$", because IsWithinBasicMeleeRange() returned false ", 'Command_Base' );
|
|
bWaitingOnMovementPlugIn = true;
|
|
SetEnemyMoveGoal(self, true,,, ShouldAttackWhileMoving() );
|
|
|
|
while( bWaitingOnMovementPlugIn && bUsePluginsForMovement )
|
|
{
|
|
Sleep(0.03);
|
|
}
|
|
`AiLog("Back from waiting for the movement plug in!!!");
|
|
|
|
if( Enemy == none )
|
|
{
|
|
Sleep( FRand() + 0.1f );
|
|
Goto( 'Begin' );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
`AILog("Enemy is invalid melee target" @ Enemy, 'Command_Base');
|
|
bFailedToMoveToEnemy = true;
|
|
}
|
|
|
|
// Check combat transitions
|
|
CheckCombatTransition();
|
|
if( bFailedToMoveToEnemy )
|
|
{
|
|
if( bFailedPathfind )
|
|
{
|
|
bFailedPathfind = false;
|
|
Sleep( 0.f );
|
|
}
|
|
else
|
|
{
|
|
Sleep( 0.f );
|
|
}
|
|
SetEnemy( GetClosestEnemy( Enemy ) );
|
|
}
|
|
else
|
|
{
|
|
Sleep(0.f);
|
|
}
|
|
Goto('Begin');
|
|
}
|
|
|
|
DefaultProperties
|
|
{
|
|
} |