RuneI
Class TreePt

source: c:\runehov\RuneI\Classes\TreePt.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.ParticleSystem
         |
         +--RuneI.BeamSystem
            |
            +--RuneI.TreePt
Direct Known Subclasses:TreeBark, TreeFern, TreeGrow, TreeVine

class TreePt
extends RuneI.BeamSystem

//============================================================================= // TreePt. //=============================================================================
Variables
 float BranchLength
           Distance to parent TreePt
 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
 float MaximumVelocityPickup
           Maximum velocity transfer allowed from collision
 TreePt Parent
           Get rid of these, use controller class to sway
 name ParentTag
           Tag of this TreePt's parent
 float SpringConstant
           Rotation stays perfectly synced with parent
 vector SwayVelocity
           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 bLeaf
           This is last TreePt in chain
 bool bRestrictVelocity
           Restrict TreePt velocity to MaxVelocityAllowed
 bool bSpring
           Rotation stays perfectly synced with parent
 bool bStiffRotation
           Rotation stays perfectly synced with parent

States
Active, Inactive

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

End Source Code