mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-03 20:40:35 +00:00
Merge pull request #1342 from Areloch/SpawnObjectOverrideOverhaul
SpawnObject Override Overhaul
This commit is contained in:
commit
8274bbbca4
8 changed files with 305 additions and 114 deletions
|
|
@ -68,7 +68,8 @@ mModuleId(StringTable->EmptyString()),
|
|||
mLoadCount( 0 ),
|
||||
mScopeSet( 0 ),
|
||||
mLocked( false ),
|
||||
mpModuleManager( NULL )
|
||||
mpModuleManager( NULL ),
|
||||
mPriority(0.0f)
|
||||
{
|
||||
// Set Vector Associations.
|
||||
VECTOR_SET_ASSOCIATION( mDependencies );
|
||||
|
|
@ -111,6 +112,8 @@ void ModuleDefinition::initPersistFields()
|
|||
|
||||
/// Misc.
|
||||
addProtectedField( "Signature", TypeString, 0, &defaultProtectedNotSetFn, &getSignature, &defaultProtectedNotWriteFn, "A unique signature of the module definition based upon its Id, version and build. This is read-only and is available only after the module has been registered by a module manager." );
|
||||
addProtectedField( "Priority", TypeF32, 0, &setPriority, &defaultProtectedGetFn, &defaultProtectedNotWriteFn, "A numeric value indicating execution priority for certain callback commands. 0 has the highest priority and is then sorted from there ascending in value. This is read-only and is available only after the module has been registered by a module manager.");
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ private:
|
|||
SimObjectId mScopeSet;
|
||||
bool mLocked;
|
||||
ModuleManager* mpModuleManager;
|
||||
F32 mPriority;
|
||||
|
||||
private:
|
||||
inline bool checkUnlocked( void ) const { if ( mLocked ) { Con::warnf("Ignoring changes for locked module definition."); } return !mLocked; }
|
||||
|
|
@ -195,6 +196,9 @@ public:
|
|||
inline bool getModuleLocked( void ) const { return mLocked; }
|
||||
inline ModuleManager* getModuleManager( void ) const { return mpModuleManager; }
|
||||
|
||||
inline void setPriority(const F32 pPriority) { if (checkUnlocked()) { mPriority = pPriority; } }
|
||||
inline F32 getPriority(void) const { return mPriority; }
|
||||
|
||||
using Parent::save;
|
||||
bool save( void );
|
||||
|
||||
|
|
@ -332,6 +336,8 @@ protected:
|
|||
}
|
||||
static bool writeDependencies( void* obj, StringTableEntry pFieldName ) { return static_cast<ModuleDefinition*>(obj)->getDependencies().size() > 0; }
|
||||
static const char* getSignature(void* obj, const char* data) { return static_cast<ModuleDefinition*>(obj)->getSignature(); }
|
||||
|
||||
static bool setPriority(void* obj, const char* index, const char* data) { static_cast<ModuleDefinition*>(obj)->setPriority((F32)dAtof(data)); return false; }
|
||||
};
|
||||
|
||||
#endif // _MODULE_DEFINITION_H
|
||||
|
|
|
|||
|
|
@ -150,8 +150,14 @@ DefineEngineMethod(ModuleManager, findModuleByFilePath, String, (const char* fil
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static S32 QSORT_CALLBACK _findModulesSortByPriority(ModuleDefinition* const* a, ModuleDefinition* const* b)
|
||||
{
|
||||
F32 diff = (*a)->getPriority() - (*b)->getPriority();
|
||||
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly), (true),
|
||||
|
||||
DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly, bool sortByPriority, const char* moduleGroup), (true, false, ""),
|
||||
"Find all the modules registered with the specified loaded state.\n"
|
||||
"@param loadedOnly Whether to return only modules that are loaded or not.\n"
|
||||
"@return A list of space - separated module definition object Ids.\n")
|
||||
|
|
@ -174,12 +180,23 @@ DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly), (true)
|
|||
char* pReturnBuffer = Con::getReturnBuffer( bufferSize );
|
||||
char* pBufferWrite = pReturnBuffer;
|
||||
|
||||
if (sortByPriority)
|
||||
moduleDefinitions.sort(_findModulesSortByPriority);
|
||||
|
||||
StringTableEntry moduleGroupStr = StringTable->insert(moduleGroup);
|
||||
|
||||
// Iterate module definitions.
|
||||
for ( ModuleManager::typeConstModuleDefinitionVector::const_iterator moduleDefinitionItr = moduleDefinitions.begin(); moduleDefinitionItr != moduleDefinitions.end(); ++moduleDefinitionItr )
|
||||
{
|
||||
// Fetch module definition.
|
||||
const ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;
|
||||
|
||||
if(moduleGroupStr != StringTable->EmptyString())
|
||||
{
|
||||
if (pModuleDefinition->getModuleGroup() != moduleGroupStr)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Format module definition.
|
||||
const U32 offset = dSprintf( pBufferWrite, bufferSize, "%d ", pModuleDefinition->getId() );
|
||||
pBufferWrite += offset;
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ function Core_ClientServer::finishMapLoad(%this)
|
|||
Core_ClientServer.GetEventManager().postEvent( "mapLoadComplete" );
|
||||
}
|
||||
|
||||
function Core_ClientServer::FailMapLoad(%this, %moduleName, %isFine)
|
||||
function Core_ClientServer::FailMapLoad(%this, %moduleName, %canContinueOnFail)
|
||||
{
|
||||
Core_ClientServer.failedModuleName = %moduleName;
|
||||
Core_ClientServer.GetEventManager().postEvent( "mapLoadFail", %isFine );
|
||||
Core_ClientServer.GetEventManager().postEvent( "mapLoadFail", %canContinueOnFail );
|
||||
}
|
||||
|
||||
function Core_ClientServerListener::onMapLoadComplete(%this)
|
||||
|
|
@ -50,9 +50,9 @@ function Core_ClientServerListener::onMapLoadComplete(%this)
|
|||
}
|
||||
}
|
||||
|
||||
function Core_ClientServerListener::onmapLoadFail(%this, %isFine)
|
||||
function Core_ClientServerListener::onMapLoadFail(%this, %canContinueOnFail)
|
||||
{
|
||||
if (%isFine)
|
||||
if (%canContinueOnFail)
|
||||
{
|
||||
%this.onMapLoadComplete();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
// anything else will be sent back as an error to the client.
|
||||
// All the connect args are passed also to onConnectRequest
|
||||
//
|
||||
function GameConnection::onConnectRequest( %client, %netAddress, %name )
|
||||
function GameConnection::onConnectRequest( %this, %netAddress, %name )
|
||||
{
|
||||
echo("Connect request from: " @ %netAddress);
|
||||
if($Server::PlayerCount >= $pref::Server::MaxPlayers)
|
||||
|
|
@ -47,11 +47,11 @@ function GameConnection::onConnect( %this, %clientData )
|
|||
sendLoadInfoToClient(%this);
|
||||
|
||||
// Simulated client lag for testing...
|
||||
// %client.setSimulatedNetParams(0.1, 30);
|
||||
// %this.setSimulatedNetParams(0.1, 30);
|
||||
|
||||
// Get the client's unique id:
|
||||
// %authInfo = %client.getAuthInfo();
|
||||
// %client.guid = getField(%authInfo, 3);
|
||||
// %authInfo = %this.getAuthInfo();
|
||||
// %this.guid = getField(%authInfo, 3);
|
||||
%this.guid = 0;
|
||||
addToServerGuidList(%this.guid);
|
||||
|
||||
|
|
@ -81,19 +81,194 @@ function GameConnection::onConnect( %this, %clientData )
|
|||
|
||||
%this.connectData = %clientData;
|
||||
|
||||
//Signal and listener logic for the spawn config/processing here
|
||||
%this.GetEventManager().registerEvent("setSpawnObjectTypeComplete");
|
||||
%this.GetEventManager().registerEvent("setSpawnObjectTypeFailed");
|
||||
%this.GetEventManager().registerEvent("setSpawnPointComplete");
|
||||
%this.GetEventManager().registerEvent("setSpawnPointFailed");
|
||||
%this.GetEventManager().registerEvent("postSpawnComplete");
|
||||
|
||||
%this.listener = new ScriptMsgListener() {
|
||||
class = GameConnectionListener;
|
||||
};
|
||||
%this.GetEventManager().subscribe( %this.listener, "setSpawnObjectTypeComplete" );
|
||||
%this.GetEventManager().subscribe( %this.listener, "setSpawnObjectTypeFailed" );
|
||||
%this.GetEventManager().subscribe( %this.listener, "setSpawnPointComplete" );
|
||||
%this.GetEventManager().subscribe( %this.listener, "setSpawnPointFailed" );
|
||||
%this.GetEventManager().subscribe( %this.listener, "postSpawnComplete" );
|
||||
|
||||
callGamemodeFunction("onClientConnect", %this);
|
||||
|
||||
$Server::PlayerCount++;
|
||||
}
|
||||
|
||||
function GameConnection::GetEventManager(%this)
|
||||
{
|
||||
if( !isObject( %this.eventManager ) )
|
||||
%this.eventManager = new EventManager() {
|
||||
queue = "GameConnectionEventManager";
|
||||
};
|
||||
|
||||
return %this.eventManager;
|
||||
}
|
||||
|
||||
function GameConnection::spawnControlObject( %this )
|
||||
{
|
||||
//baseline controlObject spawn type with extention points
|
||||
%this.spawnClass = "Camera";
|
||||
%this.spawnDBType = "CameraData";
|
||||
%this.spawnDataBlock = "Observer";
|
||||
|
||||
%this.numModsNeedingLoaded = 0;
|
||||
%this.moduleLoadedDone = 0;
|
||||
%modulesIDList = getModulesAndGameModesList(true, "Game");
|
||||
|
||||
%this.numModsNeedingLoaded = getNumCanCallOnObjectList("setSpawnObjectType", %modulesIDList);
|
||||
|
||||
if (%this.numModsNeedingLoaded)
|
||||
callOnObjectList("setSpawnObjectType", %modulesIdList, %this);
|
||||
else
|
||||
%this.GetEventManager().onSetSpawnObjectTypeComplete(); //just jump to progress
|
||||
}
|
||||
|
||||
function GameConnectionListener::onSetSpawnObjectTypeComplete( %this, %client )
|
||||
{
|
||||
%client.moduleLoadedDone++;
|
||||
|
||||
if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
|
||||
return; //continue to wait
|
||||
|
||||
if (isObject(%client.player))
|
||||
{
|
||||
// The client should not already have a player. Assigning
|
||||
// a new one could result in an uncontrolled player object.
|
||||
error("Attempting to create a player for a client that already has one!");
|
||||
}
|
||||
|
||||
// Spawn with the engine's Sim::spawnObject() function
|
||||
%client.player = spawnObject(%client.spawnClass, %client.spawnDataBlock);
|
||||
|
||||
if (!%client.player.isMemberOfClass(%client.spawnClass))
|
||||
warn("Trying to spawn a class that does not derive from "@ %client.spawnClass);
|
||||
|
||||
// Add the player object to MissionCleanup so that it
|
||||
// won't get saved into the level files and will get
|
||||
// cleaned up properly
|
||||
MissionCleanup.add(%client.player);
|
||||
|
||||
// Store the client object on the player object for
|
||||
// future reference
|
||||
%client.player.client = %client;
|
||||
|
||||
%client.setSpawnPoint();
|
||||
|
||||
// Give the client control of the camera if in the editor
|
||||
if( $startWorldEditor )
|
||||
{
|
||||
%control = %client.camera;
|
||||
%control.mode = "Fly";
|
||||
EditorGui.syncCameraGui();
|
||||
}
|
||||
else
|
||||
%control = %client.player;
|
||||
|
||||
// Allow the player/camera to receive move data from the GameConnection. Without this
|
||||
// the user is unable to control the player/camera.
|
||||
if (!isDefined("%noControl"))
|
||||
%client.setControlObject(%control);
|
||||
}
|
||||
|
||||
function GameConnectionListener::onSetSpawnObjectTypeFailed( %this, %client, %canContinueOnFail )
|
||||
{
|
||||
errorf("Failed to properly set Spawn Object Type for client: " @ %client);
|
||||
}
|
||||
|
||||
function GameConnection::setSpawnPoint( %this )
|
||||
{
|
||||
//baseline spawn point config rules with extention points
|
||||
%this.playerSpawnGroups = "PlayerSpawnPoints PlayerDropPoints";
|
||||
%this.spawnPoint = "";
|
||||
%this.spawnLocation = "0 0 0";
|
||||
|
||||
%this.numModsNeedingLoaded = 0;
|
||||
%this.moduleLoadedDone = 0;
|
||||
%modulesIDList = getModulesAndGameModesList(true, "Game");
|
||||
|
||||
%this.numModsNeedingLoaded = getNumCanCallOnObjectList("setSpawnPoint", %modulesIDList);
|
||||
|
||||
if (%this.numModsNeedingLoaded)
|
||||
callOnObjectList("setSpawnPoint", %modulesIdList, %this);
|
||||
else
|
||||
%this.GetEventManager().onSetSpawnPointComplete();
|
||||
}
|
||||
|
||||
function GameConnectionListener::onSetSpawnPointComplete( %this, %client )
|
||||
{
|
||||
%client.moduleLoadedDone++;
|
||||
if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
|
||||
return; //continue to wait
|
||||
|
||||
if (isObject(%client.player))
|
||||
%client.player.setTransform(%client.spawnLocation);
|
||||
else
|
||||
{
|
||||
// If we weren't able to create the player object then warn the user
|
||||
// When the player clicks OK in one of these message boxes, we will fall through
|
||||
// to the "if (!isObject(%player))" check below.
|
||||
if (isDefined("%this.spawnDataBlock"))
|
||||
{
|
||||
MessageBoxOK("Spawn Failed",
|
||||
"Unable to create a player with class " @ %client.spawnClass @
|
||||
" and datablock " @ %client.spawnDataBlock @ ".\n\nStarting as an Observer instead.",
|
||||
"");
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxOK("Spawn Failed",
|
||||
"Unable to create a player with class " @ %client.spawnClass @
|
||||
".\n\nStarting as an Observer instead.",
|
||||
"");
|
||||
}
|
||||
}
|
||||
%client.onPostSpawn();
|
||||
}
|
||||
|
||||
function GameConnectionListener::onSetSpawnPointFailed( %this, %client, %canContinueOnFail )
|
||||
{
|
||||
errorf("Failed to properly set Spawn Object Type for client: " @ %client);
|
||||
}
|
||||
|
||||
function GameConnection::onPostSpawn( %this )
|
||||
{
|
||||
%this.numModsNeedingLoaded = 0;
|
||||
%this.moduleLoadedDone = 0;
|
||||
%modulesIDList = getModulesAndGameModesList(true, "Game");
|
||||
|
||||
%this.numModsNeedingLoaded = getNumCanCallOnObjectList("onPostSpawn", %modulesIDList);
|
||||
|
||||
if (%this.numModsNeedingLoaded)
|
||||
callOnObjectList("onPostSpawn", %modulesIdList, %this);
|
||||
else
|
||||
%this.GetEventManager().onPostSpawnComplete();
|
||||
}
|
||||
|
||||
function GameConnectionListener::onPostSpawnComplete(%this, %client)
|
||||
{
|
||||
%client.moduleLoadedDone++;
|
||||
if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
|
||||
return; //continue to wait
|
||||
|
||||
//Continue on. Room for special handling here if needbe but not expressly required
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A player's name could be obtained from the auth server, but for
|
||||
// now we use the one passed from the client.
|
||||
// %realName = getField( %authInfo, 0 );
|
||||
//
|
||||
function GameConnection::setPlayerName(%client,%name)
|
||||
function GameConnection::setPlayerName(%this,%name)
|
||||
{
|
||||
%client.sendGuid = 0;
|
||||
%this.sendGuid = 0;
|
||||
|
||||
// Minimum length requirements
|
||||
%name = trim( strToPlayerName( %name ) );
|
||||
|
|
@ -112,8 +287,8 @@ function GameConnection::setPlayerName(%client,%name)
|
|||
}
|
||||
|
||||
// Tag the name with the "smurf" color:
|
||||
%client.nameBase = %name;
|
||||
%client.playerName = addTaggedString("\cp\c8" @ %name @ "\co");
|
||||
%this.nameBase = %name;
|
||||
%this.playerName = addTaggedString("\cp\c8" @ %name @ "\co");
|
||||
}
|
||||
|
||||
function isNameUnique(%name)
|
||||
|
|
@ -132,7 +307,7 @@ function isNameUnique(%name)
|
|||
//-----------------------------------------------------------------------------
|
||||
// This function is called when a client drops for any reason
|
||||
//
|
||||
function GameConnection::onDrop(%client, %reason)
|
||||
function GameConnection::onDrop(%this, %reason)
|
||||
{
|
||||
%entityIds = parseMissionGroupForIds("Entity", "");
|
||||
%entityCount = getWordCount(%entityIds);
|
||||
|
|
@ -148,15 +323,15 @@ function GameConnection::onDrop(%client, %reason)
|
|||
%entityIds = %entityIds SPC %child.getID();
|
||||
}
|
||||
|
||||
%entity.notify("onClientDisconnect", %client);
|
||||
%entity.notify("onClientDisconnect", %this);
|
||||
}
|
||||
|
||||
if($missionRunning)
|
||||
{
|
||||
%hasGameMode = callGamemodeFunction("onClientLeaveGame", %client);
|
||||
%hasGameMode = callGamemodeFunction("onClientLeaveGame", %this);
|
||||
}
|
||||
|
||||
removeFromServerGuidList( %client.guid );
|
||||
removeFromServerGuidList( %this.guid );
|
||||
|
||||
$Server::PlayerCount--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ function serverCmdMissionStartPhase3Ack(%client, %seq)
|
|||
%client.currentPhase = 3;
|
||||
|
||||
%hasGameMode = callGamemodeFunction("onClientEnterGame", %client);
|
||||
|
||||
%client.spawnControlObject();
|
||||
|
||||
//if that also failed, just spawn a camera
|
||||
if(%hasGameMode == 0)
|
||||
|
|
|
|||
|
|
@ -698,4 +698,88 @@ function playSoundAsset(%soundAssetId,%pos)
|
|||
}
|
||||
AssetDatabase.releaseAsset(%soundAssetId);
|
||||
return %handle;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
function getModulesAndGameModesList(%usePriority, %group)
|
||||
{
|
||||
%modulesList = ModuleDatabase.findModules(true, %usePriority, %group);
|
||||
%modulesIDList = "";
|
||||
|
||||
for(%i=0; %i < getWordCount(%modulesList); %i++)
|
||||
{
|
||||
%module = getWord(%modulesList, %i);
|
||||
|
||||
%modulesIDList = %modulesIDList SPC %module.ModuleId;
|
||||
}
|
||||
|
||||
%gamemodeList = getGameModesList();
|
||||
%gameModeCount = %gamemodeList.count();
|
||||
for(%i=0; %i < %gameModeCount; %i++)
|
||||
{
|
||||
%gameModeObj = %gamemodeList.getKey(%i);
|
||||
%active = %gamemodeList.getValue(%i);
|
||||
|
||||
if(!isObject(%gameModeObj) || !%active)
|
||||
continue;
|
||||
|
||||
%modulesIDList = %modulesIDList SPC %gameModeObj;
|
||||
}
|
||||
|
||||
%modulesIDList = strreplace(%modulesIDList, " "," ");
|
||||
%modulesIDList = trim(%modulesIDList);
|
||||
return %modulesIDList;
|
||||
}
|
||||
|
||||
function callOnObjectList(%functionName, %objectsList, %var0, %var1, %var2, %var3, %var4, %var5, %var6)
|
||||
{
|
||||
//Get our modules so we can exec any specific client-side loading/handling
|
||||
%echoList = "Called List:";
|
||||
for(%i=0; %i < getWordCount(%objectsList); %i++)
|
||||
{
|
||||
%obj = getWord(%objectsList, %i);
|
||||
%objName = %obj.getName();
|
||||
|
||||
if(!isObject(%obj))
|
||||
{
|
||||
//could be a moduleID we're trying to call against, so try a lookup
|
||||
%module = ModuleDatabase.findModule(%obj);
|
||||
if(isObject(%module))
|
||||
{
|
||||
%obj = %module.scopeSet;
|
||||
%objName = %module.ModuleId;
|
||||
}
|
||||
}
|
||||
|
||||
%echoList = %echoList SPC %objName;
|
||||
|
||||
// match this to i/o signature
|
||||
if(isObject(%obj) && %obj.isMethod(%functionName))
|
||||
%obj.call(%functionName, %var0, %var1, %var2, %var3, %var4, %var5, %var6);
|
||||
}
|
||||
|
||||
if ($reportModuleOrder)
|
||||
warn(%echoList);
|
||||
}
|
||||
|
||||
function getNumCanCallOnObjectList(%functionName, %objectsList)
|
||||
{
|
||||
%numberWithFunction = 0;
|
||||
for(%i=0; %i < getWordCount(%objectsList); %i++)
|
||||
{
|
||||
%obj = getWord(%objectsList, %i);
|
||||
if(!isObject(%obj))
|
||||
{
|
||||
//could be a moduleID we're trying to call against, so try a lookup
|
||||
%module = ModuleDatabase.findModule(%obj);
|
||||
if(isObject(%module))
|
||||
%obj = %module.scopeSet;
|
||||
}
|
||||
|
||||
// match this to i/o signature
|
||||
if(isObject(%obj) && %obj.isMethod(%functionName))
|
||||
%numberWithFunction++;
|
||||
}
|
||||
|
||||
return %numberWithFunction;
|
||||
}
|
||||
|
|
@ -51,16 +51,6 @@ function ExampleGameMode::onMissionReset(%this)
|
|||
|
||||
function ExampleGameMode::initGameVars(%this)
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
// What kind of "camera" is spawned is either controlled directly by the
|
||||
// SpawnSphere or it defaults back to the values set here. This also controls
|
||||
// which SimGroups to attempt to select the spawn sphere's from by walking down
|
||||
// the list of SpawnGroups till it finds a valid spawn object.
|
||||
// These override the values set in core/scripts/server/spawn.cs
|
||||
//-----------------------------------------------------------------------------
|
||||
%this.defaultCameraClass = "Camera";
|
||||
%this.defaultCameraDataBlock = "Observer";
|
||||
%this.defaultCameraSpawnGroups = "CameraSpawnPoints PlayerSpawnPoints PlayerDropPoints";
|
||||
}
|
||||
|
||||
function ExampleGameMode::onGameDurationEnd(%this)
|
||||
|
|
@ -82,15 +72,6 @@ function ExampleGameMode::onClientEnterGame(%this, %client)
|
|||
//Set the player name based on the client's connection data
|
||||
%client.setPlayerName(%client.connectData);
|
||||
|
||||
// Find a spawn point for the camera
|
||||
// This function currently relies on some helper functions defined in
|
||||
// core/scripts/server/spawn.cs. For custom spawn behaviors one can either
|
||||
// override the properties on the SpawnSphere's or directly override the
|
||||
// functions themselves.
|
||||
%cameraSpawnPoint = %this.pickCameraSpawnPoint(%this.DefaultCameraSpawnGroups);
|
||||
// Spawn a camera for this client using the found %spawnPoint
|
||||
%this.spawnCamera(%client, %cameraSpawnPoint);
|
||||
|
||||
// Inform the client of all the other clients
|
||||
%count = ClientGroup.getCount();
|
||||
for (%cl = 0; %cl < %count; %cl++)
|
||||
|
|
@ -175,81 +156,4 @@ function ExampleGameMode::onSubsceneUnloaded(%this)
|
|||
{
|
||||
echo("===================================");
|
||||
echo("ExampleGameMode - Subscene is unloaded");
|
||||
}
|
||||
|
||||
function ExampleGameMode::spawnCamera(%this, %client, %spawnPoint)
|
||||
{
|
||||
// Set the control object to the default camera
|
||||
if (!isObject(%client.camera))
|
||||
{
|
||||
if (%this.defaultCameraClass !$= "")
|
||||
%client.camera = spawnObject(%this.defaultCameraClass, %this.defaultCameraDataBlock);
|
||||
}
|
||||
|
||||
// If we have a camera then set up some properties
|
||||
if (isObject(%client.camera))
|
||||
{
|
||||
MissionCleanup.add( %client.camera );
|
||||
%client.camera.scopeToClient(%client);
|
||||
|
||||
%client.setControlObject(%client.camera);
|
||||
|
||||
if(!isObject(%spawnPoint))
|
||||
%spawnPoint = %this.pickCameraSpawnPoint(%this.defaultCameraSpawnGroups);
|
||||
|
||||
if (isObject(%spawnPoint))
|
||||
{
|
||||
// Attempt to treat %spawnPoint as an object
|
||||
if (getWordCount(%spawnPoint) == 1 && isObject(%spawnPoint))
|
||||
{
|
||||
%client.camera.setTransform(%spawnPoint.getTransform());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Treat %spawnPoint as an AxisAngle transform
|
||||
%client.camera.setTransform(%spawnPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// pickCameraSpawnPoint() is responsible for finding a valid spawn point for a
|
||||
// camera.
|
||||
//-----------------------------------------------------------------------------
|
||||
function ExampleGameMode::pickCameraSpawnPoint(%this, %spawnGroups)
|
||||
{
|
||||
// Walk through the groups until we find a valid object
|
||||
for (%i = 0; %i < getWordCount(%spawnGroups); %i++)
|
||||
{
|
||||
%group = getWord(%spawnGroups, %i);
|
||||
|
||||
%count = getWordCount(%group);
|
||||
|
||||
if (isObject(%group))
|
||||
%spawnPoint = %group.getRandom();
|
||||
|
||||
if (isObject(%spawnPoint))
|
||||
return %spawnPoint;
|
||||
}
|
||||
|
||||
// Didn't find a spawn point by looking for the groups
|
||||
// so let's return the "default" SpawnSphere
|
||||
// First create it if it doesn't already exist
|
||||
if (!isObject(DefaultCameraSpawnSphere))
|
||||
{
|
||||
%spawn = new SpawnSphere(DefaultCameraSpawnSphere)
|
||||
{
|
||||
dataBlock = "SpawnSphereMarker";
|
||||
spawnClass = $Game::DefaultCameraClass;
|
||||
spawnDatablock = $Game::DefaultCameraDataBlock;
|
||||
};
|
||||
|
||||
// Add it to the MissionCleanup group so that it
|
||||
// doesn't get saved to the Mission (and gets cleaned
|
||||
// up of course)
|
||||
MissionCleanup.add(%spawn);
|
||||
}
|
||||
|
||||
return DefaultCameraSpawnSphere;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue