Cleans up the ExampleModule to have up-to-date examples of module init'ing, game modes, levels and basic input logic

Cleans up prototyping module to trim unneeded extra scripts and files
Adds PlayerBot model to Prototyping module
Adds metalGray material to Prototyping module
Fixes issue where logic wasn't changed for forcing AB preview images to regenerate
Removes unneeded legacy lines from editor template level
Removes unneeded extra asset import config
Disables terrain material name field from editing in terrain material editor for now to prevent bad behavior
Adds mapTo line to newly created material asset definitions to ensure shapes doing mapTo lookups can properly utilize the materials
This commit is contained in:
JeffR 2022-05-31 00:26:20 -05:00
parent e896e663d4
commit 27b20c14d7
98 changed files with 1337 additions and 1725 deletions

View file

@ -1,15 +1,11 @@
<ModuleDefinition
canSave="true"
canSaveDynamicFields="true"
ModuleId="ExampleModule"
VersionId="1"
Group="Game"
scriptFile="ExampleModule"
scriptFile="ExampleModule.tscript"
CreateFunction="onCreate"
DestroyFunction="onDestroy">
<DeclaredAssets
canSave="true"
canSaveDynamicFields="true"
Extension="asset.taml"
Recurse="true" />
Recurse="true"/>
</ModuleDefinition>

View file

@ -1,123 +1,60 @@
//This is our create function. It's pointed to, by name, via a field defined in
//the ExampleModule.module file, which contains our module definition. It is called
//when the module is initially loaded by the engine. Generally, only common, base-level
//stuff is created(or destroyed, in the companion function), like things utilized or
//shared on both the client and server, or things that need to be loaded before anything
//else.
function ExampleModule::onCreate(%this)
{
}
//Similar to the create function, this is defined in thye module file, and called
//when the module is destroyed, usually as part of the game shutting down.
function ExampleModule::onDestroy(%this)
{
}
//This is called when the server part of the application is initially created. Torque3D
//assumes, even in a single player context, that there is ultimately a 'server' and a 'client'
//So during initial launch and startup of the engine, the server side is initialized in
//core/clientServer/scripts/server/server.tscript - in the initServer() function where this is called.
//This is called on all modules that have this function defined. This is important for
//any persistant parts of the server that always need to run such as gameplay scripts
//
//Importantly, when the gane session server is created, several functions are called to as part of the gamemode logic
//The script below contains the callbacks so the gamemode can actually be set up, but the server-side callbacks in question:
//ExampleGameMode::onMissionStart
//ExampleGameMode::onMissionEnded
//ExampleGameMode::onMissionReset
//Are called during the startup, shut down, and resetting of any and all active gamemodes, as informed by the loaded scenes
//when the game server is processed.
//These callbacks are activated in core/clientServer/scripts/server/levelLoad.tscript
//This is called when the server is initially set up by the game application
function ExampleModule::initServer(%this)
{
//This script contains our ExampleGameMode logic
%this.queueExec("./scripts/ExampleGamemodeScript");
%this.queueExec("./scripts/server/ExampleGameMode");
}
//This is called when a game session server is actually created so the game may be played. It's called
//from core/clientServer/scripts/server/server.tscript - in the createServer() function, which is called when
//A game session is actually launched, and the server is generated so game clients can connect to it.
//This is utilized to set up common things that need to be set up each time the game session server is
//created, such as common variables, datablocks to be transmitted to the client, etc.
//This is called when the server is created for an actual game/map to be played
function ExampleModule::onCreateGameServer(%this)
{
//In particular, the default client/server module handles the transmission of datablocks from
//server to client automatically as part of the connection and prepping process alongside
//validation and tramission of level objects. It does this in an abstracted way by adding
//the file paths to a master DatablockFilesList array as per below. When the server is created in
//onServerCreated(), it loads the datablocks via this array, and when when the server goes
//to pass data to the client, it iterates over this list and processes it, ensuring all datablocks
//are the most up to date possible for transmission to the connecting client
//%this.registerDatablock("./datablocks/ExampleDatablock." @ $TorqueScriptFileExtension);
//These are common managed data files. For any datablock-based stuff that gets generated by the editors
//(that doesn't have a specific associated file, like data for a player class) will go into these.
//So we'll register them now if they exist.
if(isFile("./scripts/managedData/managedDatablocks." @ $TorqueScriptFileExtension))
%this.registerDatablock("./scripts/managedData/managedDatablocks");
if(isFile("./scripts/managedData/managedForestItemData." @ $TorqueScriptFileExtension))
%this.registerDatablock("./scripts/managedData/managedForestItemData");
if(isFile("./scripts/managedData/managedForestBrushData." @ $TorqueScriptFileExtension))
%this.registerDatablock("./scripts/managedData/managedForestBrushData");
if(isFile("./scripts/managedData/managedParticleEmitterData." @ $TorqueScriptFileExtension))
%this.registerDatablock("./scripts/managedData/managedParticleEmitterData");
if(isFile("./scripts/managedData/managedParticleData." @ $TorqueScriptFileExtension))
%this.registerDatablock("./scripts/managedData/managedParticleData");
}
//This is called when a game session server is destroyed, when the game shuts down. It's called from
//core/clientServer/scripts/server/server.tscript - in the destroyServer() function, which just cleans up anything
//The module may have set up as part of the game server being created.
//This is called when the server is shut down due to the game/map being exited
function ExampleModule::onDestroyGameServer(%this)
{
}
//Similar to initServer, this is called during the initial launch of the application and the client component
//is set up. The difference is that the client may not actually be created, such as in the case for dedicated servers
//Where no UI or gameplay interface is required. It's called from core/clientServer/scripts/client/client.tscript -
//in the initClient() function. It sets up common elements that the client will always need, such as scripts, GUIs
//and the like
//This is called when the client is initially set up by the game application
function ExampleModule::initClient(%this)
{
AssetDatabase.acquireAsset("ExampleModule:exampleDatablock");
AssetDatabase.acquireAsset("ExampleModule:examplePostEffect");
AssetDatabase.acquireAsset("ExampleModule:exampleGUI");
//client scripts
//Here, we exec out keybind scripts so the player is able to move when they get into a game
%this.queueExec("./scripts/default.keybinds");
%this.queueExec("./scripts/client/inputCommands");
//client scripts
exec("./scripts/client/defaultkeybinds");
%prefPath = getPrefpath();
if(isFile(%prefPath @ "/keybinds." @ $TorqueScriptFileExtension))
exec(%prefPath @ "/keybinds." @ $TorqueScriptFileExtension);
%this.queueExec("./scripts/inputCommands");
if(isScriptFile(%prefPath @ "/keybinds"))
exec(%prefPath @ "/keybinds");
}
//This is called when a game session client successfuly connects to a game server.
//It's called from core/clientServer/scripts/client/connectionToServer.tscript - in the GameConnection::onConnectionAccepted() function
//It's used for any client-side specific game session stuff that the client needs to load or pass to the server, such as profile data
//account progress, preferences, etc.
//
//When a client is connected, the gamemode logic also has a callback activated - ExampleGameMode::onClientEnterGame().
//This is called when a client connects to a server
function ExampleModule::onCreateClientConnection(%this)
{
//This will push our keybind movemap onto the input stack, so we can control our camera in our ExampleGameMode
ExampleMoveMap.push();
ExampleMovemap.push();
}
//This is called when a client game session disconnects from a game server
//It's called from core/clientServer/scripts/client/connectionToServer.tscript - in the disconnectedCleanup() function
//It's used to clean up and potentially write out any client-side stuff that needs housekeeping when disconnecting for any reason.
//It will be called if the connection is manually terminated, or lost due to any sort of connection issue.
//
//When a client disconnects, the gamemode logic has a callback activated - ExampleGameMode::onClientLeaveGame().
//This is called when a client disconnects from a server
function ExampleModule::onDestroyClientConnection(%this)
{
//This will pop the keybind, cleaning it up from the input stack, as it no longer applies
ExampleMoveMap.pop();
}
function ExampleModule::populateOptionsMenuCategories(%this)
{
addOptionsMenuCategory("Example Options", "testExampleOptions();");
}
function testExampleOptions()
{
OptionsMenuSettingsList.clear();
OptionName.setText("");
OptionDescription.setText("");
addListOption("Test Option", "This is a test option", $testOptionValue, "OptionA\tOptionB");
}

View file

@ -1,7 +0,0 @@
<GUIAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExampleGUI"
scriptFile="@assetFile=ExampleGUI.gui"
GUIFile="@assetFile=ExampleGUI.gui"
VersionId="1" />

View file

@ -1,7 +0,0 @@
//--- OBJECT WRITE BEGIN ---
$guiContent = new GuiControl(ExampleGUI)
{
position = "0 0";
extent = "100 100";
};
//--- OBJECT WRITE END ---

View file

@ -1,9 +0,0 @@
function ExampleGUI::onWake(%this)
{
}
function ExampleGUI::onSleep(%this)
{
}

View file

@ -1,9 +0,0 @@
<ComponentAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExampleComponent"
componentName="ExampleComponent"
componentClass="Component"
description="An example script component."
scriptFile="@assetFile=ExampleComponent.cs"
VersionId="1" />

View file

@ -1,26 +0,0 @@
//onAdd is called when the component is created and then added to it's owner entity.
//You would also add any script-defined component fields via addComponentField().
function ExampleComponent::onAdd(%this)
{
}
//onRemove is called when the component is removed and deleted from it's owner entity.
function ExampleComponent::onRemove(%this)
{
}
//onClientConnect is called any time a new client connects to the server.
function ExampleComponent::onClientConnect(%this, %client)
{
}
//onClientDisconnect is called any time a client disconnects from the server.
function ExampleComponent::onClientDisconnect(%this, %client)
{
}
//update is called when the component does an update tick.
function ExampleComponent::Update(%this)
{
}

View file

@ -1,7 +0,0 @@
<ScriptAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExampleDatablock"
scriptFile="@assetFile=ExampleDatablock.cs"
dependency0="@Asset=UI:guiSounds"
VersionId="1" />

View file

@ -1,4 +0,0 @@
new ScriptObject(DummyObjectTestThing)
{
};

View file

@ -1,9 +1,10 @@
<LevelAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExampleLevel"
AssetDescription="A simple example level players can fly around in."
LevelFile="@assetFile=ExampleLevel.mis"
LevelName="Example Level"
isSubScene="false"
Description="An example level asset"
VersionId="1" />
PostFXPresetFile="@assetFile=ExampleLevel.postfxpreset.tscript"
DecalsFile="@assetFile=ExampleLevel.mis.decals"
ForestFile="@assetFile=ExampleLevel.forest"
NavmeshFile="@assetFile=ExampleLevel.nav"
VersionId="1"/>

View file

@ -1,105 +1,86 @@
//--- OBJECT WRITE BEGIN ---
new Scene(EditorTemplateLevel) {
canSave = "1";
canSaveDynamicFields = "1";
isSubScene = "0";
isEditing = "0";
isDirty = "0";
gameModeName = "ExampleGameMode";
cdTrack = "2";
CTF_scoreLimit = "5";
Enabled = "1";
musicTrack = "lush";
new Scene(ExampleLevel) {
Enabled = "1";
gameModeName="ExampleGameMode";
new LevelInfo(theLevelInfo) {
nearClip = "0.1";
visibleDistance = "1000";
visibleGhostDistance = "0";
decalBias = "0.0015";
fogColor = "0.6 0.6 0.7 1";
fogDensity = "0";
fogDensityOffset = "700";
fogAtmosphereHeight = "0";
canvasClearColor = "0 0 0 255";
ambientLightBlendPhase = "1";
ambientLightBlendCurve = "0 0 -1 -1";
soundAmbience = "AudioAmbienceDefault";
soundDistanceModel = "Linear";
canSave = "1";
canSaveDynamicFields = "1";
advancedLightmapSupport = "0";
desc0 = "A blank room template that acts as a starting point.";
Enabled = "1";
LevelName = "Blank Room Template";
advancedLightmapSupport = "0";
Enabled = "1";
};
new SkyBox(theSky) {
Material = "BlankSkyMat";
MaterialAsset = "Core_Rendering:BlankSkyMat";
drawBottom = "0";
dirtyGameObject = "0";
};
new Sun(theSun) {
azimuth = "230.396";
elevation = "45";
color = "0.968628 0.901961 0.901961 1";
ambient = "0.337255 0.533333 0.619608 1";
texSize = "2048";
overDarkFactor = "3000 1500 750 250";
shadowDistance = "200";
shadowSoftness = "0.25";
logWeight = "0.9";
fadeStartDistance = "0";
bias = "0.1";
Blur = "1";
dirtyGameObject = "0";
dynamicRefreshFreq = "8";
Enabled = "1";
height = "1024";
lightBleedFactor = "0.8";
minVariance = "0";
pointShadowType = "PointShadowType_Paraboloid";
shadowBox = "-100 -100 -100 100 100 100";
splitFadeDistances = "1 1 1 1";
staticRefreshFreq = "250";
width = "3072";
};
new GroundPlane() {
squareSize = "128";
scaleU = "25";
scaleV = "25";
MaterialAsset = "Prototyping:FloorGray";
canSave = "1";
canSaveDynamicFields = "1";
Enabled = "1";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
};
new ScatterSky() {
skyBrightness = "25";
sunSize = "1";
colorizeAmount = "0";
colorize = "0 0 0 1";
rayleighScattering = "0.0035";
sunScale = "1 1 1 1";
ambientScale = "1 1 1 1";
fogScale = "1 1 1 1";
exposure = "1";
zOffset = "0";
azimuth = "0";
elevation = "35";
moonAzimuth = "0";
moonElevation = "45";
castShadows = "1";
staticRefreshFreq = "8";
dynamicRefreshFreq = "8";
brightness = "1";
flareScale = "1";
nightColor = "0.0196078 0.0117647 0.109804 1";
nightFogColor = "0.0196078 0.0117647 0.109804 1";
moonEnabled = "1";
moonMat = "Moon_Glow_Mat";
moonScale = "0.2";
moonLightColor = "0.192157 0.192157 0.192157 1";
useNightCubemap = "1";
nightCubemap = "NightCubemap";
attenuationRatio = "0 1 1";
shadowType = "PSSM";
texSize = "1024";
overDarkFactor = "2000 1000 500 100";
shadowDistance = "400";
shadowSoftness = "0.15";
numSplits = "4";
logWeight = "0.91";
fadeStartDistance = "0";
lastSplitTerrainOnly = "0";
representedInLightmap = "0";
shadowDarkenColor = "0 0 0 -1";
includeLightmappedGeometryInShadow = "0";
position = "-19.4839 100.725 -19.5889";
dirtyGameObject = "0";
Enabled = "1";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
canSave = "1";
canSaveDynamicFields = "1";
mieScattering = "0.0045";
};
new Skylight() {
Enabled = "1";
ReflectionMode = "Baked Cubemap";
position = "-2.09752 10.8435 53.7998";
rotation = "1 0 0 0";
position = "1.37009 -5.23561 46.5817";
persistentId = "d5eb3afb-dced-11e9-a423-bb0e346e3870";
dirtyGameObject = "0";
};
new SimGroup(CameraSpawnPoints) {
canSave = "1";
canSaveDynamicFields = "1";
persistentId = "fff282f5-dced-11e9-a423-bb0e346e3870";
enabled = "1";
new SpawnSphere(DefaultCameraSpawnSphere) {
autoSpawn = "0";
spawnTransform = "0";
radius = "1";
sphereWeight = "1";
indoorWeight = "1";
outdoorWeight = "1";
isAIControlled = "0";
dataBlock = "SpawnSphereMarker";
position = "0 0 10";
rotation = "1 0 0 0";
scale = "1 1 1";
canSave = "1";
canSaveDynamicFields = "1";
enabled = "1";
homingCount = "0";
lockCount = "0";
};
};
};
//--- OBJECT WRITE END ---

View file

@ -0,0 +1,14 @@
$PostFX::HDRPostFX::Enabled = 1;
$PostFX::HDRPostFX::minLuminace = 0.001;
$PostFX::HDRPostFX::whiteCutoff = 1;
$PostFX::HDRPostFX::adaptRate = 2;
$PostFX::HDRPostFX::tonemapMode = "ACES";
$PostFX::HDRPostFX::enableBloom = 1;
$PostFX::HDRPostFX::brightPassThreshold = 1;
$PostFX::HDRPostFX::gaussMultiplier = 0.3;
$PostFX::HDRPostFX::gaussMean = 0;
$PostFX::HDRPostFX::gaussStdDev = 0.8;
$PostFX::HDRPostFX::enableAutoExposure = "0";
$PostFX::HDRPostFX::keyValue = 0.18;
$PostFX::HDRPostFX::enableBlueShift = 0;
$PostFX::HDRPostFX::blueShiftColor = "1.05 0.97 1.27";

View file

@ -1,6 +0,0 @@
<PostEffectAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExamplePostEffect"
scriptFile="@assetFile=ExamplePostEffect.cs"
VersionId="1" />

View file

@ -1,131 +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.
//-----------------------------------------------------------------------------
singleton ShaderData( ExamplePostEffect_Shader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = $Core:modulePath @ "ExamplePostEffectP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = $Core:modulePath @ "ExamplePostEffectP.glsl";
samplerNames[0] = "$inputTex";
pixVersion = 3.0;
};
singleton GFXStateBlockData( ExamplePostEffect_StateBlock )
{
samplersDefined = true;
samplerStates[0] = SamplerClampLinear;
samplerStates[1] = SamplerClampLinear;
samplerStates[2] = SamplerClampLinear;
samplerStates[3] = SamplerClampLinear;
blendDefined = true;
blendDest = GFXBlendOne;
blendSrc = GFXBlendZero;
zDefined = true;
zEnable = false;
zWriteEnable = false;
cullDefined = true;
cullMode = GFXCullNone;
};
function ExamplePostEffect::setShaderConsts( %this )
{
}
function ExamplePostEffect::preProcess( %this )
{
}
function ExamplePostEffect::onAdd(%this)
{
//Register the postFX with the manager
PostFXManager.registerPostEffect(%this);
}
function ExamplePostEffect::onEnabled( %this )
{
return true;
}
function ExamplePostEffect::onDisabled( %this )
{
}
//This is used to populate the PostFXEditor's settings so the post FX can be edited
//This is automatically polled for any postFX that has been registered(in our onAdd) and the settings
//are thus exposed for editing
function ExamplePostEffect::populatePostFXSettings(%this)
{
PostEffectEditorInspector.startGroup("ExamplePostEffect - General");
PostEffectEditorInspector.addField("$PostFXManager::Settings::EnabledExamplePostEffect", "Enabled", "bool", "", $PostFXManager::PostFX::EnableExamplePostEffect, "");
PostEffectEditorInspector.endGroup();
}
//This function pair(applyFromPreset and settingsApply) are done the way they are, with the separated variables
//so that we can effectively store the 'settings' away from the live variables that the postFX's actually utilize
//when rendering. This allows us to modify things but still leave room for reverting or temporarily applying them
function ExamplePostEffect::applyFromPreset(%this)
{
//ExamplePostEffect Settings
$PostFXManager::PostFX::EnableExamplePostEffect = $PostFXManager::Settings::EnabledExamplePostEffect;
if($PostFXManager::PostFX::EnableExamplePostEffect)
%this.enable();
else
%this.disable();
}
function ExamplePostEffect::settingsApply(%this)
{
$PostFXManager::Settings::EnabledExamplePostEffect = $PostFXManager::PostFX::EnableExamplePostEffect;
}
singleton PostEffect( ExamplePostEffect )
{
isEnabled = false;
allowReflectPass = false;
// Resolve the HDR before we render any editor stuff
// and before we resolve the scene to the backbuffer.
renderTime = "PFXBeforeBin";
renderBin = "EditorBin";
renderPriority = 9999;
// The bright pass generates a bloomed version of
// the scene for pixels which are brighter than a
// fixed threshold value.
//
// This is then used in the final HDR combine pass
// at the end of this post effect chain.
shader = ExamplePostEffect_Shader;
stateBlock = ExamplePostEffect_StateBlock;
texture[0] = "$backBuffer";
target = "$outTex";
targetFormat = "GFXFormatR16G16B16A16F";
targetScale = "1 1";
};

View file

@ -1,6 +0,0 @@
<ScriptAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExampleGamemodeScript"
scriptFile="@assetFile=ExampleGamemodeScript.cs"
VersionId="1" />

View file

@ -1,156 +0,0 @@
//-----------------------------------------------------------------------------
// The server has started up so do some game start up
//-----------------------------------------------------------------------------
//This file implements game mode logic for an Example gamemode. The primary functions:
//ExampleGameMode::onMissionStart
//ExampleGameMode::onMissionReset
//ExampleGameMode::onMissionEnd
//Are the primary hooks for the server to start, restart and end any active gamemodes
//onMissionStart, for example is called from core/clientServer/scripts/server/levelLoad.tscript
//It's called once the server has successfully loaded the level, and has parsed
//through any active scenes to get GameModeNames defined by them. It then iterates
//over them and calls these callbacks to envoke gamemode behaviors. This allows multiple
//gamemodes to be in effect at one time. Modules can implement as many gamemodes as you want.
//
//For levels that can be reused for multiple gammodes, the general setup would be a primary level file
//with the Scene in it having the main geometry, weapons, terrain, etc. You would then have subScenes that
//each contain what's necessary for the given gamemode, such as a subScene that just adds the flags and capture
//triggers for a CTF mode. The subscene would then have it's GameModeName defined to run the CTF gamemode logic
//and the levelLoad code will execute it.
function ExampleGameMode::onCreateGame()
{
// Note: The Game object will be cleaned up by MissionCleanup. Therefore its lifetime is
// limited to that of the mission.
new ScriptObject(ExampleGameMode){};
return ExampleGameMode;
}
//This function is called when the level finishes loading. It sets up the initial configuration, variables and
//spawning and dynamic objects, timers or rules needed for the gamemode to run
function ExampleGameMode::onMissionStart(%this)
{
//set up the game and game variables
%this.initGameVars();
if (%this.running)
{
error("onMissionStart: End the game first!");
return;
}
// Start the game timer
if (%this.duration)
%this.gameSchedule = schedule(%this.duration * 1000, 0, "onGameDurationEnd");
%this.running = true;
}
//This function is called when the level ends. It can be envoked due to the gamemode ending
//but is also kicked off when the game server is shut down as a form of cleanup for anything the gamemode
//created or is managing like the above mentioned dynamic objects or timers
function ExampleGameMode::onMissionEnded(%this)
{
if (!%this.running)
{
error("onMissionEnded: No game running!");
return;
}
// Stop any game timers
cancel(%this.gameSchedule);
%this.running = false;
}
//This function is called in the event the server resets and is used to re-initialize the gamemode
function ExampleGameMode::onMissionReset(%this)
{
// Called by resetMission(), after all the temporary mission objects
// have been deleted.
%this.initGameVars();
}
//This sets up our gamemode's duration time
function ExampleGameMode::initGameVars(%this)
{
// Set the gameplay parameters
%this.duration = 30 * 60;
}
//This is called when the timer runs out, allowing the gamemode to end
function ExampleGameMode::onGameDurationEnd(%this)
{
//we don't end if we're currently editing the level
if (%this.duration && !(EditorIsActive() && GuiEditorIsActive()))
%this.onMissionEnded();
}
//This is called to actually spawn a control object for the player to utilize
//A player character, spectator camera, etc.
function ExampleGameMode::spawnControlObject(%this, %client)
{
//In this example, we just spawn a camera
if (!isObject(%client.camera))
{
if(!isObject(Observer))
{
datablock CameraData(Observer)
{
mode = "Observer";
};
}
%client.camera = spawnObject("Camera", Observer);
}
// If we have a camera then set up some properties
if (isObject(%client.camera))
{
MissionCleanup.add( %this.camera );
%client.camera.scopeToClient(%client);
%client.setControlObject(%client.camera);
%client.camera.setTransform("0 0 1 0 0 0 0");
}
}
//This is called when the client has initially established a connection to the game server
//It's used for setting up anything ahead of time for the client, such as loading in client-passed
//config stuffs, saved data or the like that should be handled BEFORE the client has actually entered
//the game itself
function ExampleGameMode::onClientConnect(%this, %client)
{
}
//This is called when a client enters the game server. It's used to spawn a player object
//set up any client-specific properties such as saved configs, values, their name, etc
//These callbacks are activated in core/clientServer/scripts/server/levelDownload.tscript
function ExampleGameMode::onClientEnterGame(%this, %client)
{
//Set the player name based on the client's connection data
%client.setPlayerName(%client.connectData);
%this.spawnControlObject(%client);
}
//This is called when the player leaves the game server. It's used to clean up anything that
//was spawned or setup for the client when it connected, in onClientEnterGame
//These callbacks are activated in core/clientServer/scripts/server/levelDownload.tscript
function ExampleGameMode::onClientLeaveGame(%this, %client)
{
// Cleanup the camera
if (isObject(%client.camera))
%client.camera.delete();
}
//This is called when the player has connected and finaly setup is done and control is handed
//over to the client. It allows a point to special-case setting the client's canvas content
//(Such as a gamemode-specific GUI) or setting up gamemode-specific keybinds/control schemes
function ExampleGameMode::onInitialControlSet(%this)
{
}

View file

@ -1,25 +1,3 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
$RemapName[$RemapCount] = "Forward";
$RemapCmd[$RemapCount] = "moveforward";
$RemapActionMap[$RemapCount] = "ExampleMoveMap";
@ -92,21 +70,9 @@ ExampleMoveMap.humanReadableName = "Example Movement";
// Non-remapable binds
//------------------------------------------------------------------------------
ExampleMoveMap.bind( keyboard, F2, showPlayerList );
ExampleMoveMap.bind(keyboard, "ctrl h", hideHUDs);
ExampleMoveMap.bind(keyboard, "alt p", doScreenShotHudless);
function openPauseMenu(%val)
{
if(%val && PauseMenu.isAwake() == false)
{
echo("PUSHING PAUSE MENU");
Canvas.pushDialog(PauseMenu);
}
}
ExampleMoveMap.bind(keyboard, "escape", openPauseMenu);
ExampleMoveMap.bindCmd(keyboard, "escape", "", "Canvas.pushDialog(PauseMenu);");
//------------------------------------------------------------------------------
// Movement Keys
@ -128,21 +94,27 @@ ExampleMoveMap.bind( keyboard, space, jump );
ExampleMoveMap.bind( mouse, xaxis, yaw );
ExampleMoveMap.bind( mouse, yaxis, pitch );
ExampleMoveMap.bind( gamepad, rxaxis, "D", "-0.23 0.23", gamepadYaw );
ExampleMoveMap.bind( gamepad, ryaxis, "D", "-0.23 0.23", gamepadPitch );
ExampleMoveMap.bind( gamepad, xaxis, "D", "-0.23 0.23", gamePadMoveX );
ExampleMoveMap.bind( gamepad, yaxis, "D", "-0.23 0.23", gamePadMoveY );
ExampleMoveMap.bind( gamepad, thumbrx, "D", "-0.23 0.23", gamepadYaw );
ExampleMoveMap.bind( gamepad, thumbry, "D", "-0.23 0.23", gamepadPitch );
ExampleMoveMap.bind( gamepad, thumblx, "D", "-0.23 0.23", gamePadMoveX );
ExampleMoveMap.bind( gamepad, thumbly, "D", "-0.23 0.23", gamePadMoveY );
ExampleMoveMap.bind( gamepad, btn_a, jump );
ExampleMoveMap.bind( gamepad, btn_x, moveup );
ExampleMoveMap.bind( gamepad, btn_y, movedown );
ExampleMoveMap.bindCmd( gamepad, btn_start, "Canvas.pushDialog(PauseMenu);", "" );
ExampleMoveMap.bindCmd( gamepad, btn_back, "disconnect();", "" );
//------------------------------------------------------------------------------
// Demo recording functions
//------------------------------------------------------------------------------
ExampleMoveMap.bind( keyboard, F3, startRecordingDemo );
ExampleMoveMap.bind( keyboard, F4, stopRecordingDemo );
//------------------------------------------------------------------------------
// Helper Functions
//------------------------------------------------------------------------------
GlobalActionMap.bind(keyboard, "ctrl F3", doProfile);
//------------------------------------------------------------------------------
// Misc.
//------------------------------------------------------------------------------
GlobalActionMap.bind(keyboard, "tilde", toggleConsole);
GlobalActionMap.bindCmd(keyboard, "alt k", "cls();","");
GlobalActionMap.bindCmd(keyboard, "alt enter", "", "Canvas.toggleFullscreen();");
GlobalActionMap.bindCmd(keyboard, "F1", "", "contextHelp();");
ExampleMoveMap.bindCmd(keyboard, "n", "toggleNetGraph();", "");

View file

@ -1,29 +1,35 @@
//-----------------------------------------------------------------------------
// 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 escapeFromGame()
{
disconnect();
}
function showPlayerList(%val)
{
if (%val)
PlayerListGui.toggle();
}
function hideHUDs(%val)
{
if (%val)
HudlessPlayGui.toggle();
}
function doScreenShotHudless(%val)
{
if(%val)
{
canvas.setContent(HudlessPlayGui);
//doScreenshot(%val);
schedule(10, 0, "doScreenShot", %val);
}
else
{
%playGUIName = ProjectSettings.value("UI/playGUIName");
Canvas.setContent(%playGUIName);
}
}
$movementSpeed = 1; // m/s
function setSpeed(%speed)
@ -147,8 +153,6 @@ function gamePadMoveX( %val )
function gamePadMoveY( %val )
{
%val *= -1;
if(%val > 0)
{
$mvForwardAction = %val * $movementSpeed;
@ -185,8 +189,6 @@ function gamepadYaw(%val)
function gamepadPitch(%val)
{
%val *= -1;
%pitchAdj = getGamepadAdjustAmount(%val);
if(ServerConnection.isControlObjectRotDampedCamera())
{
@ -205,4 +207,118 @@ function gamepadPitch(%val)
$mvPitchDownSpeed = 0;
$mvPitchUpSpeed = -%pitchAdj;
}
}
function toggleZoomFOV()
{
$Player::CurrentFOV = $Player::CurrentFOV / 2;
if($Player::CurrentFOV < 5)
resetCurrentFOV();
if(ServerConnection.zoomed)
setFOV($Player::CurrentFOV);
else
{
setFov(ServerConnection.getControlCameraDefaultFov());
}
}
function resetCurrentFOV()
{
$Player::CurrentFOV = ServerConnection.getControlCameraDefaultFov() / 2;
}
function turnOffZoom()
{
ServerConnection.zoomed = false;
setFov(ServerConnection.getControlCameraDefaultFov());
Reticle.setVisible(true);
zoomReticle.setVisible(false);
// Rather than just disable the DOF effect, we want to set it to the level's
// preset values.
//DOFPostEffect.disable();
ppOptionsUpdateDOFSettings();
}
function setZoomFOV(%val)
{
if(%val)
toggleZoomFOV();
}
function toggleZoom(%val)
{
if (%val)
{
ServerConnection.zoomed = true;
setFov($Player::CurrentFOV);
Reticle.setVisible(false);
zoomReticle.setVisible(true);
DOFPostEffect.setAutoFocus( true );
DOFPostEffect.setFocusParams( 0.5, 0.5, 50, 500, -5, 5 );
DOFPostEffect.enable();
}
else
{
turnOffZoom();
}
}
function mouseButtonZoom(%val)
{
toggleZoom(%val);
}
function startRecordingDemo( %val )
{
if ( %val )
startDemoRecord();
}
function stopRecordingDemo( %val )
{
if ( %val )
stopDemoRecord();
}
//------------------------------------------------------------------------------
// Debugging Functions
//------------------------------------------------------------------------------
function showMetrics(%val)
{
if(%val)
{
if(!Canvas.isMember(FrameOverlayGui))
metrics("fps gfx shadow sfx terrain groundcover forest net");
else
metrics("");
}
}
GlobalActionMap.bind(keyboard, "ctrl F2", showMetrics);
//------------------------------------------------------------------------------
//
// Start profiler by pressing ctrl f3
// ctrl f3 - starts profile that will dump to console and file
//
function doProfile(%val)
{
if (%val)
{
// key down -- start profile
echo("Starting profile session...");
profilerReset();
profilerEnable(true);
}
else
{
// key up -- finish off profile
echo("Ending profile session...");
profilerDumpToFile("profilerDumpToFile" @ getSimTime() @ ".txt");
profilerEnable(false);
}
}

View file

@ -0,0 +1,237 @@
function ExampleGameMode::onCreateGame()
{
// Note: The Game object will be cleaned up by MissionCleanup. Therefore its lifetime is
// limited to that of the mission.
new ScriptObject(ExampleGameMode){};
return ExampleGameMode;
}
//-----------------------------------------------------------------------------
// The server has started up so do some game start up
//-----------------------------------------------------------------------------
function ExampleGameMode::onMissionStart(%this)
{
//set up the game and game variables
%this.initGameVars();
if (%this.Running)
{
error("onMissionStart: End the game first!");
return;
}
// Inform the client we're starting up
for (%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++)
{
%cl = ClientGroup.getObject(%clientIndex);
commandToClient(%cl, 'GameStart');
}
%this.Running = true;
}
function ExampleGameMode::onMissionEnded(%this)
{
if (!%this.Running)
{
error("onMissionEnded: No game running!");
return;
}
for (%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++)
{
%cl = ClientGroup.getObject(%clientIndex);
commandToClient(%cl, 'GameEnd', %this.EndGamePause);
}
%this.Running = false;
}
function ExampleGameMode::onMissionReset(%this)
{
// Called by resetMission(), after all the temporary mission objects
// have been deleted.
%this.initGameVars();
}
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)
{
}
function ExampleGameMode::onClientEnterGame(%this, %client)
{
// This function currently relies on some helper functions defined in
// core/scripts/spawn.cs. For custom spawn behaviors one can either
// override the properties on the SpawnSphere's or directly override the
// functions themselves.
//echo (%game @"\c4 -> "@ %game.class @" -> GameCore::onClientEntergame");
// Sync the client's clocks to the server's
commandToClient(%client, 'SyncClock', $Sim::Time - %this.StartTime);
//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++)
{
%other = ClientGroup.getObject(%cl);
if ((%other != %client))
{
// These should be "silent" versions of these messages...
messageClient(%client, 'MsgClientJoin', "",
%other.playerName,
%other,
%other.sendGuid,
%other.team,
%other.score,
%other.kills,
%other.deaths,
%other.isAIControlled(),
%other.isAdmin,
%other.isSuperAdmin);
}
}
// Inform the client we've joined up
messageClient(%client,
'MsgClientJoin', '\c2Welcome to the Torque demo app %1.',
%client.playerName,
%client,
%client.sendGuid,
%client.team,
%client.score,
%client.kills,
%client.deaths,
%client.isAiControlled(),
%client.isAdmin,
%client.isSuperAdmin);
// Inform all the other clients of the new guy
messageAllExcept(%client, -1, 'MsgClientJoin', '\c1%1 joined the game.',
%client.playerName,
%client,
%client.sendGuid,
%client.team,
%client.score,
%client.kills,
%client.deaths,
%client.isAiControlled(),
%client.isAdmin,
%client.isSuperAdmin);
}
function ExampleGameMode::onClientLeaveGame(%this, %client)
{
// Cleanup the camera
if (isObject(%client.camera))
%client.camera.delete();
}
function ExampleGameMode::onInitialControlSet(%this)
{
}
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;
}

View file

@ -1,7 +0,0 @@
<CppAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="ExampleCppObject"
codeFile="@assetFile=ExampleCppObject.cpp"
headerFile="@assetFile=ExampleCppObject.h"
VersionId="1" />

View file

@ -1,18 +0,0 @@
#include "core/module.h"
#include "console/engineAPI.h"
MODULE_BEGIN(ExampleModule_Module)
MODULE_INIT_AFTER(Sim)
MODULE_SHUTDOWN_BEFORE(Sim)
MODULE_INIT
{
// Setup anything needed when the engine initializes here
}
MODULE_SHUTDOWN
{
// Cleanup anything that was initialized before here
}
MODULE_END;