## XIII
Class XIIITransientACreature

source: C:\XIII\XIII\Classes\XIIITransientACreature.uc

    Core.Object
       |
       +--Engine.Actor
          |
          +--Engine.Controller
             |
             +--Engine.AIController
                |
                +--XIII.XIIITransientACreature

Direct Known Subclasses:XIIIBirds

class XIIITransientACreature
extends Engine.AIController

    //-----------------------------------------------------------

Variables
`class` | `AltPredatorType` who eats my pawns (optional)
`float` | `FlockRadius` radius in which to spawn slaves
`class` | `LocationTypeForSpawn` the points where the creatures should be spawned
`float` | `MaxSpawnDist` maximum distance for spawning in player's line of sight
`float` | `MinSpawnDist` minimum distance for spawning in player's line of sight
`XIIICreatureManager` | `MyManager`
`XIIITransientACreature` | `NextCreature` transient ambient creature list managed by AmbientCreatureManager
`int` | `NumSlaves` number of slave pawns
`class` | `PawnTypes[8]` pawns which can be controlled by this controller on land - pick one when spawning
`class` | `PickedClass` if true, my pawns are meant for underwater
`class` | `PredatorType` who eats my pawns (optional)
`XIIITransientACreature` | `Prey` if hunter, what I'm hunting
`XIIITransientACreature` | `Replacement` replacement if destroyed because of wrong zone
`Keypoint` | `StartingSpot` Starting Spot to turn/move around if needed
`class` | `UnderWaterType` who to replace me with underwater (optional)
`bool` | `bOffCameraSpawns` if true, use off camera spawns
`bool` | `bUnderWaterCreatures` if true, my pawns are meant for underwater

States
Wandering

Function Summary
`void` | `AddPawn()`
    //_____________________________________________________________________________
`void` | `AddSlaves(XIIITransientAPawn Last, int SpawnNum)`
    //_____________________________________________________________________________
`void` | `Destroyed()`
    //_____________________________________________________________________________
`vector` | `FindGround(PlayerController Viewer, vector StartLoc)`
    //_____________________________________________________________________________
`vector` | `FindSpawnLocation(float Dist, vector SpawnDir, PlayerController Viewer)`
    /* FindSpawnLocation()
    Find a suitable spawn location for the ambient creature (far enough away from the player)
    if none can be found, returns vect(0,0,0)
    */
`vector` | `InitialLocation(vector CurrentLocation)`
    //_____________________________________________________________________________
`float` | `MaxHiddenTime()`
    //_____________________________________________________________________________
`void` | `NotVisible()`
    //_____________________________________________________________________________
`void` | `PawnDied()`
    //_____________________________________________________________________________
`vector` | `PickDestination(XIIITransientAPawn P)`
    //_____________________________________________________________________________
`void` | `PickSlaveDestination(XIIITransientAPawn P)`
    //_____________________________________________________________________________
`void` | `PostBeginPlay()`
    //_____________________________________________________________________________
`void` | `SlavePawnDied(Pawn P)`
    //_____________________________________________________________________________
`Rotator` | `SpawnRotation()`
    //_____________________________________________________________________________
`XIIITransientAPawn` | `SpawnSlave()`
    //_____________________________________________________________________________

State Wandering Function Summary

Source Code

    00001
    00002	// TransientAmbientCreature
    00003	// The base class of controllers for ambient creatures which are created an destroyed
    00004	// on the client as the player walks around (small stuff like bugs, birds, etc.)
    00005
    00006	//-----------------------------------------------------------
    00007	class XIIITransientACreature extends AIController;
    00008
    00009	var XIIICreatureManager MyManager;
    00010	var XIIITransientACreature NextCreature;    // transient ambient creature list managed by AmbientCreatureManager
    00011	var class<Pawn> PawnTypes[8];               // pawns which can be controlled by this controller on land - pick one when spawning
    00012	var class<XIIITransientACreature> PredatorType;    // who eats my pawns (optional)
    00013	var class<XIIITransientACreature> AltPredatorType; // who eats my pawns (optional)
    00014	var class<XIIITransientACreature> UnderWaterType;  // who to replace me with underwater (optional)
    00015	var float MinSpawnDist;                     // minimum distance for spawning in player's line of sight
    00016	var float MaxSpawnDist;                     // maximum distance for spawning in player's line of sight
    00017	var bool  bOffCameraSpawns;                 // if true, use off camera spawns
    00018	var bool  bUnderWaterCreatures;             // if true, my pawns are meant for underwater
    00019	var class<Pawn> PickedClass;
    00020	var XIIITransientACreature Prey;            // if hunter, what I'm hunting
    00021	var float FlockRadius;                      // radius in which to spawn slaves
    00022	var int NumSlaves;                          // number of slave pawns
    00023	var XIIITransientACreature Replacement;     // replacement if destroyed because of wrong zone
    00024	var class<XIIICreaturePoint> LocationTypeForSpawn;  // the points where the creatures should be spawned
    00025	var KeyPoint StartingSpot;                  // Starting Spot to turn/move around if needed
    00026
    00027
    00028	//_____________________________________________________________________________
    00029	function PostBeginPlay()
    00030	{
    00031	    Super.PostBeginPlay();
    00032
    00033	    MyManager = XIIICreatureManager(Owner);
    00034	    Prey = MyManager.Prey;
    00035
    00036	    // make sure in an appropriate zone
    00037	    if ( PhysicsVolume.bPainCausing )
    00038	    {
    00039	      Destroy();
    00040	      return;
    00041	    }
    00042	    if ( PhysicsVolume.bWaterVolume != bUnderWaterCreatures )
    00043	    {
    00044	      // try to replace me with underwater alternative
    00045	      if ( UnderWaterType != None )
    00046	        Replacement = spawn(UnderWaterType, Owner);
    00047
    00048	      Destroy();
    00049	      return;
    00050	    }
    00051
    00052	    AddPawn();
    00053	}
    00054
    00055	//_____________________________________________________________________________
    00056	function AddSlaves(XIIITransientAPawn Last, int SpawnNum)
    00057	{
    00058	    while (SpawnNum > 0)
    00059	    {
    00060	      SpawnNum--;
    00061	      Last.NextSlave = SpawnSlave();
    00062	      if ( Last.NextSlave != None )
    00063	      {
    00064	        NumSlaves--;
    00065	        Last.NextSlave.Controller = self;
    00066	        Last = Last.NextSlave;
    00067	      }
    00068	    }
    00069	}
    00070
    00071	//_____________________________________________________________________________
    00072	function XIIITransientAPawn SpawnSlave()
    00073	{
    00074	    local vector V, HitNormal, HitLocation;
    00075	    local actor HitActor;
    00076	    local float HitTime;
    00077
    00078	    V = InitialLocation(Pawn.Location);
    00079	    // check trace
    00080	    HitActor = Trace(HitLocation, HitNormal, V, Pawn.Location, false);
    00081	    if ( HitActor != None )
    00082	      V = HitLocation - (2 + Pawn.CollisionRadius) * Normal(V - Pawn.Location);
    00083	    return XIIITransientAPawn(spawn(Pawn.Class,self,,V));
    00084	}
    00085
    00086	//_____________________________________________________________________________
    00087	function vector InitialLocation(vector CurrentLocation)
    00088	{
    00089	    return (CurrentLocation + VRand() * FlockRadius);
    00090	}
    00091
    00092	//_____________________________________________________________________________
    00093	function AddPawn()
    00094	{
    00095	    local int NumClasses;
    00096	    local Pawn P;
    00097
    00098	    // add an appropriate pawn
    00099	    // note that I've been spawned at ground level
    00100	    if ( PickedClass == None )
    00101	    {
    00102	      While ( NumClasses < ArrayCount(PawnTypes) )
    00103	      {
    00104	        if ( PawnTypes[NumClasses] != None )
    00105	          NumClasses++;
    00106	        else
    00107	          break;
    00108	      }
    00109	      if ( NumClasses == 0 )
    00110	      {
    00111	        log(self$" have No pawn classes to spawn");
    00112	        return;
    00113	      }
    00114	      PickedClass = PawnTypes[Rand(NumClasses)];
    00115	    }
    00116	    P = Spawn(PickedClass,self,,Location + (PickedClass.Default.CollisionHeight + 2) * Vect(0,0,1), SpawnRotation());
    00117	    log("AddPawn : "$self$" Spawned his pawn "$P);
    00118	    if ( P != None )
    00119	      Possess(P);
    00120	    if ( Pawn == None )
    00121	      Destroy();
    00122	    else
    00123	    {
    00124	      Pawn.LastRenderTime = Level.TimeSeconds;
    00125	      if ( NumSlaves > 0 )
    00126	        Pawn.SetTimer(0.2, true);
    00127	    }
    00128	}
    00129
    00130	//_____________________________________________________________________________
    00131	function Rotator SpawnRotation()
    00132	{
    00133	    local Rotator SpawnRot;
    00134
    00135	    SpawnRot.Yaw = Rand(65535);
    00136	    return SpawnRot;
    00137	}
    00138
    00139	//_____________________________________________________________________________
    00140	function Destroyed()
    00141	{
    00142	    if ( MyManager != None )
    00143	      MyManager.RemoveCreature(self);
    00144	    Super.Destroyed();
    00145	}
    00146
    00147	//_____________________________________________________________________________
    00148	function NotVisible()
    00149	{
    00150	    if ( Pawn == None )
    00151	    {
    00152	      PawnDied();
    00153	      return;
    00154	    }
    00155	    XIIITransientAPawn(Pawn).VerifyLastRenderTime();
    00156	    if ( Level.TimeSeconds - Pawn.LastRenderTime > MaxHiddenTime() )
    00157	      XIIITransientAPawn(Pawn).DestroyAll();
    00158	}
    00159
    00160	//_____________________________________________________________________________
    00161	function float MaxHiddenTime()
    00162	{
    00163	    return ( 10 + 5 * FRand() );
    00164	}
    00165
    00166	//_____________________________________________________________________________
    00167	function SlavePawnDied(Pawn P)
    00168	{
    00169	    if ( P == Pawn )
    00170	      PawnDied();
    00171	}
    00172
    00173	//_____________________________________________________________________________
    00174	function PawnDied()
    00175	{
    00176	    if ( XIIITransientAPawn(Pawn).NextSlave != None )
    00177	      Possess(XIIITransientAPawn(Pawn).NextSlave);
    00178	    else
    00179	      Destroy();
    00180	}
    00181
    00182	//_____________________________________________________________________________
    00183	/* FindSpawnLocation()
    00184	Find a suitable spawn location for the ambient creature (far enough away from the player)
    00185	if none can be found, returns vect(0,0,0)
    00186	*/
    00187	static function vector FindSpawnLocation(float Dist, vector SpawnDir, PlayerController Viewer)
    00188	{
    00189	    local rotator SpawnRot;
    00190	    local actor HitActor;
    00191	    local vector HitLocation, HitNormal, SpawnLoc, StartLoc;
    00192	    // FIXME - some creatures may look for fixed spawn points (e.g. bat cave)
    00193
    00194	    // if off camera spawning, then modify spawndir
    00195	    // FIXME - don't always if beyond max visible distance (where thing is less than one pixel)
    00196	    if ( Default.bOffCameraSpawns && (!Viewer.Region.Zone.bDistanceFog || (Viewer.Region.Zone.DistanceFogEnd > Dist))  )
    00197	    {
    00198	      SpawnRot = Rotator(SpawnDir);
    00199	      if ( FRand() < 0.5 )
    00200	        SpawnRot.Yaw += Viewer.FOVAngle * 182; // 65536/360
    00201	      else
    00202	        SpawnRot.Yaw -= Viewer.FOVAngle * 182; // 65536/360
    00203
    00204	      SpawnDir = Vector(SpawnRot);
    00205	    }
    00206	    SpawnLoc = Viewer.ViewTarget.Location + Dist * SpawnDir;
    00207	    // find ground
    00208	    HitActor = Viewer.Trace(HitLocation, HitNormal, SpawnLoc, Viewer.ViewTarget.Location + Viewer.ViewTarget.CollisionRadius * Vect(0,0,1), false);
    00209
    00210	    if ( HitActor == None )
    00211	      return FindGround(Viewer, SpawnLoc);
    00212
    00213	    //  OK - try to go over obstacle
    00214	    HitActor = Viewer.Trace(HitLocation, HitNormal, HitLocation - 50 * HitNormal, HitLocation, false);
    00215
    00216	    if ( HitActor != None )
    00217	    {
    00218	      // give up?
    00219	      if ( (HitNormal.Z < 0.8)
    00220	        || (VSize(HitLocation - Viewer.ViewTarget.Location) < Default.MinSpawnDist) )
    00221	        return vect(0,0,0);
    00222
    00223	      return HitLocation;
    00224	    }
    00225
    00226	    // ok- go up
    00227	    StartLoc = HitLocation - 100 * HitNormal + vect(0,0,500);
    00228	    HitActor = Viewer.Trace(HitLocation, HitNormal, StartLoc, HitLocation - 100 * HitNormal, false);
    00229
    00230	    if ( HitActor != None )
    00231	      StartLoc = HitLocation;
    00232	    Dist = VSize(HitLocation - SpawnLoc);
    00233	    HitActor = Viewer.Trace(HitLocation, HitNormal, StartLoc + Dist * SpawnDir, StartLoc, false);
    00234
    00235	    if ( HitActor == None )
    00236	      return FindGround(Viewer, SpawnLoc);
    00237	    else if ( HitNormal.Z >= 0.8 )
    00238	      return HitLocation;
    00239
    00240	    return vect(0,0,0);
    00241
} 00242 00243 //_____________________________________________________________________________ 00244 static function vector FindGround(PlayerController Viewer, vector StartLoc) 00245 { 00246 local actor HitActor; 00247 local vector HitLocation, HitNormal; 00248 00249 // find ground 00250 HitActor = Viewer.Trace(HitLocation, HitNormal, StartLoc - vect(0,0,10000), StartLoc, false); 00251 if ( (HitActor == None) || (HitNormal.Z < 0.8) ) 00252 return Vect(0,0,0); 00253 00254 return HitLocation; 00255 } 00256 00257 //_____________________________________________________________________________ 00258 function vector PickDestination(XIIITransientAPawn P) 00259 { 00260 return Pawn.Location; 00261 } 00262 00263 //_____________________________________________________________________________ 00264 function PickSlaveDestination(XIIITransientAPawn P); 00265 00266 //_____________________________________________________________________________ 00267 auto State Wandering 00268 { 00269 Begin: 00270 Destination = PickDestination(XIIITransientAPawn(Pawn)); 00271 FocalPoint = Destination; 00272 Sleep(XIIITransientAPawn(Pawn).MoveTimeTo(Destination)); 00273 if ( AmbientSound != None ) 00274 SetLocation(Pawn.Location); 00275 Goto('Begin'); 00276 } 00277 00278 // UnderWaterType=class'AmbientCreatures.FishSchool' 00279 00280 00281 defaultproperties 00282 { 00283 MinSpawnDist=500.000000 00284 MaxSpawnDist=3000.000000 00285 bOffCameraSpawns=True 00286 FlockRadius=200.000000 00287 RemoteRole=ROLE_None 00288 }

End Source Code