237 lines
14 KiB
Plaintext
237 lines
14 KiB
Plaintext
#using scripts\shared\ai\systems\animation_selector_table;
|
|
#using scripts\shared\array_shared;
|
|
|
|
|
|
|
|
|
|
|
|
function autoexec RegisterASTScriptFunctions()
|
|
{
|
|
AnimationSelectorTable::RegisterAnimationSelectorTableEvaluator("testFunction",&testFunction);;
|
|
|
|
// ------- EVALUATOR BLOCKED BY GEO ANIMATIONS -----------//
|
|
AnimationSelectorTable::RegisterAnimationSelectorTableEvaluator("evaluateBlockedAnimations",&evaluateBlockedAnimations);;
|
|
|
|
// ------- EVALUATOR HUMAN LOCOMOTION TURNS -----------//
|
|
AnimationSelectorTable::RegisterAnimationSelectorTableEvaluator("evaluateHumanTurnAnimations",&evaluateHumanTurnAnimations);;
|
|
|
|
// ------- EVALUATOR HUMAN EXPOSED ARRIVALS -----------//
|
|
AnimationSelectorTable::RegisterAnimationSelectorTableEvaluator("evaluateHumanExposedArrivalAnimations",&evaluateHumanExposedArrivalAnimations);;
|
|
}
|
|
|
|
function testFunction( entity, animations )
|
|
{
|
|
if ( IsArray( animations ) && animations.size > 0 )
|
|
{
|
|
return animations[0];
|
|
}
|
|
}
|
|
|
|
function private Evaluator_CheckAnimationAgainstGeo( entity, animation )
|
|
{
|
|
PixBeginEvent( "Evaluator_CheckAnimationAgainstGeo" );
|
|
|
|
assert( IsActor( entity ) );
|
|
|
|
// Since this check is mostly used for turn animations, a better approximation
|
|
// of movement is to use the midpoint position of the animation and the end
|
|
// point of the animation.
|
|
localDeltaHalfVector = GetMoveDelta( animation, 0, 0.5, entity );
|
|
midPoint = entity LocalToWorldCoords( localDeltaHalfVector );
|
|
// ignore any Z translation.
|
|
midPoint = ( midPoint[0], midPoint[1], entity.origin[2] );
|
|
|
|
/#
|
|
RecordLine( entity.origin, midPoint, ( 1, .5, 0 ), "Animscript", entity );
|
|
#/
|
|
|
|
if( entity MayMoveToPoint( midPoint, true, true ) )
|
|
{
|
|
localDeltaVector = GetMoveDelta( animation, 0, 1, entity );
|
|
endPoint = entity LocalToWorldCoords( localDeltaVector );
|
|
endPoint = ( endPoint[0], endPoint[1], entity.origin[2] );
|
|
|
|
/#
|
|
RecordLine( midPoint, endPoint, ( 1, .5, 0 ), "Animscript", entity );
|
|
#/
|
|
|
|
if ( entity MayMoveFromPointToPoint( midPoint, endPoint, true, true ) )
|
|
{
|
|
PixEndEvent();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
PixEndEvent();
|
|
return false;
|
|
}
|
|
|
|
function private Evaluator_CheckAnimationEndPointAgainstGeo( entity, animation )
|
|
{
|
|
PixBeginEvent( "Evaluator_CheckAnimationEndPointAgainstGeo" );
|
|
|
|
assert( IsActor( entity ) );
|
|
|
|
localDeltaVector = GetMoveDelta( animation, 0, 1, entity );
|
|
endPoint = entity LocalToWorldCoords( localDeltaVector );
|
|
endPoint = ( endPoint[0], endPoint[1], entity.origin[2] );
|
|
|
|
if( entity MayMoveToPoint( endPoint, false, false ) )
|
|
{
|
|
PixEndEvent();
|
|
return true;
|
|
}
|
|
|
|
PixEndEvent();
|
|
return false;
|
|
}
|
|
|
|
function private Evaluator_CheckAnimationForOverShootingGoal( entity, animation )
|
|
{
|
|
PixBeginEvent( "Evaluator_CheckAnimationForOverShootingGoal" );
|
|
|
|
assert( IsActor( entity ) );
|
|
|
|
localDeltaVector = GetMoveDelta( animation, 0, 1, entity );
|
|
endPoint = entity LocalToWorldCoords( localDeltaVector );
|
|
animDistSq = LengthSquared( localDeltaVector );
|
|
|
|
if( entity HasPath() )
|
|
{
|
|
startPos = entity.origin;
|
|
goalPos = entity.pathGoalPos;
|
|
|
|
assert( IsDefined( goalPos ) );
|
|
distToGoalSq = DistanceSquared( startPos, goalPos );
|
|
|
|
// goal is straight in front of the AI, just make sure that the endpoint is not beyond the goal position
|
|
if( animDistSq < distToGoalSq )
|
|
{
|
|
PixEndEvent();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
PixEndEvent();
|
|
return false;
|
|
}
|
|
|
|
function private Evaluator_CheckAnimationAgainstNavmesh( entity, animation )
|
|
{
|
|
assert( IsActor( entity ) );
|
|
|
|
localDeltaVector = GetMoveDelta( animation, 0, 1, entity );
|
|
endPoint = entity LocalToWorldCoords( localDeltaVector );
|
|
|
|
// make sure that the point is on the navmesh and away from boundary
|
|
if( IsPointOnNavMesh( endPoint, entity ) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
function private Evaluator_CheckAnimationArrivalPosition( entity, animation )
|
|
{
|
|
localDeltaVector = GetMoveDelta( animation, 0, 1, entity );
|
|
endPoint = entity LocalToWorldCoords( localDeltaVector );
|
|
animDistSq = LengthSquared( localDeltaVector );
|
|
|
|
startPos = entity.origin;
|
|
goalPos = entity.pathGoalPos;
|
|
|
|
distToGoalSq = DistanceSquared( startPos, goalPos );
|
|
|
|
return distToGoalSq < animDistSq && entity IsPosAtGoal( endPoint );
|
|
}
|
|
|
|
function private Evaluator_FindFirstValidAnimation( entity, animations, tests )
|
|
{
|
|
assert( IsArray( animations ), "An array of animations must be passed in to validate against." );
|
|
assert( IsArray( tests ), "An array of test functions must be passed in to validate an animation." );
|
|
|
|
// Only check the first animation within the group of animations, since each animation is synonymous with each other.
|
|
foreach ( aliasAnimations in animations )
|
|
{
|
|
if ( aliasAnimations.size > 0 )
|
|
{
|
|
valid = true;
|
|
animation = aliasAnimations[0];
|
|
|
|
foreach ( test in tests )
|
|
{
|
|
if ( ![[test]]( entity, animation ) )
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( valid )
|
|
{
|
|
return animation;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------- EVALUATOR BLOCKED BY GEO ANIMATIONS -----------//
|
|
function private evaluateBlockedAnimations( entity, animations )
|
|
{
|
|
if( animations.size > 0 )
|
|
{
|
|
return Evaluator_FindFirstValidAnimation(
|
|
entity,
|
|
animations,
|
|
array(
|
|
&Evaluator_CheckAnimationAgainstGeo,
|
|
&Evaluator_CheckAnimationForOverShootingGoal ) );
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
function private evaluateHumanTurnAnimations( entity, animations )
|
|
{
|
|
/#
|
|
// SUMEET - Added this check just for testing.
|
|
if( ( isdefined( level.ai_dontTurn ) && level.ai_dontTurn ) )
|
|
return undefined;
|
|
#/
|
|
|
|
/#
|
|
Record3DText( "" + GetTime() + ": Turn Evaluator", entity.origin, ( 1, .5, 0 ), "Animscript", entity );
|
|
#/
|
|
|
|
if( animations.size > 0 )
|
|
{
|
|
return Evaluator_FindFirstValidAnimation(
|
|
entity,
|
|
animations,
|
|
array(
|
|
&Evaluator_CheckAnimationForOverShootingGoal,
|
|
&Evaluator_CheckAnimationAgainstGeo,
|
|
&Evaluator_CheckAnimationAgainstNavmesh ) );
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
|
|
function private evaluateHumanExposedArrivalAnimations( entity, animations )
|
|
{
|
|
if( !IsDefined( entity.pathGoalPos ) )
|
|
return undefined;
|
|
|
|
if( animations.size > 0 )
|
|
{
|
|
return Evaluator_FindFirstValidAnimation(
|
|
entity,
|
|
animations,
|
|
array( &Evaluator_CheckAnimationArrivalPosition ) );
|
|
}
|
|
|
|
return undefined;
|
|
}
|