If you can program and you're friendly read this!
by Tim Heldna · in Torque Game Engine · 04/27/2005 (9:14 am) · 21 replies
Ok guys, i need a little help here. I know what i need to do i just don't know how to code it. If you could read on, correct my syntax, and forgive my lack of programming knowledge i'd be very appreciative.
My problem relates to vehicles and having separate keyboard / mouse controls for each of them independant from the player controls. There is a resource relating to this that allows you to have different 'maps' for vehicles and the player, which i'm using as a basis. I need to expand on this so i can have a different 'map' for each vehicle.
Here's how i'm trying to do it, i think it will work if someone would show me how to code it correctly...
In each of my vehicle scripts i have a line that says
Obviously the term "jeep" would be replaced with whatever type of vehicle it was in each individual script.
Then in vehicle.cs there is a function that looks like this...
I'm guessing to achieve what i want i need to change it to something like this...
I would then need to add an 'else' statement saying:
if (%vehicletype = "helicopter")
then i would have:
CommandToClient(%obj.client, 'PushActionMap', heliDriverMap);.
I haven't even bothered with the 'else' statement cos i can't even get it to push the 'jeepDriverMap' on mounting a jeep. Instead it remains the 'Player' map ie 'default.bind.cs'.
If someone could look at this code and show me how to rewrite it correctly that would be great.
If it helps the vehicle resource i mentioned is here www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3925
My problem relates to vehicles and having separate keyboard / mouse controls for each of them independant from the player controls. There is a resource relating to this that allows you to have different 'maps' for vehicles and the player, which i'm using as a basis. I need to expand on this so i can have a different 'map' for each vehicle.
Here's how i'm trying to do it, i think it will work if someone would show me how to code it correctly...
In each of my vehicle scripts i have a line that says
%vehicletype = "jeep";
Obviously the term "jeep" would be replaced with whatever type of vehicle it was in each individual script.
Then in vehicle.cs there is a function that looks like this...
function onPlayerMount(%player,%obj,%vehicle,%node)
{
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'PushActionMap', $Vehicle::moveMaps[node]);
CommandToClient(%obj.client,'HideCommandMenuServer');
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
// Are we driving this vehicle?
if (%node == 0) {
%obj.setControlObject(%vehicle);
}
}I'm guessing to achieve what i want i need to change it to something like this...
function onPlayerMount(%player,%obj,%vehicle,%node,%vehicletype)
{
[b]if (%vehicletype = "jeep") {[/b]
CommandToClient(%obj.client, 'PopActionMap', moveMap);
[b]CommandToClient(%obj.client, 'PushActionMap', jeepDriverMap);[/b]
CommandToClient(%obj.client,'HideCommandMenuServer');
}
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
// Are we driving this vehicle?
if (%node == 0) {
%obj.setControlObject(%vehicle);
}
}I would then need to add an 'else' statement saying:
if (%vehicletype = "helicopter")
then i would have:
CommandToClient(%obj.client, 'PushActionMap', heliDriverMap);.
I haven't even bothered with the 'else' statement cos i can't even get it to push the 'jeepDriverMap' on mounting a jeep. Instead it remains the 'Player' map ie 'default.bind.cs'.
If someone could look at this code and show me how to rewrite it correctly that would be great.
If it helps the vehicle resource i mentioned is here www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3925
About the author
#2
It's a bit confusing, but the syntax for a "catcher" command on the client side is:
clientCmdMyCommandName(...);
which will get executed when the server does a
commandToClient(%client, 'MyCommandName', ...);
in the reverse direction (client sending "commands" to the server), it's:
client side
commandToServer('MyCommandName', ...);
server side
serverCmdMyCommandName(%client, ... );
04/27/2005 (10:11 am)
What Ed said is exactly correct, except for syntax: You must write "catcher" commands on the client side script environment to handle an RPC Command.It's a bit confusing, but the syntax for a "catcher" command on the client side is:
clientCmdMyCommandName(...);
which will get executed when the server does a
commandToClient(%client, 'MyCommandName', ...);
in the reverse direction (client sending "commands" to the server), it's:
client side
commandToServer('MyCommandName', ...);
server side
serverCmdMyCommandName(%client, ... );
#3
04/27/2005 (12:43 pm)
DOH... got the serverCmdxxxxxxx and clientCmdxxxxxxxx part reversed... but I'm psyched that my answer was *almost* right... in general principle at least! :-)
#4
04/27/2005 (1:15 pm)
@Ed: Don't feel bad, I get them confused just about every time myself! I had to search in files for examples to make sure I got it right this time, and I've been using Torque for over a year :P
#5
04/27/2005 (1:18 pm)
Now I feel great... that was all off the top of my head! Whoo Hooo! :-P
#6
04/27/2005 (11:51 pm)
Thanks Ed and Stephen. This makes things a lot clearer although i still haven't managed to get this to work. I tried using your method and although there are no errors, and the console reports it is doing the keymap switch command it doesn't actually push the jeep map. It comes up with a WARNING saying something like unable to find command push. I must have done something wrong elsewhere???
#7
Also, for future measure, make your if/thens with strings if (%blah $= "string"). $= is a bitwise comparison, I believe.
04/28/2005 (12:04 am)
Does the function clientCmdPushActionMap exist?Also, for future measure, make your if/thens with strings if (%blah $= "string"). $= is a bitwise comparison, I believe.
#8
If what you're saying is true shouln't it read (%blah $== "string"). Also i was under the impression i had to use a % instead of $ cos '%' is a global variable that could be read from any script whereas '$' can only be read from the script it is in???
All this is giving me a headache, wish i could get my head around it :)
04/28/2005 (3:15 am)
@ Mike KuklinskiIf what you're saying is true shouln't it read (%blah $== "string"). Also i was under the impression i had to use a % instead of $ cos '%' is a global variable that could be read from any script whereas '$' can only be read from the script it is in???
All this is giving me a headache, wish i could get my head around it :)
#9
04/28/2005 (3:15 am)
Show us the console error, and the script code around it so that we can see what the code is that is erroring.
#10
There is a script in server/scripts called vehicle.cs that has this (amongst other things but i think this is the main area that pushes a 'map' on mounting a vehicle)...
I believe this relates to this in client/scripts client.cs...
Other areas of interest would be the player.cs file which has this...
And the client/scripts vehicleDriverMap.cs file which has this at the top (this script obviously has all the bindings for the vehicle as well and is what's being pushed on mounting a vehicle)...
I need to modify this to allow multiple vehicle 'maps' which get called upon entering a specific vehicle, and also 'pop' back to the player 'map' when you dismount.
My scripts are a little messy at the moment so i'll post my console warnings in a little bit once i've got them back to normal.
N.B. If you follow the resource as it is, unmodified, it works just fine with no relevant console warnings.
04/28/2005 (3:32 am)
Stephen, first i'll show you the unmodified code from the resource that allows you to split it up so you can have a seperate 'map' for the player and a seperate 'map' for the vehicle. Bear in mind this only gives you one vehicle 'map', i need more...There is a script in server/scripts called vehicle.cs that has this (amongst other things but i think this is the main area that pushes a 'map' on mounting a vehicle)...
function onPlayerMount(%player,%obj,%vehicle,%node)
{
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'PushActionMap', $Vehicle::moveMaps[%node]);
CommandToClient(%obj.client,'HideCommandMenuServer');
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
// Are we driving this vehicle?
if (%node == 0) {
%obj.setControlObject(%vehicle);
}
}I believe this relates to this in client/scripts client.cs...
function clientCmdPopActionMap(%map)
{
echo("Popping action map " @ %map);
%map.pop();
}
function clientCmdPushActionMap(%map)
{
echo("Pushing action map " @ %map);
%map.push();
}Other areas of interest would be the player.cs file which has this...
function Armor::onMount(%this,%obj,%vehicle,%node)
{
onPlayerMount(%this,%obj,%vehicle,%node);
}
function Armor::onUnmount( %this, %obj, %vehicle, %node )
{
onPlayerUnmount(%this, %obj, %vehicle, %node);
}
function Armor::doDismount(%this, %obj, %forced)
{
doPlayerDismount(%this, %obj, %forced);
}And the client/scripts vehicleDriverMap.cs file which has this at the top (this script obviously has all the bindings for the vehicle as well and is what's being pushed on mounting a vehicle)...
if ( isObject( vehicleDriverMap ) ) vehicleDriverMap.delete(); new ActionMap(vehicleDriverMap);
I need to modify this to allow multiple vehicle 'maps' which get called upon entering a specific vehicle, and also 'pop' back to the player 'map' when you dismount.
My scripts are a little messy at the moment so i'll post my console warnings in a little bit once i've got them back to normal.
N.B. If you follow the resource as it is, unmodified, it works just fine with no relevant console warnings.
#11
05/02/2005 (8:09 am)
Little help... :)
#12
I'll have to do a bit of research...
05/02/2005 (8:35 am)
I'm not sure %map.push() or %map.pop() are the right way to "install" an action map... but that's just a feeling more than anything else... ;-)I'll have to do a bit of research...
#13
In my jeep and helicopter *.cs files i wanna have something that says
vehicletype = "jeep"; in jeep.cs
and
vehicletype = "heli"; in heli.cs
Then in the vehicle.cs script i wanna have an if statement that starts out saying if (vehicletype $= "jeep")... then it would do everything below that if statement only if vehicletype = "jeep"; were true. Then i'd continue with an else if statement that started out saying if (vehicletype $= "heli")..., well you get the idea...
What i'm asking is how do you word vehicletype = "jeep";? I mean is the way i have it now correct or should it be vehicletype == jeep; or something completely different? Also where in jeep.cs should it go? Inside a function? Inside a datablock? How do i get the vehicle.cs file to recognize that value from inside the jeep.cs file? Also how do i word the if statement in vehicle.cs? The way i have it now or should it be something like if (%vehicletype $= "jeep")... etc.
I hope my question is clear because if someone can show me how this is supposed to be done i'll have this working...
05/03/2005 (11:11 am)
Ok, i think i've almost got this working. I just need to know one thing...In my jeep and helicopter *.cs files i wanna have something that says
vehicletype = "jeep"; in jeep.cs
and
vehicletype = "heli"; in heli.cs
Then in the vehicle.cs script i wanna have an if statement that starts out saying if (vehicletype $= "jeep")... then it would do everything below that if statement only if vehicletype = "jeep"; were true. Then i'd continue with an else if statement that started out saying if (vehicletype $= "heli")..., well you get the idea...
What i'm asking is how do you word vehicletype = "jeep";? I mean is the way i have it now correct or should it be vehicletype == jeep; or something completely different? Also where in jeep.cs should it go? Inside a function? Inside a datablock? How do i get the vehicle.cs file to recognize that value from inside the jeep.cs file? Also how do i word the if statement in vehicle.cs? The way i have it now or should it be something like if (%vehicletype $= "jeep")... etc.
I hope my question is clear because if someone can show me how this is supposed to be done i'll have this working...
#14
Then you can check the datablock of the vehicle in question and make whatever decisions you need to based on that.
2) You'd want the $= for a string comparison. If you're using '==', you're checking to see if they're exactly the same string (both in the same chunk of computer memory) rather than if both strings contain the same characters:
%a = "foo";
%b = %a;
%a == %b AND %a $= %b
If instead you started off with
%a = "foo";
%b = "foo";
%a != %b but '%a $= %b' is still true.
(unless I don't understand how torque script works yet, which is entirely possible. I've got plenty of programming background, but this particular script language isn't exactly my strong suit)
05/03/2005 (12:41 pm)
1) I'm none too experienced in torque, but it sounds to me like you could stick a 'vehicleType' member into the datablock of each heli & jeep, and be ready to go.Then you can check the datablock of the vehicle in question and make whatever decisions you need to based on that.
2) You'd want the $= for a string comparison. If you're using '==', you're checking to see if they're exactly the same string (both in the same chunk of computer memory) rather than if both strings contain the same characters:
%a = "foo";
%b = %a;
%a == %b AND %a $= %b
If instead you started off with
%a = "foo";
%b = "foo";
%a != %b but '%a $= %b' is still true.
(unless I don't understand how torque script works yet, which is entirely possible. I've got plenty of programming background, but this particular script language isn't exactly my strong suit)
#15
I've tried taking all of your advice and have it coded like this:
and on the client side:
and in my vehicle scripts:
The most frustrating thing is if i abolish the "if" & "else if" statements in the top piece of code so it reads:
Then it works!!!
The only problem being it pushes the heliDriverMap regardless of what vehicle i'm in, which brings me back to square one :(
Naturally if i changed all instances of "Helicopter & heliDriverMap" to "Jeep & jeepDriverMap" in the above code, it will push the jeepDriverMap irrespective of what vehicle i mount.
This leads me to believe two things are wrong;
(1) I'm not coding the "if" and "else if" statements right
(2) The %vehicleType value isn't being recognized
Any ideas before i go completely nuts?
05/04/2005 (8:04 am)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHH!!!I've tried taking all of your advice and have it coded like this:
function onPlayerMount(%player,%obj,%vehicle,%node)
{
if (%vehicleType $= "helicopter"){
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'DoKeymapSwitchHelicopter',heliDriverMap);
%obj.setControlObject(%vehicle);
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
}
else if (%vehicleType $= "jeep"){
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'DoKeymapSwitchJeep', jeepDriverMap);
%obj.setControlObject(%vehicle);
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
}
}and on the client side:
function clientCmdPopActionMap(%map)
{
echo("Popping action map " @ %map);
movemap.pop();
}
function clientCmdDoKeymapSwitchHelicopter()
{
echo("Pushing Helicopter action map " );
heliDriverMap.push();
}
function clientCmdDoKeymapSwitchJeep()
{
echo("Pushing Jeep action map " );
jeepDriverMap.push();
}and in my vehicle scripts:
[b]in heli.cs[/b]
datablock HeliVehicleData(DefaultHeli)
{
vehicleType = "helicopter";
category = "Vehicles";
shapeFile = "~/data/shapes/iroquis/iroquis.dts";
emap = true;
....
[b]in jeep.cs[/b]
datablock WheeledVehicleData(DefaultCar)
{
vehicleType = "jeep";
category = "Vehicles";
shapeFile = "~/data/shapes/car/buggy.dts";
emap = true;
.... The most frustrating thing is if i abolish the "if" & "else if" statements in the top piece of code so it reads:
function onPlayerMount(%player,%obj,%vehicle,%node)
{
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'DoKeymapSwitchHelicopter',heliDriverMap);
%obj.setControlObject(%vehicle);
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
}Then it works!!!
The only problem being it pushes the heliDriverMap regardless of what vehicle i'm in, which brings me back to square one :(
Naturally if i changed all instances of "Helicopter & heliDriverMap" to "Jeep & jeepDriverMap" in the above code, it will push the jeepDriverMap irrespective of what vehicle i mount.
This leads me to believe two things are wrong;
(1) I'm not coding the "if" and "else if" statements right
(2) The %vehicleType value isn't being recognized
Any ideas before i go completely nuts?
#16
This assumes that "vehicleType" is set in the datablock for each vehicle.
You could use a "switch" statement for a list of vehicle type checks instead of "if" I'd guess.
05/04/2005 (9:34 am)
Yep... that's my guess (if statements are not right)... you might try something like:if (%vehicle.vehicleType $= "helicopter") {
...blah...
}This assumes that "vehicleType" is set in the datablock for each vehicle.
You could use a "switch" statement for a list of vehicle type checks instead of "if" I'd guess.
#17
Pretty sure this is right... the getDataBlock call appears to be working for mountPointTransform().
You can pull all the redundant code out of the individual 'if's so you only have to write it once. If it happens to have a bug (and it invariably will), you only have to FIX IT once as well. Having to fix the same bug in more than one location generally means that you miss at least one copy of it. Which in turn means the bug goes underground, hiding out, but still present in some relatively rare set of circumstances. REALLY irritating. Believe me.
I'm a little suprised you had trouble with this. You're already using .getDataBlock() for the mountPointTransform() call, I wouldn't think this would be any different. My guess would be that you yanked the code out of a tutorial somewhere... :) Nothing wrong with that, it's how you get off the ground. But slowing down to understand what the heck is going on can often help out.
Like now.
Keep plugging away. You'll get it.
05/04/2005 (10:22 pm)
My guess would be:function onPlayerMount(%player,%obj,%vehicle,%node)
{
if ([b]%vehicle.getDataBlock().vehicleType[/b] $= "helicopter"){
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'DoKeymapSwitchHelicopter',heliDriverMap);
} else if ([b]%vehicle.getDataBlock().vehicleType[/b] $= "jeep") {
CommandToClient(%obj.client, 'PopActionMap', moveMap);
CommandToClient(%obj.client, 'DoKeymapSwitchJeep', jeepDriverMap);
}
%obj.setControlObject(%vehicle);
%obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
%obj.unmountImage($WeaponSlot);
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);
}Pretty sure this is right... the getDataBlock call appears to be working for mountPointTransform().
You can pull all the redundant code out of the individual 'if's so you only have to write it once. If it happens to have a bug (and it invariably will), you only have to FIX IT once as well. Having to fix the same bug in more than one location generally means that you miss at least one copy of it. Which in turn means the bug goes underground, hiding out, but still present in some relatively rare set of circumstances. REALLY irritating. Believe me.
I'm a little suprised you had trouble with this. You're already using .getDataBlock() for the mountPointTransform() call, I wouldn't think this would be any different. My guess would be that you yanked the code out of a tutorial somewhere... :) Nothing wrong with that, it's how you get off the ground. But slowing down to understand what the heck is going on can often help out.
Like now.
Keep plugging away. You'll get it.
#18
Mark, the code you posted above worked perfectly!!! Thank you, Thank you, Thank you!!! You have just added 10 years to my lifespan by severely reducing my stress levels. I looked at your code and gave myself a swift kick up the butt cos you're right, i should have been able to work this out myself. Oh well, it's working now. Once again thank you all for the help, it's so appreciated.
A big meaningful THANK YOU to everyone who posted on this thread, couldn't have done it without your help.
:) :) :)
05/04/2005 (11:09 pm)
EUREKA!!!!!!!Mark, the code you posted above worked perfectly!!! Thank you, Thank you, Thank you!!! You have just added 10 years to my lifespan by severely reducing my stress levels. I looked at your code and gave myself a swift kick up the butt cos you're right, i should have been able to work this out myself. Oh well, it's working now. Once again thank you all for the help, it's so appreciated.
A big meaningful THANK YOU to everyone who posted on this thread, couldn't have done it without your help.
:) :) :)
#19
05/05/2005 (6:52 am)
Great! I new Mark had it with the ".getDatablock()." thing... it didn't occur to me that you couldn't access data in the object's datablock directly with the object handle... but I'm learning too, which is why I subscribed to this thread. ;-)
#20
CommandToClient(%obj.client, %vehicle.KeymapSwitchRoutine, %vehicle.DriverMap);
Add the appropriate entries to your vehicle definitions, and a suitable default to the base class.
05/07/2005 (11:10 am)
If you have a small number of vehicles then if/else and switch have acceptible performance. But for a larger number of cases, use a table lookup or object dereference. You could do something like:CommandToClient(%obj.client, %vehicle.KeymapSwitchRoutine, %vehicle.DriverMap);
Add the appropriate entries to your vehicle definitions, and a suitable default to the base class.
Torque Owner EddieRay
function clientCmdDoKeymapSwitch(...) { ... PushActionMap(...) }And in the server code, the calls need to be something like:
I'm still not very familiar with the "stock" code in TGE, but my guess is that 'PushActionMap' is actually a function in the client common code, and you can't access that directly with a CommandToClient() call from the server... you have to create a message handler with the "clientCmd" prefix to its name, and do the call in the code inside this message handler.
Hope this helps...
Ed
EDIT: fixed to match Stephen's corrections