| Author: beffy (c++programmer) |
The short snipits and examples here are just random stuff I came across while scripting, programming, browsing the GG site or
hanging around in the IRC... hope you'll find something useful here!
The snipits are from various people and various sources, so please forgive me
that I didn't include all the authors' names...
This page will be updated regularly, so make sure you come back every now and then... ;-)
This little function lets you turn the names above the players / bots on and off with a keypress... simply put it in default.bind.cs and put the "bind" command into this file, too AND in your "{modname}\client\config.cs" file...
function toggleNames(%val)
{
if(%val)
{
for(%i = 0;%i < PlayGui.getCount(); %i++)
{
%obj = PlayGui.getObject(%i);
if(%obj.getClassName()$="GuiShapeNameHud")
{
%obj.visible = !%obj.visible;
return;
}
}
}
}
moveMap.bind(keyboard,"ctrl n",toggleNames);
This little snipit lets every player and bot spawn with a weapon at startup.
Put it into "\server\scripts\game.cs" -> function GameConnection::createPlayer(), at the end of the function...
%player.incInventory(Rifle,1); %player.incInventory(RifleAmmo,RifleAmmo.maxInventory); %player.use(Rifle);Or, if you're using Tim's InventoryManager, the commands look like this:
%player.incInvItem(Rifle,1); %player.incInvItem(RifleAmmo,RifleAmmo.maxInventory); %player.use(Rifle);
This little snipit finds all vehicles within a 50m radius.
function findVehicle(%obj)
{
%position = %obj.getTransform();
%radius = 50;
InitContainerRadiusSearch(%position, %radius, $TypeMasks::VehicleObjectType);
while ((%targetObject = containerSearchNext()) != 0)
{
%dist = containerSearchCurrRadiusDist();
echo("found vehicle:" SPC %targetObject SPC ",distance is:" SPC %dist);
}
}
Or, another example: search other players within view
// usage: e.g. search other players:
// commandToServer('SearchObject', "0.1");
function serverCmdSearchObject(%client, %radius)
{
// example: search for other players
%typeMask = $TypeMasks::PlayerObjectType;
%StartPos=%client.player.gettransform();
%Eye = %client.player.getEyeVector();
%EndPos = vectorScale(%Eye, -1);
%EndPos = vectorsub(%StartPos,%EndPos);
// point, radius, mask
InitContainerRadiusSearch(%EndPos, %radius, %typeMask);
%rayCast=ContainerSearchNext();
while(%rayCast != 0 )
{
// now %rayCast is the object found!
if(isObject(%rayCast))
{
echo("Object found for typeMask:" SPC %typeMask);
// dump
%rayCast.dump();
}
// get next Object
%rayCast=ContainerSearchNext();
}
}
This little snipit finds all Items by their name and returns the nearest to %myPos.
Call it like this:
%nextHealthObjPos = findNearestItem(%this.player.getPosition(), "HealthPatch");
function findNearestItem(%myPos, %name)
{
%dataGroup = "MissionGroup";
for(%i = 0; %i < %dataGroup.getCount(); %i++)
{
%obj = %dataGroup.getObject(%i);
if(%obj.getClassName() !$= "Item")
{
echo("NO ITEM!");
continue;
}
if(%obj.getDatablock().getName() $= %name && isObject(%obj))
{
%objPos = %obj.position;
//%obj.dump();
echo(%i SPC "Found object: Datablockname is:" SPC %obj.getDatablock().getName() SPC "POSITION:"
SPC %obj.position SPC "ClassName:" SPC %obj.getClassName());
%tempDist = VectorDist(%objPos, %myPos);
if(%shortestDist > %tempDist || %shortestDist $= "")
{
%shortestDist = %tempDist;
%finalPos = %objPos;
}
echo("shortestDist:" SPC %shortestDist);
}
}
return %finalPos;
}
Ever wondered how to disable the "dos" console that launches everytime you start the engine?
Here's how to do it...
project->settings Select the "Torque Demo" click on the "Link Tab" Under project options find /subsystem:console and change it to /subsystem:windowsthen hit "Build -> Clean" and "Build -> Build torqueDemo.exe" and it's gone!
This is from another thread I came across in the GG forums which I found VERY useful
for the overall understanding of the engine
So let's just cite Badguy, who wrote
this post...
"... ShapeBase is the base class for anything that is a 3d model. being how many of the game objects had use for these properties .. they were placed in the class to reduce code im sure. (energy, muzzlepoint,...) I would say the line between using this class , and using GameBase.. could be drawn by stating : if this object needs interaction with the player ie: mounting, collecting, carrying. then it should prolly be shapebase. if this object does not need direct interaction with the player.. yet needs to be processed everytick ie: an elevator, door it could be GameBase. if the object needs no processing or interacting. but needs to remain in the scene to draw it should be SceneObject ..."Some more thoughts from Phil C.:
"...sceneobect is there for drawing but doesnt support datablocks or time based incrementation (processtick etc) gamebase adds time based updating. shapebase adds a few useless things AND support for image mounting (i.e. sub object mounts) My best advice is to find something thats doing close to what you need and see what thats derived from. Most of my stuff is gamebase derived."
To find any object, you can either use a SimSetIterator or use
Sim::findObject(objectName) directly (if it's one specific object/group you're looking for).
The following code searches all objects of type "Interior" (this is, ".dif" objects).
Btw., you can see all the available object types in "engine\game\objectTypes.h".
for (SimSetIterator itr(conn); *itr; ++itr) {
// check if it's an interior...
if ((*itr)->getType() & InteriorObjectType) {
// okay, so cast it...
InteriorInstance* shape = static_cast(*itr);
if (shape->getType() & InteriorObjectType) {
// now do something with the Interiors...
Point3F newCoord = shape->getBoxCenter();
Box3F shapeBox = shape->getWorldBox();
// ...
}
}
}
// searching the Sim for the "MissionArea" object... MissionArea * mArea = dynamic_cast(Sim::findObject("MissionArea")); RectI mAreaRect = mArea->getArea(); // ...
Well, this is an easy one...
In C++, you can first search for the object (see [007]) and then use the function getPosition(), which will give you a Point3F ...TerrainBlock * mTerr = dynamic_castIn script it's even easier, you can simply do:(Sim::findObject("Terrain")); Point3F terrPos = mTerr->getPosition(); float terrX = terrPos.x; ...
%player = %client.player; %currPlayerPos = %player.getPosition(); // or // %currPlayerPos = %player.getTransform(); // see numer [011] below ...
By default, every player using a vehicle is mouted to mountpoint 0, this is done in player.cs, Armor::onCollision():
// Mount vehicles
%this = %col.getDataBlock();
if ((%this.className $= WheeledVehicleData || %this.className $= WaterCraftData || %this.className $= FlyingVehicleData)
&& %obj.mountVehicle && %obj.getState() $= "Move" && %col.mountable) {
// Only mount drivers for now.
%node = 0;
...
}
Now, instead of setting %node to 0, you could use a little function I found in the forums:
%node = findEmptySeat(%col, %this);
function findEmptySeat(%vehicle, %vehicleblock)
{
for (%i = 0; %i < %vehicleblock.numMountPoints; %i++)
{
%node = %vehicle.getMountNodeObject(%i);
if (%node == 0)
{
return %i;
}
}
return -1;
}
Just make sure your vehicle has at least mount0 and mount1, and that's it.
If you use the debug build, you can view various metrics by using the console. Simly turn on the console by pressing the "tilde" key (or whatever key is mapped to it), then type
metrics(%what);where %what can be one of these values:
audio debug interior fps time terrain texture video vehicle water
metrics(fps);which then pops up a little text gui on your PlayGui showing the current fps value...
Or, use these great uitilities, where you got all this (and much more) in a nice GUI...
If you do something like
%t = %client.player.getTransform();you don't just get a Point3F with the position of the player (that's what %client.player.getPosition() will return), actually you get 7 numbers back, which are:
1) x-axis position 2) y-axis position 3) z-axis position 4) x-axis rotation 5) y-axis rotation 6) z-axis rotation These rotation numbers make up the axis of rotation of the object, and the 7th and final number is the ... 7) rotation about that axis in radiansSo now in script you could get any of these with
%x = getWord(%t, 0);
%y = getWord(%t, 1);
...
The addMaterialMapping function has more components then what are listed in the documentation.
AddMaterialMapping("scorched_dk","detail: fps/data/terrains/details/detail1",
"environment: fps/data/skies/sunset_0007 0.25", "color: color: 0.46 0.36 0.26 0.4 0.0", "sound: 0");
"scorched_dk",Texture name without extension
"detail: fps/data/terrains/details/detail1",Texture to use for detail overlay, no extension.
"environment: fps/data/skies/sunset_0007 0.25",Texture to use for environment map, Percent of reflection (?), Only usable for interior object textures.
"color: color: 0.46 0.36 0.26 0.4 0.0",Footpuff color, Red Green Blue Alpha1 Alpha2.
"sound: 0"Sound to play when player walks on this texture.
Sound Chart:
0 FootSoftSound
1 FootHardSound
2 FootMetalSound
3 FootSnowSound
ShapeBaseImageData in itself is much like anyother datablock class defined the engine (and instantiated in scripts the same way too).
Instead of being an entire object (it doesn't process ticks, or interpolate, moves, insert render images, and so forth) it only handles timed/triggered states. So in itself it really is a "datablock" as it just holds data for the ShapeBase class (and it's derivatives, your turret would probably be an example as players are).
When you tell a ShapeBase object to mount an image to a certain slot it will add it into the mMountedImageList array (member of ShapeBase) referencing the image's datablock. I believe the index of that array is equivalent to the slot number. A slot isn't necessarily equivalent to a mountpoint on the ShapeBase object (you define that in the ShapeBaseImage datablock). The mountpoint is the node which will be used as the image's shape's origin when rendered. For example a player has a mount0 (that's the node's name in the dts shape) on it's hand. If you want to mount a weapon to that hand, you would set the mountpoint in the weapon's datablock to 0.
Also, triggers are relative to slots. Right now, for the player, only the first two triggers are used and they only trigger slots 0 and 1.
--------------------------------------------------------------------------------
//
//... in player.cc Player::updateMove(...)
setImageTriggerState(0,move->trigger[0]);
setImageTriggerState(1,move->trigger[1]);
//...
--------------------------------------------------------------------------------
If you check out how ShapeBase renders, it'll render it's own image (ie: a player) and then
render all the mounted ones (ie: packs, weapons, even body parts...).
Images have a variety of other little functions like correcting the muzzle vector (which is on the muzzle node on the image's shape transformed relative the player/object's mountpoint plus image defined offset) with the eye vector (so you shoot smack on the reticle). In first person you can give them any offset you like, provided the shapebase object isn't set to render in first person otherwise it'll be relative to the mountpoint. I personally always use the mountpoint so you can see the weapon bob with the player as it breathes and animates.
So here's how it all plays out in script:
--------------------------------------------------------------------------------
datablock ShapeBaseImageData(RifleImage)
{
// the shape and rendering settings
shapeFile = "~/data/shapes/rifle/weapon.dts";
emap = true;
// mountPoint is the mount# on the objects
// this will mount to
mountPoint = 0;
// offset is any extra displacement you want
// to add to the mountPoint's, for tweeking
// image position
offset = "0 0 0";
// offset used when in first person
eyeOffset = "0.1 0.2 -0.55";
// this will correct the muzzle vector to point
// towards the same imaginary point on the horizon
// as your eye vector in first person
correctMuzzleVector = true;
// Projectile && Ammo.
// now the projectile data is actually stored here
// engine side, keep a note of that so you define
// your projectiles before this image
// you may want this if you want your turret to
// estimate ahead of a moving target object...
// if you do you'll need the projectile's velocity
// and like this you'll be able to claim it engine
// side
projectile = RifleProjectile;
// script use variables removed for brevity
// image states removed for brevity
};
--------------------------------------------------------------------------------
So now, this image will render relative to mountPoint 0 (attached to) with no extra offset. So the origin of mountPoint 0 will line up with that of the image shape (unless you define a mountPoint on the image shape, it should then use that instead of the origin).
To mount it to an object you would do:object.mountImage(RifleImage, slot);
If you want it to be triggered by your script bound mouse fire key, it must be on slot 0. There are a max of 8 slots on an object and 6 triggers.
To remove it, either mount another image over the same slot or:object.unMountImage(slot);The images all throw script side callbacks like
-------------------------------------------------------------------------------- RifleImage::onmountImage(%slot); RifleImage::onUnmountImage(%slot); --------------------------------------------------------------------------------And you can define your own callbacks in the scripted image states (onFire being one).
Another thing to note is that even though an image can be mounted on multiple players, you will always have only one shape instance for the image and that's in the image datablock.
(you can find further details in this thread!)(by Melv May, found here)
Things to check are:
- The object should be based upon a SceneObject.
- It should override the OnAdd/OnRemove with at least...
bool MyConeObj::onAdd()
{
if(!Parent::onAdd()) return(false);
// Set initial object-space bounding box.
mObjBox.min.set( -0.5f, -0.5f, -0.5f );
mObjBox.max.set( 0.5f, 0.5f, 0.5f );
// Reset the World Box.
resetWorldBox();
// Set the Render Transform.
setRenderTransform(mObjToWorld);
// Add to Scene.
addToScene();
// Return OK.
return(true);
}
void MyConeObj::onRemove()
{
// Remove from Scene.
removeFromScene();
// Do Parent.
Parent::onRemove();
}
- A minimal prepRenderImage function like...
bool MyConeObj::prepRenderImage( SceneState* state, const U32 stateKey, const U32 startZone,
const bool modifyBaseZoneState)
{
// Return if last state.
if (isLastState(state, stateKey)) return false;
// Set Last State.
setLastState(state, stateKey);
// Is Object Rendered?
if (state->isObjectRendered(this))
{
// Yes, so get a SceneRenderImage.
SceneRenderImage* image = new SceneRenderImage;
// Populate it.
image->obj = this;
image->isTranslucent = false;
image->sortType = SceneRenderImage::Normal;
// Insert it into the scene images.
state->insertRenderImage(image);
}
return false;
}
- Make sure you are at least passing the appropriate positional information from server to client...
U32 MyConeObj::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
{
// Pack Parent.
U32 retMask = Parent::packUpdate(con, mask, stream);
// Write MyConeObj Mask Flag.
if (stream->writeFlag(mask & MyConeObjMask))
{
stream->writeAffineTransform(mObjToWorld);
}
// Were done ...
return(retMask);
}
void MyConeObj::unpackUpdate(NetConnection * con, BitStream * stream)
{
// Unpack Parent.
Parent::unpackUpdate(con, stream);
// Read MyConeObjMask Flag.
if(stream->readFlag())
{
MatrixF MyConeObjObjectMatrix;
stream->readAffineTransform(&MyConeObjObjectMatrix);
// Set Transform.
setTransform(MyConeObjObjectMatrix);
}
}
- Make sure that your object-space box (above) completely encapsulates your object otherwise it will be culled.
Imagine you want to delete all *.dso files everytime the game exits, or you want to delete all *cs files
before you publish a new version of the game... here is how to do it within the engine...
Credits go to Daniel Eden, who posted this snippit here.
// Adds the deleteFile function to the console
ConsoleFunction(deleteFile, bool, 2, 2, "deleteFile(fileName)")
{
argc;
Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
return bool(ResourceManager->deleteFile(scriptFilenameBuffer));
}
Then, add the following function to resManager.cc:
// Delete file functionality, returns 0 on fail, 1 on succeed
bool ResManager::deleteFile (const char *fileName)
{
// If there's no filename, fail out.
if (!fileName)
return 0;
// Prevent a little nastiness...
if(!dStrstr(fileName, ".."))
{
// Comment the Con::warnf out if you want quiet deletion (ie. no console spam)
Con::warnf("Deleting file '%s'.", fileName);
// Actually delete the file.
dFileDelete(fileName);
}
return 1;
}
Then add the following to resManager.h (at line 315 or thereabouts):
bool deleteFile(const char * fileName);Finally, add the following function to your common package in the main.cs file (found in example\common\):
// Quit override
function quit()
{
echo("Deleting DSOs...");
// Create a new script object to handle the list of dso files
%tmp = new ScriptObject() {};
// Set the initial file count to zero
%num = 0;
// Search for *.dso files
%search = "*.dso";
// Search the directory tree for .dso files and construct a list.
for(%file = findFirstFile(%search); %file !$= ""; %file = findNextFile(%search))
{
%tmp.file[%num] = %file;
%num++;
}
// Cycle through the list and delete each file.
for (%i = 0; %i < %num; %i++)
{
deleteFile(%tmp.file[%i]);
}
// Delete the script object.
%tmp.delete();
// Return to the parent function.
return parent::quit();
}
Credits go to Harold "LabRat" Brown, the original GG post can be found here.
function readfile(%filename)
{
%file = new FileObject();
if(%file.openForRead(%filename))
{
while(!%file.isEOF())
{
%input = %file.readLine();
echo(%input);
}
}
%file.close();
%file.delete();
}
function write(%filename)
{
%file = new FileObject();
%file.openforWrite(%filename);
%file.writeLine( "This is an output file);
%file.writeLine( "I can contain any plain text that the user wishes to output." );
%file.close();
%file.delete();
}
// Usage:
// openFile("name","fileHandle","R");
// Open a file named "name" assign a fileHandle ID of "fileHandle", open as Readonly.
// Reference in another function:
// fileHandle.readLine();
//
// openfile("name","fileHandle","W");
// Open a file named "name" assign a fileHandle ID of "fileHandle", open as Writeonly.
// Reference in another function:
// fileHandle.writeLine();
//
// closeFile("fileHandle");
// Closes the file associated with the fileHandle ID of "fileHandle"
function openFile(%filename,%IDname,%rw)
{
%file = new FileObject(%IDname);
if (%rw $= "R")
{
if(%file.openForRead(%filename))
{
return 1;
}
else
{
return 0;
}
}
else if (%rw $= "W")
{
%file.openForWrite(%filename);
return 1;
}
else
{
return 0;
}
}
function closeFile(%IDname)
{
%IDname.close();
%IDname.delete();
}
getSaveFilename() is a scripted function / GUI that allows you to pick a
filename for the file you wish to save using file specs.
function SaveFile()
{
getSaveFilename("*.txt",saveTextFile,"default.txt");
}
function saveTextFile(%fileName)
{
%file = new FileObject();
%file.openforWrite(%filename);
%file.writeLine( "This is an output file);
%file.writeLine( "I can contain any plain text that the user wishes to output." );
%file.close();
%file.delete();
}
There is also a simliar function for loading files named getLoadFilename. It
only uses the first two arguements though.
function LoadFile()
{
getLoadFilename("*.txt",loadTextFile);
}
function loadTextFile(%fileName)
{
%file = new FileObject();
if(%file.openForRead(%filename))
{
while(!%file.isEOF())
{
%input = %file.readLine();
echo(%input);
}
}
%file.close();
%file.delete();
}
Credits go to Sam Guffey and Harold "LabRat" Brown,
the original GG post can be found here.
This will test to see if the weapon you have is able to zoom based on the images
datablock, if you want the gun to zoom you must put ' canZoom = true; ' in the
guns image. If not then it wont zoom at all.
//------------------------------------------------------------------------------
// Zoom and FOV functions
//------------------------------------------------------------------------------
if($Pref::player::CurrentFOV $= "")
$Pref::player::CurrentFOV = 45;
function setZoomFOV(%val)
{
if(%val)
toggleZoomFOV();
}
function serverCmdGetCurrentWeapon(%client)
{
%player = %client.player;
%weapon = %player.getMountedImage($WeaponSlot);
if(%weapon) // Testing to see if we are packing.
if(%weapon.canZoom) // Testing the image to see if we can zoom
commandToClient(%client, 'applyZoom');
// it is so we apply the zoom. If not we dont do anything.
}
function clientCmdapplyZoom()
{
$ZoomOn = true;
setFov( $Pref::player::CurrentFOV );
zoomcrosshair.Visible = 1; // show crosshair for zoom.
playerReticle.Visible = 0; // make normal crosshair invisible.
}
function toggleZoom( %val )
{
if ( %val )
commandToServer('GetCurrentWeapon');
else
{
$ZoomOn = false;
setFov( $Pref::player::DefaultFov );
zoomcrosshair.Visible = 0; // make zoom crosshair invisible.
playerReticle.Visible = 1; // show the normal one again.
}
}
function toggleZoomFOV()
{
if($pref::player::currentFOV == $pref::player::defaultFov / 2)
$pref::player::currentFOV = $pref::player::defaultFov / 5;
else
$pref::player::currentFOV = $pref::player::currentFOV / 2;
if($pref::player::currentFOV < 4)
$pref::player::currentFOV = $pref::player::defaultFov / 2;
if($ZoomOn)
setFov( $pref::player::currentFOV );
}
moveMap.bind(keyboard, z, setZoomFOV);
moveMap.bind(keyboard, e, toggleZoom);
Credits go to Daniel Neilsen who posted this in his plan...
The TGE engine uses a looped audio sound which, for fast firing weapons was causing all of the audio channels to fill up. I reworked this code to use one audio channel only and use singular (non-looped) sounds. The result is a much cleaner and clearer sounding weapon.
Lines at approx 1616 look like this
// Play sound
if (stateData.sound && isGhost()) {
Point3F vel = getVelocity();
image.animSound = alxPlay(stateData.sound, &getRenderTransform(), &vel);
ALint value = 0;
alxGetSourcei(image.animSound, AL_LOOPING, &value);
image.animLoopingSound = (value == AL_TRUE);
}
Replace them with this
// Play sound
if (stateData.sound && isGhost()) {
Point3F vel = getVelocity();
if(image.animSound)
{
alxStop(image.animSound);
image.animSound = 0;
}
image.animSound = alxPlay(stateData.sound, &getRenderTransform(), &vel);
ALint value = 0;
//alxGetSourcei(image.animSound, AL_LOOPING, &value);
image.animLoopingSound = false;//(value == AL_TRUE);
}
What this does is plays a sound and, if that sound is still playign when the next firing sound is played, it stops it before playing the next sound. This means you can use a nice long 2 second rifle sound in an automatic rifle (if you wish) and the last firing sound will have that nice long fade.
// Get the current transform matrix %matrix = %obj.getTransform(); %xpos = getWord(%matrix, 0); %ypos = getWord(%matrix, 1); %zpos = getWord(%matrix, 2); // Set the rotation matrix stuff %xrot = 0; %yrot = 0; %zrot = 1; %angle = ($SomeAngleInDegrees * 3.14) / 180.0; // apply the transformation. %obj.setTransform(%xpos SPC %ypos SPC %zpos SPC %xrot SPC %yrot SPC %zrot SPC %angle);
If you set $Pref::Net::DisplayOnMaster = "Never" in fps/server/prefs.cs, then your server won't talk to the master anymore.
//if true the inventory is being hidden this is
//tru, otherwise false.
$isHiding=false;
//cancel whatever movement was going on and reverse direction
function toggleHud()
{
cancel($hudSlider);
$isHiding = !$isHiding;
if (!$isHiding) ItemArea.setVisible(true);
slideHud(10,$isHiding,ItemArea);
}
//move the obj by val amount. If shrink is true
//it moves off the screen, or else it moves back onto
//the screen
function slideHud(%val,%shrink,%obj)
{
%res = getResolution();
%pos=%obj.getPosition();
%size = %obj.getExtent();
if (%shrink)//move off the screen
{
if (getWord(%pos,1)>getWord(%res,1))
{
%obj.setVisible(false); //off screen hide it totally
return;
} %obj.resize(getWord(%pos,0),getWord(%pos,1)+2,getWord(%size,0),getWord
(%size,1));
}
else //move onto screen
{
if (getWord(%pos,1) <=435*(getWord(%res,1)/480)) return;
%obj.resize(getWord(%pos,0),getWord(%pos,1)-2,getWord(%size,0),getWord
(%size,1));
}
$hudSlider = schedule(5,0,"slideHud",%val-1,%shrink,%obj);
}
moveMap.bind( keyboard, i, toggleInterface );
function toggleInterface(%val)
{
if(%val)
toggleHud();
}
Open the engine file fx/precipitation.cc, and around line 697 add only the code in bold below:
mFallingObj[x].stillFalling = false;
}
}
//-----------------------------------------------
RayInfo rInfo;
if (gClientContainer.castRay( mFallingObj[x].curPos,
Point3F( mFallingObj[x].curPos.x,
mFallingObj[x].curPos.y,
mFallingObj[x].curPos.z + 10000 ),
InteriorObjectType, &rInfo) )
mFallingObj[x].stillFalling = false;
//-----------------------------------------------
if(mFallingObj[x].stillFalling)// && mBox.isContained(mFallingObj[x].curPos))
{
coordX = mTexCoord[mFallingObj[x].texIndex].x;
Found here.
Con::addCommand creates a script function which calls a static function in C++, static functions are class functions and do not require an instance of the class for invocation, e.g. Con::addCommand("ShapeBase", "setRepairRate", cSetRepairRate, "obj.setRepairRate(value)", 3, 3); a check of ShapeBase::setRepairRate will show that it is static and can be invoked as:
ShapeBase::setRepairRate(args);ConsoleMethod creates a script function which calls a non-static function in C++, these can only be invoked on an object of the class. e.g.
aiPlayer player = new aiPlayer(); player.getAimObject();
posted by Tim Gift here.
Well to start with, Torque is heavily scripted. Most of what you talk about; damage, weapon management, fire rates, spawning, item pickup, etc. is all scripted, so there is no avoiding the language :) At least not if you want to work within the current game structure. Besides fixing bugs, and general cleanup (and the web site), our focus has been on getting the demo done, so that it would provide a starting point for developers looking at how a game is put together.
As a quick overview... most objects provide pretty bare bones functionality and export attributes, functions and event callbacks to the scripting language. The player is an example of this, the basic player.cc file adds movement, collision, action animation (animation based on the current move, run, jump, falling etc.) and misc. eye candy (such as foot prints and dust puffs). Thatīs it.. there is no weapon management, or game specific code (though there are some assumptions about what a player can do). The rest is handed off to the scripting language.
So basically the game portion of the engine consists of a collection of objects which each provides some core functionality used by the script to implement the game.
These are the core game classes:
There are others, but these are sort of the core game classes. To read a little more about object ghost and datablocks, you might try the
tribes networking article Mark and I wrote for CGDC.
I also posted a list of some of the script event callbacks generated by these classes in an earlier plan file.
Posted by Jared Schnelle here.
Open up the file fps/server/scripts/game.cs
At the end of the createGame() function put this.
dbgsetparameters("4500","myPass"); //Start the Debugger!
Then click Edit->Preferences -> Debugger Icon
Posted here.
Item *pItem = new Item; ItemData *pHealthKit = dynamic_castHere is code to remove a Item that was created from the function above.(Sim::findObject("HealthKit")); pItem->onNewDataBlock( pHealthKit ); pItem->setPosition(Point3F(300,300,300)); if (pItem->registerObject()) { delete pItem; pItem = 0; }
if( pItem )
{
Con::printf("Deleting object %s", pItem->getShapeName());
pItem->deleteObject();
}
Remember to add the include file "item.h"
Also remember to remove all the Items you created before shutting the engine down or you will get an error.