1
0
KF2-Dev-Scripts/GameFramework/Classes/GameCrowdBehavior_PlayAnimation.uc
2020-12-13 18:01:13 +03:00

224 lines
5.3 KiB
Ucode

/**
*
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
class GameCrowdBehavior_PlayAnimation extends GameCrowdAgentBehavior
native
placeable
dependsOn(GameCrowdAgent);
/** List of animations to play */
var() Array<name> AnimationList;
/** Time to blend into next animation. */
var() float BlendInTime;
/** Time to blend out of animation. */
var() float BlendOutTime;
/** Whether to use root motion. */
var() bool bUseRootMotion;
/** If true, face player before starting animation. */
var() bool bLookAtPlayer;
/** Used by kismet PlayAgentAnimation */
var Actor CustomActionTarget;
/** If true, loop the animation in the list specified by LoopIndex. */
var() bool bLooping;
/** Which animation to loop in AnimationList if bLooping == TRUE */
var() int LoopIndex;
/** How long to loop the animation if bLooping == TRUE, -1.f == infinite */
var() float LoopTime;
/** Whether should blend between animations in the list. Set True if they don't match at start/end */
var() bool bBlendBetweenAnims;
/** Kismet AnimSequence that spawned this behavior (optional) */
var SeqAct_PlayAgentAnimation AnimSequence;
/** Index into animationlist of current animation action */
var int AnimationIndex;
function InitBehavior(GameCrowdAgent Agent)
{
local PlayerController PC, ClosestPC;
local float ClosestDist, NewDist;
local GameCrowdAgentSkeletal SkAgent;
Super.InitBehavior(Agent);
if ( CustomActionTarget != None )
{
ActionTarget = CustomActionTarget;
}
else if ( bLookAtPlayer )
{
ClosestDist = 1000000.0;
// find local player, make it the action target
foreach Agent.LocalPlayerControllers(class'PlayerController', PC)
{
if ( PC.Pawn != None )
{
NewDist = VSize(PC.Pawn.Location - Agent.Location);
if ( NewDist < ClosestDist )
{
ClosestDist = NewDist;
ClosestPC = PC;
}
}
}
if ( ClosestPC != None )
{
ActionTarget = ClosestPC.Pawn;
}
}
SkAgent = GameCrowdAgentSkeletal(Agent);
if ( SKAgent == None )
{
`warn("PlayAnimation behavior "$self$" called on non-skeletal agent "$Agent);
return;
}
AnimationIndex = 0;
if ( !bFaceActionTargetFirst )
{
PlayAgentAnimationNow();
}
}
/**
* Facing target, so play animation
*/
event FinishedTargetRotation()
{
PlayAgentAnimationNow();
}
/**
* Set the "Out Agent" output of the current sequence to be MyAgent.
*/
native function SetSequenceOutput();
/**
* When an animation ends, play the next animation in the list.
* If done with list, if associated with a sequence, trigger its output.
*/
event OnAnimEnd(AnimNodeSequence SeqNode, float PlayedTime, float ExcessTime)
{
// called because we asked for early notify
AnimationIndex++;
if ( AnimationList.Length > AnimationIndex )
{
PlayAgentAnimationNow();
}
else
{
// see if there is another sequence attached to this one
if ( (AnimSequence != None) && (AnimSequence.OutputLinks[0].Links.Length > 0) )
{
SetSequenceOutput();
MyAgent.ClearLatentAction(class'SeqAct_PlayAgentAnimation', false);
AnimSequence.ActivateOutputLink(0);
}
MyAgent.StopBehavior();
}
}
/**
* Play the requested animation
*/
function PlayAgentAnimationNow()
{
local float CurrentBlendInTime, CurrentBlendOutTime;
local GameCrowdAgentSkeletal MySkAgent;
MySkAgent = GameCrowdAgentSkeletal(MyAgent);
bFaceActionTargetFirst = false;
MySkAgent.SetRootMotion(bUseRootMotion);
CurrentBlendInTime = 0.0;
CurrentBlendOutTime = 0.0;
// loop if bLooping set AND marked for looping
if ( bLooping && AnimationIndex == LoopIndex )
{
if ( bBlendBetweenAnims || (AnimationIndex == 0) )
{
CurrentBlendInTime = BlendInTime;
}
MySkAgent.FullBodySlot.PlayCustomAnim(AnimationList[AnimationIndex], 1.f, CurrentBlendInTime, CurrentBlendOutTime, bLooping, true);
if ( LoopTime > 0.0 )
{
MySkAgent.SetTimer(LoopTime,FALSE,nameof(OnAnimEnd));
}
}
else
{
if ( bBlendBetweenAnims )
{
CurrentBlendInTime = BlendInTime;
CurrentBlendOutTime = BlendOutTime;
}
else if ( AnimationIndex == 0 )
{
CurrentBlendInTime = BlendInTime;
}
MySkAgent.FullBodySlot.PlayCustomAnim(AnimationList[AnimationIndex], 1.f, CurrentBlendInTime, CurrentBlendOutTime, false, true);
MySkAgent.FullBodySlot.SetActorAnimEndNotification(true);
}
if ( AnimSequence != None )
{
AnimSequence.ActivateOutputLink(2);
}
}
function StopBehavior()
{
GameCrowdAgentSkeletal(MyAgent).FullBodySlot.StopCustomAnim(BlendOutTime);
GameCrowdAgentSkeletal(MyAgent).SetRootMotion(FALSE);
super.StopBehavior();
}
/**
* Get debug string about agent behavior
*/
function string GetBehaviorString()
{
local string BehaviorString;
BehaviorString = "Behavior: "$self;
if ( bFaceActionTargetFirst )
{
BehaviorString = BehaviorString@"Turning toward "$ActionTarget;
}
else if ( (AnimationList.length <= AnimationIndex) || (AnimationList[AnimationIndex] == '') )
{
BehaviorString = BehaviorString@"MISSING ANIMATION";
}
else
{
BehaviorString = BehaviorString@"Playing "$AnimationList[AnimationIndex];
}
return BehaviorString;
}
defaultproperties
{
bIdleBehavior=true
AnimationIndex=0
BlendInTime=0.2
BlendOutTime=0.2
bBlendBetweenAnims=false
LoopTime=-1.f
}