Does the function command mountObject work in TGE1.5.2?
by Infinitum3D · in Torque Game Engine · 04/20/2009 (2:38 pm) · 12 replies
I originally posted this in the Artist Forum, but I think it belongs here. Sorry about the double post, but I couldn't delete it from the other forum.
I'm trying to mount an object with a single "mountpoint" to an object with a single "mount0" mountnode.
It works in ShowTool, but not in Stronghold. I get "unknown command mountObject"...
Any ideas why?
Tony
I'm trying to mount an object with a single "mountpoint" to an object with a single "mount0" mountnode.
It works in ShowTool, but not in Stronghold. I get "unknown command mountObject"...
Any ideas why?
Tony
#2
Everything else works, it just doesn't mount. Is my Datablock wrong? Should mountpoint = "0"; only be part of the object which gets mounted (the door) or only the object which gets mounted to (the hinge)?
Thanks!
Tony
04/21/2009 (12:37 pm)
//--Thanks Tim Feni for the resource
//--See Also: Interaction.cs
// -----------------------------------------------------------------------------
// Datablocks - shapes
// -----------------------------------------------------------------------------
datablock StaticShapeData(doorHinge){
category = "doors";
className = door;
shapeFile = "~/data/shapes/doors/hinge_rotate.dts";
position = "0 0 0";
Scale="1 1 1";
emap = true;
receiveSunLight = "1";
mountpoint = "0";
};
datablock StaticShapeData(theDoor){
category = "doors";
className = door;
shapeFile = "~/data/shapes/doors/door_mountpoint.dts";
position = "0 0 0";
scale="1 1 1";
emap = true;
receiveSunLight = "1";
mountpoint = "0";
};
// ----------------------------------------------------------------------------------
// Functions - door open events
// ----------------------------------------------------------------------------------
// This function is called whenever the client presses the 'use interaction' key ("u" key)
// within the set distance.
// calls from interaction.cs change distance there.
function door::onAdd(%this, %obj)
{
%this.mountObject(%doorHinge, 0); //<<----WHAT IS CORRECT SYNTAX HERE?
}
function door::interact(%this, %obj, %client)
{
%this.MoveDoor(%obj);
echo("just open the door %this.MoveDoor!");
messageClient(%client, 'MsgDoorOpen');
}
function door::OpenDoor(%this, %door)
{
//This calls the function that incrementally moves the door to give the
//illusion of animation
%this.MoveDoor(%door);
}
function door::MoveDoor(%this, %door)
{
if (!%door.open)
{
%door.open = true;
%door.setthreaddir(0,"true");
%door.playthread(0,"open");
}
else
{
//does a distance check between the door and what hit it last
//I have it set for 2... but you can use whatever you like
%dist = VectorDist(%col.getTransform(), %door.getTransform());
if (%dist > 2)
{
%door.setthreaddir(0,"false");
%door.open = false;
}
}
}Everything else works, it just doesn't mount. Is my Datablock wrong? Should mountpoint = "0"; only be part of the object which gets mounted (the door) or only the object which gets mounted to (the hinge)?
Thanks!
Tony
#3
//-------------------------- 4/21/2009 -- 15:41:12 -----
...
edited for length
...
Object 'hinge' is not a member of the 'GameBaseData' data block class
starter.fps/data/missions/SouthYalgophaeMain.mis (0): Register object failed for object (null) of class StaticShape.
Object 'door' is not a member of the 'GameBaseData' data block class
starter.fps/data/missions/SouthYalgophaeMain.mis (0): Register object failed for object (null) of class StaticShape.
...
starter.fps/server/scripts/door.cs (42): Unknown command mountObject.
Object doorHinge(98) doorHinge -> door -> StaticShapeData -> ShapeBaseData -> GameBaseData -> SimDataBlock -> SimObject
starter.fps/server/scripts/door.cs (42): Unknown command mountObject.
Object theDoor(99) theDoor -> door -> StaticShapeData -> ShapeBaseData -> GameBaseData -> SimDataBlock -> SimObject
That's all that pertains to the mounting...
Thanks!
Tony
04/21/2009 (12:56 pm)
CONSOLE.LOG//-------------------------- 4/21/2009 -- 15:41:12 -----
...
edited for length
...
Object 'hinge' is not a member of the 'GameBaseData' data block class
starter.fps/data/missions/SouthYalgophaeMain.mis (0): Register object failed for object (null) of class StaticShape.
Object 'door' is not a member of the 'GameBaseData' data block class
starter.fps/data/missions/SouthYalgophaeMain.mis (0): Register object failed for object (null) of class StaticShape.
...
starter.fps/server/scripts/door.cs (42): Unknown command mountObject.
Object doorHinge(98) doorHinge -> door -> StaticShapeData -> ShapeBaseData -> GameBaseData -> SimDataBlock -> SimObject
starter.fps/server/scripts/door.cs (42): Unknown command mountObject.
Object theDoor(99) theDoor -> door -> StaticShapeData -> ShapeBaseData -> GameBaseData -> SimDataBlock -> SimObject
That's all that pertains to the mounting...
Thanks!
Tony
#4
BUT if I shoot the hinge (with the crossbow) the sequence suddenly appears as a Dynamic Field (open | 0). Now the animation will play correctly.
Why on earth is that?!?!?
How could collision by a projectile correct things?
Tony
04/21/2009 (2:00 pm)
Well, here's something interesting. When I add the doorHinge by using the World Editor Creator, when I check it using the Inspector, it doesn't have the animation sequence listed as a Dynamic Field at the bottom. The hinge animation ("open") doesn't play, because it's not recognized as existing.BUT if I shoot the hinge (with the crossbow) the sequence suddenly appears as a Dynamic Field (open | 0). Now the animation will play correctly.
Why on earth is that?!?!?
How could collision by a projectile correct things?
Tony
#5
Line 44. %doorHinge isn't defined
Line 08. Try calling the datablock "hinge"
Line 20. Try calling the datablock "door"
04/21/2009 (6:06 pm)
Things I notice in your code block, not sure if they are big problems or not:Line 44. %doorHinge isn't defined
Line 08. Try calling the datablock "hinge"
Line 20. Try calling the datablock "door"
#6
Thanks!
Tony
04/21/2009 (6:23 pm)
Yes, you're right %doorHinge isn't defined. That's what I can't figure out. I know its not right, but what IS the right syntax to put in the mountObject part of the on::add function?Thanks!
Tony
#7
Now, if you want to create a hinge for the door, you'll need to actually create the object in the door::onAdd function. Like this:
I noticed you added position and scale members to your StaticShape datablocks. This suggests to me that you're misunderstanding what datablocks actually are. Don't worry - I had the exact same problem when I started Torque. When I got over it, everything started making more sense ;). The fundamental isue is the divide between actual objects and datablock objects. Datablocks aren't real - they just hold static information that should be the same for all objects of that type. A datablock is like a stereotype - say the stereotype that Australians speak like Steve Irwin. If we define an Australian datablock, it might look like this:
When you define a static shape datablock, you're defining a 'type' of static shape - in your case, a door. It is true that all doors should have a handle - but is is certainly not true that every door should be placed at the position "1 1 1". Different doors may be in different locations, and that is a property of each individual door object, not the door datablock. Just like living in Sydney or living in Melbourne is a property of each individual Australian - not of the Australian stereotype.
04/22/2009 (8:18 am)
I'm guessing you want to create a doorHinge object when you add a door. But before that, here's what's causing your original problem - you're trying to mount an object to a datablock. Datablocks do not exist, only objects.function door::onAdd(%this, %obj)
{
%this.mountObject(%doorHinge, 0); //<<----WHAT IS CORRECT SYNTAX HERE?
}Assuming the object %doorHinge actually existed, you'd still be off. 'door', which is the namespace where your function is declared, is a datablock (your theDoor datablock is of type 'door'). The first parameter in a datablock method will refer to the datablock - so %this refers to the theDoor datablock. %obj refers to the actual door object that was created and caused onAdd to be called.Now, if you want to create a hinge for the door, you'll need to actually create the object in the door::onAdd function. Like this:
function door::onAdd(%this, %obj)
{
%doorHinge = new StaticShape() {
datablock = doorHinge;
};
%obj.mountObject(%doorHinge, 0);
}I don't know if that's technically correct, but it's something like what you've got there.I noticed you added position and scale members to your StaticShape datablocks. This suggests to me that you're misunderstanding what datablocks actually are. Don't worry - I had the exact same problem when I started Torque. When I got over it, everything started making more sense ;). The fundamental isue is the divide between actual objects and datablock objects. Datablocks aren't real - they just hold static information that should be the same for all objects of that type. A datablock is like a stereotype - say the stereotype that Australians speak like Steve Irwin. If we define an Australian datablock, it might look like this:
datablock AussieData(NormalAussiePerson) {
speaksLikeSteveIrwin = true;
};However, the following would not be useful:datablock AussieData(NormalAussiePerson) {
speaksLikeSteveIrwin = true;
currentLocation = Sydney;
};Because it is not true that all Australians are in Sydney - in fact, none of the sane ones are. ;)When you define a static shape datablock, you're defining a 'type' of static shape - in your case, a door. It is true that all doors should have a handle - but is is certainly not true that every door should be placed at the position "1 1 1". Different doors may be in different locations, and that is a property of each individual door object, not the door datablock. Just like living in Sydney or living in Melbourne is a property of each individual Australian - not of the Australian stereotype.
#8
A very good point! I knew this, I just needed reminded :)
So are "NAMESPACE" and "TYPE" the same thing? 'Namespace' is the term used in a function and 'type' is the term when in a Datablock?
The first parameter in a datablock method will refer to the datablock ALWAYS and the second always refers to the object? Is that standard in all coding (C++?) or just TorqueScript? If so, then that's probably the most important thing I've learned all day :)
Unfortunately the script doesn't work. It compiles, but when I go into the Creator and try to add "theDoor" or "doorHinge" TGE just shuts off. No console errors.
So I changed this line
%doorHinge = new StaticShape()
to this
%doorHinge = new StaticShape("doorHinge")
Now I get the console error - Object 'doorHinge' is not a member of 'GameBaseData' datablock...
Again, thank you for helping with this. I wish there was a primer for this kind of stuff. Like "Torque for Dummies". (I guess there is, it's called University!)
I really appreciate all your help!
Tony
04/24/2009 (5:03 am)
Thank you Daniel for having so much patience with me. You've explained things very well.Quote:
Datablocks do not exist, only objects.
A very good point! I knew this, I just needed reminded :)
Quote:
'door', which is the namespace where your function is declared, is a datablock (your theDoor datablock is of type 'door').
So are "NAMESPACE" and "TYPE" the same thing? 'Namespace' is the term used in a function and 'type' is the term when in a Datablock?
Quote:
The first parameter in a datablock method will refer to the datablock - so %this refers to the theDoor datablock. %obj refers to the actual door object that was created and caused onAdd to be called.
The first parameter in a datablock method will refer to the datablock ALWAYS and the second always refers to the object? Is that standard in all coding (C++?) or just TorqueScript? If so, then that's probably the most important thing I've learned all day :)
Unfortunately the script doesn't work. It compiles, but when I go into the Creator and try to add "theDoor" or "doorHinge" TGE just shuts off. No console errors.
function door::onAdd(%this, %obj)
{
%doorHinge = new StaticShape()
{
datablock = doorHinge;
};
%obj.mountObject(%doorHinge, 0);
}So I changed this line
%doorHinge = new StaticShape()
to this
%doorHinge = new StaticShape("doorHinge")
Now I get the console error - Object 'doorHinge' is not a member of 'GameBaseData' datablock...
Again, thank you for helping with this. I wish there was a primer for this kind of stuff. Like "Torque for Dummies". (I guess there is, it's called University!)
I really appreciate all your help!
Tony
#9
04/24/2009 (7:40 pm)
@Daniel: I'm still laughing at your datablock explanation XD
#10
Here's how you'd have to do it if we were just using the datablock's normal namespaces:
To answer your question more clearly: when you call a method on an object, the object is actually passed as the first parameter. So if you call a function like this:
Your problem creating a hinge seems weird. Have you tried running it in a debug build and seeing what error you get?
04/25/2009 (7:19 am)
Quote:So are "NAMESPACE" and "TYPE" the same thing? 'Namespace' is the term used in a function and 'type' is the term when in a Datablock?Hmm... namespace is a C++ term so I'm not exactly sure exactly what it is ;P. However, you're basically right - the 'type' field deermines what namespace the datablock uses. But I think the datablock namealso defines a namespace - so you could have functions declared like
function theDoor::somethingSpedific(%this)that would only be valid for the theDoor datablock. However, it's more useful to write generic functions for a broader namespace, so you don't have to rewrite lots of functions. Here's some example scripts, which bryce will probably enjoy ;)
Here's how you'd have to do it if we were just using the datablock's normal namespaces:
dataBlock AussieData(SydneyResident) {
talksLikeSteveIrwin = true;
livesIn = Sydney;
};
dataBlock AussieData(MelbourneResident) {
talksLikeSteveIrwin = true;
livesIn = Melbourne;
};
//--------------
function SydneyResident::saySomething(%this,%obj)
{
echo(%obj @ "says: G\'day, mate");
}
function MelbourneResident::saySomething(%this,%obj)
{
echo(%obj @ "says: G\'day, mate");
}Now, we might create an Australian object with either datablock and call this code somewhere:%australian.getDataBlock().saySomething(%australian);And we'd get in the console:
[whatever the object ID is] says: G\'day, mateWhichever datablock we use, we get the same output, because the methods for both datablocks are identical (because, of course, all Australians say 'G'day, mate' ;P. This is kind of inelegant, because for every different type of Australian we're going to have to write a new method that does the same thing. So instead:
dataBlock AussieData(SydneyResident) {
talksLikeSteveIrwin = true;
livesIn = Sydney;
type = AustralianPerson;
};
dataBlock AussieData(MelbourneResident) {
talksLikeSteveIrwin = true;
livesIn = Melbourne;
type = AustralianPerson;
};
//--------------
function AustralianPerson::saySomething(%this,%obj)
{
echo(%obj @ "says: G\'day, mate");
}Now we can call the saySomething function the same way as before, and obtain the same result - but we've written less code and we can now add more datablocks for different types of Aussie more easily (becaue we only need to define a datablock and don't need to worry about writinga new function).Quote:The first parameter in a datablock method will refer to the datablock ALWAYS and the second always refers to the object? Is that standard in all coding (C++?) or just TorqueScript? If so, then that's probably the most important thing I've learned all day :)I think this is the case. It's nothing to do with C++ - in code, there is no concept of a datablock. Datablocks are programmed the same way as objects, both of them are things referred to as 'classes'. It's just that some classes are designated as datablocks and do a certain job. So you could say that it's a Torque thing, not a C++ thing.
To answer your question more clearly: when you call a method on an object, the object is actually passed as the first parameter. So if you call a function like this:
%anyObject.anyFunction(%param1,%param2);you will actually pass three parameters into the function: %anyObjtct, %param1 and %param2. So if we defined th function like this:
function namespace::anyFunction(%first,%second,%third)Then %first = %anyObject, %second = %param1, and %third = %param2.
Your problem creating a hinge seems weird. Have you tried running it in a debug build and seeing what error you get?
Quote:Object 'doorHinge' is not a member of 'GameBaseData' datablock...This usually indicates that there is no datablock named 'doorHinge', but you have defined it. Very odd.
#11
04/28/2009 (4:10 am)
here's what finally worked for me://--Thanks Tim Feni for the resource
//--See Also: Interaction.cs
// -----------------------------------------------------------------------------
// Datablocks - shapes
// -----------------------------------------------------------------------------
datablock StaticShapeData(doorHinge)
{
category = "doors";
className = hinge;
shapeFile = "~/data/shapes/doors/hinge0424.dts";
emap = true;
receiveSunLight = "1";
mountPoint = 0;
name = "hinge";
};
datablock StaticShapeData(theDoor)
{
category = "doors";
className = door;
shapeFile = "~/data/shapes/doors/door0424.dts";
emap = true;
receiveSunLight = "1";
mountPoint = 0;
name = "door";
};
// ----------------------------------------------------------------------------------
// Functions - door open events
// ----------------------------------------------------------------------------------
// This function is called whenever the client presses the 'use interaction' key ("u" key)
// within the set distance.
// calls from interaction.cs change distance there.
function hinge::onAdd(%this, %obj)
{
%theDoor = new StaticShape("mountedDoor")
{
datablock = theDoor;
};
%obj.mountObject(%theDoor);
}
function hinge::interact(%this, %obj, %client)
{
%this.OpenDoor(%obj);
echo("just open the door %this.OpenDoor!");
messageClient(%client, 'MsgDoorOpen');
}
function hinge::OpenDoor(%this, %door)
{
//This calls the function that incrementally moves the door to give the
//illusion of animation
%this.MoveDoor(%door);
}
function hinge::MoveDoor(%this, %door)
{
if (!%door.open)
{
%door.open = true;
%door.setthreaddir(0,"true");
%door.playthread(0,"open");
}
else
{
//does a distance check between the door and what hit it last
//I have it set for 2... but you can use whatever you like
%dist = VectorDist(%col.getTransform(), %door.getTransform());
if (%dist > 2)
{
%door.setthreaddir(0,"false");
%door.open = false;
}
}
}
#12
04/29/2009 (11:47 am)
SO that worked for you without the crash you had last time? Good, but odd. Ah well, it probably does make more sense to mount the door to the hinge anyway.
Torque 3D Owner Daniel Buckmaster