Ai Notes
For those struggling with their own AI - this might be a useful starting point. Note it delibrately doesn't play back animations. You'll need to do that yourself.
It also relies on a number of other classes - so it is unlikely to compile on your TC. It's more for guidance than copy & paste.
Here's my FFTimmy.uc which extends Pawn
//=============================================================================
// Timmy the dog
//=============================================================================
class FFTimmy extends Pawn
placeable;
#exec OBJ LOAD FILE="..\Animations\Animals.ukx"
#exec OBJ LOAD FILE="..\Textures\TimmySkins.utx"
// PostBeginPlay() is originally defined in Actor().
event PostBeginPlay()
{
local FFTimmyController FFTC;
Log("Spawning FFTimmy");
Super.PostBeginPlay();
if ( ( ControllerClass != None ) && ( Controller == None ) )
{
Controller = spawn( ControllerClass );
Log("Spawning FFTimmyControllerClass");
}
else
{
Log("Controller class already exists");
FFTC = FFTimmyController( Controller );
if ( FFTC !=None )
{
Log("Controller class is already FFTimmy");
}
else
{
Log("Wrong Controller class created");
}
}
if ( Controller != None )
{
Controller.Possess( self );
Log("Possessing FFTimmy");
}
}
defaultproperties
{
// IdleAnim(0)="stand"
// IdleAnim(1)="bark"
// IdleAnim(2)="piss"
// IdleAnim(3)="lay_in"
// IdleAnim(4)="lay_on"
// IdleAnim(5)="lay_out"
// bMeleeFighter=True
// bCanDodge=False
// bCanDodgeDoubleJump=False
// WallDodgeAnims(0)="stand"
// WallDodgeAnims(1)="stand"
// WallDodgeAnims(2)="stand"
// WallDodgeAnims(3)="stand"
// IdleHeavyAnim="Stand"
// IdleRifleAnim="Stand"
bCanJump=False
bCanClimbLadders=False
bCanStrafe=False
bCanDoubleJump=False
bCanUse=False
MeleeRange=250.000000
GroundSpeed=400.000000
WaterSpeed=75.000000
JumpZ=75.000000
ControllerClass=Class'FFTimmyController'
MovementAnims(0)="Run"
MovementAnims(1)="Run"
MovementAnims(2)="Run"
MovementAnims(3)="Run"
TurnLeftAnim="Walk"
TurnRightAnim="Walk"
SwimAnims(0)="Run"
SwimAnims(1)="Run"
SwimAnims(2)="Run"
SwimAnims(3)="Run"
WalkAnims(0)="Walk"
WalkAnims(1)="Walk"
WalkAnims(2)="Walk"
WalkAnims(3)="Walk"
AirAnims(0)="stand"
AirAnims(1)="stand"
AirAnims(2)="stand"
AirAnims(3)="stand"
TakeoffAnims(0)="stand"
TakeoffAnims(1)="stand"
TakeoffAnims(2)="stand"
TakeoffAnims(3)="stand"
LandAnims(0)="stand"
LandAnims(1)="stand"
LandAnims(2)="stand"
LandAnims(3)="stand"
DoubleJumpAnims(0)="stand"
DoubleJumpAnims(1)="stand"
DoubleJumpAnims(2)="stand"
DoubleJumpAnims(3)="stand"
DodgeAnims(0)="stand"
DodgeAnims(1)="stand"
DodgeAnims(2)="stand"
DodgeAnims(3)="stand"
AirStillAnim="stand"
TakeoffStillAnim="stand"
IdleCrouchAnim="Stand"
IdleSwimAnim="Walk"
IdleWeaponAnim="Stand"
IdleRestAnim="Stand"
Mesh=SkeletalMesh'Animals.meshDog'
skins(0)=Texture'TimmySkins.Dog'
PrePivot=(Z=0.000000)
CollisionRadius=34.000000
CollisionHeight=34.000000
Mass=+00150.000000
Buoyancy=+00150.000000
RotationRate=(Pitch=3072,Yaw=60000,Roll=2048)
HeadScale=+1.0
SightRadius=+05000.000000
MaxDesiredSpeed=+00001.000000
AirSpeed=+00440.000000
AccelRate=+02048.000000
DesiredSpeed=+00001.000000
Physics=PHYS_Walking
}
And the corresponding FFTimmyController class which extends AIController
class FFTimmyController extends AIController;
/*SIT
Stays still
Switches into lay animations
FOLLOW
Locates a valid position behind the player
Walks to this location
If Treasure is spotted - switch to TreasureHunter
TREASURE_HUNTER
Searches for Treasure within a specified radius.
Walks towards treasure
Switches to Sit
WANDER (extra)
Randomly chooses locations close to a central point
*/
var Actor followTarget;
var Actor nextPathPoint;
var float distanceToTarget;
var int randomChoice;
var int treasureLevel;
var int dogBiscuits;
var bool treasureHunting;
function AddBiscuits(int i)
{
dogBiscuits+=i;
}
function FindNewFollowTarget()
{
local ExamplePawn EP;
Log("Timmy (FindNewFollowTarget)");
ForEach DynamicActors(class'ExamplePawn', EP )
{
// should probably check for the closest?
// or someone with a reason to follow
followTarget = EP;
Log("Timmy (FindNewFollowTarget) FOUND");
}
}
function FindNewTreasureTarget()
{
local HiddenTreasure HT;
Log("Timmy (FindNewTreasureTarget)");
ForEach DynamicActors(class'HiddenTreasure', HT )
{
// should probably check for the closest?
// or someone with a reason to follow
followTarget = HT;
Log("Timmy (FindNewFollowTarget) FOUND");
}
}
event PostBeginPlay()
{
Super.PostBeginPlay();
Log("Timmy (PostBeginPlay)");
GotoState('Sit');
}
auto state Sit
{
Begin:
Log("Timmy (SIT) Begin");
Sleep(RandRange(3,10));
GotoState('ChooseBehaviour');
}
state ChooseBehaviour
{
Begin:
randomChoice = rand(3);
if ( dogBiscuits > 2 )
{
// treasure hunt
// if we reward Timmy - only then should we go into the treasure hunter mode.
// dog biscuits?
// if we stop very close then he'll find it for us
// otherwise we need to return home to find more biscuits
FindNewTreasureTarget();
treasureHunting = true;
dogBiscuits = dogBiscuits - 3;
GotoState('Follow');
}
switch( rand(2) )
{
case 0:
// follow player
FindNewFollowTarget();
GotoState('Follow');
break;
case 1:
// sit
followTarget = NONE;
GotoState('Sit');
break;
}
GotoState('ChooseBehaviour');
}
state WaitByTreasure
{
Begin:
if ( followTarget !=NONE )
{
//Pawn.PlayAnim();
Sleep(3);
GotoState('WaitByTreasure');
}
else
{
// treasure has been taken
treasureHunting = false;
GotoState('ChooseBehaviour');
}
}
state Follow
{
// tick?
Begin:
Log("Timmy (Follow) Begin");
if ( followTarget == NONE )
{
FindNewFollowTarget();
}
distanceToTarget = vsize(Pawn.Location - followTarget.Location);
Log( "Distance Timmy to Target: " $ distanceToTarget );
if ( distanceToTarget < 100.0f)
{
if ( treasureHunting == true )
{
GotoState('WaitByTreasure');
}
else
{
GotoState('ChooseBehaviour');
}
}
else
{
GotoState('MoveTowards');
}
}
state MoveTowards
{
Begin:
Log("Timmy (Follow) MoveTo New Target");
Log("Timmy Location: "$Pawn.Location);
Log("Target Location: "$followTarget.Location);
if ( PointReachable( followTarget.Location ))
{
Log("Point reachable");
MoveTo( followTarget.Location);//,, true ); // should walk = true
}
else
{
Log("Point Unreachable using current locomotion method - using FindPathTo");
nextPathPoint = FindPathTo( followTarget.Location );
if (nextPathPoint != NONE)
{
Log("Found path - following");
MoveToward(nextPathPoint);
}
else
{
Log("Failed to generate path");
Log("Using FindPathToward");
nextPathPoint = FindPathToward( followTarget );
if (nextPathPoint != NONE)
{
Log("Found path - following");
MoveToward(nextPathPoint);
}
else
{
Log("Total Failure - lets give up and go home!");
}
}
}
GotoState('Follow');
}
defaultProperties
{
treasureLevel = 1
dogBiscuits = 0
treasureHunting = false
FovAngle=+00085.000000
bCanOpenDoors=true
bCanDoSpecial=true
bIsPlayer=false
bStasis=false
RotationRate=(Pitch=3072,Yaw=30000,Roll=2048)
RemoteRole=ROLE_None
}
page revision: 1, last edited: 26 Nov 2009 11:25