Torque 101: Intro to Torque
by Infinitum3D · in Torque Game Engine · 10/05/2006 (10:12 am) · 155 replies
I have just purchased and downloaded the TorqueGameEngineSDK_1.4
I will be documenting my experiences with it here. I am new to Torque and C++, so I hope others here will be able to learn from my mistakes.
UPDATE: Since I make several mistakes, you should always read through the entire thread of posts before trying anything. There are times that I ruin everything and have to start over entirely. Also, I have upgraded to Torque 1.5 since this post.
Thanks!
1. Download and run the TorqueGameEngineSDK-1-4.exe
This will install the Torque SDK on your computer. It will also place a link on the desktop called Torque Game Engine SDK.
This link is to twelve shortcuts;
FPS Starter Kit
Getting Started Tutorial
readMe.html
Racing Starter Kit
Torque Developer network (online)
Torque Game Engine Demo
Torque Game Engine Home Page
Tutorial Base
Torque Show Tool Pro
Torque Documentation (online)
Torque SDK forums (online)
Uninstall Torque Game Engine
I will read up on these and post more soon. I am starting with the ReadMe.html and the getting Started Tutorial.
UPDATE 10/07/06:
The ReadMe.html is just a one page note about where to find help. Look it over or skip straight to the Getting Starting .pdf tutorial.
2. The Getting Started tutorial is excellent. Follow it through, word by word, step by step, from start to finish, even if a section looks like common sense. !!!Be sure to place the TorqueScript in the EXACT location, exactly as the tutorial says!!! This was my first mistake.
All we have left to do is make sure that our 'clientGame.cs' file gets loaded. Open up GameOne/main.cs and find the 'Client scripts' section of the function called initClient. At the bottom of that list, add the following line, which will load our file:
I added the line at the bottom of the page, not at the bottom of the initClient function.
Update 10/11/06:
Next try to make some changes. For example: tdn.garagegames.com/wiki/Beginner
a. Make a new Torque Logo model that is blue instead of red.
b. Make it give 2 points instead of just 1.
c. Make a yellow one that gives 5 points.
Once I have done this, I'll explain how to do it.
Tony
I will be documenting my experiences with it here. I am new to Torque and C++, so I hope others here will be able to learn from my mistakes.
UPDATE: Since I make several mistakes, you should always read through the entire thread of posts before trying anything. There are times that I ruin everything and have to start over entirely. Also, I have upgraded to Torque 1.5 since this post.
Thanks!
1. Download and run the TorqueGameEngineSDK-1-4.exe
This will install the Torque SDK on your computer. It will also place a link on the desktop called Torque Game Engine SDK.
This link is to twelve shortcuts;
FPS Starter Kit
Getting Started Tutorial
readMe.html
Racing Starter Kit
Torque Developer network (online)
Torque Game Engine Demo
Torque Game Engine Home Page
Tutorial Base
Torque Show Tool Pro
Torque Documentation (online)
Torque SDK forums (online)
Uninstall Torque Game Engine
I will read up on these and post more soon. I am starting with the ReadMe.html and the getting Started Tutorial.
UPDATE 10/07/06:
The ReadMe.html is just a one page note about where to find help. Look it over or skip straight to the Getting Starting .pdf tutorial.
2. The Getting Started tutorial is excellent. Follow it through, word by word, step by step, from start to finish, even if a section looks like common sense. !!!Be sure to place the TorqueScript in the EXACT location, exactly as the tutorial says!!! This was my first mistake.
All we have left to do is make sure that our 'clientGame.cs' file gets loaded. Open up GameOne/main.cs and find the 'Client scripts' section of the function called initClient. At the bottom of that list, add the following line, which will load our file:
I added the line at the bottom of the page, not at the bottom of the initClient function.
Update 10/11/06:
Next try to make some changes. For example: tdn.garagegames.com/wiki/Beginner
a. Make a new Torque Logo model that is blue instead of red.
b. Make it give 2 points instead of just 1.
c. Make a yellow one that gives 5 points.
Once I have done this, I'll explain how to do it.
Tony
#122
try adding this code (changed from the buggy vehicle code):
function DoorItem::create(%block)
{
%obj = new StaticShape() {
dataBlock = %block;
};
return(%obj);
}
07/19/2007 (8:09 pm)
Quote: //--TODO - modify the hard-coding so that a door can be placed using the World Editor.
try adding this code (changed from the buggy vehicle code):
function DoorItem::create(%block)
{
%obj = new StaticShape() {
dataBlock = %block;
};
return(%obj);
}
#123
UPDATE: Sorry I've been away for so long. I stepped away from Torque for awhile to build a RPGMakerXP game for my son. It was fun, finished a whole game in a month, and even learned a few things about programming/scripting. Maybe I'll try to "port" it to Torque. :)
I'll be back with more Torque posts in a few days.
Tony
08/17/2007 (5:52 am)
Thanks mb! I'll test this when I can.UPDATE: Sorry I've been away for so long. I stepped away from Torque for awhile to build a RPGMakerXP game for my son. It was fun, finished a whole game in a month, and even learned a few things about programming/scripting. Maybe I'll try to "port" it to Torque. :)
I'll be back with more Torque posts in a few days.
Tony
#124
Tony
09/06/2007 (10:23 am)
Update: I have a post coming, but the network access at work has been restricted for the time being. I will update with a real post soon. I am currently trying to figure out how to teleport into another mission. I'm checking the forums and resources. If anyone has any help I'd be very appreciative.Tony
#125
Let's try changing the default Orc (Kork) to the TGE_Elf in the Stronghold mission.
1. in server/scripts/player.cs
at the top, look for this
// Load dts shapes and merge animations
comment out this line
//exec("~/data/shapes/player/player.cs");
add this line
exec("~/data/shapes/tge_elf/elf.cs");
so now it looks like this
// Load dts shapes and merge animations
//exec("~/data/shapes/player/player.cs");
exec("~/data/shapes/tge_elf/elf.cs");
I don't think you have to comment out the other exec command. I just did it to show where we're making a change.
2. Further down, under datablock PlayerData(PlayerBody) still in server/scripts/player.cs
comment out this line
shapeFile = "~/data/shapes/player/player.dts";
and add this line
shapeFile = "~/data/shapes/tge_elf/elf.dts";
So it looks like this
This seems to work. I now have the Elf loaded as my default character. In the Stronghold mission, I have no Orcs, only Elves, with an incorrectly mounted crossbow image.
3. Now, we still need to replace the crossbow with a wand.
note: this is a hack, and not the proper way to change mounted objects
I'm going to hijack the crossbow.cs file.
go into the file server/scripts/crossbow.cs
in datablock ItemData(Crossbow)
comment out this line
// shapeFile = "~/data/shapes/crossbow/weapon.dts";
and add this line
shapeFile = "~/data/shapes/staff/weapon.dts";
so it should look like this
4. and further down under datablock ShapeBaseImageData(CrossbowImage)
do the same. comment out the crossbow/weapon.dts and add the line about /staff/weapon.dts
It should look like this
Well darn. Still not working. Where else can the weapon.dts be changed?
OOPS.. Forgot to delete my .dso's and recompile.
Now my Elf has a staff, but it still fires a projectile like the crossbow. Well, not exactly like a crossbow. No arrow goes flying, just a small white light that explodes on contact. That's still kinda neat, but if we just want it to be a melee staff, we'd have to change things.
5. I'm going to remove the projectile code, so it will no longer be a magic staff, just a basic wooden staff.
Back in crossbow.cs I'm just commenting out the entire function for datablock ProjectileData(CrossbowProjectile)
Deleting .dso.s, and running Torque.
It works. I've successfully removed the use of a crossbow from my game.
Why would I do that? I'm working on a game for a six-year old child. I don't want any violence in it. This was the first step.
Now I can go in and make the game all dialog, with no killing.
6. To expand on this, I want my NPC's to spawn without the staff. So in server/scripts/aiplayer.cs I comment out these two lines
OK, so in the Stronghold mission, the Elf (still named Kork) spawns without a staff, but my character still has her staff.
More to come.
Tony
09/10/2007 (10:59 am)
08-23-2007 Torque 101 - TGE_ElfLet's try changing the default Orc (Kork) to the TGE_Elf in the Stronghold mission.
1. in server/scripts/player.cs
at the top, look for this
// Load dts shapes and merge animations
comment out this line
//exec("~/data/shapes/player/player.cs");
add this line
exec("~/data/shapes/tge_elf/elf.cs");
so now it looks like this
// Load dts shapes and merge animations
//exec("~/data/shapes/player/player.cs");
exec("~/data/shapes/tge_elf/elf.cs");
I don't think you have to comment out the other exec command. I just did it to show where we're making a change.
2. Further down, under datablock PlayerData(PlayerBody) still in server/scripts/player.cs
comment out this line
shapeFile = "~/data/shapes/player/player.dts";
and add this line
shapeFile = "~/data/shapes/tge_elf/elf.dts";
So it looks like this
Quote:
datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
emap = true;
className = Armor;
//shapeFile = "~/data/shapes/player/player.dts";
shapeFile = "~/data/shapes/tge_elf/elf.dts";
This seems to work. I now have the Elf loaded as my default character. In the Stronghold mission, I have no Orcs, only Elves, with an incorrectly mounted crossbow image.
3. Now, we still need to replace the crossbow with a wand.
note: this is a hack, and not the proper way to change mounted objects
I'm going to hijack the crossbow.cs file.
go into the file server/scripts/crossbow.cs
in datablock ItemData(Crossbow)
comment out this line
// shapeFile = "~/data/shapes/crossbow/weapon.dts";
and add this line
shapeFile = "~/data/shapes/staff/weapon.dts";
so it should look like this
Quote:
datablock ItemData(Crossbow)
{
// Mission editor category
category = "Weapon";
// Hook into Item Weapon class hierarchy. The weapon namespace
// provides common weapon handling functions in addition to hooks
// into the inventory system.
className = "Weapon";
// Basic Item properties
// shapeFile = "~/data/shapes/crossbow/weapon.dts";
shapeFile = "~/data/shapes/staff/weapon.dts";
4. and further down under datablock ShapeBaseImageData(CrossbowImage)
do the same. comment out the crossbow/weapon.dts and add the line about /staff/weapon.dts
It should look like this
Quote:
datablock ShapeBaseImageData(CrossbowImage)
{
// Basic Item properties
// shapeFile = "~/data/shapes/crossbow/weapon.dts";
shapeFile = "~/data/shapes/staff/weapon.dts";
Well darn. Still not working. Where else can the weapon.dts be changed?
OOPS.. Forgot to delete my .dso's and recompile.
Now my Elf has a staff, but it still fires a projectile like the crossbow. Well, not exactly like a crossbow. No arrow goes flying, just a small white light that explodes on contact. That's still kinda neat, but if we just want it to be a melee staff, we'd have to change things.
5. I'm going to remove the projectile code, so it will no longer be a magic staff, just a basic wooden staff.
Back in crossbow.cs I'm just commenting out the entire function for datablock ProjectileData(CrossbowProjectile)
Deleting .dso.s, and running Torque.
It works. I've successfully removed the use of a crossbow from my game.
Why would I do that? I'm working on a game for a six-year old child. I don't want any violence in it. This was the first step.
Now I can go in and make the game all dialog, with no killing.
6. To expand on this, I want my NPC's to spawn without the staff. So in server/scripts/aiplayer.cs I comment out these two lines
Quote:
// %player.mountImage(CrossbowImage,0);
// %player.setInventory(CrossbowAmmo,1000);
OK, so in the Stronghold mission, the Elf (still named Kork) spawns without a staff, but my character still has her staff.
More to come.
Tony
#126
I've been away for awhile but now I'm back with TGE.
First thing I did was restore Kork. When I stepped away from the game last fall, I had replaced the Orc with the Elf Girl, and removed the crossbow and ability to cause damage. I was planning on making a non-violent game.
I may go back to that at some point, but in order to fully learn the art of game programming with TGE, I'm going back to the basic FPS.
So here's how I got Kork back;
1. in Server\Scripts\player.cs
reset the dts by commenting out the elf.cs and uncommenting the player.cs
// Load dts shapes and merge animations
exec("~/data/shapes/player/player.cs");
//exec("~/data/shapes/tge_elf/elf.cs");
2. still in Server\Scripts\player.cs just halfway down the page;
reset the dts in the datablock by commenting out the elf.dts and uncommenting the player.dts
//----------------
//----------------
datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
emap = true;
className = Armor;
shapeFile = "~/data/shapes/player/player.dts";
// shapeFile = "~/data/shapes/tge_elf/elf.dts";
3. Save the player.cs file.
4. Open Server\Scripts\crossbow.cs
uncomment everything in the datablock ProjectileData
//-----------------------------------------------------------------------------
// Projectile Object
//
datablock ProjectileData(CrossbowProjectile)
{
projectileShapeName = "~/data/shapes/crossbow/projectile.dts";
directDamage = 20;
radiusDamage = 20;
damageRadius = 1.5;
areaImpulse = 2000;
explosion = CrossbowExplosion;
waterExplosion = CrossbowWaterExplosion;
particleEmitter = CrossbowBoltEmitter;
particleWaterEmitter= CrossbowBoltBubbleEmitter;
splash = CrossbowSplash;
muzzleVelocity = 100;
velInheritFactor = 0.3;
armingDelay = 0;
lifetime = 5000;
fadeDelay = 5000;
bounceElasticity = 0;
bounceFriction = 0;
isBallistic = false;
gravityMod = 0.80;
hasLight = true;
lightRadius = 4;
lightColor = "0.5 0.5 0.25";
hasWaterLight = true;
waterLightColor = "0 0.5 0.5";
};
function CrossbowProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
// Apply damage to the object all shape base objects
if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
%col.damage(%obj,%pos,%this.directDamage,"CrossbowBolt");
// Radius damage is a support scripts defined in radiusDamage.cs
// Push the contact point away from the contact surface slightly
// along the contact normal to derive the explosion center. -dbs
radiusDamage(%obj, %pos, %this.damageRadius, %this.radiusDamage, "Radius", %this.areaImpulse);
}
//-----------------------------------------------------------------------------
5. further down (under datablock ItemData(Crossbow)) you need to reset the shapeFile
// Basic Item properties
shapeFile = "~/data/shapes/crossbow/weapon.dts";
// shapeFile = "~/data/shapes/staff/weapon.dts";
6. Save crossbow.cs
7. delete your .dso files to force a recompile
That's it. You should now have Kork back with a crossbow.
So now, what if I wanted to display an Orc and an Elf?
I'm going to copy the file server\scripts\Player.cs and re-name the copy AI_Elf.cs.
Change the dts shape to the elf;
and change the datablock (change the word Player to AI_Elf)
and under functionArmor
change %obj.mountImage(crossbowImage, 0 );
to %obj.mountImage(staffImage, 0 );
and don't forget to exec the .cs in game.cs
OK, I'm going to delete my .dso's and run...
Torque loads, AI_Elf.cs compiles, no error in the console. So far, so good. My NPC's are still Orc's, but now my player is an Elf (with a mis-positioned crossbow). This is good, two different models in the world at the same time. I just wish I knew what I did :)
Back in server\scripts\ there is a file called aiPlayer.cs. Maybe we should have used that instead of copying Player.cs
I'll check the forums (and re-read my steps in this post) and see what I can come up with.
-----
OK, here's what I found.
In my RPGDialog.cs file there is a function to spawn NPC's.
So I've been spawning my NPC's with this script;
So I'm guessing that by using the AI_Elf.cs that I created earlier, I can spawn other NPC's like this;
I'm going into my spawnNPC.cs and adding
Wish me luck...
OK, no NPC's were spawned. In the console I get a parse error and spawnNPC.cs does not compile. Why? Because I still have %player = AI_Elf::spawn(%Name,%location);
%player needs to be changed to what? %ai_elf? Let's try it.
Nope. Didn't work. Getting a console error. Oops, I didn't close my function with a }
I'm adding this
so now my function looks like this...
trying again...
OK, I have my Orc NPC's back, but no AI_Elf... Console says "no script compilation errors occurred", but I am getting a compiling error in gray (not red). "unable to find function AI_Elf::spawn".
I'll post in the forums, asking what in my function is incorrect...
More later...
~Tony
05/28/2008 (3:28 am)
05 27 2008 Torque 101: Coming BackI've been away for awhile but now I'm back with TGE.
First thing I did was restore Kork. When I stepped away from the game last fall, I had replaced the Orc with the Elf Girl, and removed the crossbow and ability to cause damage. I was planning on making a non-violent game.
I may go back to that at some point, but in order to fully learn the art of game programming with TGE, I'm going back to the basic FPS.
So here's how I got Kork back;
1. in Server\Scripts\player.cs
reset the dts by commenting out the elf.cs and uncommenting the player.cs
// Load dts shapes and merge animations
exec("~/data/shapes/player/player.cs");
//exec("~/data/shapes/tge_elf/elf.cs");
2. still in Server\Scripts\player.cs just halfway down the page;
reset the dts in the datablock by commenting out the elf.dts and uncommenting the player.dts
//----------------
//----------------
datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
emap = true;
className = Armor;
shapeFile = "~/data/shapes/player/player.dts";
// shapeFile = "~/data/shapes/tge_elf/elf.dts";
3. Save the player.cs file.
4. Open Server\Scripts\crossbow.cs
uncomment everything in the datablock ProjectileData
//-----------------------------------------------------------------------------
// Projectile Object
//
datablock ProjectileData(CrossbowProjectile)
{
projectileShapeName = "~/data/shapes/crossbow/projectile.dts";
directDamage = 20;
radiusDamage = 20;
damageRadius = 1.5;
areaImpulse = 2000;
explosion = CrossbowExplosion;
waterExplosion = CrossbowWaterExplosion;
particleEmitter = CrossbowBoltEmitter;
particleWaterEmitter= CrossbowBoltBubbleEmitter;
splash = CrossbowSplash;
muzzleVelocity = 100;
velInheritFactor = 0.3;
armingDelay = 0;
lifetime = 5000;
fadeDelay = 5000;
bounceElasticity = 0;
bounceFriction = 0;
isBallistic = false;
gravityMod = 0.80;
hasLight = true;
lightRadius = 4;
lightColor = "0.5 0.5 0.25";
hasWaterLight = true;
waterLightColor = "0 0.5 0.5";
};
function CrossbowProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
// Apply damage to the object all shape base objects
if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
%col.damage(%obj,%pos,%this.directDamage,"CrossbowBolt");
// Radius damage is a support scripts defined in radiusDamage.cs
// Push the contact point away from the contact surface slightly
// along the contact normal to derive the explosion center. -dbs
radiusDamage(%obj, %pos, %this.damageRadius, %this.radiusDamage, "Radius", %this.areaImpulse);
}
//-----------------------------------------------------------------------------
5. further down (under datablock ItemData(Crossbow)) you need to reset the shapeFile
// Basic Item properties
shapeFile = "~/data/shapes/crossbow/weapon.dts";
// shapeFile = "~/data/shapes/staff/weapon.dts";
6. Save crossbow.cs
7. delete your .dso files to force a recompile
That's it. You should now have Kork back with a crossbow.
So now, what if I wanted to display an Orc and an Elf?
I'm going to copy the file server\scripts\Player.cs and re-name the copy AI_Elf.cs.
Change the dts shape to the elf;
Quote:
// Load dts shapes and merge animations
exec("~/data/shapes/tge_elf/elf.cs");
and change the datablock (change the word Player to AI_Elf)
Quote:
//----------------
//----------------
datablock AI_ElfData(AI_ElfBody)
{
renderFirstPerson = false;
emap = true;
className = Armor;
shapeFile = "~/data/shapes/tge_elf/elf.dts";
and under functionArmor
change %obj.mountImage(crossbowImage, 0 );
to %obj.mountImage(staffImage, 0 );
and don't forget to exec the .cs in game.cs
Quote:
// Load up all datablocks, objects etc. This function is called when
// a server is constructed.
exec("AI_Elf.cs");
OK, I'm going to delete my .dso's and run...
Torque loads, AI_Elf.cs compiles, no error in the console. So far, so good. My NPC's are still Orc's, but now my player is an Elf (with a mis-positioned crossbow). This is good, two different models in the world at the same time. I just wish I knew what I did :)
Back in server\scripts\ there is a file called aiPlayer.cs. Maybe we should have used that instead of copying Player.cs
I'll check the forums (and re-read my steps in this post) and see what I can come up with.
-----
OK, here's what I found.
In my RPGDialog.cs file there is a function to spawn NPC's.
Quote:
function SpawnNPC(%Name,%Script,%Portrait,%startQuestion,%location)
{
%player = AIPlayer::spawn(%Name,%location);
%player.RPGDialogScript = %Script;
%player.RPGDialogPortrait = %Portrait;
%player.RPGDialogStartQuestion = %startQuestion;
%player.RPGDialogBusy = false;
%player.RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
%player.RPGDialogTalkingTo = 0;
%player.mountImage(CrossbowImage,0);
%player.setInventory(CrossbowAmmo,10);
return %player;
}
So I've been spawning my NPC's with this script;
Quote:
//--SpawnNPC(%Name,%Script,%Portrait,%startQuestion,%location)
SpawnNPC("Guard Frank", sentry, "girl1.png", 1, "182 -688 108.1 0 0 1 160");
//-- location is X coord., Y coord., Z coord., X-rotation boolean (0=false, 1=true), Y, Z, degrees rotation--//
So I'm guessing that by using the AI_Elf.cs that I created earlier, I can spawn other NPC's like this;
Quote:
function SpawnAI_Elf(%Name,%Script,%Portrait,%startQuestion,%location)
{
%player = AI_Elf::spawn(%Name,%location);
I'm going into my spawnNPC.cs and adding
Quote:
function SpawnAI_Elf(%Name,%Script,%Portrait,%startQuestion,%location)
{
%player = AI_Elf::spawn(%Name,%location);
SpawnAI_Elf("AI Elf", merchant1, "girl3.png", 1, "182 -687 108.1 0 0 1 160");
Wish me luck...
OK, no NPC's were spawned. In the console I get a parse error and spawnNPC.cs does not compile. Why? Because I still have %player = AI_Elf::spawn(%Name,%location);
%player needs to be changed to what? %ai_elf? Let's try it.
Nope. Didn't work. Getting a console error. Oops, I didn't close my function with a }
I'm adding this
Quote:
return %ai_elf;
}
so now my function looks like this...
Quote:
function SpawnAI_Elf(%Name,%Script,%Portrait,%startQuestion,%location)
{
%ai_elf = AI_Elf::spawn(%Name,%location);
return %ai_elf;
}
trying again...
OK, I have my Orc NPC's back, but no AI_Elf... Console says "no script compilation errors occurred", but I am getting a compiling error in gray (not red). "unable to find function AI_Elf::spawn".
I'll post in the forums, asking what in my function is incorrect...
More later...
~Tony
#127
Note: aiName is the name you create for your datablock. Make it unique and specific, since you will need to use it in any functions that relate to this datablock.
Why PlayerData and PlayerBody if its not the player?
Because it behaves like a player -whatever that means :)
//-----------------
OK, now I need some programming help (or more correctly 'scripting' help) with some of the syntax.
I know that % sets a local variable (and $ is a global variable), however, what does (%this, %obj) mean? Does this refer to this specific function? And does objtell it that the function acts on an object?
How do you know when to use %this,%obj? and why does it sometimes have more, like %path,%node,%slot? Obviously path, node, and slot tell it to reference a path a node and a slot, but I don't know what a slot is. Does it just take experience? I mean, I guess I don't understand the concepts (theory).
As you can tell, I'm a true scripting newbie. I can cut/copy/paste/steal code with the best, but now I want to actually understand what I'm doing :)
Thanks for any help explaining this!!!
UPDATE: SOME OF THESE QUESTIONS ARE ANSWERED IN THIS LINK
www.garagegames.com/mg/forums/result.thread.php?qt=75606
~Tony
06/06/2008 (9:56 am)
05-28-2008 Torque 101: Deconstructing aiPlayer.csdatablock PlayerData(aiName : PlayerBody) //-- this datablock will contain all the information needed //--to create an AI (NPC) character //--aiName will become the name of the character type //--in MY case as follows //--datablock PlayerData(ElfGirl : PlayerBody)
Note: aiName is the name you create for your datablock. Make it unique and specific, since you will need to use it in any functions that relate to this datablock.
Why PlayerData and PlayerBody if its not the player?
Because it behaves like a player -whatever that means :)
{
shapeFile = "~/data/shapes/[b]file.dts[/b]";
//--change file.dts to the appropriate .dts file
//--in our case as follows
//--shapeFile ="~/data/shapes/tge_elf/elf.dts
shootingDelay = 2000;
//--NOT SURE WHAT SHOOTINGDELAY MEANS?
};function aiName::onReachDestination(%this,%obj)
//--this function tells the AI character to move
//--along a path from node to node
//--again, change aiName
//--in our case as follows
//--function ElfGirl::onReachDestination(%this,%obj)
{
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "")
{
if (%obj.currentNode == %obj.targetNode)
//--this checks to see if the AI character has reached
//--the end of the path, if it is the end of the path,
//--then it calls (goes to) the onEndOfPath function
%this.onEndOfPath(%obj,%obj.path);
else
//--if it is not the end of the path (hence the 'else')
//--then the AI character will move to
//--the next node on the path
%obj.moveToNextNode();
}
}function aiName::onEndOfPath(%this,%obj,%path)
//--again, aiName gets changed to the
//--appropriate name for this character
//--in our case as follows
//--function ElfGirl::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
//--when this function is called, the
//--program moves on to the next task
}function aiName::onEndSequence(%this,%obj,%slot)
//--and once again, change aiName
//--function ElfGirl::onEndSequence(%this,%obj,%slot)
{
echo("Sequence Done!");
//--echo should appear in the console
//--this tells you that the function has been run
%obj.stopThread(%slot);
//--this seems self explanitory
//--when the sequence is finished, the thread stops
%obj.nextTask();
//--when the thread stops,
//--the program goes on to the next task
}//-----------------
OK, now I need some programming help (or more correctly 'scripting' help) with some of the syntax.
I know that % sets a local variable (and $ is a global variable), however, what does (%this, %obj) mean? Does this refer to this specific function? And does objtell it that the function acts on an object?
How do you know when to use %this,%obj? and why does it sometimes have more, like %path,%node,%slot? Obviously path, node, and slot tell it to reference a path a node and a slot, but I don't know what a slot is. Does it just take experience? I mean, I guess I don't understand the concepts (theory).
As you can tell, I'm a true scripting newbie. I can cut/copy/paste/steal code with the best, but now I want to actually understand what I'm doing :)
Thanks for any help explaining this!!!
UPDATE: SOME OF THESE QUESTIONS ARE ANSWERED IN THIS LINK
www.garagegames.com/mg/forums/result.thread.php?qt=75606
~Tony
#128
06/06/2008 (4:19 pm)
This post is great. Two years of work. Thanks for keeping this up, Tony!
#129
These are just names.
But they must correspond with the script within the function.
I'm reading as much as I can about TorqueScript in the TDN and forums, and I'm also reading some beginning C++ books, which are a bit advanced for me, but I'm still gleaning a thing or two from them.
More to come.
~Tony
06/20/2008 (10:35 am)
OK, I've learned that %this and %obj are just variables. They could have been called %var1, %var2, or even %infinitum, %3d.These are just names.
But they must correspond with the script within the function.
I'm reading as much as I can about TorqueScript in the TDN and forums, and I'm also reading some beginning C++ books, which are a bit advanced for me, but I'm still gleaning a thing or two from them.
More to come.
~Tony
#130
I've been able to spawn duplicates of the Player (an Orc) by using the RPGDialog resource. It seems that the resource hijacks the AIPlayer datablock rather than creating a unique datablock. Or maybe it's the aiPlayer.cs that hijacks the Player.cs datablock... No wait. I think it's the RPGDialog resource that hijacks the AIPlayer datablock...
Anyways, what I need to do now is change things (i.e. create unique datablocks for each AI/NPC) so that I can spawn Orcs, Elves, Humans, etc. I have .dts files for the default TGE Orc (Kork), a female elf, a human male, a human female, and a lich, as well as various animals (horse, rat, spider, etc.)
Let's keep the Player as an Orc, and try to load an Elf.
Note: I get help for this process in this post (read it first).
www.garagegames.com/mg/forums/result.thread.php?qt=75606
First thing we need to do is create a new .cs file. In server/scripts make aiElfSpawn.cs.
Create the datablock;
Next we add the pathfinding portion;
And we have to add the spawn function which draws on the aiElf datablock
And finally we want to incorporate the NPCDialog resource. Note the %player.mountimage has been changed to a staff, because the Elf doesn't hold the crossbow correctly.
Save the file as aiElfSpawn.cs and in the same server/scripts folder open game.cs. Somewhere around line 35 you'll see
At the end of the exec("./ list add this line to execute the aiElfSpawn.cs form.
The last step (or at least the next step) is to add the animations. In the folder data/shapes/player there is a file called player.cs that lists all the animation sequences for the player. My Elf has the same animations, so I just saved the player.cs file as aiElfAnim.cs and moved it to the folder data/shapes/Elf. Remember to change player to aiElf throughout the datablock and code in this file.
Since the player animations get exec'd in server/scripts/player.cs, I'm going to exec aiElfAnim.cs in the same place.
add the line in this area
That's everything. Delete your .dso's to force a recompile and run. I now spawn an elf, holding a staff, and performing the "breathing" (root) animation.
Next step will be to have her walk around (follow a path).
Thanks!
~Tony
06/27/2008 (9:50 am)
06-27-2008 Torque 101: aiElfSpawn.csI've been able to spawn duplicates of the Player (an Orc) by using the RPGDialog resource. It seems that the resource hijacks the AIPlayer datablock rather than creating a unique datablock. Or maybe it's the aiPlayer.cs that hijacks the Player.cs datablock... No wait. I think it's the RPGDialog resource that hijacks the AIPlayer datablock...
%player = AIPlayer::spawn(%Name,%location);
Anyways, what I need to do now is change things (i.e. create unique datablocks for each AI/NPC) so that I can spawn Orcs, Elves, Humans, etc. I have .dts files for the default TGE Orc (Kork), a female elf, a human male, a human female, and a lich, as well as various animals (horse, rat, spider, etc.)
Let's keep the Player as an Orc, and try to load an Elf.
Note: I get help for this process in this post (read it first).
www.garagegames.com/mg/forums/result.thread.php?qt=75606
First thing we need to do is create a new .cs file. In server/scripts make aiElfSpawn.cs.
Create the datablock;
//--SPAWNING ELVES
//--Load the shapefile, note the name aiElf
datablock PlayerData(aiElf : PlayerBody)
{
shapeFile = "~/data/shapes/elf/elf.dts";
shootingDelay = 2000;
};Next we add the pathfinding portion;
//--pathfinding, again note the name aiElf
function aiElf::onReachDestination(%this,%obj)
{
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "")
{
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}
function aiElf::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
}
function aiElf::onEndSequence(%this,%obj,%slot)
{
echo("Sequence Done!");
%obj.stopThread(%slot);
%obj.nextTask();
}And we have to add the spawn function which draws on the aiElf datablock
function aiElf::spawn(%name,%location)
{
// Create the aiElf player object
%player = new AIPlayer() {
dataBlock = aiElf;
path = "";
};
//MissionCleanup.add(%player);
%player.setShapeName(%name);
%player.setTransform(%location);
return %player;
}And finally we want to incorporate the NPCDialog resource. Note the %player.mountimage has been changed to a staff, because the Elf doesn't hold the crossbow correctly.
function SpawnaiElf(%Name,%Script,%Portrait,%startQuestion,%location)
{
%player = aiElf::spawn(%Name,%location);
%player.RPGDialogScript = %Script;
%player.RPGDialogPortrait = %Portrait;
%player.RPGDialogStartQuestion = %startQuestion;
%player.RPGDialogBusy = false;
%player.RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
%player.RPGDialogTalkingTo = 0;
%player.mountImage(staffImage,0);
%player.setInventory(CrossbowAmmo,10);
return %player;
}Save the file as aiElfSpawn.cs and in the same server/scripts folder open game.cs. Somewhere around line 35 you'll see
// Load up all datablocks, objects etc. This function is called when
// a server is constructed.
exec("./audioProfiles.cs");
exec("./envAudioProfiles.cs");
...At the end of the exec("./ list add this line to execute the aiElfSpawn.cs form.
exec("./aiElfSpawn.cs");Back in 2007, or more specifically on 06-06-2007, I created a SpawnNPC.cs file. Now I go back into that file and add the call which spawns the AiElf//--Spawn Elves--//
//--("NAME", SCRIPT, "PORTRAIT", STARTQUESTION, "LOCATION")--//
//-- location is X coord., Y coord., Z coord., X-rotation boolean (0=false, 1=true), Y, Z, degrees rotation--//
SpawnaiElf("aiElf", oversayer, "female1.png", 0, "200 -740 108.8 0 0 1 160");The last step (or at least the next step) is to add the animations. In the folder data/shapes/player there is a file called player.cs that lists all the animation sequences for the player. My Elf has the same animations, so I just saved the player.cs file as aiElfAnim.cs and moved it to the folder data/shapes/Elf. Remember to change player to aiElf throughout the datablock and code in this file.
Since the player animations get exec'd in server/scripts/player.cs, I'm going to exec aiElfAnim.cs in the same place.
add the line in this area
// Load dts shapes and merge animations for player
exec("~/data/shapes/player/playerAnim.cs");
//--note, I changed the name to show it's animation purpose
//Load dts shapes and merge animations for AI and NPC's
exec("~/data/shapes/elf/aiElfAnim.cs"); //--THIS IS MY NEW EXEC CODE--//
// Timeouts for corpse deletion.
$CorpseTimeoutValue = 22 * 1000;That's everything. Delete your .dso's to force a recompile and run. I now spawn an elf, holding a staff, and performing the "breathing" (root) animation.
Next step will be to have her walk around (follow a path).
Thanks!
~Tony
#131
NOTE: This spawns a standing elf that does not walk around. She just stands there breathing, but you can talk to her since the RPGDialog has been incorporated.
More to come...
Tony
06/27/2008 (9:54 am)
This is my final aiElfSpawn.cs file://--SPAWNING ELVES--//
//--load Elf animations
exec("~/data/shapes/tge_elf/aiElfAnim.cs");
datablock PlayerData(aiElf : PlayerBody)
{
shapeFile = "~/data/shapes/tge_elf/elf.dts";
shootingDelay = 2000;
};
function aiElf::onReachDestination(%this,%obj)
{
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "")
{
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}
function aiElf::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
}
function aiElf::onEndSequence(%this,%obj,%slot)
{
echo("Sequence Done!");
%obj.stopThread(%slot);
%obj.nextTask();
}
function aiElf::spawn(%name,%location)
{
// Create the aiElf player object
%player = new AIPlayer() {
dataBlock = aiElf;
path = "";
};
//MissionCleanup.add(%player);
%player.setShapeName(%name);
%player.setTransform(%location);
return %player;
}
function SpawnaiElf(%Name,%Script,%Portrait,%startQuestion,%location)
{
%player = aiElf::spawn(%Name,%location);
%player.RPGDialogScript = %Script;
%player.RPGDialogPortrait = %Portrait;
%player.RPGDialogStartQuestion = %startQuestion;
%player.RPGDialogBusy = false;
%player.RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
%player.RPGDialogTalkingTo = 0;
%player.mountImage(staffImage,0);
%player.setInventory(CrossbowAmmo,10);
return %player;
}
//-- look in SpawnNPC.cs for spawn locations--//NOTE: This spawns a standing elf that does not walk around. She just stands there breathing, but you can talk to her since the RPGDialog has been incorporated.
More to come...
Tony
#132
Virtually identical to my aiElfSpawn code (at this point). This gives me the freedom to have aiElves which will hunt down the Player, and friendly NPC Elves which will be strictly for dialog (bartering, quests, etc.)
I've done the same for aiOrcSpawn, NPCOrcSpawn, etc...
Tony
06/27/2008 (10:00 am)
OK, I really want to separate my NPC (non-enemy) characters from my AI (enemy) characters. So I've made a separate file for my NPC Elves, called NPCELFSPAWN.cs//--SPAWNING ELVES--//
//--load Elf animations
exec("~/data/shapes/tge_elf/aiElfAnim.cs");
datablock PlayerData(NPCElf : PlayerBody)
{
shapeFile = "~/data/shapes/tge_elf/elf.dts";
shootingDelay = 2000;
};
function NPCElf::onReachDestination(%this,%obj)
{
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "")
{
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}
function NPCElf::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
}
function NPCElf::onEndSequence(%this,%obj,%slot)
{
echo("Sequence Done!");
%obj.stopThread(%slot);
%obj.nextTask();
}
function NPCElf::spawn(%name,%location)
{
// Create the NPCElf player object
%player = new AIPlayer() {
dataBlock = NPCElf;
path = "";
};
//MissionCleanup.add(%player);
%player.setShapeName(%name);
%player.setTransform(%location);
return %player;
}
function SpawnNPCElf(%Name,%Script,%Portrait,%startQuestion,%location)
{
%player = NPCElf::spawn(%Name,%location);
%player.RPGDialogScript = %Script;
%player.RPGDialogPortrait = %Portrait;
%player.RPGDialogStartQuestion = %startQuestion;
%player.RPGDialogBusy = false;
%player.RPGDialogBusyText = 'Sorry but I\'m busy talking to %1 right now.';
%player.RPGDialogTalkingTo = 0;
%player.mountImage(staffImage,0);
%player.setInventory(CrossbowAmmo,10);
return %player;
}
//-- look in SpawnNPC.cs for spawn locations--//Virtually identical to my aiElfSpawn code (at this point). This gives me the freedom to have aiElves which will hunt down the Player, and friendly NPC Elves which will be strictly for dialog (bartering, quests, etc.)
I've done the same for aiOrcSpawn, NPCOrcSpawn, etc...
Tony
#133
I have a rat.dts as well as several rat animation .dsq's.
I'm going to attempt to create a path, spawn a rat on said path, play a walking animation as the rat follows the path, and change to a different animation for death of the rat. The difference between this and some of my previous work is that this one will be creating a aiRatSpawn.cs file from scratch rather than just copying aiPlayer.cs and changing the name :)
Disclaimer: In all honesty, I'm still going to cut/copy/paste sections of other .cs files, but I'm going to try to explain each step along the way, so we could actually create one from scratch if we wanted to.
Here we go...
So my rat.dts file is in ~data/shapes/rat/rat.dts
What I've found is that the animation sequences usually get loaded in a .cs file with the same name as the datablock file (like player.cs) I find it confusing to have two files with the same name doing different things, so I changed all the .cs files with animation sequences from things like player.cs to things like playerAnim.cs.
1. So in ~data/shapes/rat, I made ratAnim.cs and listed all the animation sequences as follows;
2. Save the file as ratAnim.cs and go into ~server/scripts and create a new .cs file called aiRatSpawn.cs. For me (and my organizaional purposes), anything that can attack the Player in my game gets named aiWhatever, so I have aiOrc, aiElf, and now aiRat.
The very first lines at the top of the page for aiRatSpawn.cs will load the animation files, or rather, it will execute ratAnim.cs
3. Next, since the rat has two different death animation sequences, we have to define them as variables.
4. Now we need to create the rat datablock.
5. Next we want to define the spawn function for the pathfinding. We use aiManager rather than aiRat because this hooks into a later function we will code called function aiRat::spawn(%this,%location). (See step 12, below.) This calls the spawnOnPath function (see step 12, below). Why two different functions? I really don't know.
6. The aiRat::spawnOnPath function calls the followPath function.
7. The followPath function calls the moveToNextNode function, which moves the aiRat to the next node on the path, hence the function aiRat::moveToNextNode
8. moveToNextNode calls moveToNode, which sets the destination (the node)
9. The next function checks to see if the rat is at its destination (the next node). It basically says, "if the rat is at its destination, then run the onEndOfPath code, otherwise, move on to the next node." I don't fully understand this, since the rat is going to continue following a path. There is no end since this is a circular path, but this worked for me. I think this allows breaks in the pathfinding sequence so that other events can occur, and therefore the pathfinding loop isn't closed.
10. The onEndOfPath function simply calls the nextTask function.
06/27/2008 (10:06 am)
06-27-2008 Torque 101: Death of a RatI have a rat.dts as well as several rat animation .dsq's.
I'm going to attempt to create a path, spawn a rat on said path, play a walking animation as the rat follows the path, and change to a different animation for death of the rat. The difference between this and some of my previous work is that this one will be creating a aiRatSpawn.cs file from scratch rather than just copying aiPlayer.cs and changing the name :)
Disclaimer: In all honesty, I'm still going to cut/copy/paste sections of other .cs files, but I'm going to try to explain each step along the way, so we could actually create one from scratch if we wanted to.
Here we go...
So my rat.dts file is in ~data/shapes/rat/rat.dts
What I've found is that the animation sequences usually get loaded in a .cs file with the same name as the datablock file (like player.cs) I find it confusing to have two files with the same name doing different things, so I changed all the .cs files with animation sequences from things like player.cs to things like playerAnim.cs.
1. So in ~data/shapes/rat, I made ratAnim.cs and listed all the animation sequences as follows;
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
datablock TSShapeConstructor(ratDts)
{
baseShape = "./rat.dts";
sequence0 = "./rat_root.dsq root";
sequence1 = "./rat_run.dsq run";
sequence2 = "./rat_attack.dsq attack";
sequence3 = "./rat_death1.dsq death1";
sequence4 = "./rat_death2.dsq death2";
};2. Save the file as ratAnim.cs and go into ~server/scripts and create a new .cs file called aiRatSpawn.cs. For me (and my organizaional purposes), anything that can attack the Player in my game gets named aiWhatever, so I have aiOrc, aiElf, and now aiRat.
The very first lines at the top of the page for aiRatSpawn.cs will load the animation files, or rather, it will execute ratAnim.cs
//--load rat animation
exec("~/data/shapes/rat/ratAnim.cs");3. Next, since the rat has two different death animation sequences, we have to define them as variables.
//--define the different rat death animations $RatDeathAnim::Death1 = 1; //dollar sign is a global variable $RatDeathAnim::Death2 = 2;
4. Now we need to create the rat datablock.
datablock PlayerData(aiRat)
{
className = Rat; //creates a new Class? I don't know if this is wise, but it works.
shapeFile = "~/data/shapes/Rat/Rat.dts"; //loads the rat.dts
maxForwardSpeed = 2; //self explanitory
mass = 10; //affects impulse force
maxDamage = 10; //self explanitory
};5. Next we want to define the spawn function for the pathfinding. We use aiManager rather than aiRat because this hooks into a later function we will code called function aiRat::spawn(%this,%location). (See step 12, below.) This calls the spawnOnPath function (see step 12, below). Why two different functions? I really don't know.
function AIManager::spawn(%this)
{
%player = aiRat::spawnOnPath("aiRat","MissionGroup/Paths/Path1");
// "aiRat" is the name in green above the rat
// "MissionGroup/Path/Path1" is the directory structure in the mission editor
if (isObject(%player))
{
%player.followPath("MissionGroup/Paths/Path1", -1);
return %player;
}
else
return 0;
}6. The aiRat::spawnOnPath function calls the followPath function.
function aiRat::followPath(%this,%path,%node)
{
// Start the aiRat following a path
%this.stopThread(0);
if (!isObject(%path)) {
%this.path = "";
return;
}
if (%node > %path.getCount() - 1)
%this.targetNode = %path.getCount() - 1;
else
%this.targetNode = %node;
if (%this.path $= %path)
%this.moveToNode(%this.currentNode);
else {
%this.path = %path;
%this.moveToNode(0);
}
}7. The followPath function calls the moveToNextNode function, which moves the aiRat to the next node on the path, hence the function aiRat::moveToNextNode
function aiRat::moveToNextNode(%this)
{
if (%this.targetNode < 0 || %this.currentNode < %this.targetNode) {
if (%this.currentNode < %this.path.getCount() - 1)
%this.moveToNode(%this.currentNode + 1);
else
%this.moveToNode(0);
}
else
if (%this.currentNode == 0)
%this.moveToNode(%this.path.getCount() - 1);
else
%this.moveToNode(%this.currentNode - 1);
}8. moveToNextNode calls moveToNode, which sets the destination (the node)
function aiRat::moveToNode(%this,%index)
{
// Move to the given path node index
%this.currentNode = %index;
%node = %this.path.getObject(%index);
%this.setMoveDestination(%node.getTransform(), %index == %this.targetNode);
}9. The next function checks to see if the rat is at its destination (the next node). It basically says, "if the rat is at its destination, then run the onEndOfPath code, otherwise, move on to the next node." I don't fully understand this, since the rat is going to continue following a path. There is no end since this is a circular path, but this worked for me. I think this allows breaks in the pathfinding sequence so that other events can occur, and therefore the pathfinding loop isn't closed.
function aiRat::onReachDestination(%this,%obj)
{
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "") {
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}10. The onEndOfPath function simply calls the nextTask function.
function aiRat::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
}more coming...
#134
11. and the nextTask function determines which function gets called and executed next by ::executeTask
Two other "task" functions used are pushTask and clearTasks, which keep track of which task gets called (I think).
12. there are three "static functions?" for aiRat spawning. The first create an aiRat using the aiPlayer class (is that right?) and aiRat datablock, along with two variables (name and location). The second calls the aiRat::spawn function, so I don't know why its needed. The third is famous spawnOnPath function that is called by other scripts.
13. The next two functions are wait which sets up a delay before calling the "next task" and done which calls "delete". I don't know if calls is the right term. Its not calling a script function, I think its calling an engine function.
14. The next two functions are damage related; damage and onDamage. damage checks to see if the aiRat dies $="Dead" and if not, then it applies damage to the aiRat "Body". I think "Dead" and "Body" are, again, engine calls, not script calls.
onDamage controls the special effects which occur during damage. It checks to see if the aiRat is "Dead", and it calls some kind of a DamageFlash effect and audio effect playPain.
15. The last three functions are for animation sequences. animate loads the appropriate animation sequence, onDisabled calls the DeathAnimation and also fades out then deletes the corpse, and PlayDeathAnimation chooses which of the two animations to play.
I'v still got more work to do. I wish someone with some experience would follow this thread and correct my many mistakes :)
Tony
06/27/2008 (10:06 am)
continued...11. and the nextTask function determines which function gets called and executed next by ::executeTask
function aiRat::nextTask(%this)
{
if (%this.taskCurrent != -1)
if (%this.taskCurrent < %this.taskIndex - 1)
%this.executeTask(%this.taskCurrent++);
else
%this.taskCurrent = -1;
}
function aiRat::executeTask(%this,%index)
{
%this.taskCurrent = %index;
eval(%this.getId() @ "." @ %this.task[%index] @ ";");
}Two other "task" functions used are pushTask and clearTasks, which keep track of which task gets called (I think).
function aiRat::pushTask(%this,%method)
{
if (%this.taskIndex $= "") {
%this.taskIndex = 0;
%this.taskCurrent = -1;
}
%this.task[%this.taskIndex] = %method;
%this.taskIndex++;
if (%this.taskCurrent == -1)
%this.executeTask(%this.taskIndex - 1);
}
function aiRat::clearTasks(%this)
{
%this.taskIndex = 0;
%this.taskCurrent = -1;
}12. there are three "static functions?" for aiRat spawning. The first create an aiRat using the aiPlayer class (is that right?) and aiRat datablock, along with two variables (name and location). The second calls the aiRat::spawn function, so I don't know why its needed. The third is famous spawnOnPath function that is called by other scripts.
//-----------------------------------------------------------------------------
// aiRat static functions
//-----------------------------------------------------------------------------
function aiRat::spawn(%name,%location)
{
// Create the aiRat
%player = new AiPlayer() {
dataBlock = aiRat;
path = "";
};
%player.setShapeName(%name);
%player.setTransform(%location);
return %player;
}
function SpawnaiRat(%Name,%location)
{
%player = aiRat::spawn(%Name,%location);
%player.unmountImage(Crossbow); //because aiRat needs no crossbow
// %player.setInventory(CrossbowAmmo,10);
return %player;
}
function aiRat::spawnOnPath(%name,%path)
{
// Spawn a aiRat and place it on the first node of the path
if (!isObject(%path))
return 0;
%node = %path.getObject(0);
%player = aiRat::spawn(%name,%node.getTransform());
return %player;
}13. The next two functions are wait which sets up a delay before calling the "next task" and done which calls "delete". I don't know if calls is the right term. Its not calling a script function, I think its calling an engine function.
//-----------------------------------------------------------------------------
function aiRat::wait(%this,%time)
{
%this.schedule(%time * 1000,"nextTask");
}
function aiRat::done(%this,%time)
{
%this.schedule(0,"delete");
}14. The next two functions are damage related; damage and onDamage. damage checks to see if the aiRat dies $="Dead" and if not, then it applies damage to the aiRat "Body". I think "Dead" and "Body" are, again, engine calls, not script calls.
onDamage controls the special effects which occur during damage. It checks to see if the aiRat is "Dead", and it calls some kind of a DamageFlash effect and audio effect playPain.
function aiRat::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
if (%obj.getState() $= "Dead")
return;
%obj.applyDamage(%damage);
%location = "Body";
// Deal with client callbacks here because we don't have this
// information in the onDamage or onDisable methods
%client = %obj.client;
%sourceClient = %sourceObject ? %sourceObject.client : 0;
if (%obj.getState() $= "Dead")
%client.onDisabled(%sourceObject, %sourceClient, %damageType, %location);
}
function aiRat::onDamage(%this, %obj, %delta)
{
// This method is invoked by the ShapeBase code whenever the
// object's damage level changes.
if (%delta > 0 && %obj.getState() !$= "Dead") {
// Increment the flash based on the amount.
%flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);
if (%flash > 0.75)
%flash = 0.75;
%obj.setDamageFlash(%flash);
// If the pain is excessive, let's hear about it.
if (%delta > 10)
%obj.playPain();
}
}15. The last three functions are for animation sequences. animate loads the appropriate animation sequence, onDisabled calls the DeathAnimation and also fades out then deletes the corpse, and PlayDeathAnimation chooses which of the two animations to play.
//begin animating the aiRat by selecting the appropriate animation sequence
function aiRat::animate(%this,%seq)
{
%this.setActionThread(%seq);
}
//when aiRat dies (becomes disabled)
function aiRat::onDisabled(%this,%obj,%seq)
{
%obj.playDeathCry();
%obj.playDeathAnimation();
%obj.setDamageFlash(0.75);
// Schedule corpse removal. Just keeping the place clean.
%obj.schedule($CorpseTimeoutValue - 1000, "startFade", 1000, 0, true);
%obj.schedule($CorpseTimeoutValue, "delete");
}
function aiRat::playDeathAnimation(%this)
{
if (%this.deathIdx++ > 2) // there are 2 death animations to choose from
%this.deathIdx = 1;
%this.setActionThread("Death" @ %this.deathIdx);
}I'v still got more work to do. I wish someone with some experience would follow this thread and correct my many mistakes :)
Tony
#135
Here is the complete, final, working version of my aiRatSpawn.cs file
I do have some problems still. I can only spawn a rat on one path. I have two paths, and I can spawn a rat on either one, but not both... I've also used this to create aiWolfSpawn.cs and aiGhostSpawn.cs, and I can spawn all of them as stationary figures using the root animation, but only one path will ever have a moving figure on it. So I currently have a ghost going around a path, with a couple dozen wolves and rats just standing around watching it and breathing...
More to come...
06/27/2008 (10:10 am)
06-27-2008 Torque 101: Death of a Rat, part deuxHere is the complete, final, working version of my aiRatSpawn.cs file
//-------------aiRat.cs
//--a simple aiRat walking around a path
//---------------------------------------
//--load Rat animation
exec("~/data/shapes/Rat/RatAnim.cs");
$RatDeathAnim::Death1 = 1;
$RatDeathAnim::Death2 = 2;
//----------------------------------------------------------------------------
datablock PlayerData(aiRat : PlayerBody)
{
// className = Horse;
shapeFile = "~/data/shapes/Rat/Rat.dts";
maxForwardSpeed = 2;
mass = 250;
maxDamage = 100;
};
function AIManager::spawn(%this)
{
%player = aiRat::spawnOnPath("aiRat","MissionGroup/Paths/Path1");
if (isObject(%player))
{
%player.followPath("MissionGroup/Paths/Path1", -1);
echo("=====rat spawned on path2=====");
return %player;
}
else
echo("=====cannot spawn rat on path 2=====");
return 0;
}
function aiRat::onReachDestination(%this,%obj)
{
//Moves to the next node on the path.
//Override for all player. Normally we'd override this for only
//a specific player datablock or class of players.
if (%obj.path !$= "") {
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}
function aiRat::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
}
function aiRat::onEndSequence(%this,%obj,%slot)
{
echo("Sequence Done!");
%obj.stopThread(%slot);
%obj.nextTask();
}
//-----------------------------------------------------------------------------
// aiRat static functions
//-----------------------------------------------------------------------------
function aiRat::spawn(%name,%location)
{
// Create the aiRat
%player = new AiPlayer() {
dataBlock = aiRat;
path = "";
};
%player.setShapeName(%name);
%player.setTransform(%location);
%player.unmountImage(Crossbow);
return %player;
}
function SpawnaiRat(%Name,%location)
{
%player = aiRat::spawn(%Name,%location);
%player.unmountImage(Crossbow);
// %player.setInventory(CrossbowAmmo,10);
return %player;
}
function aiRat::spawnOnPath(%name,%path)
{
// Spawn a aiRat and place it on the first node of the path
if (!isObject(%path))
return 0;
%node = %path.getObject(0);
%player = aiRat::spawn(%name,%node.getTransform());
return %player;
}
//-----------------------------------------------------------------------------
// aiRat methods
//-----------------------------------------------------------------------------
function aiRat::followPath(%this,%path,%node)
{
// Start the aiRat following a path
%this.stopThread(0);
if (!isObject(%path)) {
%this.path = "";
return;
}
if (%node > %path.getCount() - 1)
%this.targetNode = %path.getCount() - 1;
else
%this.targetNode = %node;
if (%this.path $= %path)
%this.moveToNode(%this.currentNode);
else {
%this.path = %path;
%this.moveToNode(0);
}
}
function aiRat::moveToNextNode(%this)
{
if (%this.targetNode < 0 || %this.currentNode < %this.targetNode) {
if (%this.currentNode < %this.path.getCount() - 1)
%this.moveToNode(%this.currentNode + 1);
else
%this.moveToNode(0);
}
else
if (%this.currentNode == 0)
%this.moveToNode(%this.path.getCount() - 1);
else
%this.moveToNode(%this.currentNode - 1);
}
function aiRat::moveToNode(%this,%index)
{
// Move to the given path node index
%this.currentNode = %index;
%node = %this.path.getObject(%index);
%this.setMoveDestination(%node.getTransform(), %index == %this.targetNode);
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
function aiRat::pushTask(%this,%method)
{
if (%this.taskIndex $= "") {
%this.taskIndex = 0;
%this.taskCurrent = -1;
}
%this.task[%this.taskIndex] = %method;
%this.taskIndex++;
if (%this.taskCurrent == -1)
%this.executeTask(%this.taskIndex - 1);
}
function aiRat::clearTasks(%this)
{
%this.taskIndex = 0;
%this.taskCurrent = -1;
}
function aiRat::nextTask(%this)
{
if (%this.taskCurrent != -1)
if (%this.taskCurrent < %this.taskIndex - 1)
%this.executeTask(%this.taskCurrent++);
else
%this.taskCurrent = -1;
}
function aiRat::executeTask(%this,%index)
{
%this.taskCurrent = %index;
eval(%this.getId() @ "." @ %this.task[%index] @ ";");
}
//-----------------------------------------------------------------------------
function aiRat::wait(%this,%time)
{
%this.schedule(%time * 1000,"nextTask");
}
function aiRat::done(%this,%time)
{
%this.schedule(0,"delete");
}
function aiRat::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
if (%obj.getState() $= "Dead")
return;
%obj.applyDamage(%damage);
%location = "Body";
// Deal with client callbacks here because we don't have this
// information in the onDamage or onDisable methods
%client = %obj.client;
%sourceClient = %sourceObject ? %sourceObject.client : 0;
if (%obj.getState() $= "Dead")
%client.onDisabled(%sourceObject, %sourceClient, %damageType, %location);
}
function aiRat::onDamage(%this, %obj, %delta)
{
// This method is invoked by the ShapeBase code whenever the
// object's damage level changes.
if (%delta > 0 && %obj.getState() !$= "Dead") {
// Increment the flash based on the amount.
%flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);
if (%flash > 0.75)
%flash = 0.75;
%obj.setDamageFlash(%flash);
// If the pain is excessive, let's hear about it.
if (%delta > 10)
%obj.playPain();
}
}
function aiRat::animate(%this,%seq)
{
%this.setActionThread(%seq);
}
function aiRat::onDisabled(%this,%obj,%seq)
{
// %obj.playDeathCry();
%obj.playDeathAnimation();
// %obj.setDamageFlash(0.75);
// Schedule corpse removal. Just keeping the place clean.
%obj.schedule($CorpseTimeoutValue - 1000, "startFade", 1000, 0, true);
%obj.schedule($CorpseTimeoutValue, "delete");
}
function aiRat::playDeathAnimation(%this)
{
if (%this.deathIdx++ > 2)
%this.deathIdx = 1;
%this.setActionThread("Death" @ %this.deathIdx);
}
//-----------------------------------------------------------------------------
//
//function AIManager::think(%this)
//{
// // We could hook into the player's onDestroyed state instead of
// // having to "think", but thinking allows us to consider other
// // things...
// if (!isObject(%this.player))
// %this.player = %this.spawn();
// %this.schedule(500,think);
//}
//I do have some problems still. I can only spawn a rat on one path. I have two paths, and I can spawn a rat on either one, but not both... I've also used this to create aiWolfSpawn.cs and aiGhostSpawn.cs, and I can spawn all of them as stationary figures using the root animation, but only one path will ever have a moving figure on it. So I currently have a ghost going around a path, with a couple dozen wolves and rats just standing around watching it and breathing...
More to come...
#136
NOTE: Always backup your files first. I can't say this enough. I make many mistakes, and its so much easier to replace a single file than to start the whole process over!!! Read through the entire posting before trying this. I make a mistake and have to start again, but the ending does work!
TGE defaults with two "stat bars", a red HP bar and a blue Energy Points bar. I'm going to attempt to change the blue bar to "SpellPoints" and also add a third, green, "energy" bar or endurance/fatigue counter.
I've previously added a "run" feature which allows the player to move at 5X normal walking rate. Naturally, no one can maintain that speed forever, so I need to limit this ability by fatiguing the player.
My concept is going to be simple.
>80% = 5X normal speed
>60% = 4X
>40% = 3X
>20% = 2X
As the energy level drops, the player will slow down, and when it hits 20%, it will drop immediately to 0. It will regain automatically at a rate of 1% per 3 seconds, or 20% per minute. Later I plan to add potions to increase Energy faster.
1. First thing I did was BackUp my starter.fps folder!!! Then fire up TGE, and load a mission.
Go into the Gui Editor (F-10)
Click on the red Health Bar frame, which is a GuiBitmapCtrl. Edit>Copy then Edit>Paste, and drag the copy over to the right. In the top right window panel you'll see the new GuiBitmapCtrl (you may have to click the [+] to expland). My original frame was number 1213:, and my new one is 1930:
In the bottom right window panel you can see "position". My original red is 11 299, the blue next to it is 50 299, so I'm going to add another 39 so my third will be 89 299. FILE>SAVE GUI client\ui\playGui.gui
I now have three "status bar" frames (red, blue, and empty). In the top right window panel, I have 1211:GuiHealthBarHud (which is the red bar) and 1214:GuiHealthBarHud (which is the blue bar) If you click on 1211:GuiHealthBar in the top right panel, then scroll down the lower right panel to the section called
COLORS, the variable damageFillColor is set to 0.8 0 0 1 (which is red). If you click on 1214:GuiHealthBarHud, and scroll down to colors, damageFillColor is set to 0 0 0.8 1 (which is blue).
Edit>Copy and Edit>Paste the GuiHealthBarHud, change its position to 92 315, and its damageFillColor to 0 0.8 0 1 (which is green).
FILE>SAVE GUI
Exit Torque.
Now delete your .dso's and reload the mission.
The green bar fills just like the blue bar fills... but the green rectangle is on top of the frame, not below it... Click on the green rectangle to select it, then go up to the toolbar and click Layout>Send to back. There. Now the green bar is behind the frame.
FILE>SAVE GUI
Delete dso.s and reload the mission...
Three "health" bars, red, blue, and green, but green doesn't do anything yet... and worse, now my mouse buttons don't work to turn the player camera view or fire the crossbow. I can still walk in all directions, but I can't turn...
I checked the forums, and I was told that Energy is a standard feature in Torque, and I remember seeing a Boolean check box for showEnergy... Let's see. I'm replacing my messed up PlayGui.gui file with my working backup PlayGui_bak.gui, so I can start fresh.
2. Starting Over... Launching Torque again. Gui editor (F-10)...
I think the reason my mouse locked was because my player somehow lost focus.
So instead of copying/pasting, I'm going to make new original ctrl's.
Click at the top "New Control" and click on GuiBitmapCtrl. There is now a new item in the top right window panel of the Gui editor.
In the bottom right window panel, scroll down to Extent in the Parent section. Change it from 64 64 to 32 172. Then change its position to 91 299. Make sure the HorizSizing and VertSizing are set to 'right' and 'top' respectively. Scroll down to "bitmap" in the Misc section and click. It opens up a window. Browse to find
client/ui/healthBar.png
Now we have a third frame established. We need a new GuiHealthBarHud in green to fill it. Click New Control again, and scroll down to GuiHealthBarHud. Remember to change the sizing to 'right' and 'top' and change the extent to 26 138 (just like the red and blue bars). Position needs to be 91 315 (or maybe 92 315).
Make sure your PlayGui.gui is backed up, because this may not work!!!
File>Save Gui
Exit Torque.
Delete .dso's (I use the DeleteDSOs.bat file. I even have a shortcut to it on my desktop.)
Restart Torque.
Load a mission.
Sonofab@#$%! Still not working. My mouse still doesn't function in game.....
Replace the messed up PlayGui.gui with the backup and we'll try again...
3. Starting small. Let's do something easy. Let's just try to change the color of the blue bar to green.
Start Torque, load a mission, (F-10) into the Gui Editor.
Top right window panel select 1214:GuiHealthBarHud
Bottom right window panel scroll down to COLORS and change damageFillColor to 0 0.8 0 1
(Make sure playGui.gui backup is still available!)
FILE>SAVE GUI
Exit TGE, delete dso's, restart TGE, load mission...
@#$%&*!!!!!
Mouse locks again!
Why!?!?!?!
If I (F-11) into the World Editor, the mouse works fine, just not in the game after making any changes to GuiHealthBarHud. OK, Using a text editor, I've opened up the messed up PlayGui.gui and the original working PlayGui_BAK.gui, side by side to compare. The original does NOT have anything about can save Dynamic field, but the messed up one has it for EVERY new section.
This is what works for me
Let's try something by text.
I'm replacing the messed up copy of PlayGui.gui with the working original (and keeping a backup copy of the working original in case this gets screwed up!)
Now my game has the original working PlayGui.gui. I open it in the text editor and the only change I'm making is to the "damageFillColor" at position 53 315. I change it from
to
save it, delete dso's, reload, and...
OK, that worked... Well, let's just keep editing text, shall we?
We'll add this;
We should now have a red, green, and blue "health" bar, green and blue for energy and red for health.
Saving PlayGui.gui, deleing dso's, reloading...
HOORAY!!!
It works! That means there was a problem with the Gui editor! Turns out, you cannot edit the screen that is active. It confuses TGE.
Next step? Figuring out how to implement this new bar. We need to tie it into the Player.cs file somehow.
Tony
08/01/2008 (11:55 am)
07-30-2008 Torque 101: Energy BarNOTE: Always backup your files first. I can't say this enough. I make many mistakes, and its so much easier to replace a single file than to start the whole process over!!! Read through the entire posting before trying this. I make a mistake and have to start again, but the ending does work!
TGE defaults with two "stat bars", a red HP bar and a blue Energy Points bar. I'm going to attempt to change the blue bar to "SpellPoints" and also add a third, green, "energy" bar or endurance/fatigue counter.
I've previously added a "run" feature which allows the player to move at 5X normal walking rate. Naturally, no one can maintain that speed forever, so I need to limit this ability by fatiguing the player.
My concept is going to be simple.
>80% = 5X normal speed
>60% = 4X
>40% = 3X
>20% = 2X
As the energy level drops, the player will slow down, and when it hits 20%, it will drop immediately to 0. It will regain automatically at a rate of 1% per 3 seconds, or 20% per minute. Later I plan to add potions to increase Energy faster.
1. First thing I did was BackUp my starter.fps folder!!! Then fire up TGE, and load a mission.
Go into the Gui Editor (F-10)
Click on the red Health Bar frame, which is a GuiBitmapCtrl. Edit>Copy then Edit>Paste, and drag the copy over to the right. In the top right window panel you'll see the new GuiBitmapCtrl (you may have to click the [+] to expland). My original frame was number 1213:, and my new one is 1930:
In the bottom right window panel you can see "position". My original red is 11 299, the blue next to it is 50 299, so I'm going to add another 39 so my third will be 89 299. FILE>SAVE GUI client\ui\playGui.gui
I now have three "status bar" frames (red, blue, and empty). In the top right window panel, I have 1211:GuiHealthBarHud (which is the red bar) and 1214:GuiHealthBarHud (which is the blue bar) If you click on 1211:GuiHealthBar in the top right panel, then scroll down the lower right panel to the section called
COLORS, the variable damageFillColor is set to 0.8 0 0 1 (which is red). If you click on 1214:GuiHealthBarHud, and scroll down to colors, damageFillColor is set to 0 0 0.8 1 (which is blue).
Edit>Copy and Edit>Paste the GuiHealthBarHud, change its position to 92 315, and its damageFillColor to 0 0.8 0 1 (which is green).
FILE>SAVE GUI
Exit Torque.
Now delete your .dso's and reload the mission.
The green bar fills just like the blue bar fills... but the green rectangle is on top of the frame, not below it... Click on the green rectangle to select it, then go up to the toolbar and click Layout>Send to back. There. Now the green bar is behind the frame.
FILE>SAVE GUI
Delete dso.s and reload the mission...
Three "health" bars, red, blue, and green, but green doesn't do anything yet... and worse, now my mouse buttons don't work to turn the player camera view or fire the crossbow. I can still walk in all directions, but I can't turn...
I checked the forums, and I was told that Energy is a standard feature in Torque, and I remember seeing a Boolean check box for showEnergy... Let's see. I'm replacing my messed up PlayGui.gui file with my working backup PlayGui_bak.gui, so I can start fresh.
2. Starting Over... Launching Torque again. Gui editor (F-10)...
I think the reason my mouse locked was because my player somehow lost focus.
So instead of copying/pasting, I'm going to make new original ctrl's.
Click at the top "New Control" and click on GuiBitmapCtrl. There is now a new item in the top right window panel of the Gui editor.
In the bottom right window panel, scroll down to Extent in the Parent section. Change it from 64 64 to 32 172. Then change its position to 91 299. Make sure the HorizSizing and VertSizing are set to 'right' and 'top' respectively. Scroll down to "bitmap" in the Misc section and click. It opens up a window. Browse to find
client/ui/healthBar.png
Now we have a third frame established. We need a new GuiHealthBarHud in green to fill it. Click New Control again, and scroll down to GuiHealthBarHud. Remember to change the sizing to 'right' and 'top' and change the extent to 26 138 (just like the red and blue bars). Position needs to be 91 315 (or maybe 92 315).
Make sure your PlayGui.gui is backed up, because this may not work!!!
File>Save Gui
Exit Torque.
Delete .dso's (I use the DeleteDSOs.bat file. I even have a shortcut to it on my desktop.)
Restart Torque.
Load a mission.
Sonofab@#$%! Still not working. My mouse still doesn't function in game.....
Replace the messed up PlayGui.gui with the backup and we'll try again...
3. Starting small. Let's do something easy. Let's just try to change the color of the blue bar to green.
Start Torque, load a mission, (F-10) into the Gui Editor.
Top right window panel select 1214:GuiHealthBarHud
Bottom right window panel scroll down to COLORS and change damageFillColor to 0 0.8 0 1
(Make sure playGui.gui backup is still available!)
FILE>SAVE GUI
Exit TGE, delete dso's, restart TGE, load mission...
@#$%&*!!!!!
Mouse locks again!
Why!?!?!?!
If I (F-11) into the World Editor, the mouse works fine, just not in the game after making any changes to GuiHealthBarHud. OK, Using a text editor, I've opened up the messed up PlayGui.gui and the original working PlayGui_BAK.gui, side by side to compare. The original does NOT have anything about can save Dynamic field, but the messed up one has it for EVERY new section.
This is what works for me
Let's try something by text.
I'm replacing the messed up copy of PlayGui.gui with the working original (and keeping a backup copy of the working original in case this gets screwed up!)
Now my game has the original working PlayGui.gui. I open it in the text editor and the only change I'm making is to the "damageFillColor" at position 53 315. I change it from
Quote:
damageFillColor = "0.000000 0.000000 0.800000 1.000000";
to
Quote:
damageFillColor = "0.000000 0.800000 0.000000 1.000000";
save it, delete dso's, reload, and...
OK, that worked... Well, let's just keep editing text, shall we?
We'll add this;
Quote:
new GuiHealthBarHud() {
profile = "GuiDefaultProfile";
horizSizing = "right";
vertSizing = "top";
position = "92 315";
extent = "26 138";
minExtent = "8 8";
visible = "1";
helpTag = "0";
showFill = "1";
displayEnergy = "1";
showFrame = "1";
fillColor = "0.000000 0.000000 0.000000 0.500000";
frameColor = "0.000000 1.000000 0.000000 0.000000";
damageFillColor = "0.000000 0.000000 0.8000000 1.000000";
pulseRate = "1000";
pulseThreshold = "0.5";
value = "1";
};
new GuiBitmapCtrl() {
profile = "GuiDefaultProfile";
horizSizing = "right";
vertSizing = "top";
position = "89 299";
extent = "32 172";
minExtent = "8 8";
visible = "1";
helpTag = "0";
bitmap = "./healthBar";
wrap = "0";
};
We should now have a red, green, and blue "health" bar, green and blue for energy and red for health.
Saving PlayGui.gui, deleing dso's, reloading...
HOORAY!!!
It works! That means there was a problem with the Gui editor! Turns out, you cannot edit the screen that is active. It confuses TGE.
Next step? Figuring out how to implement this new bar. We need to tie it into the Player.cs file somehow.
Tony
#137
helped me a lot getting the RPGDialog going.
i'd say i'll be back before long.
thanks again.
08/25/2008 (1:14 pm)
This is a fantastic post!!helped me a lot getting the RPGDialog going.
i'd say i'll be back before long.
thanks again.
#138
08/25/2008 (1:36 pm)
Great work on posting this Tony. 8-)
#139
Thanks David!
I've been adding art to my game world which now consists of a single continent (a large island really) with two small villages, several dozen NPC's with the RPGDialog resource, and ambient animations of swaying signs, flying flags, and banners flapping in the breeze.
I'll get back to TorqueScripting soon, but in the meantime, feel free to use the art on David's website.
~Tony
ps. I don't get much time online with my PC. I usually check the web via cell-phone, however, this thread has gotten so long that it takes forever to scroll down to the newest posts. I may start posting updates as a blog rather than in this thread. If/when I do, I'll announce it here first. Thanks!
09/24/2008 (11:16 am)
I haven't updated this thread any lately because I've been working on 3D art. I have some ambient animations that work in-game, and are skinnable by script. David Janssens has graciously hosted the pack along with my "Castle Builder Kits" at difdts.nebulagame.com/Thanks David!
I've been adding art to my game world which now consists of a single continent (a large island really) with two small villages, several dozen NPC's with the RPGDialog resource, and ambient animations of swaying signs, flying flags, and banners flapping in the breeze.
I'll get back to TorqueScripting soon, but in the meantime, feel free to use the art on David's website.
~Tony
ps. I don't get much time online with my PC. I usually check the web via cell-phone, however, this thread has gotten so long that it takes forever to scroll down to the newest posts. I may start posting updates as a blog rather than in this thread. If/when I do, I'll announce it here first. Thanks!
#140
NOTE: Always backup your files first. I can't say this enough. I make many mistakes, and its so much easier to replace a single file than to start the whole process over!!! Read through the entire posting before trying this. I may make a mistake and have to start again!!
I'm following a resource on garagegames called Code: Health repair/recharge rate by Dustin Mullen (Jun 16, 2008)
It allows the player's health to restore gradually (verrrrry slowly) over time. It just a simple mod of player.cs, changing two lines:
First change
repairRate = 0.33;
to
repairRate = 0.001; //--NOTE: repair is for HEALTH
then down under
function Armor::onAdd(%this,%obj)
change the setRepairRate from
%obj.setRepairRate(0);
to
%obj.setRepairRate(%this.repairRate);
That's it. Now when Player takes damage, he will slowly heal (regain health) over time.
delete .dso's and restart.
Now, to edit the Sprint function so that energy depletes and gradually returns.
I already have a Sprint function.
I add this:
This may not work in multiplayer mode since it directly affects the PlayerBody datablock.
What I'd really like is to add the Energy amount directly to the equation, like this:
$mvForwardAction = %val * $movementSpeed * ENERGY;
but I haven't figured out the proper syntax yet.
In player.cs I set rechargeRate 0.1
Note: "recharge" is for energy, "repair" is for health.
Back in default.bind.cs, add the change to the [b]moveforward[/b[ function also
So basically, when you sprint, you lose energy, when you stand still, you regain energy, and when you walk, your energy doesn't increase or decrease.
Save player.cs and default.bind.cs, delete dso's, and restart.
Tony
10/07/2008 (10:33 am)
10-07-2008 Torque 101: Sprinting with an Energy BarNOTE: Always backup your files first. I can't say this enough. I make many mistakes, and its so much easier to replace a single file than to start the whole process over!!! Read through the entire posting before trying this. I may make a mistake and have to start again!!
I'm following a resource on garagegames called Code: Health repair/recharge rate by Dustin Mullen (Jun 16, 2008)
It allows the player's health to restore gradually (verrrrry slowly) over time. It just a simple mod of player.cs, changing two lines:
First change
repairRate = 0.33;
to
repairRate = 0.001; //--NOTE: repair is for HEALTH
then down under
function Armor::onAdd(%this,%obj)
change the setRepairRate from
%obj.setRepairRate(0);
to
%obj.setRepairRate(%this.repairRate);
That's it. Now when Player takes damage, he will slowly heal (regain health) over time.
delete .dso's and restart.
Now, to edit the Sprint function so that energy depletes and gradually returns.
I already have a Sprint function.
//-----------------
function sprint(%val)
{
$mvForwardAction = %val * $movementSpeed * 3;
}
//-----------------I add this:
if (%val)
{
playerbody.runEnergyDrain = 1;
}
else playerbody.runEnergyDrain = 0.2;So that it ends up looking like this:function sprint(%val)
{
$mvForwardAction = %val * $movementSpeed * 3;
if (%val)
{
playerbody.runEnergyDrain = 1;
}
else playerbody.runEnergyDrain = 0.2;
}This may not work in multiplayer mode since it directly affects the PlayerBody datablock.
What I'd really like is to add the Energy amount directly to the equation, like this:
$mvForwardAction = %val * $movementSpeed * ENERGY;
but I haven't figured out the proper syntax yet.
In player.cs I set rechargeRate 0.1
Note: "recharge" is for energy, "repair" is for health.
Back in default.bind.cs, add the change to the [b]moveforward[/b[ function also
function moveforward(%val)
{
$mvForwardAction = %val * $movementSpeed;
if (%val)
{
playerbody.runEnergyDrain = 0.1;//--this is equal to the recharge rate
}
else playerbody.runEnergyDrain = 0;
} So basically, when you sprint, you lose energy, when you stand still, you regain energy, and when you walk, your energy doesn't increase or decrease.
Save player.cs and default.bind.cs, delete dso's, and restart.
Tony
Torque Owner J
Act 7
J.