Milkshape Modeling Tutorial for Return to Castle Wolfenstein Part IV – Working with Tags

O.k. What is a tag and why do we need them? A tag is a location marker on a model. It defines two things. First, it defines a point in space relative to the model. Second, it has a vector orientation relative to the model in 3D space. Imagine it like an arrow. You can put the arrow anywhere around the model, and then arrow can be pointing in any direction, up, down, at an angle, etc.

That’s what a tag is but what does it do? A tag is used to attach models together at “run-time” when the game starts. Why not just put the model where you want them in Radiant then? Why use tags? Because once the models are attached you can control only one of the models and the other models move with it. You can also switch the attached models using a script “in-game”. You can also control a separate animation sequence on the various models instead of making a bunch of animation on the main model. By using tags we can have animation for the top rotor blade and rear rotor blade and control them separately while moving the helicopter around. Remember the tank from single player wolfy? The tank trends were attached with tags so the trends could be animated and controlled separate from the tank model.

 

Placing tags

First thing we need to do is know how to create a tag. A tag is typically a group (i.e. if you should see it under the groups tab in Milkshape) Tags must always be named in the following convention: tag_xxx; where xxx is the name for the tag.

So a tag is a group with the name tag_xxx. What shape is it? Where do I put it?

The shape of the tag is a right triangle, where one leg is longer than the other one. Like this:

You can make this shape by clicking and adding vertex points and then using the Face button to generate a triangle from those points (we already talked about this).

Does it matter its orientation. Yes. The longer leg of the triangle corresponds to the +Z direction, the shorter leg of the triangle corresponds to the –X direction and the gray face (the positive vertex face) looks into the +Y direction. This is what I mean:

Funny shaped triangles and objects that are not triangles will give unpredictable results.

So where do I put it? For now just put the tag near where you want to connect the two models. The placement of the tag is and is not important which I’ll explain when you go to export the model. Don’t worry if you don’t get it.

So lets add some tags to the heli. Here where the top rotor is and here where the rear rotor is. Great. Group them and name them tag_rotortop and tag_rotortail. They should show up under the groups tab.

 

Partial Export from Milkshape

We want to export the model in three pieces. The first piece is the main fuselage of the helicopter and all its parts. The second model will be the top rotor. The third model will be the tail rotor. How do you do this from a single model? The trick is in the .qc file.

Go under Tools->Quake III Arena->Generate Control file… This should bring up a Save As box. Save the .qc file as the exact SAME NAME as the file name of the intended .md3. (i.e. rotor.md3 will have a .qc file called rotor.qc). When you type in a name and save, a text file appears. This gives all the info from your entire model. Notice there are two tags!! Wooohooo!

We want to export the heli without the parts for the rotor assemblies. So go through the meshes (surfaces) list in the .qc file and delete all the groups that belong to the rotor assemblies from the top and tail of the heli.

Now make sure that the “//”’s are deleted in front of the $tag’s and that the “//” are present in front of the $parenttag’s. Good now save the text file by doing File->Save.

O.K. you have a .qc file for the body of the heli. This is the ‘main’ part of the model we are creating. The ‘main’ model should get the $tags. Now you need to save a .qc file for the top rotor and the tail rotor. Repeat as above. Generate another .qc file except name this one something like ‘rotortop.qc’. Now go through and delete all meshes not part of the top rotor assembly. Great. Now for the tags. Delete the “//” in front of the tag that says “$parenttag “tag_rotortop””. Leave the other parent tag with it’s “//”. Now place a “//” in front of both of the lines that start “$tag ….”. The yet-to-be-attached models should contain $parenttags. Save the file.

Repeat for the tail rotor expect you will uncomment the $parenttag “tag_rotortail” this time. Comment out the $tags and the other $parenttag. Save that file.

You should have three .qc files saved now. Now go to File->Export->Quake III Arena MD3. A Save As box pops up. Save the model as the NAME YOU GAVE THE FIRST QC FILE. (i.e. heli.qc was the first file so name this model heli.md3, etc.)

Now export again. This time save the model as what you named the second .qc file, in my case this would be rotortop.md3. Repeat for the last model.

To check if you exported 3 models try to re-import them back into Milkshape. Notice the tag is not there!!! It is but it has been turned into a coordinate in the .md3 file!!

That’s all there is to it.

Ooops. Before we go on I must admit I lied to you. The orientation, shape and placement of the tags doesn’t seem that important when you export the .qc files using the $parenttag/$tag combinations as above. If you have no tags on the attachment models, however, the orientation, position and shape of the orginal tag in the ‘main’ model is very important and will determine the orientation (based on the vector of the tag) and position (it will use the xyz axis) of the attachment model.

Getting it into Radiant

O.K. now we need for Radiant to recognize the models. We are going to need to “script” the models so that this will work, so we are going to use a different entity called a script_model_med. A script_model_med is an entity that exists in Radiant to allow scripted models. Why scripted? You’ll see.

Open up radiant and add a script_model_med. The placement of the ‘main’ part of the model is important, the ‘attached’ models can go anywhere in the map. So, for the first script_model_med place it where you want the ‘main’ model to appear. Remember that the blue box that represents the model (as you will not ‘see’ the model – just a box) represents where the xyz colored axis was in relation to ‘main’ model. (i.e. if you made the model to the left of the xyz axis in Milkshape, your model will show up to the left of the blue box your placing).

Select the script_model_med and open up the entities window. There is a classname and an origin already as properties of the entity. Just leave them alone. You’ll need to add a few things though. In the ‘key’ textbox add the line “model” and in the ‘value’ textbox add the line “models/mapobjects/Heli/Helia.md3”. The value is where you have saved your model (starting from the /main directory in wolfy). In this I assumed to have a folder in /main called models and inside of that there is a folder /mapobjects, etc. Remember to press ENTER so that the line shows up in the entities window! The next line to add is: under ‘key’ add “scriptname” and under ‘value’ add “heli. The name of the script for the body of the helicopter will be called heli. Don’t worry about scripting yet I explain it a bit later. You can rotate the model by pressing one of the numbered buttons at the bottom. If you do the keypair ‘angle’’#’ will show up.

Oh, and one last thing if you push the ‘solid’ button, your model will clip players (no having to make clip brushes!!!), however, it will not block gunfire. You’ll need to clip it with a texture that blocks weapons. Great the ‘main’ body of the helicopter is in. Now we need to add two more script_model_meds. One is needed for the rotortop and another for the rotortail. You’ll use the same keypairs as before except the value for model will reflect the name of the model, and you need to pick a new scriptname. Call the rotortop scriptname ‘rotortop’, and the rotortail script ‘rotortail’. It doesn’t matter where you put the ‘to-be-attached’ script_model_meds, as their positions will change in-game anyway. It also doesn’t matter if you try to rotate them using the angle keypair as their positions will change anyway. (i.e. don’t do it).

 

Model Scripting

Normally we could just run the map and our model would show up. We are using scripts however, and so we need to do things a bit differently.

In Radiant you need to add an entity called a script_multiplayer. (If your using info_player_deathmatch I don’t think this is necessary, however, I am only using an info_playerstart). It is a little pink box. Bring up its properties in the Entity window. You need to add the following exactly: under ‘key’ add “scriptname” and under ‘value’ add “game_manager”. The placement of this entity is not important.

Now the map is ready to go so you can go ahead and bsp it. We need to now write the script. First of all remember that there are 4 scriptnames we’re using: game_manager, heli, rotortop, and rotortail. So, create a new text document. You can do this by right clicking on the desktop and selecting ‘text document’. Rename the document whateveryounamedthemap.script. Mine is called Heli.script. Open the file up and you want to add the following:

game_manager
{
spawn
{
}
}

This MUST be the first thing in front of every multiplayer script. You can add things to this script but we are going to leave the game_manager script alone. Now add the other three scripts after the game_manager script:

heli
{
spawn
{
}
}
rotortop
{
spawn
{
}
}
rotortail
spawn
{
}
}

Hey what’s the deal with the spawn stuff! Spawn means what the game should do with the entity attached to this script when it appears in the game. We want the rotortail and the rotortop to attach to the heli. Modify the above script like this:

heli
{
spawn
{
}
}
rotortop
{
spawn
{
attachtotag heli tag_rotortop
}
}
rotortail
{
spawn
{
attachtotag heli tag_rotortail
}
}

This tells the game that when the enitities (the script_model_meds) attached to these scripts spawn, they should attach themselves to the entity associated with the heli script at the following model tag. Remember these are the tags that we exported with the .md3 file for the ‘main’ heli model.

Remember that there is animation with the rotortop and rotortail so go back and modify the script again:

heli
{
spawn
{
}
}
rotortop
{
spawn
{
wait 100
attachtotag heli tag_rotortop
playanim 1 18 looping forever
}
}
rotortail
{
spawn
{
wait 100
attachtotag heli tag_rotortail
playanim 1 18 looping forever
}
}

What’s new here? Well first you need to add the wait 100. This is so that the animation will work correctly. The heli must spawn first and then the attached animated models should attach after a delay and do their thing. Otherwise you might get some funny animation. 100 means 0.1 seconds as (I believe) every 1000 = 1 second.

The other command is playanim. The command tells the game that the model AFTER it attaches should play an animation sequence associated with it. In fact it should play frames 1 to 18 and then loop forever………………………… or until you exit the game : )

That’s the script! Now save the file and place it under the /main/maps directory.

Packaging the PK3

This section doesn’t have a lot to do with modeling. However, it has been my experience that getting scripts to run is sometimes more trouble than it’s worth. Therefore, this is a good way to make sure they do work.

Normally you would devmap from the console in wolfy (like we did with the misc_model we added previously). This doesn’t seem to produce the best results when scripting. The foolproof way of doing this is to make the .pk3 file and then run it. Well how do we do that??

A great way of compiling your map is with Wolfcompile, which is over at PlanetPointy. The advantage of Wolfcompile is that you can remake the .pk3 very quickly while testing your scripts. If you are using Wolfcompile here are some things I’ve learned:

Click the ‘arena’ button to generate an arena file. You must do this before you compile your .pk3 or otherwise your map will not show up on the maps list in wolfy. Just click it and Wolfcompile makes it for you.

Click the yellow folder to generate your .pk3. When you do this you get a box called “Generate pk3 file”. Under the file list is the name of your map and a folder. Click the + signs to see what it will add. A lot of times it adds ‘crap’ to your .pk3 and misses other stuff. You can control what it adds. Right click on the first fold and select “export list”. Now save the file (whatever name). Go to the file and open it up. It’s a just a text file. Now you should see something like:

maps 1
Heli.bsp 7
Heli.script 5
Heli.map 7
scripts 1
Heli.arena 5
textures 1
common 1
caulk.tga 4

???? What? Ok you can modify this to import what you want into your pk3 file every time you package it. The file is tabbed – how you place tabs gives the structure of the tree displayed. The name is the name of the file, folder, etc. The number is an icon Wolfcompile displays. They are as follows:

1 = folder
2 = wolf folder
3 = sound
4 = picture
5 = text file
6 = model
7 = unknown file

Save it once modified and to use the list, the next time you click the “Generate pk3 file” button right click the main file displayed and select “import list”. Select the .wcl file you just saved and Walla! those files will now all be added to the .pk3.

For those of you not inclined to use Wolfcompile you first need to make an arena file. An arena file is a file that allows you to ‘see’ your map in the maps list So, if you run wolfy and go to “create sever” your map will show up there. To make an arena file just create a new text file and rename it whateveryounamedyourmap.arena.

Open up the file. You need to add the following:

{
map “Heli”
longname “Helicopter Animation”
type “wolfmp”
timelimit 10
axisRespawnTime 30
alliedRespawnTime 30
}

The map name is the name of the .bsp file you made. The longname is the name that appears under the map list. The type is the type of map you want the map to be (I haven’t experiment with this much). Timelimit, and re-spawns are self-explanatory. Save this file and put it in the /main/scripts directory. Now you’ll need to package everything into a .pk3 file. Create a new zip file. There are a lot of ways to do this. A .pk3 is the same thing as a .zip file such as the files made by Winzip. Make a new zip file and then add (as the minimum) the following stuff:

Your .bsp file
Your .md3 files
Your custom .tga files
Your .script file
Your .arena file

STOP!!! Look over the right hand side of the zip file. You should see /path names. These path names MUST correspond to path names used in the game! The .bsp file should be under /maps. The script file should be under /maps. The arena file should be under /scripts. The custom files you added (models, pictures, sounds) must be under the path you specified under their respective entities in Radiant. If not they will NOT APPEAR. Models will show up as a three pronged colored xyz axis because it can’t find the model! (Remember they are being added at runtime so no errors will be generated in Radiant) If this is not the case and you are not using Wolfcompile you need to create the appropriate folders under the C:\\ drive. (i.e. C:\maps, C:\scripts, C:\models\mapobjects\mymodel, etc.) Paste the files to these directories and remake the zip file with these files in it. Go back and check the /pathnames. They should be correct.

Of course you would add any sounds, etc. But we don’t have any of that here. You don’t need to add the .map, .qc or. ms3d files unless you want people to explore and fiddle with your map.

Once you’ve added those files rename the file whateveryouwant.pk3. Remember that what you name the .pk3 file is the name that id will show when running your map on a server.

Now put the .pk3 file in the /main directory. Your ready to go!!!\

Test it

Load up wolfy and click “multiplayer” then select “create server”. Look down the map list on the left and Dada!!!!! There it is! Run your map.

Everything should work. If not (as is the case quite often when scripting) wolfy will spit out a message about what it didn’t like.

Check out that heli! Incoming! Now there are a lot of things you can do from here….. Such as you can create a trigger to change the blades to another model (maybe a broken set when hit with a rocket)! Or you could trigger a different animation on the tail rotor while keeping the top rotor spinning, etc. You can move the heli while adding / shooting missiles in flight, and changing the animation of the tailrotor as the main model changes directions……..

Cool stuff.
Big credits go to No_1sonuk for helping me out on this stuff.

-paposo