diff --git a/Templates/BaseGame/game/core/Core.cs b/Templates/BaseGame/game/core/Core.cs
index 5559760ae..99efdd706 100644
--- a/Templates/BaseGame/game/core/Core.cs
+++ b/Templates/BaseGame/game/core/Core.cs
@@ -20,10 +20,11 @@ function CoreModule::onCreate(%this)
ModuleDatabase.LoadExplicit( "Core_Rendering" );
ModuleDatabase.LoadExplicit( "Core_Utility" );
ModuleDatabase.LoadExplicit( "Core_GUI" );
- ModuleDatabase.LoadExplicit( "CoreModule" );
ModuleDatabase.LoadExplicit( "Core_Lighting" );
ModuleDatabase.LoadExplicit( "Core_SFX" );
ModuleDatabase.LoadExplicit( "Core_PostFX" );
+ ModuleDatabase.LoadExplicit( "Core_Components" );
+ ModuleDatabase.LoadExplicit( "Core_GameObjects" );
ModuleDatabase.LoadExplicit( "Core_ClientServer" );
%prefPath = getPrefpath();
@@ -32,63 +33,6 @@ function CoreModule::onCreate(%this)
else
exec("data/defaults.cs");
- %der = $pref::Video::displayDevice;
-
- //We need to hook the missing/warn material stuff early, so do it here
- /*$Core::MissingTexturePath = "core/images/missingTexture";
- $Core::UnAvailableTexturePath = "core/images/unavailable";
- $Core::WarningTexturePath = "core/images/warnMat";
- $Core::CommonShaderPath = "core/shaders";
-
- /*%classList = enumerateConsoleClasses( "Component" );
-
- foreach$( %componentClass in %classList )
- {
- echo("Native Component of type: " @ %componentClass);
- }*/
-
- //exec("./helperFunctions.cs");
-
- // We need some of the default GUI profiles in order to get the canvas and
- // other aspects of the GUI system ready.
- //exec("./profiles.cs");
-
- //This is a bit of a shortcut, but we'll load the client's default settings to ensure all the prefs get initialized correctly
-
-
- // Initialization of the various subsystems requires some of the preferences
- // to be loaded... so do that first.
- /*exec("./globals.cs");
-
- exec("./canvas.cs");
- exec("./cursor.cs");
-
- exec("./renderManager.cs");
- exec("./lighting.cs");
-
- exec("./audio.cs");
- exec("./sfx/audioAmbience.cs");
- exec("./sfx/audioData.cs");
- exec("./sfx/audioDescriptions.cs");
- exec("./sfx/audioEnvironments.cs");
- exec("./sfx/audioStates.cs");
-
- exec("./parseArgs.cs");
-
- // Materials and Shaders for rendering various object types
- exec("./gfxData/commonMaterialData.cs");
- exec("./gfxData/shaders.cs");
- exec("./gfxData/terrainBlock.cs");
- exec("./gfxData/water.cs");
- exec("./gfxData/scatterSky.cs");
- exec("./gfxData/clouds.cs");
-
- // Initialize all core post effects.
- exec("./postFx.cs");
-
- //VR stuff
- exec("./oculusVR.cs");*/
-
// Seed the random number generator.
setRandomSeed();
diff --git a/Templates/BaseGame/game/core/Core.module b/Templates/BaseGame/game/core/Core.module
index c7ab7b64b..b9a2490e3 100644
--- a/Templates/BaseGame/game/core/Core.module
+++ b/Templates/BaseGame/game/core/Core.module
@@ -5,15 +5,4 @@
ScriptFile="Core.cs"
CreateFunction="onCreate"
DestroyFunction="onDestroy"
- Group="Core">
-
-
-
\ No newline at end of file
+ Group="Core"/>
\ No newline at end of file
diff --git a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.cs b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.cs
index 693c7fff7..11df6afd6 100644
--- a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.cs
+++ b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.cs
@@ -43,7 +43,7 @@ function GameConnection::initialControlSet(%this)
// first check if the editor is active
if (!isToolBuild() || !isMethod("Editor", "checkActiveLoadDone") || !Editor::checkActiveLoadDone())
{
- if (Canvas.getContent() != PlayGui.getId())
+ if (isObject(PlayGui) && Canvas.getContent() != PlayGui.getId())
Canvas.setContent(PlayGui);
}
}
diff --git a/Templates/BaseGame/game/core/components/components/actionAnimationComponent.asset.taml b/Templates/BaseGame/game/core/components/components/actionAnimationComponent.asset.taml
new file mode 100644
index 000000000..36d5b9a90
--- /dev/null
+++ b/Templates/BaseGame/game/core/components/components/actionAnimationComponent.asset.taml
@@ -0,0 +1,8 @@
+
diff --git a/Templates/BaseGame/game/core/components/components/aiControllerComponent.asset.taml b/Templates/BaseGame/game/core/components/components/aiControllerComponent.asset.taml
new file mode 100644
index 000000000..0111cd999
--- /dev/null
+++ b/Templates/BaseGame/game/core/components/components/aiControllerComponent.asset.taml
@@ -0,0 +1,8 @@
+
diff --git a/Templates/BaseGame/game/core/components/components/armAnimationComponent.asset.taml b/Templates/BaseGame/game/core/components/components/armAnimationComponent.asset.taml
new file mode 100644
index 000000000..d9fd4ef80
--- /dev/null
+++ b/Templates/BaseGame/game/core/components/components/armAnimationComponent.asset.taml
@@ -0,0 +1,8 @@
+
diff --git a/Templates/BaseGame/game/core/components/components/game/controlObject.cs b/Templates/BaseGame/game/core/components/components/game/controlObject.cs
deleted file mode 100644
index 7f477ecca..000000000
--- a/Templates/BaseGame/game/core/components/components/game/controlObject.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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)
-{
- %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);
-}
\ No newline at end of file
diff --git a/Templates/BaseGame/game/core/utility/Core_Utility.cs b/Templates/BaseGame/game/core/utility/Core_Utility.cs
index d412f3544..e38d474d5 100644
--- a/Templates/BaseGame/game/core/utility/Core_Utility.cs
+++ b/Templates/BaseGame/game/core/utility/Core_Utility.cs
@@ -4,6 +4,8 @@ function Core_Utility::onCreate(%this)
exec("./scripts/parseArgs.cs");
exec("./scripts/globals.cs");
exec("./scripts/helperFunctions.cs");
+ exec("./scripts/gameObjectManagement.cs");
+ exec("./scripts/persistanceManagement.cs");
}
function Core_Utility::onDestroy(%this)
diff --git a/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.cs b/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.cs
new file mode 100644
index 000000000..f496111eb
--- /dev/null
+++ b/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.cs
@@ -0,0 +1,181 @@
+
+//Game Object management
+function findGameObject(%name)
+{
+ //find all GameObjectAssets
+ %assetQuery = new AssetQuery();
+ if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset"))
+ return 0; //if we didn't find ANY, just exit
+
+ %count = %assetQuery.getCount();
+
+ for(%i=0; %i < %count; %i++)
+ {
+ %assetId = %assetQuery.getAsset(%i);
+
+ //%assetName = AssetDatabase.getAssetName(%assetId);
+
+ if(%assetId $= %name)
+ {
+ %gameObjectAsset = AssetDatabase.acquireAsset(%assetId);
+
+ %assetQuery.delete();
+ return %gameObjectAsset;
+ }
+ }
+
+ %assetQuery.delete();
+ return 0;
+}
+
+function spawnGameObject(%name, %addToScene)
+{
+ if(%addToScene $= "")
+ %addToScene = true;
+
+ //First, check if this already exists in our GameObjectPool
+ if(isObject(GameObjectPool))
+ {
+ %goCount = GameObjectPool.countKey(%name);
+
+ //if we have some already in the pool, pull it out and use that
+ if(%goCount != 0)
+ {
+ %goIdx = GameObjectPool.getIndexFromKey(%name);
+ %go = GameObjectPool.getValue(%goIdx);
+
+ %go.setHidden(false);
+ %go.setScopeAlways();
+
+ if(%addToMissionGroup == true) //save instance when saving level
+ getScene(0).add(%go);
+ else // clear instance on level exit
+ MissionCleanup.add(%go);
+
+ //remove from the object pool's list
+ GameObjectPool.erase(%goIdx);
+
+ return %go;
+ }
+ }
+
+ //We have no existing pool, or no existing game objects of this type, so spawn a new one
+
+ %gameObjectAsset = findGameObject(%name);
+
+ if(isObject(%gameObjectAsset))
+ {
+ %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath);
+
+ if(%addToScene == true) //save instance when saving level
+ getScene(0).add(%newSGOObject);
+ else // clear instance on level exit
+ MissionCleanup.add(%newSGOObject);
+
+ return %newSGOObject;
+ }
+
+ return 0;
+}
+
+function saveGameObject(%name, %tamlPath, %scriptPath)
+{
+ %gameObjectAsset = findGameObject(%name);
+
+ //find if it already exists. If it does, we'll update it, if it does not, we'll make a new asset
+ if(isObject(%gameObjectAsset))
+ {
+ %assetID = %gameObjectAsset.getAssetId();
+
+ %gameObjectAsset.TAMLFilePath = %tamlPath;
+ %gameObjectAsset.scriptFilePath = %scriptPath;
+
+ TAMLWrite(%gameObjectAsset, AssetDatabase.getAssetFilePath(%assetID));
+ AssetDatabase.refreshAsset(%assetID);
+ }
+ else
+ {
+ //Doesn't exist, so make a new one
+ %gameObjectAsset = new GameObjectAsset()
+ {
+ assetName = %name @ "Asset";
+ gameObjectName = %name;
+ TAMLFilePath = %tamlPath;
+ scriptFilePath = %scriptPath;
+ };
+
+ //Save it alongside the taml file
+ %path = filePath(%tamlPath);
+
+ TAMLWrite(%gameObjectAsset, %path @ "/" @ %name @ ".asset.taml");
+ AssetDatabase.refreshAllAssets(true);
+ }
+}
+
+//Allocates a number of a game object into a pool to be pulled from as needed
+function allocateGameObjects(%name, %amount)
+{
+ //First, we need to make sure our pool exists
+ if(!isObject(GameObjectPool))
+ {
+ new ArrayObject(GameObjectPool);
+ }
+
+ //Next, we loop and generate our game objects, and add them to the pool
+ for(%i=0; %i < %amount; %i++)
+ {
+ %go = spawnGameObject(%name, false);
+
+ //When our object is in the pool, it's not "real", so we need to make sure
+ //that we don't ghost it to clients untill we actually spawn it.
+ %go.clearScopeAlways();
+
+ //We also hide it, so that we don't 'exist' in the scene until we spawn
+ %go.hidden = true;
+
+ //Lastly, add us to the pool, with the key being our game object type
+ GameObjectPool.add(%name, %go);
+ }
+}
+
+function Entity::delete(%this)
+{
+ //we want to intercept the delete call, and add it to our GameObjectPool
+ //if it's a game object
+ if(%this.gameObjectAsset !$= "")
+ {
+ %this.setHidden(true);
+ %this.clearScopeAlways();
+
+ if(!isObject(GameObjectPool))
+ {
+ new ArrayObject(GameObjectPool);
+ }
+
+ GameObjectPool.add(%this.gameObjectAsset, %this);
+
+ %missionSet = %this.getGroup();
+ %missionSet.remove(%this);
+ }
+ else
+ {
+ %this.superClass.delete();
+ }
+}
+
+function clearGameObjectPool()
+{
+ if(isObject(GameObjectPool))
+ {
+ %count = GameObjectPool.count();
+
+ for(%i=0; %i < %count; %i++)
+ {
+ %go = GameObjectPool.getValue(%i);
+
+ %go.superClass.delete();
+ }
+
+ GameObjectPool.empty();
+ }
+}
\ No newline at end of file
diff --git a/Templates/BaseGame/game/core/utility/scripts/globals.cs b/Templates/BaseGame/game/core/utility/scripts/globals.cs
index fcf52390a..adb035fdc 100644
--- a/Templates/BaseGame/game/core/utility/scripts/globals.cs
+++ b/Templates/BaseGame/game/core/utility/scripts/globals.cs
@@ -36,9 +36,6 @@ $pref::Input::JoystickEnabled = 0;
// Set directory paths for various data or default images.
$pref::Video::ProfilePath = "core/rendering/scripts/gfxprofile";
-/*$pref::Video::missingTexturePath = "core/images/missingTexture.png";
-$pref::Video::unavailableTexturePath = "core/images/unavailable.png";
-$pref::Video::warningTexturePath = "core/images/warnMat.dds";*/
$pref::Video::disableVerticalSync = 1;
$pref::Video::mode = "800 600 false 32 60 4";
diff --git a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs
index 8abe3e6e6..d620d08b1 100644
--- a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs
+++ b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs
@@ -636,503 +636,6 @@ function mvReset()
// There are others.
}
-//Persistance Manager tests
-
-new PersistenceManager(TestPManager);
-
-function runPManTest(%test)
-{
- if (!isObject(TestPManager))
- return;
-
- if (%test $= "")
- %test = 100;
-
- switch(%test)
- {
- case 0:
- TestPManager.testFieldUpdates();
- case 1:
- TestPManager.testObjectRename();
- case 2:
- TestPManager.testNewObject();
- case 3:
- TestPManager.testNewGroup();
- case 4:
- TestPManager.testMoveObject();
- case 5:
- TestPManager.testObjectRemove();
- case 100:
- TestPManager.testFieldUpdates();
- TestPManager.testObjectRename();
- TestPManager.testNewObject();
- TestPManager.testNewGroup();
- TestPManager.testMoveObject();
- TestPManager.testObjectRemove();
- }
-}
-
-function TestPManager::testFieldUpdates(%doNotSave)
-{
- // Set some objects as dirty
- TestPManager.setDirty(AudioGui);
- TestPManager.setDirty(AudioSim);
- TestPManager.setDirty(AudioMessage);
-
- // Alter some of the existing fields
- AudioEffect.isLooping = true;
- AudioMessage.isLooping = true;
- AudioEffect.is3D = true;
-
- // Test removing a field
- TestPManager.removeField(AudioGui, "isLooping");
-
- // Alter some of the persistent fields
- AudioGui.referenceDistance = 0.8;
- AudioMessage.referenceDistance = 0.8;
-
- // Add some new dynamic fields
- AudioGui.foo = "bar";
- AudioEffect.foo = "bar";
-
- // Remove an object from the dirty list
- // It shouldn't get updated in the file
- TestPManager.removeDirty(AudioEffect);
-
- // Dirty an object in another file as well
- TestPManager.setDirty(WarningMaterial);
-
- // Update a field that doesn't exist
- WarningMaterial.glow[0] = true;
-
- // Drity another object to test for crashes
- // when a dirty object is deleted
- TestPManager.setDirty(SFXPausedSet);
-
- // Delete the object
- SFXPausedSet.delete();
-
- // Unless %doNotSave is set (by a batch/combo test)
- // then go ahead and save now
- if (!%doNotSave)
- TestPManager.saveDirty();
-}
-
-function TestPManager::testObjectRename(%doNotSave)
-{
- // Flag an object as dirty
- if (isObject(AudioGui))
- TestPManager.setDirty(AudioGui);
- else if (isObject(AudioGuiFoo))
- TestPManager.setDirty(AudioGuiFoo);
-
- // Rename it
- if (isObject(AudioGui))
- AudioGui.setName(AudioGuiFoo);
- else if (isObject(AudioGuiFoo))
- AudioGuiFoo.setName(AudioGui);
-
- // Unless %doNotSave is set (by a batch/combo test)
- // then go ahead and save now
- if (!%doNotSave)
- TestPManager.saveDirty();
-}
-
-function TestPManager::testNewObject(%doNotSave)
-{
- // Test adding a new named object
- new SFXDescription(AudioNew)
- {
- volume = 0.5;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 2;
- };
-
- // Flag it as dirty
- TestPManager.setDirty(AudioNew, "core/scripts/client/audio.cs");
-
- // Test adding a new unnamed object
- %obj = new SFXDescription()
- {
- volume = 0.75;
- isLooping = true;
- bar = 3;
- };
-
- // Flag it as dirty
- TestPManager.setDirty(%obj, "core/scripts/client/audio.cs");
-
- // Test adding an "empty" object
- new SFXDescription(AudioEmpty);
-
- TestPManager.setDirty(AudioEmpty, "core/scripts/client/audio.cs");
-
- // Unless %doNotSave is set (by a batch/combo test)
- // then go ahead and save now
- if (!%doNotSave)
- TestPManager.saveDirty();
-}
-
-function TestPManager::testNewGroup(%doNotSave)
-{
- // Test adding a new named SimGroup
- new SimGroup(TestGroup)
- {
- foo = "bar";
-
- new SFXDescription(TestObject)
- {
- volume = 0.5;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 1;
- };
- new SimGroup(SubGroup)
- {
- foo = 2;
-
- new SFXDescription(SubObject)
- {
- volume = 0.5;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 3;
- };
- };
- };
-
- // Flag this as dirty
- TestPManager.setDirty(TestGroup, "core/scripts/client/audio.cs");
-
- // Test adding a new unnamed SimGroup
- %group = new SimGroup()
- {
- foo = "bar";
-
- new SFXDescription()
- {
- volume = 0.75;
- channel = $GuiAudioType;
- foo = 4;
- };
- new SimGroup()
- {
- foo = 5;
-
- new SFXDescription()
- {
- volume = 0.75;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 6;
- };
- };
- };
-
- // Flag this as dirty
- TestPManager.setDirty(%group, "core/scripts/client/audio.cs");
-
- // Test adding a new unnamed SimSet
- %set = new SimSet()
- {
- foo = "bar";
-
- new SFXDescription()
- {
- volume = 0.75;
- channel = $GuiAudioType;
- foo = 7;
- };
- new SimGroup()
- {
- foo = 8;
-
- new SFXDescription()
- {
- volume = 0.75;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 9;
- };
- };
- };
-
- // Flag this as dirty
- TestPManager.setDirty(%set, "core/scripts/client/audio.cs");
-
- // Unless %doNotSave is set (by a batch/combo test)
- // then go ahead and save now
- if (!%doNotSave)
- TestPManager.saveDirty();
-}
-
-function TestPManager::testMoveObject(%doNotSave)
-{
- // First add a couple of groups to the file
- new SimGroup(MoveGroup1)
- {
- foo = "bar";
-
- new SFXDescription(MoveObject1)
- {
- volume = 0.5;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 1;
- };
-
- new SimSet(SubGroup1)
- {
- new SFXDescription(SubObject1)
- {
- volume = 0.75;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 2;
- };
- };
- };
-
- // Flag this as dirty
- TestPManager.setDirty(MoveGroup1, "core/scripts/client/audio.cs");
-
- new SimGroup(MoveGroup2)
- {
- foo = "bar";
-
- new SFXDescription(MoveObject2)
- {
- volume = 0.5;
- isLooping = true;
- channel = $GuiAudioType;
- foo = 3;
- };
- };
-
- // Flag this as dirty
- TestPManager.setDirty(MoveGroup2, "core/scripts/client/audio.cs");
-
- // Unless %doNotSave is set (by a batch/combo test)
- // then go ahead and save now
- if (!%doNotSave)
- TestPManager.saveDirty();
-
- // Set them as dirty again
- TestPManager.setDirty(MoveGroup1);
- TestPManager.setDirty(MoveGroup2);
-
- // Give the subobject an new value
- MoveObject1.foo = 4;
-
- // Move it into the other group
- MoveGroup1.add(MoveObject2);
-
- // Switch the other subobject
- MoveGroup2.add(MoveObject1);
-
- // Also add a new unnamed object to one of the groups
- %obj = new SFXDescription()
- {
- volume = 0.75;
- isLooping = true;
- bar = 5;
- };
-
- MoveGroup1.add(%obj);
-
- // Unless %doNotSave is set (by a batch/combo test)
- // then go ahead and save now
- if (!%doNotSave)
- TestPManager.saveDirty();
-}
-
-function TestPManager::testObjectRemove(%doNotSave)
-{
- TestPManager.removeObjectFromFile(AudioSim);
-}
-
-//Game Object management
-function findGameObject(%name)
-{
- //find all GameObjectAssets
- %assetQuery = new AssetQuery();
- if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset"))
- return 0; //if we didn't find ANY, just exit
-
- %count = %assetQuery.getCount();
-
- for(%i=0; %i < %count; %i++)
- {
- %assetId = %assetQuery.getAsset(%i);
-
- //%assetName = AssetDatabase.getAssetName(%assetId);
-
- if(%assetId $= %name)
- {
- %gameObjectAsset = AssetDatabase.acquireAsset(%assetId);
-
- %assetQuery.delete();
- return %gameObjectAsset;
- }
- }
-
- %assetQuery.delete();
- return 0;
-}
-
-function spawnGameObject(%name, %addToMissionGroup)
-{
- if(%addToMissionGroup $= "")
- %addToMissionGroup = true;
-
- //First, check if this already exists in our GameObjectPool
- if(isObject(GameObjectPool))
- {
- %goCount = GameObjectPool.countKey(%name);
-
- //if we have some already in the pool, pull it out and use that
- if(%goCount != 0)
- {
- %goIdx = GameObjectPool.getIndexFromKey(%name);
- %go = GameObjectPool.getValue(%goIdx);
-
- %go.setHidden(false);
- %go.setScopeAlways();
-
- if(%addToMissionGroup == true) //save instance when saving level
- MissionGroup.add(%go);
- else // clear instance on level exit
- MissionCleanup.add(%go);
-
- //remove from the object pool's list
- GameObjectPool.erase(%goIdx);
-
- return %go;
- }
- }
-
- //We have no existing pool, or no existing game objects of this type, so spawn a new one
-
- %gameObjectAsset = findGameObject(%name);
-
- if(isObject(%gameObjectAsset))
- {
- %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath);
-
- if(%addToMissionGroup == true) //save instance when saving level
- MissionGroup.add(%newSGOObject);
- else // clear instance on level exit
- MissionCleanup.add(%newSGOObject);
-
- return %newSGOObject;
- }
-
- return 0;
-}
-
-function saveGameObject(%name, %tamlPath, %scriptPath)
-{
- %gameObjectAsset = findGameObject(%name);
-
- //find if it already exists. If it does, we'll update it, if it does not, we'll make a new asset
- if(isObject(%gameObjectAsset))
- {
- %assetID = %gameObjectAsset.getAssetId();
-
- %gameObjectAsset.TAMLFilePath = %tamlPath;
- %gameObjectAsset.scriptFilePath = %scriptPath;
-
- TAMLWrite(%gameObjectAsset, AssetDatabase.getAssetFilePath(%assetID));
- AssetDatabase.refreshAsset(%assetID);
- }
- else
- {
- //Doesn't exist, so make a new one
- %gameObjectAsset = new GameObjectAsset()
- {
- assetName = %name @ "Asset";
- gameObjectName = %name;
- TAMLFilePath = %tamlPath;
- scriptFilePath = %scriptPath;
- };
-
- //Save it alongside the taml file
- %path = filePath(%tamlPath);
-
- TAMLWrite(%gameObjectAsset, %path @ "/" @ %name @ ".asset.taml");
- AssetDatabase.refreshAllAssets(true);
- }
-}
-
-//Allocates a number of a game object into a pool to be pulled from as needed
-function allocateGameObjects(%name, %amount)
-{
- //First, we need to make sure our pool exists
- if(!isObject(GameObjectPool))
- {
- new ArrayObject(GameObjectPool);
- }
-
- //Next, we loop and generate our game objects, and add them to the pool
- for(%i=0; %i < %amount; %i++)
- {
- %go = spawnGameObject(%name, false);
-
- //When our object is in the pool, it's not "real", so we need to make sure
- //that we don't ghost it to clients untill we actually spawn it.
- %go.clearScopeAlways();
-
- //We also hide it, so that we don't 'exist' in the scene until we spawn
- %go.hidden = true;
-
- //Lastly, add us to the pool, with the key being our game object type
- GameObjectPool.add(%name, %go);
- }
-}
-
-function Entity::delete(%this)
-{
- //we want to intercept the delete call, and add it to our GameObjectPool
- //if it's a game object
- if(%this.gameObjectAsset !$= "")
- {
- %this.setHidden(true);
- %this.clearScopeAlways();
-
- if(!isObject(GameObjectPool))
- {
- new ArrayObject(GameObjectPool);
- }
-
- GameObjectPool.add(%this.gameObjectAsset, %this);
-
- %missionSet = %this.getGroup();
- %missionSet.remove(%this);
- }
- else
- {
- %this.superClass.delete();
- }
-}
-
-function clearGameObjectPool()
-{
- if(isObject(GameObjectPool))
- {
- %count = GameObjectPool.count();
-
- for(%i=0; %i < %count; %i++)
- {
- %go = GameObjectPool.getValue(%i);
-
- %go.superClass.delete();
- }
-
- GameObjectPool.empty();
- }
-}
-
//
function switchCamera(%client, %newCamEntity)
{
@@ -1155,4 +658,17 @@ function switchCamera(%client, %newCamEntity)
%client.setControlCameraFov(%cam.FOV);
%client.camera = %newCamEntity;
+}
+
+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!");
+
+ %control.setConnectionControlObject(%client);
}
\ No newline at end of file
diff --git a/Templates/BaseGame/game/core/utility/scripts/persistanceManagement.cs b/Templates/BaseGame/game/core/utility/scripts/persistanceManagement.cs
new file mode 100644
index 000000000..aab054161
--- /dev/null
+++ b/Templates/BaseGame/game/core/utility/scripts/persistanceManagement.cs
@@ -0,0 +1,315 @@
+//Persistance Manager tests
+
+new PersistenceManager(TestPManager);
+
+function runPManTest(%test)
+{
+ if (!isObject(TestPManager))
+ return;
+
+ if (%test $= "")
+ %test = 100;
+
+ switch(%test)
+ {
+ case 0:
+ TestPManager.testFieldUpdates();
+ case 1:
+ TestPManager.testObjectRename();
+ case 2:
+ TestPManager.testNewObject();
+ case 3:
+ TestPManager.testNewGroup();
+ case 4:
+ TestPManager.testMoveObject();
+ case 5:
+ TestPManager.testObjectRemove();
+ case 100:
+ TestPManager.testFieldUpdates();
+ TestPManager.testObjectRename();
+ TestPManager.testNewObject();
+ TestPManager.testNewGroup();
+ TestPManager.testMoveObject();
+ TestPManager.testObjectRemove();
+ }
+}
+
+function TestPManager::testFieldUpdates(%doNotSave)
+{
+ // Set some objects as dirty
+ TestPManager.setDirty(AudioGui);
+ TestPManager.setDirty(AudioSim);
+ TestPManager.setDirty(AudioMessage);
+
+ // Alter some of the existing fields
+ AudioEffect.isLooping = true;
+ AudioMessage.isLooping = true;
+ AudioEffect.is3D = true;
+
+ // Test removing a field
+ TestPManager.removeField(AudioGui, "isLooping");
+
+ // Alter some of the persistent fields
+ AudioGui.referenceDistance = 0.8;
+ AudioMessage.referenceDistance = 0.8;
+
+ // Add some new dynamic fields
+ AudioGui.foo = "bar";
+ AudioEffect.foo = "bar";
+
+ // Remove an object from the dirty list
+ // It shouldn't get updated in the file
+ TestPManager.removeDirty(AudioEffect);
+
+ // Dirty an object in another file as well
+ TestPManager.setDirty(WarningMaterial);
+
+ // Update a field that doesn't exist
+ WarningMaterial.glow[0] = true;
+
+ // Drity another object to test for crashes
+ // when a dirty object is deleted
+ TestPManager.setDirty(SFXPausedSet);
+
+ // Delete the object
+ SFXPausedSet.delete();
+
+ // Unless %doNotSave is set (by a batch/combo test)
+ // then go ahead and save now
+ if (!%doNotSave)
+ TestPManager.saveDirty();
+}
+
+function TestPManager::testObjectRename(%doNotSave)
+{
+ // Flag an object as dirty
+ if (isObject(AudioGui))
+ TestPManager.setDirty(AudioGui);
+ else if (isObject(AudioGuiFoo))
+ TestPManager.setDirty(AudioGuiFoo);
+
+ // Rename it
+ if (isObject(AudioGui))
+ AudioGui.setName(AudioGuiFoo);
+ else if (isObject(AudioGuiFoo))
+ AudioGuiFoo.setName(AudioGui);
+
+ // Unless %doNotSave is set (by a batch/combo test)
+ // then go ahead and save now
+ if (!%doNotSave)
+ TestPManager.saveDirty();
+}
+
+function TestPManager::testNewObject(%doNotSave)
+{
+ // Test adding a new named object
+ new SFXDescription(AudioNew)
+ {
+ volume = 0.5;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 2;
+ };
+
+ // Flag it as dirty
+ TestPManager.setDirty(AudioNew, "core/scripts/client/audio.cs");
+
+ // Test adding a new unnamed object
+ %obj = new SFXDescription()
+ {
+ volume = 0.75;
+ isLooping = true;
+ bar = 3;
+ };
+
+ // Flag it as dirty
+ TestPManager.setDirty(%obj, "core/scripts/client/audio.cs");
+
+ // Test adding an "empty" object
+ new SFXDescription(AudioEmpty);
+
+ TestPManager.setDirty(AudioEmpty, "core/scripts/client/audio.cs");
+
+ // Unless %doNotSave is set (by a batch/combo test)
+ // then go ahead and save now
+ if (!%doNotSave)
+ TestPManager.saveDirty();
+}
+
+function TestPManager::testNewGroup(%doNotSave)
+{
+ // Test adding a new named SimGroup
+ new SimGroup(TestGroup)
+ {
+ foo = "bar";
+
+ new SFXDescription(TestObject)
+ {
+ volume = 0.5;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 1;
+ };
+ new SimGroup(SubGroup)
+ {
+ foo = 2;
+
+ new SFXDescription(SubObject)
+ {
+ volume = 0.5;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 3;
+ };
+ };
+ };
+
+ // Flag this as dirty
+ TestPManager.setDirty(TestGroup, "core/scripts/client/audio.cs");
+
+ // Test adding a new unnamed SimGroup
+ %group = new SimGroup()
+ {
+ foo = "bar";
+
+ new SFXDescription()
+ {
+ volume = 0.75;
+ channel = $GuiAudioType;
+ foo = 4;
+ };
+ new SimGroup()
+ {
+ foo = 5;
+
+ new SFXDescription()
+ {
+ volume = 0.75;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 6;
+ };
+ };
+ };
+
+ // Flag this as dirty
+ TestPManager.setDirty(%group, "core/scripts/client/audio.cs");
+
+ // Test adding a new unnamed SimSet
+ %set = new SimSet()
+ {
+ foo = "bar";
+
+ new SFXDescription()
+ {
+ volume = 0.75;
+ channel = $GuiAudioType;
+ foo = 7;
+ };
+ new SimGroup()
+ {
+ foo = 8;
+
+ new SFXDescription()
+ {
+ volume = 0.75;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 9;
+ };
+ };
+ };
+
+ // Flag this as dirty
+ TestPManager.setDirty(%set, "core/scripts/client/audio.cs");
+
+ // Unless %doNotSave is set (by a batch/combo test)
+ // then go ahead and save now
+ if (!%doNotSave)
+ TestPManager.saveDirty();
+}
+
+function TestPManager::testMoveObject(%doNotSave)
+{
+ // First add a couple of groups to the file
+ new SimGroup(MoveGroup1)
+ {
+ foo = "bar";
+
+ new SFXDescription(MoveObject1)
+ {
+ volume = 0.5;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 1;
+ };
+
+ new SimSet(SubGroup1)
+ {
+ new SFXDescription(SubObject1)
+ {
+ volume = 0.75;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 2;
+ };
+ };
+ };
+
+ // Flag this as dirty
+ TestPManager.setDirty(MoveGroup1, "core/scripts/client/audio.cs");
+
+ new SimGroup(MoveGroup2)
+ {
+ foo = "bar";
+
+ new SFXDescription(MoveObject2)
+ {
+ volume = 0.5;
+ isLooping = true;
+ channel = $GuiAudioType;
+ foo = 3;
+ };
+ };
+
+ // Flag this as dirty
+ TestPManager.setDirty(MoveGroup2, "core/scripts/client/audio.cs");
+
+ // Unless %doNotSave is set (by a batch/combo test)
+ // then go ahead and save now
+ if (!%doNotSave)
+ TestPManager.saveDirty();
+
+ // Set them as dirty again
+ TestPManager.setDirty(MoveGroup1);
+ TestPManager.setDirty(MoveGroup2);
+
+ // Give the subobject an new value
+ MoveObject1.foo = 4;
+
+ // Move it into the other group
+ MoveGroup1.add(MoveObject2);
+
+ // Switch the other subobject
+ MoveGroup2.add(MoveObject1);
+
+ // Also add a new unnamed object to one of the groups
+ %obj = new SFXDescription()
+ {
+ volume = 0.75;
+ isLooping = true;
+ bar = 5;
+ };
+
+ MoveGroup1.add(%obj);
+
+ // Unless %doNotSave is set (by a batch/combo test)
+ // then go ahead and save now
+ if (!%doNotSave)
+ TestPManager.saveDirty();
+}
+
+function TestPManager::testObjectRemove(%doNotSave)
+{
+ TestPManager.removeObjectFromFile(AudioSim);
+}
\ No newline at end of file