KF2-Server-Extension/ServerExt/Classes/Ext_AICommandBasePet.uc

155 lines
3.9 KiB
Ucode
Raw Normal View History

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