2
0
Эх сурвалжийг харах

Adds some example components, game objects and the tools and scripts to utilize them.

Areloch 9 жил өмнө
parent
commit
6fe0b1789d
32 өөрчлөгдсөн 1812 нэмэгдсэн , 0 устгасан
  1. 13 0
      Templates/Full/game/art/art.module.taml
  2. 3 0
      Templates/Full/game/art/shapes/actors/Soldier/soldier.asset.taml
  3. 1 0
      Templates/Full/game/main.cs
  4. 13 0
      Templates/Full/game/scripts/scripts.module.taml
  5. 7 0
      Templates/Full/game/scripts/server/components/animationComponent.asset.taml
  6. 7 0
      Templates/Full/game/scripts/server/components/cameraOrbiterComponent.asset.taml
  7. 7 0
      Templates/Full/game/scripts/server/components/collisionComponent.asset.taml
  8. 7 0
      Templates/Full/game/scripts/server/components/game/camera.asset.taml
  9. 198 0
      Templates/Full/game/scripts/server/components/game/camera.cs
  10. 7 0
      Templates/Full/game/scripts/server/components/game/controlObject.asset.taml
  11. 91 0
      Templates/Full/game/scripts/server/components/game/controlObject.cs
  12. 7 0
      Templates/Full/game/scripts/server/components/game/itemRotate.asset.taml
  13. 49 0
      Templates/Full/game/scripts/server/components/game/itemRotate.cs
  14. 7 0
      Templates/Full/game/scripts/server/components/game/playerSpawner.asset.taml
  15. 70 0
      Templates/Full/game/scripts/server/components/game/playerSpawner.cs
  16. 7 0
      Templates/Full/game/scripts/server/components/input/fpsControls.asset.taml
  17. 249 0
      Templates/Full/game/scripts/server/components/input/fpsControls.cs
  18. 82 0
      Templates/Full/game/scripts/server/components/input/inputManager.cs
  19. 7 0
      Templates/Full/game/scripts/server/components/meshComponent.asset.taml
  20. 7 0
      Templates/Full/game/scripts/server/components/playerControllerComponent.asset.taml
  21. 7 0
      Templates/Full/game/scripts/server/components/stateMachineComponent.asset.taml
  22. 25 0
      Templates/Full/game/scripts/server/gameCore.cs
  23. 28 0
      Templates/Full/game/scripts/server/gameObjects/GameObjectList.xml
  24. 75 0
      Templates/Full/game/scripts/server/gameObjects/GameObjectManager.cs
  25. 5 0
      Templates/Full/game/scripts/server/gameObjects/ThirdPersonPlayerObject.asset.taml
  26. 253 0
      Templates/Full/game/scripts/server/gameObjects/ThirdPersonPlayerObject.cs
  27. 99 0
      Templates/Full/game/scripts/server/gameObjects/ThirdPersonPlayerObject.taml
  28. 20 0
      Templates/Full/game/scripts/server/scriptExec.cs
  29. 45 0
      Templates/Full/game/tools/componentEditor/gui/superToolTipDlg.ed.gui
  30. 28 0
      Templates/Full/game/tools/componentEditor/main.cs
  31. 155 0
      Templates/Full/game/tools/componentEditor/scripts/SuperToolTipDlg.ed.cs
  32. 233 0
      Templates/Full/game/tools/componentEditor/scripts/componentEditor.ed.cs

+ 13 - 0
Templates/Full/game/art/art.module.taml

@@ -0,0 +1,13 @@
+<ModuleDefinition
+	ModuleId="Art"
+	VersionId="1"
+	Description="Default module for the Full template game assets."
+	ScriptFile=""
+	CreateFunction="create"
+	DestroyFunction="destroy"
+	Group="Game"
+	Dependencies="">
+    <DeclaredAssets
+      Extension="asset.taml"
+      Recurse="true"/>
+</ModuleDefinition>

+ 3 - 0
Templates/Full/game/art/shapes/actors/Soldier/soldier.asset.taml

@@ -0,0 +1,3 @@
+<ShapeAsset
+    AssetName="SoldierPlayer"
+    fileName="art/shapes/actors/Soldier/soldier_rigged.DAE"/>

+ 1 - 0
Templates/Full/game/main.cs

@@ -254,6 +254,7 @@ else {
 
    //You can also explicitly decalre some modules here to be loaded by default if they are part of your game
    //Ex: ModuleDatabase.LoadExplicit( "AppCore" );
+   ModuleDatabase.LoadGroup( "Game" );
 
    if( !$isDedicated )
    {

+ 13 - 0
Templates/Full/game/scripts/scripts.module.taml

@@ -0,0 +1,13 @@
+<ModuleDefinition
+	ModuleId="Scripts"
+	VersionId="1"
+	Description="Default module for the Full template game assets."
+	ScriptFile=""
+	CreateFunction="create"
+	DestroyFunction="destroy"
+	Group="Game"
+	Dependencies="">
+    <DeclaredAssets
+      Extension="asset.taml"
+      Recurse="true"/>
+</ModuleDefinition>

+ 7 - 0
Templates/Full/game/scripts/server/components/animationComponent.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="AnimationComponentAsset"
+    componentName=""
+    componentClass="AnimationComponent"
+    friendlyName="Animation"
+    componentType="Animation"
+    description="Allows a mesh component to be animated."/>

+ 7 - 0
Templates/Full/game/scripts/server/components/cameraOrbiterComponent.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="CameraOrbiterComponentAsset"
+    componentName=""
+    componentClass="CameraOrbiterComponent"
+    friendlyName="Camera Orbiter"
+    componentType="Game"
+    description="Acts as a boon arm for a camera component."/>

+ 7 - 0
Templates/Full/game/scripts/server/components/collisionComponent.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="CollisionComponentAsset"
+    componentName=""
+    componentClass="CollisionComponent"
+    friendlyName="Collision"
+    componentType="Collision"
+    description="Enables an entity to collide with things."/>

+ 7 - 0
Templates/Full/game/scripts/server/components/game/camera.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="CameraComponentAsset"
+    componentName=""
+    componentClass="CameraComponent"
+    friendlyName="Camera"
+    componentType="Game"
+    description="Allows the component owner to operate as a camera."/>

+ 198 - 0
Templates/Full/game/scripts/server/components/game/camera.cs

@@ -0,0 +1,198 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function CameraComponent::onAdd(%this) 
+{
+   Parent::onBehaviorAdd(%this);
+
+   %this.addComponentField(clientOwner, "The client that views this camera", "int", "1", "");
+
+   %test = %this.clientOwner;
+
+   %barf = ClientGroup.getCount();
+
+   %clientID = %this.getClientID();
+   if(%clientID && !isObject(%clientID.camera))
+   {
+      %this.scopeToClient(%clientID);
+      %this.setDirty();
+
+      %clientID.setCameraObject(%this.owner);
+      %clientID.setControlCameraFov(%this.FOV);
+      
+      %clientID.camera = %this.owner;
+   }
+
+   %res = $pref::Video::mode;
+   %derp = 0;
+}
+
+function CameraComponent::onRemove(%this)
+{
+   %clientID = %this.getClientID();
+   if(%clientID)
+      %clientID.clearCameraObject();
+}
+
+function CameraComponent::onInspectorUpdate(%this)
+{
+   //if(%this.clientOwner)
+      //%this.clientOwner.setCameraObject(%this.owner);
+}
+
+function CameraComponent::getClientID(%this)
+{
+	return ClientGroup.getObject(%this.clientOwner-1);
+}
+
+function CameraComponent::isClientCamera(%this, %client)
+{
+	%clientID = ClientGroup.getObject(%this.clientOwner-1);
+	
+	if(%client.getID() == %clientID)
+		return true;
+	else
+	    return false;
+}
+
+function CameraComponent::onClientConnect(%this, %client)
+{
+   //if(%this.isClientCamera(%client) && !isObject(%client.camera))
+   //{
+      %this.scopeToClient(%client);
+      %this.setDirty();
+      
+      %client.setCameraObject(%this.owner);
+      %client.setControlCameraFov(%this.FOV);
+      
+      %client.camera = %this.owner;
+   //}
+   //else
+   //{
+   //   echo("CONNECTED CLIENT IS NOT CAMERA OWNER!");
+   //}
+}
+
+function CameraComponent::onClientDisconnect(%this, %client)
+{
+   Parent::onClientDisconnect(%this, %client);
+   
+   if(isClientCamera(%client)){
+      %this.clearScopeToClient(%client);
+      %client.clearCameraObject();
+   }
+}
+
+//move to the editor later
+GlobalActionMap.bind("keyboard", "alt c", "toggleEditorCam");
+
+function switchCamera(%client, %newCamEntity)
+{
+	if(!isObject(%client) || !isObject(%newCamEntity))
+		return error("SwitchCamera: No client or target camera!");
+		
+	%cam = %newCamEntity.getComponent(CameraComponent);
+		
+	if(!isObject(%cam))
+		return error("SwitchCamera: Target camera doesn't have a camera behavior!");
+		
+	//TODO: Cleanup clientOwner for previous camera!
+	if(%cam.clientOwner == 0 || %cam.clientOwner $= "")
+		%cam.clientOwner = 0;
+		
+	%cam.scopeToClient(%client);
+	%cam.setDirty();
+	
+	%client.setCameraObject(%newCamEntity);
+	%client.setControlCameraFov(%cam.FOV);
+	
+	%client.camera = %newCamEntity;
+}
+
+function buildEditorCamera()
+{
+	if(isObject("EditorCamera"))
+		return EditorCamera;
+		
+    %camObj = SGOManager.spawn("SpectatorObject", false);
+	
+	%camObj.name = "EditorCamera";
+	
+	%client = ClientGroup.getObject(0);
+	
+	%camObj.getComponent(SpectatorControls).setupControls(%client);
+	
+	MissionCleanup.add(%camObj);
+	
+	return %camObj;
+}
+
+//TODO: Move this somewhere else!
+function toggleEditorCam(%val)
+{
+   if(!%val)
+      return;
+      
+   %client = ClientGroup.getObject(0);
+
+   if(!isObject(%client.camera))
+      return error("ToggleEditorCam: no existing camera!");
+   
+   %editorCam = buildEditorCamera();
+
+   //if this is our first switch, just go to the editor camera
+   if(%client.lastCam $= "" || %client.camera.getId() != %editorCam.getId())
+   {
+	   if(%client.lastCam $= "")
+	   {
+	      //set up the position
+		  %editorCam.position = %client.camera.position;
+		  %editorCam.rotation = %client.camera.rotation;
+	   }
+	
+	   %client.lastCam = %client.camera;
+	   %client.lastController = %client.getControlObject();
+	   switchCamera(%client, %editorCam); 
+	   switchControlObject(%client, %editorCam);
+   }
+   else  
+   {
+       switchCamera(%client, %client.lastCam); 
+	   switchControlObject(%client, %client.lastController); 
+       %client.lastCam = %editorCam;
+	   %client.lastController = %editorCam;
+   }
+}
+
+function serverCmdSetClientAspectRatio(%client, %width, %height)
+{
+   echo("Client: " @ %client SPC "changing screen res to: " @ %width SPC %height);
+   %client.screenExtent = %width SPC %height;
+   %cam = %client.getCameraObject();
+   
+   if(!isObject(%cam))
+      return;
+      
+   %cameraComp = %cam.getComponent(CameraComponent);
+
+   %cameraComp.ScreenAspect = %width SPC %height;
+}

+ 7 - 0
Templates/Full/game/scripts/server/components/game/controlObject.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="ControlObjectComponentAsset"
+    componentName="ControlObjectComponent"
+    componentClass="Component"
+    friendlyName="Control Object"
+    componentType="Game"
+    description="Allows the component owner to be controlled by a client."/>

+ 91 - 0
Templates/Full/game/scripts/server/components/game/controlObject.cs

@@ -0,0 +1,91 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+//registerComponent("ControlObjectComponent", "Component", "Control Object", "Game", false, "Allows the behavior owner to operate as a camera.");
+
+function ControlObjectComponent::onAdd(%this)
+{
+   Parent::onBehaviorAdd(%this);
+
+   %this.addComponentField(clientOwner, "The shape to use for rendering", "int", "1", "");
+
+   %clientID = %this.getClientID();
+
+   if(%clientID && !isObject(%clientID.getControlObject()))
+      %clientID.setControlObject(%this.owner);
+}
+
+function ControlObjectComponent::onRemove(%this)
+{
+   %clientID = %this.getClientID();
+	
+   if(%clientID)
+      %clientID.setControlObject(0);
+}
+
+function ControlObjectComponent::onClientConnect(%this, %client)
+{
+   if(%this.isControlClient(%client) && !isObject(%client.getControlObject()))
+      %client.setControlObject(%this.owner);
+}
+
+function ControlObjectComponent::onClientDisconnect(%this, %client)
+{
+   if(%this.isControlClient(%client))
+      %client.setControlObject(0);
+}
+
+function ControlObjectComponent::getClientID(%this)
+{
+	return ClientGroup.getObject(%this.clientOwner-1);
+}
+
+function ControlObjectComponent::isControlClient(%this, %client)
+{
+	%clientID = ClientGroup.getObject(%this.clientOwner-1);
+	
+	if(%client.getID() == %clientID)
+		return true;
+	else
+	    return false;
+}
+
+function ControlObjectComponent::onInspectorUpdate(%this, %field)
+{
+   %clientID = %this.getClientID();
+	
+   if(%clientID && !isObject(%clientID.getControlObject()))
+      %clientID.setControlObject(%this.owner);
+}
+
+function switchControlObject(%client, %newControlEntity)
+{
+	if(!isObject(%client) || !isObject(%newControlEntity))
+		return error("SwitchControlObject: No client or target controller!");
+		
+	%control = %newControlEntity.getComponent(ControlObjectComponent);
+		
+	if(!isObject(%control))
+		return error("SwitchControlObject: Target controller has no conrol object behavior!");
+		
+    %client.setControlObject(%newControlEntity);
+}

+ 7 - 0
Templates/Full/game/scripts/server/components/game/itemRotate.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="ItemRotationComponentAsset"
+    componentName="ItemRotationComponent"
+    componentClass="Component"
+    friendlyName="Item Rotation"
+    componentType="Game"
+    description="Rotates the entity around an axis, like an item pickup."/>

+ 49 - 0
Templates/Full/game/scripts/server/components/game/itemRotate.cs

@@ -0,0 +1,49 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+//registerComponent("ItemRotationComponent", "Component", "Item Rotation", "Game", false, "Rotates the entity around the z axis, like an item pickup.");
+
+function ItemRotationComponent::onAdd(%this)
+{
+   %this.addComponentField(rotationsPerMinute, "Number of rotations per minute", "float", "5", "");
+   %this.addComponentField(forward, "Rotate forward or backwards", "bool", "1", "");
+   %this.addComponentField(horizontal, "Rotate horizontal or verticle, true for horizontal", "bool", "1", "");
+}
+
+function ItemRotateBehavior::Update(%this)
+{
+    %tickRate = 0.032;
+    
+	//Rotations per second is calculated based on a standard update tick being 32ms. So we scale by the tick speed, then add that to our rotation to 
+	//get a nice rotation speed.
+	if(%this.horizontal)
+	{
+		if(%this.forward)
+			%this.owner.rotation.z += ( ( 360 * %this.rotationsPerMinute ) / 60 ) * %tickRate;
+		else
+			%this.owner.rotation.z -= ( ( 360 * %this.rotationsPerMinute ) / 60 ) * %tickRate;
+	}
+	else
+	{
+		%this.owner.rotation.x += ( ( 360 * %this.rotationsPerMinute ) / 60 ) * %tickRate;
+	}
+}

+ 7 - 0
Templates/Full/game/scripts/server/components/game/playerSpawner.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="PlayerSpawnerComponentAsset"
+    componentName="PlayerSpawner"
+    componentClass="Component"
+    friendlyName="Player Spawner"
+    componentType="Game"
+    description="When a client connects, it spawns a player object for them and attaches them to it."/>

+ 70 - 0
Templates/Full/game/scripts/server/components/game/playerSpawner.cs

@@ -0,0 +1,70 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+//registerComponent("PlayerSpawner", "Component", 
+//			"Player Spawner", "Game", false, "When a client connects, it spawns a player object for them and attaches them to it");
+
+function PlayerSpawner::onAdd(%this)
+{
+	%this.clientCount = 1;
+	%this.friendlyName = "Player Spawner";
+	%this.componentType = "Spawner";
+	
+	%this.addComponentField("GameObjectName", "The name of the game object we spawn for the players", string, "PlayerObject");
+}
+
+function PlayerSpawner::onClientConnect(%this, %client)
+{
+	%playerObj = SGOManager.spawn(%this.GameObjectName);
+	
+	if(!isObject(%playerObj))
+		return;
+
+	%playerObj.position = %this.owner.position;
+	
+	MissionCleanup.add(%playerObj);
+	
+	for(%b = 0; %b < %playerObj.getComponentCount(); %b++)
+    {
+       %comp = %playerObj.getComponentByIndex(%b);
+
+	   if(%comp.isMethod("onClientConnect"))
+         %comp.onClientConnect(%client);
+    }
+	
+	switchControlObject(%client, %playerObj);
+	switchCamera(%client, %playerObj);
+	
+	//%playerObj.getComponent(FPSControls).setupControls(%client);
+	
+	%this.clientCount++;
+}
+
+function PlayerSpawner::onClientDisConnect(%this, %client)
+{
+	
+}
+
+function PlayerSpawner::getClientID(%this)
+{
+	return ClientGroup.getObject(%this.clientOwner-1);
+}

+ 7 - 0
Templates/Full/game/scripts/server/components/input/fpsControls.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="FPSControlsComponentAsset"
+    componentName="FPSControls"
+    componentClass="Component"
+    friendlyName="FPS Controls"
+    componentType="Input"
+    description="First Person Shooter-type controls."/>

+ 249 - 0
Templates/Full/game/scripts/server/components/input/fpsControls.cs

@@ -0,0 +1,249 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+//registerComponent("FPSControls", "Component", "FPS Controls", "Input", false, "First Person Shooter-type controls");
+
+function FPSControls::onAdd(%this)
+{
+   Parent::onBehaviorAdd(%this);
+
+   //
+	%this.beginGroup("Keys");
+		%this.addComponentField(forwardKey, "Key to bind to vertical thrust", keybind, "keyboard w");
+		%this.addComponentField(backKey, "Key to bind to vertical thrust", keybind, "keyboard s");
+		%this.addComponentField(leftKey, "Key to bind to horizontal thrust", keybind, "keyboard a");
+		%this.addComponentField(rightKey, "Key to bind to horizontal thrust", keybind, "keyboard d");
+		
+		%this.addComponentField(jump, "Key to bind to horizontal thrust", keybind, "keyboard space");
+	%this.endGroup();
+	
+	%this.beginGroup("Mouse");
+		%this.addComponentField(pitchAxis, "Key to bind to horizontal thrust", keybind, "mouse yaxis");
+		%this.addComponentField(yawAxis, "Key to bind to horizontal thrust", keybind, "mouse xaxis");
+	%this.endGroup();
+	
+	%this.addComponentField(moveSpeed, "Horizontal thrust force", float, 300.0);
+	%this.addComponentField(jumpStrength, "Vertical thrust force", float, 3.0);
+   //
+
+   %control = %this.owner.getComponent( ControlObjectComponent );
+   if(!%control)
+   	   return echo("SPECTATOR CONTROLS: No Control Object behavior!");
+		
+	//%this.Physics = %this.owner.getComponent( PlayerPhysicsComponent );
+	
+	//%this.Animation = %this.owner.getComponent( AnimationComponent );
+	
+	//%this.Camera = %this.owner.getComponent( MountedCameraComponent );
+	
+	//%this.Animation.playThread(0, "look");
+	
+	%this.setupControls(%control.getClientID());
+}
+
+function FPSControls::onRemove(%this)
+{
+   Parent::onBehaviorRemove(%this);
+   
+   commandToClient(%control.clientOwnerID, 'removeInput', %this.forwardKey);
+   commandToClient(%control.clientOwnerID, 'removeInput', %this.backKey);
+   commandToClient(%control.clientOwnerID, 'removeInput', %this.leftKey);
+   commandToClient(%control.clientOwnerID, 'removeInput', %this.rightKey);
+   
+   commandToClient(%control.clientOwnerID, 'removeInput', %this.pitchAxis);
+   commandToClient(%control.clientOwnerID, 'removeInput', %this.yawAxis);
+}
+
+function FPSControls::onBehaviorFieldUpdate(%this, %field)
+{
+   %controller = %this.owner.getBehavior( ControlObjectBehavior );
+   commandToClient(%controller.clientOwnerID, 'updateInput', %this.getFieldValue(%field), %field);
+}
+
+function FPSControls::onClientConnect(%this, %client)
+{
+   %this.setupControls(%client);
+}
+
+
+function FPSControls::setupControls(%this, %client)
+{
+   %control = %this.owner.getComponent( ControlObjectComponent );
+   if(!%control.isControlClient(%client))
+   {
+      echo("FPS CONTROLS: Client Did Not Match");
+      return;
+   }
+   
+   %inputCommand = "FPSControls";
+
+   %test = %this.forwardKey;
+   
+   /*SetInput(%client, %this.forwardKey.x,  %this.forwardKey.y,  %inputCommand@"_forwardKey");
+   SetInput(%client, %this.backKey.x,     %this.backKey.y,     %inputCommand@"_backKey");
+   SetInput(%client, %this.leftKey.x,     %this.leftKey.y,     %inputCommand@"_leftKey");
+   SetInput(%client, %this.rightKey.x,    %this.rightKey.y,    %inputCommand@"_rightKey");
+   
+   SetInput(%client, %this.jump.x,        %this.jump.y,        %inputCommand@"_jump");
+      
+   SetInput(%client, %this.pitchAxis.x,   %this.pitchAxis.y,   %inputCommand@"_pitchAxis");
+   SetInput(%client, %this.yawAxis.x,     %this.yawAxis.y,     %inputCommand@"_yawAxis");*/
+
+   SetInput(%client, "keyboard",  "w",  %inputCommand@"_forwardKey");
+   SetInput(%client, "keyboard",  "s",     %inputCommand@"_backKey");
+   SetInput(%client, "keyboard",  "a",     %inputCommand@"_leftKey");
+   SetInput(%client, "keyboard",  "d",    %inputCommand@"_rightKey");
+   
+   SetInput(%client, "keyboard",  "space",        %inputCommand@"_jump");
+      
+   SetInput(%client, "mouse",   "yaxis",   %inputCommand@"_pitchAxis");
+   SetInput(%client, "mouse",   "xaxis",     %inputCommand@"_yawAxis");
+
+   SetInput(%client, "keyboard",   "f",     %inputCommand@"_flashlight");
+ 
+}
+
+function FPSControls::onMoveTrigger(%this, %triggerID)
+{
+   //check if our jump trigger was pressed!
+   if(%triggerID == 2)
+   {
+      %this.owner.applyImpulse("0 0 0", "0 0 " @ %this.jumpStrength);
+   }
+}
+
+function FPSControls::Update(%this)
+{
+	return;
+	
+	%moveVector = %this.owner.getMoveVector();
+	%moveRotation = %this.owner.getMoveRotation();
+	
+	%this.Physics.moveVector = "0 0 0";
+
+   if(%moveVector.x != 0)
+   {
+		%fv = VectorNormalize(%this.owner.getRightVector());
+      
+		%forMove = VectorScale(%fv, (%moveVector.x));// * (%this.moveSpeed * 0.032)));
+		
+   		//%this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove);
+		
+		%this.Physics.moveVector = VectorAdd(%this.Physics.moveVector, %forMove);
+	
+		//if(%forMove > 0)
+		//	%this.Animation.playThread(1, "run");
+   }
+	/*else
+	{
+		%fv = VectorNormalize(%this.owner.getRightVector());
+      
+		%forMove = VectorScale(%fv, (%moveVector.x * (%this.moveSpeed * 0.032)));
+	
+	    if(%forMove <= 0)
+			%this.Animation.stopThread(1);
+		
+	}*/
+   
+   if(%moveVector.y != 0)
+   {
+      %fv = VectorNormalize(%this.owner.getForwardVector());
+      
+      %forMove = VectorScale(%fv, (%moveVector.y));// * (%this.moveSpeed * 0.032)));
+	
+	  //%this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove);
+	
+	  %this.Physics.moveVector = VectorAdd(%this.Physics.moveVector, %forMove);
+      
+	//if(VectorLen(%this.Physics.velocity) < 2)
+    //  		%this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove);
+   }
+   
+   /*if(%moveVector.z)
+   {
+      %fv = VectorNormalize(%this.owner.getUpVector());
+      
+      %forMove = VectorScale(%fv, (%moveVector.z * (%this.moveSpeed * 0.032)));
+      
+      %this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove);
+   }*/
+   
+   if(%moveRotation.x != 0)
+   {
+		%look = mRadToDeg(%moveRotation.x) / 180;
+		
+		//%this.Animation.setThreadPos(0, %look);
+		
+		%this.owner.getComponent( MountedCameraComponent ).rotationOffset.x += mRadToDeg(%moveRotation.x);
+		
+		//%this.Camera.rotationOffset.x += mRadToDeg(%moveRotation.x);
+   }
+   //   %this.owner.rotation.x += mRadToDeg(%moveRotation.x);
+   
+   if(%moveRotation.z != 0)
+   {
+	  %zrot = mRadToDeg(%moveRotation.z);
+	  %this.owner.getComponent( MountedCameraComponent ).rotationOffset.z += %zrot;
+      //%this.owner.rotation.z += %zrot;
+   }
+}
+
+//
+function FPSControls_forwardKey(%val)
+{
+   $mvForwardAction = %val;
+}
+
+function FPSControls_backKey(%val)
+{
+   $mvBackwardAction = %val;
+}
+
+function FPSControls_leftKey(%val)
+{
+   $mvLeftAction = %val;
+}
+
+function FPSControls_rightKey(%val)
+{
+   $mvRightAction = %val;
+}
+
+function FPSControls_yawAxis(%val)
+{
+   $mvYaw += getMouseAdjustAmount(%val);
+}
+
+function FPSControls_pitchAxis(%val)
+{
+   $mvPitch += getMouseAdjustAmount(%val);
+}
+
+function FPSControls_jump(%val)
+{
+   $mvTriggerCount2++;
+}
+
+function FPSControls_flashLight(%val)
+{
+   $mvTriggerCount3++;
+}

+ 82 - 0
Templates/Full/game/scripts/server/components/input/inputManager.cs

@@ -0,0 +1,82 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function SetInput(%client, %device, %key, %command, %bindMap, %behav)
+{
+   commandToClient(%client, 'SetInput', %device, %key, %command, %bindMap, %behav);  
+}
+
+function RemoveInput(%client, %device, %key, %command, %bindMap)
+{
+   commandToClient(%client, 'removeInput', %device, %key, %command, %bindMap);  
+}
+
+function clientCmdSetInput(%device, %key, %command, %bindMap, %behav)
+{
+   //if we're requesting a custom bind map, set that up
+   if(%bindMap $= "")
+      %bindMap = moveMap;
+   
+   if (!isObject(%bindMap)){
+      new ActionMap(moveMap);
+      moveMap.push();
+   }
+      
+   //get our local
+   //%localID = ServerConnection.resolveGhostID(%behav); 
+   
+   //%tmpl = %localID.getTemplate();
+   //%tmpl.insantiateNamespace(%tmpl.getName());
+      
+   //first, check if we have an existing command
+   %oldBind = %bindMap.getBinding(%command);
+   if(%oldBind !$= "")
+      %bindMap.unbind(getField(%oldBind, 0), getField(%oldBind, 1));
+    
+   //now, set the requested bind   
+   %bindMap.bind(%device, %key, %command);
+}
+
+function clientCmdRemoveSpecCtrlInput(%device, %key, %bindMap)
+{
+   //if we're requesting a custom bind map, set that up
+   if(%bindMap $= "")
+      %bindMap = moveMap;
+   
+   if (!isObject(%bindMap))
+      return;
+      
+   %bindMap.unbind(%device, %key);
+}
+
+function clientCmdSetupClientBehavior(%bhvrGstID)
+{
+   %localID = ServerConnection.resolveGhostID(%bhvrGstID); 
+   %tmpl = %localID.getTemplate();
+   %tmpl.insantiateNamespace(%tmpl.getName());
+}
+
+function getMouseAdjustAmount(%val)
+{
+   // based on a default camera FOV of 90'
+   return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity;
+}

+ 7 - 0
Templates/Full/game/scripts/server/components/meshComponent.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="MeshComponentAsset"
+    componentName=""
+    componentClass="MeshComponent"
+    friendlyName="Mesh"
+    componentType="Render"
+    description="Enables an entity to render a shape."/>

+ 7 - 0
Templates/Full/game/scripts/server/components/playerControllerComponent.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="PlayerControllerComponentAsset"
+    componentName=""
+    componentClass="PlayerControllerComponent"
+    friendlyName="Player Controller"
+    componentType="Game"
+    description="Enables an entity to move like a player object."/>

+ 7 - 0
Templates/Full/game/scripts/server/components/stateMachineComponent.asset.taml

@@ -0,0 +1,7 @@
+<ComponentAsset
+    AssetName="StateMachineComponentAsset"
+    componentName=""
+    componentClass="StateMachineComponent"
+    friendlyName="State Machine"
+    componentType="Game"
+    description="Enables a state machine on the entity."/>

+ 25 - 0
Templates/Full/game/scripts/server/gameCore.cs

@@ -573,6 +573,31 @@ function GameCore::onClientEnterGame(%game, %client)
       %client.isAiControlled(),
       %client.isAdmin,
       %client.isSuperAdmin);
+      
+   %entityIds = parseMissionGroupForIds("Entity", "");
+   %entityCount = getWordCount(%entityIds);
+   
+   for(%i=0; %i < %entityCount; %i++)
+   {
+      %entity = getWord(%entityIds, %i);
+      
+      for(%e=0; %e < %entity.getCount(); %e++)
+      {
+         %child = %entity.getObject(%e);
+         if(%child.getCLassName() $= "Entity")
+            %entityIds = %entityIds SPC %child.getID();  
+      }
+      
+      for(%c=0; %c < %entity.getComponentCount(); %c++)
+      {
+         %comp = %entity.getComponentByIndex(%c);
+         
+         if(%comp.isMethod("onClientConnect"))
+         {
+            %comp.onClientConnect(%client);  
+         }
+      }
+   }
 }
 
 function GameCore::onClientLeaveGame(%game, %client)

+ 28 - 0
Templates/Full/game/scripts/server/gameObjects/GameObjectList.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<GameObjects>
+    <GameObject>
+        <Name>ScriptedTriggerObject</Name>
+        <TAMLPath>data/EC/scripts/gameObjects/ScriptedTriggerObject.taml</TAMLPath>
+        <ScriptPath>data/EC/scripts/gameObjects/ScriptedTriggerObject.cs</ScriptPath>
+    </GameObject>
+    <GameObject>
+        <Name>PlayerObject</Name>
+        <TAMLPath>data/EC/scripts/gameObjects/playerObject.taml</TAMLPath>
+        <ScriptPath>data/EC/scripts/gameObjects/playerObject.cs</ScriptPath>
+    </GameObject>
+    <GameObject>
+        <Name>spectatorObject</Name>
+        <TAMLPath>data/EC/scripts/gameObjects/spectatorObject.taml</TAMLPath>
+        <ScriptPath>data/EC/scripts/gameObjects/spectatorObject.cs</ScriptPath>
+    </GameObject>
+    <GameObject>
+        <Name>ThirdPersonPlayerObject</Name>
+        <TAMLPath>data/EC/scripts/gameObjects/ThirdPersonPlayerObject.taml</TAMLPath>
+        <ScriptPath>data/EC/scripts/gameObjects/ThirdPersonPlayerObject.cs</ScriptPath>
+    </GameObject>
+    <GameObject>
+        <Name>FirstPersonArms</Name>
+        <TAMLPath>data/EC/scripts/gameObjects/FirstPersonArms.taml</TAMLPath>
+        <ScriptPath>data/EC/scripts/gameObjects/FirstPersonArms.cs</ScriptPath>
+    </GameObject>
+</GameObjects>

+ 75 - 0
Templates/Full/game/scripts/server/gameObjects/GameObjectManager.cs

@@ -0,0 +1,75 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+function execGameObjects()
+{
+   //find all GameObjectAssets
+   %assetQuery = new AssetQuery();
+   if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset"))
+      return; //if we didn't find ANY, just exit
+      
+   %count = %assetQuery.getCount();
+      
+	for(%i=0; %i < %count; %i++)
+	{
+	   %assetId = %assetQuery.getAsset(%i);
+      
+      %gameObjectAsset = AssetDatabase.acquireAsset(%assetId);
+      
+      if(isFile(%gameObjectAsset.scriptFilePath))
+         exec(%gameObjectAsset.scriptFilePath);
+	}
+}
+
+function spawnGameObject(%name, %addToMissionGroup)
+{
+	if(%addToMissionGroup $= "")
+		%addToMissionGroup = true;
+		
+   //find all GameObjectAssets
+   %assetQuery = new AssetQuery();
+   if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset"))
+      return; //if we didn't find ANY, just exit
+      
+   %count = %assetQuery.getCount();
+      
+	for(%i=0; %i < %count; %i++)
+	{
+	   %assetId = %assetQuery.getAsset(%i);
+      
+      %gameObjectAsset = AssetDatabase.acquireAsset(%assetId);
+      
+      if(%gameObjectAsset.gameObjectName $= %name)
+		{
+		   if(isFile(%gameObjectAsset.TAMLFilePath))
+         {
+            %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath);
+            
+            if(%addToMissionGroup == true)
+               MissionGroup.add(%newSGOObject);
+               
+            return %newSGOObject;
+         }
+		}
+	}
+		
+	return 0;
+}

+ 5 - 0
Templates/Full/game/scripts/server/gameObjects/ThirdPersonPlayerObject.asset.taml

@@ -0,0 +1,5 @@
+<GameObjectAsset
+    AssetName="ThirdPersonPlayerGameObjectAsset"
+    gameObjectName="ThirdPersonPlayer"
+    TAMLFilePath="scripts/server/gameObjects/ThirdPersonPlayerObject.taml"
+    scriptFilePath="scripts/server/gameObjects/ThirdPersonPlayerObject.cs"/>

+ 253 - 0
Templates/Full/game/scripts/server/gameObjects/ThirdPersonPlayerObject.cs

@@ -0,0 +1,253 @@
+function ThirdPersonPlayerObject::onAdd(%this)
+{
+   %this.turnRate = 0.3;
+
+   %this.phys = %this.getComponent("PlayerControllerComponent");
+   %this.collision = %this.getComponent("CollisionComponent");
+   %this.cam = %this.getComponent("CameraComponent");
+   %this.camArm = %this.getComponent("CameraOrbiterComponent");
+   %this.animation = %this.getComponent("AnimationComponent");
+   %this.stateMachine = %this.getComponent("StateMachineComponent");
+   %this.mesh = %this.getComponent("MeshComponent");
+
+   %this.stateMachine.forwardVector = 0;
+
+   %this.crouch = false;
+   
+   %this.firstPerson = false;
+   
+   %this.crouchSpeedMod = 0.5;
+   
+   %this.aimOrbitDist = 1.5;
+   %this.regularOrbitDist = 5;
+   
+   %this.regularOrbitMaxPitch = 70;
+   %this.regularOrbitMinPitch = -10;
+   
+   %this.aimedMaxPitch = 90;
+   %this.aimedMinPitch = -90;
+   
+   %this.arms = SGOManager.spawn("FirstPersonArms", true);
+   
+   %this.add(arms);
+   
+   //%this.mesh.mountObject(%this.arms, "Eye");
+}
+
+function ThirdPersonPlayerObject::onRemove(%this)
+{
+
+}
+
+function ThirdPersonPlayerObject::moveVectorEvent(%this)
+{
+    %moveVector = %this.getMoveVector();
+
+    // forward of the camera on the x-z plane
+    %cameraForward = %this.cam.getForwardVector();
+
+    %cameraRight = %this.cam.getRightVector();
+
+    %moveVec = VectorAdd(VectorScale(%cameraRight, %moveVector.x), VectorScale(%cameraForward, %moveVector.y));
+
+   if(%this.aiming || %this.firstPerson)
+   {
+      %forMove = "0 0 0";
+      
+      if(%moveVector.x != 0)
+      {
+         %this.phys.inputVelocity.x = %moveVector.x * 10;
+      }
+      else
+      {
+         %this.phys.inputVelocity.x = 0;
+      }
+
+      if(%moveVector.y != 0)
+      {
+
+         %this.phys.inputVelocity.y = %moveVector.y * 10;
+      }
+      else
+      {
+         %this.phys.inputVelocity.y = 0;
+      }
+   }
+   else
+   {
+      if(%moveVec.x == 0 && %moveVec.y == 0)
+      {
+         %this.phys.inputVelocity = "0 0 0";
+         %this.stateMachine.forwardVector = 0;
+      }
+      else
+      {
+         %moveVec.z = 0;
+
+         %curForVec = %this.getForwardVector();
+
+         %newForVec = VectorLerp(%curForVec, %moveVec, %this.turnRate);
+
+         %this.setForwardVector(%newForVec);
+         
+         %this.phys.inputVelocity.y = 10;
+
+         %this.stateMachine.forwardVector = 1;
+      }
+   }
+   
+   if(%this.crouch)
+      %this.phys.inputVelocity = VectorScale(%this.phys.inputVelocity, %this.crouchSpeedMod);
+}
+
+function ThirdPersonPlayerObject::moveYawEvent(%this)
+{
+   %moveRotation = %this.getMoveRotation();
+
+    %camOrb = %this.getComponent("CameraOrbiterComponent");
+    
+    if(%this.aiming || %this.firstPerson)
+    {
+      %this.rotation.z += %moveRotation.z * 10;
+    }
+
+    %camOrb.rotation.z += %moveRotation.z * 10;
+}
+
+function ThirdPersonPlayerObject::movePitchEvent(%this)
+{
+   %moveRotation = %this.getMoveRotation();
+
+    %camOrb = %this.getComponent("CameraOrbiterComponent");
+
+    %camOrb.rotation.x += %moveRotation.x * 10;
+}
+
+function ThirdPersonPlayerObject::moveRollEvent(%this){}
+
+function ThirdPersonPlayerObject::moveTriggerEvent(%this, %triggerNum, %triggerValue)
+{
+   if(%triggerNum == 3 && %triggerValue)
+   {
+      if(%triggerValue)
+      {
+        %this.firstPerson = !%this.firstPerson;
+        
+        if(%this.firstPerson)
+        {
+            %this.rotation.z = %this.cam.rotationOffset.z;
+            %this.camArm.orbitDistance = 0;
+            %this.camArm.maxPitchAngle = %this.aimedMaxPitch;
+            %this.camArm.minPitchAngle = %this.aimedMinPitch;
+            
+            %this.cam.positionOffset = "0 0 0";
+            %this.cam.rotationOffset = "0 0 0";
+        }
+        else if(%this.aiming)
+        {
+            %this.camArm.orbitDistance = %this.aimOrbitDist;
+            
+            %this.camArm.maxPitchAngle = %this.aimedMaxPitch;
+            %this.camArm.minPitchAngle = %this.aimedMinPitch;
+        }
+        else
+        {
+            %this.camArm.orbitDistance = %this.regularOrbitDist;
+            
+            %this.camArm.maxPitchAngle = %this.regularOrbitMaxPitch;
+            %this.camArm.minPitchAngle = %this.regularOrbitMinPitch;
+        }
+        
+        commandToClient(localclientConnection, 'SetClientRenderShapeVisibility', 
+            localclientConnection.getGhostID(%this.getComponent("MeshComponent")), !%this.firstPerson);
+      }
+   }
+	else if(%triggerNum == 2 && %triggerValue == true)
+	{
+	   //get our best collision assuming up is 0 0 1
+	   %collisionAngle = %this.collision.getBestCollisionAngle("0 0 1");
+	   
+	   if(%collisionAngle >= 80)
+	   {
+	      %surfaceNormal = %this.collision.getCollisionNormal(0);
+	      %jumpVector = VectorScale(%surfaceNormal, 200);
+	      echo("Jump surface Angle is at: " @ %surfaceNormal);
+	      
+	      %this.phys.applyImpulse(%this.position, %jumpVector);
+	      %this.setForwardVector(%jumpVector);
+	   }
+      else
+         %this.phys.applyImpulse(%this.position, "0 0 300");
+	}
+	else if(%triggerNum == 4)
+	{
+      %this.crouch = %triggerValue;
+	}
+	else if(%triggerNum == 1)
+	{
+	   %this.aiming = %triggerValue;  
+	   
+	   if(%this.aiming)
+      {
+         %this.rotation.z = %this.cam.rotationOffset.z;
+         %this.camArm.orbitDistance = %this.aimOrbitDist;
+         %this.camArm.maxPitchAngle = %this.aimedMaxPitch;
+         %this.camArm.minPitchAngle = %this.aimedMinPitch;
+      }
+      else
+      {
+         %this.camArm.orbitDistance = %this.regularOrbitDist;
+         %this.camArm.maxPitchAngle = %this.regularOrbitMaxPitch;
+         %this.camArm.minPitchAngle = %this.regularOrbitMinPitch;
+      }
+	}
+}
+
+function ThirdPersonPlayerObject::onCollisionEvent(%this, %colObject, %colNormal, %colPoint, %colMatID, %velocity)
+{
+   if(!%this.phys.isContacted())
+    echo(%this @ " collided with " @ %colObject);
+}
+
+function ThirdPersonPlayerObject::processTick(%this)
+{
+   %moveVec = %this.getMoveVector();
+   %bestFit = "";
+   
+   if(%this.crouch)
+   {
+      if(%moveVec.x != 0 || %moveVec.y != 0)
+         %bestFit = "Crouch_Forward";
+      else
+         %bestFit = "Crouch_Root";
+   }
+   else
+   {
+      if(%moveVec.x != 0 || %moveVec.y != 0)
+         %bestFit = "Run";
+      else
+         %bestFit = "Root";
+   }
+   
+   if(%this.animation.getThreadAnimation(0) !$= %bestFit)
+      %this.animation.playThread(0, %bestFit);
+}
+
+//Used for first person mode
+function clientCmdSetClientRenderShapeVisibility(%id, %visiblilty)
+{
+   %localID = ServerConnection.resolveGhostID(%id); 
+   %localID.enabled = %visiblilty;
+}
+
+function serverToClientObject( %serverObject )
+{
+   assert( isObject( LocalClientConnection ), "serverToClientObject() - No local client connection found!" );
+   assert( isObject( ServerConnection ), "serverToClientObject() - No server connection found!" );      
+         
+   %ghostId = LocalClientConnection.getGhostId( %serverObject );
+   if ( %ghostId == -1 )
+      return 0;
+                
+   return ServerConnection.resolveGhostID( %ghostId );   
+}

+ 99 - 0
Templates/Full/game/scripts/server/gameObjects/ThirdPersonPlayerObject.taml

@@ -0,0 +1,99 @@
+<Entity
+    scale="1 1 1"
+    isSelectionEnabled="false"
+    class="ThirdPersonPlayerObject"
+    canSave="true"
+    canSaveDynamicFields="true"
+    position="0 0 0"
+    rotation="0 0 0">
+    <Component
+        networked="false"
+        enabled="true"
+        class="ControlObjectComponent"
+        clientOwner="1" />
+    <CollisionComponent
+        friendlyName="Collision(Component)"
+        networked="false"
+        enabled="true"
+        collisionType="Bounds"
+        LineOfSightType="Collision Mesh"
+        decalType="Collision Mesh"
+        CollisionMeshPrefix="Collision"
+        BlockCollisions="true" />
+    <PlayerControllerComponent
+        componentType="Physics"
+        friendlyName="Simple Physics"
+        description="Simple physics behavior that allows gravity and impulses."
+        networked="false"
+        enabled="true"
+        gravity="0 0 -9"
+        velocity="0 0 0"
+        isStatic="false" />
+    <MeshComponent
+        componentType="Render"
+        friendlyName="Mesh Component"
+        description="Causes the object to render a non-animating 3d shape using the file provided."
+        networked="true"
+        enabled="true"
+        MeshAsset="Art:SoldierPlayer" />
+    <Component
+        networked="false"
+        enabled="true"
+        class="FPSControls" />
+    <CameraComponent
+        networked="false"
+        enabled="true"
+        FOV="80"
+        MinFOV="5"
+        MaxFOV="175"
+        ScreenAspect="1024 768"
+        targetNode="Eye"
+        positionOffset="0 0 0"
+        rotationOffset="0 0 0"
+        useParentTransform="false" />
+    <CameraOrbiterComponent
+        orbitDistance="5"
+        maxPitchAngle="70"
+        minPitchAngle="-70"
+        networked="false"
+        enabled="true" />
+	<AnimationComponent
+        componentType="Render"
+        friendlyName="Animation Component"
+        description="An animation component"
+        networked="true"
+        enabled="true"/>
+    <SpotLight
+        range="10"
+        innerAngle="40"
+        outerAngle="45"
+        isEnabled="true"
+        color="1 1 1 1"
+        brightness="1"
+        castShadows="false"
+        priority="1"
+        animate="true"
+        animationPeriod="1"
+        animationPhase="1"
+        flareScale="1"
+        attenuationRatio="0 1 1"
+        shadowType="Spot"
+        texSize="512"
+        overDarkFactor="2000 1000 500 100"
+        shadowDistance="400"
+        shadowSoftness="0.15"
+        numSplits="1"
+        logWeight="0.91"
+        fadeStartDistance="0"
+        lastSplitTerrainOnly="false"
+        representedInLightmap="false"
+        shadowDarkenColor="0 0 0 -1"
+        includeLightmappedGeometryInShadow="false"
+        position="0 0 1.6137"
+        rotation="0 0 1 0"
+        mountNode="-1"
+        mountPos="0 0 1.5"
+        mountRot="1 0 0 0"
+        canSave="true"
+        canSaveDynamicFields="true" />
+</Entity>

+ 20 - 0
Templates/Full/game/scripts/server/scriptExec.cs

@@ -58,3 +58,23 @@ exec("./turret.cs");
 // Load our gametypes
 exec("./gameCore.cs"); // This is the 'core' of the gametype functionality.
 exec("./gameDM.cs"); // Overrides GameCore with DeathMatch functionality.
+
+//Entity/Component stuff
+if(isFile("./components/game/camera.cs"))
+   exec("./components/game/camera.cs");
+if(isFile("./components/game/controlObject.cs"))
+   exec("./components/game/controlObject.cs");
+if(isFile("./components/game/itemRotate.cs"))
+   exec("./components/game/itemRotate.cs");
+if(isFile("./components/game/playerSpawner.cs"))
+   exec("./components/game/playerSpawner.cs");
+if(isFile("./components/input/fpsControls.cs"))
+   exec("./components/input/fpsControls.cs");
+if(isFile("./components/input/inputManager.cs"))
+   exec("./components/input/inputManager.cs");
+   
+if(isFile("./gameObjects/GameObjectManager.cs"))
+{
+   exec("./gameObjects/GameObjectManager.cs");
+   execGameObjects();  
+}

+ 45 - 0
Templates/Full/game/tools/componentEditor/gui/superToolTipDlg.ed.gui

@@ -0,0 +1,45 @@
+%guiContent = new GuiControl(SuperTooltipDlg) {
+   canSaveDynamicFields = "0";
+   Profile = "GuiTransparentProfileModeless";
+   class = "SuperTooltip";
+   HorizSizing = "right";
+   VertSizing = "bottom";
+   position = "0 0";
+   Extent = "640 480";
+   MinExtent = "8 2";
+   canSave = "1";
+   Visible = "1";
+   hovertime = "1000";
+
+   new GuiControl(SuperTooltipWindow) {
+      canSaveDynamicFields = "0";
+      Profile = "EditorTextEditBoldModeless";
+      HorizSizing = "right";
+      VertSizing = "bottom";
+      position = "216 160";
+      Extent = "221 134";
+      MinExtent = "8 2";
+      canSave = "1";
+      Visible = "1";
+      hovertime = "1000";
+      internalName = "tooltipWindow";
+
+      new GuiMLTextCtrl(SuperTooltipMLText) {
+         canSaveDynamicFields = "0";
+         Profile = "EditorMLTextProfileModeless";
+         HorizSizing = "right";
+         VertSizing = "bottom";
+         position = "5 5";
+         Extent = "210 14";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         lineSpacing = "2";
+         allowColorChars = "0";
+         maxChars = "-1";
+         internalName = "tooltipMLText";
+      };
+   };
+};
+

+ 28 - 0
Templates/Full/game/tools/componentEditor/main.cs

@@ -0,0 +1,28 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+//Scripts
+exec("./scripts/componentEditor.ed.cs");
+exec("./scripts/superToolTipDlg.ed.cs");
+
+//gui
+exec("./gui/superToolTipDlg.ed.gui");

+ 155 - 0
Templates/Full/game/tools/componentEditor/scripts/SuperToolTipDlg.ed.cs

@@ -0,0 +1,155 @@
+function createSuperTooltipTheme(%name)
+{
+   %theme = new ScriptObject()
+   {
+      class = SuperTooltipTheme;      
+   };
+   
+   %theme.setName(%name);
+   
+   return %theme;
+}
+
+function SuperTooltipTheme::addStyle(%this, %name, %style)
+{
+   %this.styles[%name] = %style;   
+}
+
+function SuperTooltipTheme::setDefaultStyle(%this, %type, %default)
+{
+   %this.defaultStyles[%type] = %default;   
+}
+
+function SuperTooltipTheme::setSpacing(%this, %verticalSpace, %horizontalSpace)
+{
+   %this.verticalSpace = %verticalSpace;
+   %this.horizontalSpace = %horizontalSpace;   
+}
+
+function SuperTooltipTheme::getStyle(%this, %name)
+{
+   return %this.styles[%name];   
+}
+
+function SuperTooltip::init(%this, %theme)
+{
+   %this.clearTooltip();
+      
+   if(isObject(%theme))
+      %this.setTheme(%theme);
+}
+
+function SuperTooltip::clearTooltip(%this)
+{
+   if(%this.paramCount > 0)
+   {
+      for(%i=0;%i<%this.paramCount;%i++)
+         %this.param[%i] = "";      
+   }
+   
+   %this.title = "";
+   %this.paramCount = 0;   
+}
+
+function SuperTooltip::processTooltip(%this, %globalPos, %verticalAlign, %horizontalAlign)
+{
+   if (%verticalAlign $= "")
+      %verticalAlign = 1;
+   if (%horizontalAlign $= "")
+      %horizontalAlign = 0;
+   
+   %tooltipWindow = %this.findObjectByInternalName("tooltipWindow");
+   
+   if(isObject(%tooltipWindow))
+      %tooltipMLText = %tooltipWindow.findObjectByInternalName("tooltipMLText");
+   else
+      return false;
+      
+   if(!isObject(%tooltipMLText))
+      return false;
+   
+   %verticalSpace = %this.theme.verticalSpace;
+   %horizontalSpace = %this.theme.horizontalSpace;
+   
+   if (%verticalAlign == 1)
+      %verticalSpace = -%verticalSpace;
+   if (%horizontalAlign == 1)
+      %horizontalSpace = -%horizontalSpace;
+   
+   %text = %this.getFormatedText();
+   %tooltipMLText.setText(%text);
+   
+   canvas.pushDialog(%this);
+   
+   %tooltipMLText.forceReflow();
+   %MLExtent = %tooltipMLText.extent;
+   %MLHeight = getWord(%MLExtent, 1);
+   
+   %tooltipExtent = %tooltipWindow.extent;
+   %tooltipWidth = getWord(%tooltipExtent, 0);
+   %tooltipHeight = %MLHeight;
+   %tooltipWindow.extent = %tooltipWidth SPC %tooltipHeight;  
+   
+   %globalPosX = getWord(%globalPos, 0);
+   %globalPosY = getWord(%globalPos, 1);
+   
+   %tooltipPosX = %globalPosX - (%horizontalAlign * %tooltipWidth) + %horizontalSpace;
+   %tooltipPosY = %globalPosY - (%verticalAlign * %tooltipHeight) + %verticalSpace;
+   
+   %tooltipWindow.setPosition(%tooltipPosX, %tooltipPosY); 
+   
+   return true;
+}
+
+function SuperTooltip::hide(%this)
+{
+   canvas.popDialog(%this);   
+
+   %this.clearTooltip();
+}
+
+function SuperTooltip::setTheme(%this, %theme)
+{
+   %this.theme = %theme;   
+}
+
+function SuperTooltip::setTitle(%this, %title, %style)
+{
+   if(%style !$= "")
+      %themeStyle = %this.theme.styles[%style];
+   else
+      %themeStyle = %this.theme.getStyle(%this.theme.defaultStyles[Title]);
+   
+   %this.title = %themeStyle @ %title;      
+}
+
+function SuperTooltip::addParam(%this, %title, %text, %paramTitleStyle, %paramStyle)
+{
+   if(%paramTitleStyle !$= "")
+      %themeTitleStyle = %this.theme.styles[%paramTitleStyle];
+   else
+      %themeTitleStyle = %this.theme.getStyle(%this.theme.defaultStyles[ParamTitle]);
+      
+   if(%paramStyle !$= "")
+      %themeStyle = %this.theme.styles[%paramStyle];
+   else
+      %themeStyle = %this.theme.getStyle(%this.theme.defaultStyles[Param]);
+   
+   if (%title $= "")
+      %this.param[%this.paramCount] = %themeStyle @ %text @ "\n";
+   else
+      %this.param[%this.paramCount] = %themeTitleStyle @ %title @ ":  " @ %themeStyle @ %text @ "\n";
+   %this.paramCount++;   
+}
+
+function SuperTooltip::getFormatedText(%this)
+{
+   %text = %this.title @ "\n\n";
+   
+   for(%i=0;%i<%this.paramCount;%i++)
+   {
+      %text = %text @ %this.param[%i];      
+   }
+   
+   return %text;
+}

+ 233 - 0
Templates/Full/game/tools/componentEditor/scripts/componentEditor.ed.cs

@@ -0,0 +1,233 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function GuiInspectorEntityGroup::CreateContent(%this)
+{
+}
+
+function GuiInspectorEntityGroup::InspectObject( %this, %targetObject )
+{
+   %this.stack.clear();
+   %this.stack.addGuiControl(%this.createAddComponentList());
+}
+
+function GuiInspectorEntityGroup::createAddComponentList(%this)
+{
+   %extent = %this.getExtent();
+   
+   %container = new GuiControl()
+   {
+      Profile = "EditorContainerProfile";
+      HorizSizing = "width";
+      VertSizing = "bottom";
+      Position = "0 0";
+      Extent = %extent.x SPC "25";
+   };
+
+   %componentList = new GuiPopUpMenuCtrlEx(QuickEditComponentList) 
+   {
+      Profile = "GuiPopupMenuProfile";
+      HorizSizing = "width";
+      VertSizing = "bottom";
+      position = "28 4";
+      Extent = (%extent.x - 28) SPC "18";
+      hovertime = "100";
+      tooltip = "The component to add to the object";
+      tooltipProfile = "EditorToolTipProfile";
+   };
+
+   %addButton = new GuiIconButtonCtrl() {
+      class = AddComponentQuickEditButton;
+      Profile = "EditorButton";
+      HorizSizing = "right";
+      VertSizing = "bottom";
+      Position = "2 0";
+      Extent = "24 24";
+      buttonMargin = "4 4";
+      iconLocation = "Left";
+      sizeIconToButton = "0";
+      iconBitmap = "tools/gui/images/iconAdd.png";
+      hovertime = "100";
+      tooltip = "Add the selected component to the object";
+      tooltipProfile = "EditorToolTipProfile";
+      componentList = %componentList;
+   };
+   
+   %componentList.refresh();
+   
+   %container.add(%componentList);
+   %container.add(%addButton);
+   
+   if(!isObject("componentTooltipTheme"))
+   {
+      %theme = createsupertooltiptheme("componentTooltipTheme");
+      %theme.addstyle("headerstyle", "<just:left><font:arial bold:16><color:000000>");
+      %theme.addstyle("headertwostyle", "<font:arial bold:14><color:000000>");
+      %theme.addstyle("basictextstyle", "<font:arial:14><color:000000>");
+      %theme.setdefaultstyle("title", "headerstyle");
+      %theme.setdefaultstyle("paramtitle", "headertwostyle");
+      %theme.setdefaultstyle("param", "basictextstyle");
+      %theme.setspacing(3, 0);
+   }
+   
+   return %container;
+}
+
+function QuickEditComponentList::refresh(%this)
+{
+   %this.clear();
+   
+   //find all ComponentAssets
+   %assetQuery = new AssetQuery();
+   if(!AssetDatabase.findAssetType(%assetQuery, "ComponentAsset"))
+      return; //if we didn't find ANY, just exit
+   
+   // Find all the types.
+   %count = %assetQuery.getCount();
+
+   %categories = "";
+   for (%i = 0; %i < %count; %i++)
+   {
+      %assetId = %assetQuery.getAsset(%i);
+      
+      %componentAsset = AssetDatabase.acquireAsset(%assetId);
+      %componentType = %componentAsset.componentType;
+      if (!isInList(%componentType, %categories))
+         %categories = %categories TAB %componentType;
+   }
+   
+   %categories = trim(%categories);
+   
+   %index = 0;
+   %categoryCount = getFieldCount(%categories);
+   for (%i = 0; %i < %categoryCount; %i++)
+   {
+      %category = getField(%categories, %i);
+      %this.addCategory(%category);
+      
+      for (%j = 0; %j < %count; %j++)
+      {
+         %assetId = %assetQuery.getAsset(%j);
+      
+         %componentAsset = AssetDatabase.acquireAsset(%assetId);
+         %componentType = %componentAsset.componentType;
+         %friendlyName = %componentAsset.friendlyName;
+		
+         if (%componentType $= %category)
+         {
+            //TODO: Haven't worked out getting categories to look distinct
+            //from entries in the drop-down so for now just indent them for the visual distinction
+            %spacedName = "    " @ %friendlyName;
+            %this.add(%spacedName, %index);
+            %this.component[%index] = %componentAsset;
+            %index++;
+         }
+      }
+   }
+}
+
+function QuickEditComponentList::onHotTrackItem( %this, %itemID )
+{
+   %componentObj = %this.component[%itemID];
+   if( isObject( %componentObj ) && %this.componentDesc != %componentObj )
+   {
+      SuperTooltipDlg.init("componentTooltipTheme");
+      SuperTooltipDlg.setTitle(%componentObj.friendlyName);
+      SuperTooltipDlg.addParam("", %componentObj.description @ "\n");
+      
+      %fieldCount = %componentObj.getComponentFieldCount();
+      for (%i = 0; %i < %fieldCount; %i++)
+      {
+         %name = getField(%componentObj.getComponentField(%i), 0);
+
+         SuperTooltipDlg.addParam(%name, %description @ "\n");
+      }
+      %position = %this.getGlobalPosition();
+      SuperTooltipDlg.processTooltip( %position,0,1 );
+      %this.opened = true;    
+      %this.componentDesc = %componentObj;
+   }
+   else if( !isObject( %componentObj ) )
+   {
+      if( %this.opened == true )
+         SuperTooltipDlg.hide();
+      %this.componentDesc = "";
+   }      
+}
+
+function QuickEditComponentList::setProperty(%this, %object)
+{
+   %this.objectToAdd = %object;
+}
+
+function QuickEditComponentList::onSelect(%this)
+{
+   if( %this.opened == true )
+      SuperTooltipDlg.hide();
+   
+   %this.componentToAdd = %this.component[%this.getSelected()];
+}
+
+function QuickEditComponentList::onCancel( %this )
+{
+   if( %this.opened == true )
+      SuperTooltipDlg.hide();
+}
+
+function AddComponentQuickEditButton::onClick(%this)
+{
+   %component = %this.componentList.componentToAdd;
+	
+	%componentName = %this.componentList.componentToAdd.componentName;
+	%componentClass = %this.componentList.componentToAdd.componentClass;
+	
+	%command = "$ComponentEditor::newComponent = new" SPC %componentClass SPC "(){ class = \"" 
+	@ %componentName @ "\"; };";
+	
+	eval(%command);
+   
+   %instance = $ComponentEditor::newComponent;
+   %undo = new UndoScriptAction()
+   {
+      actionName = "Added Component";
+      class = UndoAddComponent;
+      object = %this.componentList.objectToAdd;
+      component = %instance;
+   };
+
+   %undo.addToManager(LevelBuilderUndoManager);
+   
+   %instance.owner = Inspector.getInspectObject(0);
+   %instance.owner.add(%instance);
+   
+   Inspector.schedule( 50, "refresh" );
+   EWorldEditor.isDirty = true;
+}
+
+function addComponent(%obj, %instance)
+{
+   echo("Adding the component!");
+   %obj.addComponent(%instance);
+   Inspector.schedule( 50, "refresh" );
+   EWorldEditor.isDirty = true;
+}
+