RuneI
Class TreePoint

source: c:\runehov\RuneI\Classes\TreePoint.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--RuneI.Accelerator
         |
         +--RuneI.TreePoint
Direct Known Subclasses:None

class TreePoint
extends RuneI.Accelerator

//============================================================================= // TreePoint. //=============================================================================
Variables
 Actor Attraction
           Actor attracted to
 Actor BeamActor
           Beam actor for drawing
 float BranchLength
           Distance to parent TreePoint
 float DampFactor
           Dampening Factor [0..1] (1=infinite damp)
 float GravAccel
           Acceleration magnitude of gravitation
 vector GravDir
           Direction of gravitation
 float MaxVelocityAllowed
           Creates cone centered at DesiredRotation
 TreePoint Parent
           Get rid of these, use controller class to sway
 name ParentTag
           Tag of this TreePoint's parent
 float SpringConstant
           Rotation stays perfectly synced with parent
 vector SwayDir
           Get rid of these, use controller class to sway
 float SwayMagnitude
           Get rid of these, use controller class to sway
 bool bAffectsParent
           If children affect parent velocity
 bool bApplyAcceleration
           Apply local gravitation force
 bool bApplySway
           Get rid of these, use controller class to sway
 bool bDrawRope
           Draw our fake rope between this and child
 bool bHooker
           Whether this point "hooks" actors
 bool bLeaf
           This is last TreePoint in chain
 bool bRestrictVelocity
           Restrict TreePoint velocity to MaxVelocityAllowed
 bool bSpring
           Rotation stays perfectly synced with parent
 bool bStiffRotation
           Rotation stays perfectly synced with parent
 rotator hookOrientation
           Orientation of Hooked actors
 Actor hooked
           Actor hooked to point

States
Active, Inactive

Function Summary
 void ApplySwing(TreePoint r1, TreePoint r2, float DeltaTime)
     
// r1 = parent,  r2 = child
 void ElasticCollision(Actor a1, Actor a2)
 void HitWall(vector HitNormal, Actor HitWall)
 void PostBeginPlay()
 void PreBeginPlay()
     
// Private members
// --------------------------------------------------------
 void SetAttraction(Actor Other)
 void SetBranchLength(float len)
 void SetDrawRope(bool on)
 void SetGravDir(vector dir)
     
// Public interface members
// --------------------------------------------------------
 void SpawnChild()
 void Touch(Actor Other)
 void TreePointTick(float DeltaSeconds)
 void UnTouch(Actor Other)
 void UpdateBeam()
 void WakeSelfAndChildren()
 void WakeSelfAndParents()
 void WakeUp()


State Active Function Summary
 void BeginState()
 void Tick(float DeltaTime)


State Inactive Function Summary
 void BeginState()



Source Code


00001	//=============================================================================
00002	// TreePoint.
00003	//=============================================================================
00004	class TreePoint extends Accelerator
00005		native;
00006	
00007	var() bool bHooker;					// Whether this point "hooks" actors
00008	var() bool bRestrictVelocity;		// Restrict TreePoint velocity to MaxVelocityAllowed
00009	var() bool bAffectsParent;			// If children affect parent velocity
00010	var() bool bDrawRope;				// Draw our fake rope between this and child
00011	var() float MaxVelocityAllowed;		// Creates cone centered at DesiredRotation
00012	var() float GravAccel;				// Acceleration magnitude of gravitation
00013	var() float DampFactor;				// Dampening Factor [0..1] (1=infinite damp)
00014	var() name ParentTag;				// Tag of this TreePoint's parent
00015	var() bool bApplyAcceleration;		// Apply local gravitation force
00016	var() bool bStiffRotation;			// Rotation stays perfectly synced with parent
00017	var() bool bSpring;
00018	var() float SpringConstant;
00019	
00020	var() bool bApplySway;				// Get rid of these, use controller class to sway
00021	var() vector SwayDir;
00022	var() float SwayMagnitude;
00023	
00024	var(Sounds)	sound WhileMoving;		
00025	var(Sounds) sound HitAWall;
00026	
00027	var TreePoint Parent;
00028	var bool bLeaf;						// This is last TreePoint in chain
00029	var private vector GravDir;			// Direction of gravitation
00030	var float BranchLength;				// Distance to parent TreePoint
00031	var actor Attraction;				// Actor attracted to
00032	var actor BeamActor;				// Beam actor for drawing
00033	
00034	const MaximumVelocityPickup = 500;	// Maximum velocity transfer allowed from collision
00035	
00036	// To be implimented
00037	var actor hooked;					// Actor hooked to point
00038	var rotator hookOrientation;		// Orientation of Hooked actors
00039	
00040	
00041	native(654) final function TreePointTick(float DeltaSeconds);
00042	
00043	
00044	// Public interface members
00045	// --------------------------------------------------------
00046	
00047	function SetGravDir(vector dir)
00048	{
00049		GravDir = Normal(dir);
00050	}
00051	
00052	function SetBranchLength(float len)
00053	{
00054		BranchLength = len;
00055		UpdateBeam();
00056	}
00057	
00058	function SetAttraction(actor Other)
00059	{
00060		Attraction = None;
00061	}
00062	
00063	function SetDrawRope(bool on)
00064	{
00065		if (on)
00066		{
00067			if (BeamActor == None)
00068				Spawn(class'Beam',,,Location,);
00069			UpdateBeam();
00070			bDrawRope = true;
00071		}
00072		else
00073		{
00074			if (BeamActor != None)
00075				BeamActor.Destroy();
00076			bDrawRope = false;
00077		}
00078	}
00079	
00080	function SpawnChild()
00081	{
00082	}
00083	
00084	
00085	// Private members
00086	// --------------------------------------------------------
00087	
00088	
00089	function PreBeginPlay()
00090	{
00091		// Validate user set variables
00092		SetPhysics(PHYS_PROJECTILE);	// Don't force this, may want gravity
00093		bLeaf = true;					// Nodes are leaves until proven otherwise
00094		Parent = None;
00095		BeamActor = None;
00096		Attraction = None;
00097		DampFactor = FClamp(DampFactor, -1.0, 1.0);
00098	}
00099	
00100	
00101	function PostBeginPlay()
00102	{
00103		local TreePoint PotentialParent;
00104	
00105		if (ParentTag == '')
00106		{	// Root
00107			SetPhysics(PHYS_NONE);
00108		}
00109		else
00110		{	// Fill in 'Parent' based on 'ParentTag'
00111			foreach AllActors(class'TreePoint', PotentialParent, ParentTag)
00112			{
00113				// Notice: If more than one matches ParentTag, the last is used
00114				Parent = PotentialParent;
00115				PotentialParent.bLeaf = false;
00116	
00117				// Pre-calc variables
00118				GravDir = Location - PotentialParent.Location;
00119				BranchLength = VSize(GravDir);
00120				Gravdir = Normal(GravDir);
00121			}
00122			
00123			SetDrawRope(bDrawRope);
00124		}
00125		
00126		if (Skeletal != None)
00127		{
00128			LoopAnim('run', 1.0, 0.0);
00129		}
00130	}
00131	
00132	function ElasticCollision(actor a1, actor a2)
00133	{
00134		local float m1,m2,mt;
00135		local vector v1,v2;
00136		
00137		m1 = a1.Mass;
00138		m2 = a2.Mass;
00139		mt = m1+m2;
00140		v1 = a1.Velocity;
00141		v2 = a2.Velocity;
00142		a1.Velocity = (m1*v1 + 2*m2*v2 - m2*v1) / mt;
00143		a2.Velocity = (m2*v2 + 2*m1*v1 - m1*v2 ) / mt;
00144	}
00145	
00146	function HitWall(vector HitNormal, actor HitWall)
00147	{
00148		PlaySound(HitAWall, , 1.0);
00149	}
00150	
00151	function Touch(actor Other)
00152	{
00153		// Note:
00154		//	When objects are internally in order such that this touch gets called
00155		//	after the swing calculations, velocity can be transfered continually,
00156		//	moving the TreePoint out of it's orbit.  Maybe Touch/UnTouch are not
00157		//	behaving as expected.  Perhaps moving this swing logic to the physics
00158		//	subsystem would cure this ordering problem.
00159	
00160		// Non-blocking velocity transfer
00161		if (!Other.IsA('TreePoint'))
00162		{
00163			Velocity += Normal(Other.Velocity) * Min(VSize(Other.Velocity), MaximumVelocityPickup);
00164			Disable('Touch');
00165			WakeUp();
00166		}
00167		return;
00168	
00169		// Rigid body elastic collision
00170		ElasticCollision(Other, self);
00171		Disable('Touch');
00172		WakeUp();
00173	}
00174	
00175	function UnTouch(actor Other)
00176	{
00177		Enable('Touch');
00178	}
00179	
00180	function UpdateBeam()
00181	{
00182		if (BeamActor != None)
00183		{
00184			Beam(BeamActor).SetEndPoints(Location, Parent.Location);
00185		}
00186	}
00187	
00188	// r1 = parent,  r2 = child
00189	function ApplySwing(TreePoint r1, TreePoint r2, float DeltaTime)
00190	{
00191		local vector RopeVector, VelocityLookahead, RopeDir, NewLocation,NewVelocity;
00192		local float velmag;
00193		local rotator rot;
00194		local float stretchAmount;
00195		local vector SpringAccel;
00196		local vector loc1, loc2;
00197			
00198		if ((r1 == None)||(r2 == None))
00199			return;
00200	
00201		loc1 = r1.Location;
00202		loc2 = r2.Location;
00203		
00204		// Apply Acceleration
00205		if (r2.bApplyAcceleration)
00206			r2.Velocity += r2.GravDir*(r2.GravAccel*DeltaTime);
00207	
00208		// Apply sway
00209		if (r2.bApplySway && (FRand() < 0.1))
00210			r2.Velocity += Normal(r2.SwayDir) * FRand() * SwayMagnitude * DeltaTime;
00211	
00212		// Apply velocity on child TreePoint
00213		VelocityLookahead = Loc2 + (r2.Velocity * DeltaTime);
00214		RopeDir = Normal(Loc1 - VelocityLookahead);
00215	
00216		// Find Next child Location
00217		if (r2.bSpring)
00218		{	// Apply spring acceleration
00219			RopeVector = Loc1 - Loc2;
00220			stretchAmount = VSize(RopeVector) - r2.BranchLength;
00221			SpringAccel = Normal(RopeVector) * (r2.SpringConstant * stretchAmount / r2.Mass);
00222			NewLocation = VelocityLookahead + SpringAccel * (DeltaTime * DeltaTime);
00223		}
00224		else
00225		{
00226			RopeVector = RopeDir * r2.BranchLength;
00227			NewLocation = Loc1 - RopeVector;
00228		}
00229		
00230		NewVelocity = NewLocation - Loc2;
00231		if (r2.bRestrictVelocity)
00232		{
00233			velmag = VSize(NewVelocity);
00234			if (velmag > r2.MaxVelocityAllowed)
00235			{
00236				NewVelocity = Normal(NewVelocity) * r2.MaxVelocityAllowed;
00237			}
00238		}
00239		r2.Velocity = NewVelocity *(1.0-r2.DampFactor)/ DeltaTime;
00240	
00241		// Set child's rotation
00242		if (bStiffRotation)
00243			rot = rotator(-RopeVector);				// Predicted location
00244		else
00245			rot = rotator(Loc2-Loc1);	// Last location (lagged)
00246		rot.Roll = rot.Yaw;
00247		r2.SetRotation(rot);
00248		
00249	//*** This needs to be moved to C side ***
00250		if (r1.Parent == None)						// Set root rotation too
00251			r1.SetRotation(rot);
00252	
00253		// Apply velocity on parent TreePoint
00254		if (r2.bAffectsParent)
00255		{
00256			r1.Velocity = (r1.Velocity + (r2.Velocity * 0.5)) * 0.5;
00257		}
00258	
00259		// Play WhileMoving Sound
00260		if (VSize(r2.Velocity) > 1.0)
00261			PlaySound(r2.WhileMoving, , 1.0);
00262	}
00263	
00264	
00265	function WakeSelfAndParents()
00266	{
00267		if (Parent != None)
00268		{
00269			GotoState('Active');
00270			Parent.WakeSelfAndParents();
00271		}
00272	}
00273		
00274	function WakeSelfAndChildren()
00275	{
00276		local TreePoint point;
00277		
00278		// Wake myself if not the root
00279		if (Parent != None)
00280			GotoState('Active');
00281			foreach AllActors(class'TreePoint', point)
00282		{
00283			if (point.Parent == self)
00284				point.WakeSelfAndChildren();
00285		}
00286	}
00287	
00288	function WakeUp()
00289	{
00290		WakeSelfAndParents();
00291		WakeSelfAndChildren();
00292	}
00293	
00294	state Inactive
00295	{
00296		ignores Tick;
00297	
00298		function BeginState()
00299		{
00300			SetPhysics(PHYS_NONE);
00301		}
00302	}
00303	
00304	
00305	auto state Active
00306	{
00307		function Tick(float DeltaTime)
00308		{
00309			local TreePoint point;
00310	
00311			UpdateBeam();
00312			
00313			if (bLeaf)
00314			{
00315	//			TreePointTick(DeltaTime);
00316	//			
00317				point = self;
00318				while (point != None)
00319				{
00320					ApplySwing(point.Parent, point, DeltaTime);
00321					point = point.Parent;
00322				}
00323	//
00324			}
00325			
00326			if (VSize(Velocity) < 0.1)
00327			{
00328				Velocity = vect(0,0,0);
00329				GotoState('Inactive');
00330			}
00331		}
00332		
00333		function BeginState()
00334		{
00335			SetPhysics(PHYS_PROJECTILE);
00336		}
00337	}
00338	
00339	defaultproperties
00340	{
00341	     bAffectsParent=True
00342	     bDrawRope=True
00343	     GravAccel=950.000000
00344	     DampFactor=0.010000
00345	     bApplyAcceleration=True
00346	     Physics=PHYS_Projectile
00347	     CollisionRadius=20.000000
00348	     CollisionHeight=30.000000
00349	     bCollideActors=True
00350	     bCollideWorld=True
00351	}

End Source Code