Game Development Community

Few questions on Unit Group Selection and Camera follow

by William Urban · in RTS Starter Kit · 05/08/2005 (12:39 pm) · 10 replies

Hello all, been playing around with the starter.rts today just messing with unit attributes and stuff. I was wondering if there were ways to do the following.

I am thinking of limiting the units to like 8 total but making them beefier, more rpg/jagged alliance ish. What I wanted to do was when the 8 units spawn, how do you keep track of them? Do they have a different ID each time? Will I have to make 8 seperate datablocks?

So, once they spawn in the world, I wanted to automatically assign them to the hotkey groups 1-8. That way when you hit 3 it brings up the 3rd guy automatically without having to first set the hotkey groups. This kind of follows the previous question, how do you select the unit when the game starts to put them in a group.

Then, what I would like to do is find how when you double tap say 3, the camera instantly moves and centers on that unit/group #3. I want to figure out how to do this all the time and follow the unit. So that if I have unit 1 selected, he is in the middle of the screen and the camera follows him as he moves always keeping him in the middle, but if I hit 3, it jumps to unit 3 and then follows that unit around. Possibly there could be a way to toggle between free mouse looking and always tied to a unit/group number.

This has a ton of things that can be done with it, rpgs ala Baldurs gate or diablo, strategy games like jagged alliance/xcom, etc :)

Thanks as always,

-Will

#1
05/08/2005 (12:47 pm)
You've pretty much actually outlined what you want to do yourself:

A) Create a separate datablock for each of the unit types (set your attribs, your model, etc. here).
B) in /server/scripts/core/gameConnection.cs--RTSConnection::onClientEnterGame() is where the stock units are spawned. You would want to change this to just instantiate your "unique" units singly, and store them in %client.units (which is done in the RTSConnection::createPlayer() script function).
C) auto-assign group hotkeys: you would have to take a look at how the group assignment is done currently, and adjust it to happen on the client after the units have been net ghosted to them, but with a bit of research this shouldn't be too difficult.
D) camera follow: out of the box the RTS-SK isn't set up to do this exact requirement, but it wouldn't be too difficult, and could be done in a variety of ways. The simplest (and least elegant) is to look at the code that moves the camera to a unit when you double-tap it's group key, and simply copy it to a new function and use schedule() to have that happen every 100 milliseconds or so).
#2
05/08/2005 (6:31 pm)
Awesome reply, gives me tons to start working with :) Thanks!

-Will
#3
05/08/2005 (10:06 pm)
Williams, coolness. Please keep us updated here in the forums about how you proceed. If you make good progress, it'll be cool to see the RTS SK used like this, and interesting to see how you modified and extended it. You and Stephen are on the right track here as far as changes go.

Quick note on the camera, between looking at the code Stepehn points to and the position interpolation code in the camera's movement code, you should pretty quickly be able to get a smooth camera that does what you're after going.
#4
05/09/2005 (10:14 pm)
Like the new forum layout. Took a bit to get used to it though. Ok so I am still having some issues with understanding how the spawning of the units is working. I tried commenting out the For loop by the for(%i=%offset; %i<(%offset + %unitsPerDir); %i++) etc and tried to put in something like %this.createPlayer(1 1 250, 1); but that didn't do anything. It seems to still spawn the default bunch of units and I can't track down where it is that it is calling that. If I comment out the %this.createPlayer then noone shows up. Trying to just find where I can do something like
%this.createPlayer(rifelman, location, index number) or something like that. Speaking of that, the %index number when it's spawning, is that its number all the time that can be used to refer to a certain unit? Like if I say Player 1, unit 3 is always index 17 then can I use that all the time kind of thing? Just wondering.

Thanks as always,

-Will
#5
05/10/2005 (12:37 am)
Post your code (with what you commented out) here, so we can take a quick look and see if we see anything.

Most likely, you had an error in your changes, so when you re-ran Torque, it recognized the error (check your console.log), and used the "last known working" .dso--which was from the original, stock code.
#6
05/10/2005 (6:52 am)
Oh that's probably it, I just commented out the For loop and added %this.createPlayer(1 1 250, 1); Just making up random numbers. I assumed that the %this.createPlayer(x y z, index) I just didn't know where the index value was coming from or why it was still doing the huge block of guys when the game starts up.

-Will
#7
05/10/2005 (7:39 pm)
Ok more questions on this spawing thing. What exactly is %unitsPerDir? I set it to 1 just to mess around with the for loop but ended up commenting that out anyhow. Few questions/thoughts.

1) What is %unitsPerDir
2) Is the %offset just used in this particular loop to make something quick or is it needed?
3) How do I find the ID of something that is spawning, is it dynamic or static to the way it was spawned

4) I was able to control some of the spawning by commenting out the for loop and adding in:
%this.createPlayer((0+0) SPC (0+0) SPC "250", 3); But what are the values being passed? (?) SPC (?) SPC "250"? And whats the SPC? I figured out the last variable gets sent to the create player and gets moduled to find the unit type but I am going to rewrite that so it just sends the value I want and spawns it from a case statement.

Just confused why it was written this way. Still trying to get my head wrapped around it.

Thanks,

-Will
#8
05/10/2005 (10:21 pm)
Good questions!

First thing to keep in mind is that entire for loop has nothing to do really with actually creating the units--it was just a quick and dirty way to get 16 (or was it 25?) units on the screen when a player logs in, of different types, and in an orderly formation. What is important is understanding the createPlayer() method, and what it's params are, so let's focus on that. (in other words, totally ignore the %unitsPerDir, %offset, etc.).

function RTSConnection::createPlayer(%this, %spawnPoint, %index)
{
   switch(%index % 3)
   {
      case 0:
         %data = botBlock;
      case 1:
         %data = riflemanBlock;
      case 2:
         %data = shockerBlock;
   }
      
   %player = new RTSUnit() 
   {
      scale = "1 1 1";
      dataBlock = %data;
      shapeFile = "~/data/shapes/player/player.dts";
      path = "";
   };

   MissionCleanup.add(%player);
   
   %player.setControllingConnection(%this);
   %player.setSkinName( getWord($Pref::Server::TeamInfo[%this.getTeam()], 3) );
   %player.setTeam(%this.getTeam());
   %player.setTransform(%spawnPoint);
   %player.client = %this;
                    
   %player.stats["Kills"] = (getRandom() * 5) % 5;
   %player.stats["Damage Delt"] = (getRandom() * 1000) % 1000;
   
   // Add the unit to the group of units
   %this.units.add(%player);
}

The three params that are sent are:

%this : a "sneaky" parameter that the console adds in whenever you call a function in TorqueScript using the %objectID.functionName() syntax. On the handling side of the function call (where the function is implemented), the engine adds in the object ID of the object that had the method called upon as a parameter automatically. Don't worry too much about it, but just realize that for any script function that is declared with a namespace (RTSConnection:: part of the function name), you should use %this as the first param, and know that it contains the objectID of the object calling the function.
(con't)
#9
05/10/2005 (10:21 pm)
%spawnPoint : although this isn't distinctly obvious by looking at the function itself, as you become more familiar with Torque you will begin to get used to the way variables are passed back and forth between the console and the underlying engine implementation--and that is by strings.

A spawnPoint is a 3-D grid coordinate in the form "X Y Z", separated by spaces. TorqueScript also gives you the operator SPC (it's actually an operator just like a + sign, a * sign, etc), which concatenates two strings with a space character, making them one string. So the net result of (0+0) SPC (0+0) SPC "250" is a single string: "0 0 250". In other words, the spawnPoint is x=0, y=0, z=250.

If you dig down deeper into the actual implementation of the console method setTransform() that %player.setTransform(%spawnPoint) calls, you'll see eventually that it passes this string in, and the engine knows to interpret it as a location.

%index: while it looks complicated (especially with the % operator in there), all this is is a numerical index to determine which datablock should be used when spawning the unit. The very first statement in the function is:

switch(%index % 3)

Which says, "first, divide the number %index by the constant 3, and use the remainder as an integer result". This is simply a safety measure so that if, for example, you sent in the number 8 as an index, it would divide by 3, and then take the remainder (2) and treat it as an integer, giving you a switch case of "2"...which would make this example a shockerBlock.

In other words, it's simply an example implementation, and in fact should be completely discarded for any project, as you'll want to be able to determine which datablock should be used without an artifical limitation. If you were to define 8 new unit types for example, each with their own datablocks, you would remove the %3 part of the safety check, and simply do a

switch(%index)

and of course have a case body for each of your units.

Hopefully this helps a bit, but what you should take out of this is that the specific technique used to get 16 units of different types in a nice, orderly square is all the code that is confusing you does, and should just be treated as an example--any "real" (as opposed to demo) RTS project will want to customize and/or completely change how the player's initial starting units are set.
#10
05/11/2005 (6:37 am)
@Stephen, that was an awesome clarification. Cleared up a lot of questions I had as to what was going on. I'm sure I'll have more questions along this line soon enough but that was a great help. Thanks a ton!

-Will