Can't get objects to show up properly in mission editor
by Justin Tolchin · in RTS Starter Kit · 02/24/2005 (4:27 pm) · 5 replies
Hi all,
I'm trying to set up my objects so that I can place one via the Mission Editor. Based on what I've seen in other classes, I have to add a "category" field to the datablock, and also implement a "create" method which generates the object from the datablock. So I tried to test this out with my "barracks" building.
Here is the datablock:
datablock RTSUnitData(barracksBlock : UnitBaseBlock)
{
category = "Buildings";
shapeFile = "~/data/shapes/barracks/barracks.dts";
RTSUnitTypeName = "barracks";
boundingBox = "10.0 10.0 2.0";
moveSpeed = 0.0;
};
and here's the "create" method:
//-----------------------------------------------------------------------------
// Hook into the mission editor.
function RTSUnitData::create(%data)
{
// The mission editor invokes this method when it wants to create
// an object of the given datablock type.
%obj = new RTSUnit()
{
dataBlock = %data;
};
return %obj;
}
What I'm seeing is that the mission editor creates a yellow box but there's no shape being displayed in it. Also, I cannot move the box in the Z direction. X and Y work fine. I tried typing in the values directly in the position field for the object but it doesn't move at all. And even when I move it in the X and Y directions, the position field does not update its values. I don't know what the heck is going on, but I'm sure I missed a crucial step somewhere. Can anyone help me out?
Thanks!
I'm trying to set up my objects so that I can place one via the Mission Editor. Based on what I've seen in other classes, I have to add a "category" field to the datablock, and also implement a "create" method which generates the object from the datablock. So I tried to test this out with my "barracks" building.
Here is the datablock:
datablock RTSUnitData(barracksBlock : UnitBaseBlock)
{
category = "Buildings";
shapeFile = "~/data/shapes/barracks/barracks.dts";
RTSUnitTypeName = "barracks";
boundingBox = "10.0 10.0 2.0";
moveSpeed = 0.0;
};
and here's the "create" method:
//-----------------------------------------------------------------------------
// Hook into the mission editor.
function RTSUnitData::create(%data)
{
// The mission editor invokes this method when it wants to create
// an object of the given datablock type.
%obj = new RTSUnit()
{
dataBlock = %data;
};
return %obj;
}
What I'm seeing is that the mission editor creates a yellow box but there's no shape being displayed in it. Also, I cannot move the box in the Z direction. X and Y work fine. I tried typing in the values directly in the position field for the object but it doesn't move at all. And even when I move it in the X and Y directions, the position field does not update its values. I don't know what the heck is going on, but I'm sure I missed a crucial step somewhere. Can anyone help me out?
Thanks!
#2
I don't want the building to be visible to players who shouldn't see it, so I don't want to set it to always be in scope. But I do want it to act like a "normal" building that the player who owns it can select and build other units from, etc., so I don't want it to be just a shape that gets drawn but is non-interactive.
I was able to figure out (thanks to your post) that this was a scoping issue. Whenever I placed one of these "invisible" buildings I was getting a crash during the next event (moving another unit or whatever) because the "controlling connection" object wasn't set. I looked at the "normal" code for placing a building and based on that I added in some additional lines:
function RTSUnitData::create(%data)
{
// The mission editor invokes this method when it wants to create
// an object of the given datablock type.
%obj = new RTSUnit()
{
dataBlock = %data;
scale = "1 1 1";
};
%conn = GameConnection::getServerConnection();
%obj.client = %conn;
%obj.setTeam(%conn.getTeam());
%obj.setControllingConnection(%conn);
%conn.buildings.add(%obj);
return %obj;
}
and now the building shows up fine. Yea! The only line that doesn't seem to be working is the %conn.buildings.add(...) line. It doesn't seem to know what "%conn.buildings" is. Any thoughts?
I think I should be creating an RTSBuilding instead of RTSUnit anyway (which I guess means I should create a new datablock class called RTSBuildingData to use instead of RTSUnitData), but I'll try that in a few minutes. :-)
Thanks!
02/25/2005 (11:27 am)
Hi Martin,I don't want the building to be visible to players who shouldn't see it, so I don't want to set it to always be in scope. But I do want it to act like a "normal" building that the player who owns it can select and build other units from, etc., so I don't want it to be just a shape that gets drawn but is non-interactive.
I was able to figure out (thanks to your post) that this was a scoping issue. Whenever I placed one of these "invisible" buildings I was getting a crash during the next event (moving another unit or whatever) because the "controlling connection" object wasn't set. I looked at the "normal" code for placing a building and based on that I added in some additional lines:
function RTSUnitData::create(%data)
{
// The mission editor invokes this method when it wants to create
// an object of the given datablock type.
%obj = new RTSUnit()
{
dataBlock = %data;
scale = "1 1 1";
};
%conn = GameConnection::getServerConnection();
%obj.client = %conn;
%obj.setTeam(%conn.getTeam());
%obj.setControllingConnection(%conn);
%conn.buildings.add(%obj);
return %obj;
}
and now the building shows up fine. Yea! The only line that doesn't seem to be working is the %conn.buildings.add(...) line. It doesn't seem to know what "%conn.buildings" is. Any thoughts?
I think I should be creating an RTSBuilding instead of RTSUnit anyway (which I guess means I should create a new datablock class called RTSBuildingData to use instead of RTSUnitData), but I'll try that in a few minutes. :-)
Thanks!
#3
new RTSUnit() {
position = "-77 -24.0878 400";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "barracksBlock";
client = "1456";
mountVehicle = "1";
};
but the client id "1456" won't be valid the next time around so I won't have the client connection info that the VisManager::processServer() code expects to find. That code calls:
RTSConnection* client = unit->getControllingConnection();
but I'm guessing that will return an invalid value (or NULL since 1456 won't resolve to a valid object). So I need a way to populate the client connection info back in when the mission loads. Do you know how/where to do this? I'm not familiar with how that stuff works. :-(
02/25/2005 (11:46 am)
Hmmm... actually I still have the same problem if I save the mission with the new building and then reload it. The mission file only saves the following info:new RTSUnit() {
position = "-77 -24.0878 400";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "barracksBlock";
client = "1456";
mountVehicle = "1";
};
but the client id "1456" won't be valid the next time around so I won't have the client connection info that the VisManager::processServer() code expects to find. That code calls:
RTSConnection* client = unit->getControllingConnection();
but I'm guessing that will return an invalid value (or NULL since 1456 won't resolve to a valid object). So I need a way to populate the client connection info back in when the mission loads. Do you know how/where to do this? I'm not familiar with how that stuff works. :-(
#4
It sounds like you either want to have persistent buildings across a server reboot (assuming dedicated server, and a fully persistent world), or you want to pre-assign certain buildings to certain teams for the mission.
If the second is accurate, or close, what you really want to do is to create a new field, something like assignToTeam = x;, and then just prior to starting the game off (but after all clients have connected), scroll through each of these "pre-assigned" buildings/units, and using setControllingConnection() (and/or setTeam() )for each of them as appropriate.
You'll need to look carefully at the team assignment code (it's in /server/scripts/core/gameConnection.cs IIRC), figure out how the team id's are assigned, and then also look at the onClientEnterGame() code to see how they assign a unit's controlling connection when it is created.
As you noted, clientID's are not static, and will change each time the client connects, so you'll need a "meta field" that you can interpret after the clients have all connected to tie the units/buildings to the "current" clients.
02/25/2005 (3:41 pm)
Could you state your root issue/desired functionality? That would make it much easier for us to understand what you want to do, and possibly help lead to a better solution.It sounds like you either want to have persistent buildings across a server reboot (assuming dedicated server, and a fully persistent world), or you want to pre-assign certain buildings to certain teams for the mission.
If the second is accurate, or close, what you really want to do is to create a new field, something like assignToTeam = x;, and then just prior to starting the game off (but after all clients have connected), scroll through each of these "pre-assigned" buildings/units, and using setControllingConnection() (and/or setTeam() )for each of them as appropriate.
You'll need to look carefully at the team assignment code (it's in /server/scripts/core/gameConnection.cs IIRC), figure out how the team id's are assigned, and then also look at the onClientEnterGame() code to see how they assign a unit's controlling connection when it is created.
As you noted, clientID's are not static, and will change each time the client connects, so you'll need a "meta field" that you can interpret after the clients have all connected to tie the units/buildings to the "current" clients.
#5
Yeah, sorry, I was being vague. :-) I want to pre-assign certain buildings to certain teams. I was actually thinking I would need to do exactly what you described: assign a team id (instead of a client connection id) to each building, and then populate the client connection stuff after the mission is loaded. I just wasn't sure where to look. I will check the code you mentioned.
Thanks!
02/25/2005 (11:20 pm)
Hi Stephen,Yeah, sorry, I was being vague. :-) I want to pre-assign certain buildings to certain teams. I was actually thinking I would need to do exactly what you described: assign a team id (instead of a client connection id) to each building, and then populate the client connection stuff after the mission is loaded. I just wasn't sure where to look. I will check the code you mentioned.
Thanks!
Torque 3D Owner Martin "Founder" Hoover
If you are wanting a building that is visible all the time to every player, you might consider using the staticShape class, otherwise you'll need to do some tinkering to the rtsUnit class, or perhapse derive a new class from it.