<<< Return to part 2
Part 3: building a better boulder
In this final part of the series, I will show you how to turn the boring train we made in part 1 into a fully-featured rolling boulder. There is a lot of work to do, but unlike the last tutorial none of this work will involve complex logical relationships between entities. It will, however, introduce both the Movewith and Locus systems of Spirit. The ripple effect, in particular, is perhaps the most horrendously complex system of entities I have ever made. You have been warned!
Fortunately each effect can be treated separately, so unlike the last tutorial you won?t have to hold all the entity relationships in your head at the same time! We will begin by replacing the visible body of the train ? currently just a box ? with an animated model. We will start with ?map4? from the previous tutorial; this is included in the example maps for part 3, together with the final product, which is called ?map5?.
I assume that you are using Merl?s custom build of Zoner?s compile tools, or XP-Cagey?s custom build of Merl?s tools. These both include the ?null texture?.
Load up the example map ?map4?. Click the ?ignore groups? button and select all the faces on the main train block (not the origin brush). Texture them with ?null?. This will cause the polygons to be totally removed from the game. Toggle ?ignore groups? off.
Create a cycler entity; place it so that the bottom of the cycler (which is marked in the 3 editor orthographic views as a cross) lies exactly over the centre of the train. Select the cycler and give it the following properties:
Now we will adjust the cycler effect so that the boulder always turns to face the correct direction. I should forewarn you that we are about to have a lot more entities, and as the tutorial progresses you are likely to become confused by the clutter. You can either use VisGroups to hide entities, or you can make new rooms in which to put them. For most of the entities, it doesn?t matter where you put them; I will be quite specific about the location of the others.
We will use a Spirit entity called an env_customize; in fact, we will make 8 of them. At every turn, we will trigger the correct env_customize, which will swap the model of the cycler. For the first one, create an env_customize with:
Now you just need to tell the boulder to turn at each relevant path_corner. Looking at the map from above, in the top editing panel, you can use this image to tell you which way each model rolls:
For example, select both the path_corners ?1? and ?2? and add:
Now we will make the boulder squash people. Create a trigger_hurt that fits closely around the visible boulder model. The best way to line it up is to use the model-viewing feature in Hammer 3.5, in combination with the 3D view. Give it these properties:
Our final effects involve a visible trail and a sound. When the boulder is on land, we want it to make a rumbling sound and to leave a trail of dust. When the boulder is in water, we want it to make a splashing sound and leave a trail of ripples. It might also be useful to turn all these effects off, for when the boulder is falling through the air. This isn?t covered in the tutorial, but if you follow the method below it will be an obvious extension.
First let?s set up the rumbling sound. For this we will use an invisible func_rotating. The func_rotating will play a sound only when it is on. We will have it move with the boulder and trigger it when we want to toggle the sound. Make a block textured with the null texture, and put an origin brush in its centre. Turn this into a func_rotating, and set:
Create a mm:
Compile the example map and observe the trail of smoke. It looks pretty good, but still not quite right. Let?s make it better. For this, we will make use of Spirit?s locus system. Locus is a very clever effects system, but quite hard to understand. It is very versatile. When you set the properties of the env_shooter, you may remember one called ?Fire on spawn (locus=shot)?. We gave this the value ?fade?. Now every time a new smoke puff is spawned, it will become the new ?locus? for this fade entity to act upon. We?re going to use this to make the puffs enlarge and fade out smoothly.
Create an env_render with:
The only problem is that the dust trail is still generated when the boulder is over water. This doesn?t make sense; instead, we will make a ripple effect for the water. But first let?s turn off the dust at the appropriate time. This is a lot simpler than you might expect: just select the mm ?dust_mm? and add:
There?s just one more effect left to make ? the water ripples. This uses a much more sophisticated application of the locus system, together with a novel use of beam entities. To start with, I?d like you to create an env_sprite:
Now create an env_laser with:
You will then have 4 lasers associated with four different calcs. What?s a calc? Well it?s just a name, but here it will represent a truly wonderful entity called a locus_variable. We will use the locus_variable to calculate the position of the boulder, and then tell each beam successively to draw its start sprite at this position. This way, we can reuse the 4 beams endlessly.
Create a locus_variable with:
I?d like to give a brief explanation of why it?s not possible to use just the same method for the ripples as we did for the dust trail. The crucial difference is this: the ripples must be axis-locked sprites, whereas the smoke balls were just ordinary sprites that turn to face you. Unfortunately, it is not possible to set the direction in which an axis-locked sprite faces when emitted from an env_shooter (and the default direction is wrong). The beams get around this problem by using the properties of the env_sprites themselves to render their start sprite.
Now let?s finish the ripple effect. Select all four env_sprites and make the change:
Now create another env_render and add:
Again, make 3 copies (total of 4); change the names to be ?laser2_rend2?, ?laser3_rend2?, ?laser4_rend2?. Change the targets to "sprite2?, ?sprite3?, ?sprite4?.
Congratulations, you?re done! Compile the map and see the oh-so-beautiful and oh-so-clever ripple effects in all their glory. Now it?s your turn ? feel free to build on what you?ve learned from these tutorials, and please show me anything that you come up with. I?d love to see any maps that use these ideas. Good luck.
Addendum
There is an alternative method for making ripples that is much simpler. Credit goes to deathz0rz for making this; I don't like it as much but it does save 19 entities:
Delete all of the env_lasers, the env_sprites, the locus_variables and the env_renders (except the "fade" one, which is used for the dust effect).
Select the mm "ripple_mm" and remove all of the keys (except it's targetname). Add:
Part 3: building a better boulder
In this final part of the series, I will show you how to turn the boring train we made in part 1 into a fully-featured rolling boulder. There is a lot of work to do, but unlike the last tutorial none of this work will involve complex logical relationships between entities. It will, however, introduce both the Movewith and Locus systems of Spirit. The ripple effect, in particular, is perhaps the most horrendously complex system of entities I have ever made. You have been warned!
Fortunately each effect can be treated separately, so unlike the last tutorial you won?t have to hold all the entity relationships in your head at the same time! We will begin by replacing the visible body of the train ? currently just a box ? with an animated model. We will start with ?map4? from the previous tutorial; this is included in the example maps for part 3, together with the final product, which is called ?map5?.
I assume that you are using Merl?s custom build of Zoner?s compile tools, or XP-Cagey?s custom build of Merl?s tools. These both include the ?null texture?.
Load up the example map ?map4?. Click the ?ignore groups? button and select all the faces on the main train block (not the origin brush). Texture them with ?null?. This will cause the polygons to be totally removed from the game. Toggle ?ignore groups? off.
Create a cycler entity; place it so that the bottom of the cycler (which is marked in the 3 editor orthographic views as a cross) lies exactly over the centre of the train. Select the cycler and give it the following properties:
- Name cycler
- Moves with boulder
- Model models/boulder7.mdl
Now we will adjust the cycler effect so that the boulder always turns to face the correct direction. I should forewarn you that we are about to have a lot more entities, and as the tutorial progresses you are likely to become confused by the clutter. You can either use VisGroups to hide entities, or you can make new rooms in which to put them. For most of the entities, it doesn?t matter where you put them; I will be quite specific about the location of the others.
We will use a Spirit entity called an env_customize; in fact, we will make 8 of them. At every turn, we will trigger the correct env_customize, which will swap the model of the cycler. For the first one, create an env_customize with:
- Name cycler_env1
- Target to affect cycler
- Set model models/boulder1.mdl
Now you just need to tell the boulder to turn at each relevant path_corner. Looking at the map from above, in the top editing panel, you can use this image to tell you which way each model rolls:

For example, select both the path_corners ?1? and ?2? and add:
- Fire on pass cycler_env7
- cycler_env4 0
Now we will make the boulder squash people. Create a trigger_hurt that fits closely around the visible boulder model. The best way to line it up is to use the model-viewing feature in Hammer 3.5, in combination with the 3D view. Give it these properties:
- Moves with boulder
- Damage 1000
- Name shake
- Moves with boulder
- Amplitude 8
- Effect radius 500
- Duration 1
- 0.1=jerk, 255.0=rumble 255
- Name shake_mm
- shake 0
- shake_mm 0.5
- Multi-threaded
- Start on
Our final effects involve a visible trail and a sound. When the boulder is on land, we want it to make a rumbling sound and to leave a trail of dust. When the boulder is in water, we want it to make a splashing sound and leave a trail of ripples. It might also be useful to turn all these effects off, for when the boulder is falling through the air. This isn?t covered in the tutorial, but if you follow the method below it will be an obvious extension.
First let?s set up the rumbling sound. For this we will use an invisible func_rotating. The func_rotating will play a sound only when it is on. We will have it move with the boulder and trigger it when we want to toggle the sound. Make a block textured with the null texture, and put an origin brush in its centre. Turn this into a func_rotating, and set:
- Name rumble
- Moves with boulder
- Wav name boulder1.wav
- Not solid
- Large radius
- Name splash
- Wav name river.wav
Create a mm:
- Name ground_water
- rumble 0
- splash 0
- Name water_off
- splash 0
- Name off_ground
- rumble 0
- water_off 0
- Fire on pass ground_water
- Fire on pass path1_mm
- Name path1_mm
- cycler_env7 0
- off_ground 0
- Name shooter_dust
- Moves with boulder
- Number of shots 1
- Delay between shots 0
- Gib speed factor 20
- Course variance 2
- Shot lifetime 2
- Fire on spawn (locus=shot) fade
- Render mode Additive
- FX amount 255
- Render color 237 170 80
- Model or sprite name sprites/ballsmoke.spr
- Scale 0.5
- Framerate 10
- Behaviour of children Noclip
- Blood color Don?t bleed
- Material sound none
- Shot size (X Y Z) 10 10 10
- Name dust_mm
- Trigger to send on
- shooter_dust 0
- dust_mm 0.1
- Multi-threaded
- dust_mm 0.1
Compile the example map and observe the trail of smoke. It looks pretty good, but still not quite right. Let?s make it better. For this, we will make use of Spirit?s locus system. Locus is a very clever effects system, but quite hard to understand. It is very versatile. When you set the properties of the env_shooter, you may remember one called ?Fire on spawn (locus=shot)?. We gave this the value ?fade?. Now every time a new smoke puff is spawned, it will become the new ?locus? for this fade entity to act upon. We?re going to use this to make the puffs enlarge and fade out smoothly.
Create an env_render with:
- Name fade
- Render mode Additive
- FX amount 0
- Scale 3
- Target to affect (LE) *locus
- Fade time 2
- No render FX
- No render mode
- No render color
The only problem is that the dust trail is still generated when the boulder is over water. This doesn?t make sense; instead, we will make a ripple effect for the water. But first let?s turn off the dust at the appropriate time. This is a lot simpler than you might expect: just select the mm ?dust_mm? and add:
- Master rumble
There?s just one more effect left to make ? the water ripples. This uses a much more sophisticated application of the locus system, together with a novel use of beam entities. To start with, I?d like you to create an env_sprite:
- Name sprite1
- Render mode Additive
- FX amount 255
- FX color 16 200 239
- Sprite name sprites/test.spr
- Scale 1
Now create an env_laser with:
- Name laser
- Start at (LP) calc1
- Fire towards calc1
- Meaning of fire towards Position (LP)
- Start sprite sprite1
- Start on
You will then have 4 lasers associated with four different calcs. What?s a calc? Well it?s just a name, but here it will represent a truly wonderful entity called a locus_variable. We will use the locus_variable to calculate the position of the boulder, and then tell each beam successively to draw its start sprite at this position. This way, we can reuse the 4 beams endlessly.
Create a locus_variable with:
- Name calc1
- Position to record (LP) shooter_dust
- Name ripple_mm
- Master splash
- Trigger to send On
- Multi-threaded
- calc1 0
- laser1_rend 0.1
- calc2 0.3
- laser2_rend 0.4
- calc3 0.6
- laser3_rend 0.7
- calc4 0.9
- laser4_rend 1
- ripple_mm 1.2
I?d like to give a brief explanation of why it?s not possible to use just the same method for the ripples as we did for the dust trail. The crucial difference is this: the ripples must be axis-locked sprites, whereas the smoke balls were just ordinary sprites that turn to face you. Unfortunately, it is not possible to set the direction in which an axis-locked sprite faces when emitted from an env_shooter (and the default direction is wrong). The beams get around this problem by using the properties of the env_sprites themselves to render their start sprite.
Now let?s finish the ripple effect. Select all four env_sprites and make the change:
- FX amount 0
- Name laser1_rend
- Render mode Additive
- FX Amount 255
- FX color 16 200 239
- Scale 0.01
- Target to affect (LE) sprite1
- Fade time 0
- Trigger after fading laser1_rend2
Now create another env_render and add:
- Name laser1_rend2
- Render mode Additive
- FX Amount 0
- FX color 16 200 239
- Scale 1
- Target to affect (LE) sprite1
- Fade time 1
Again, make 3 copies (total of 4); change the names to be ?laser2_rend2?, ?laser3_rend2?, ?laser4_rend2?. Change the targets to "sprite2?, ?sprite3?, ?sprite4?.
Congratulations, you?re done! Compile the map and see the oh-so-beautiful and oh-so-clever ripple effects in all their glory. Now it?s your turn ? feel free to build on what you?ve learned from these tutorials, and please show me anything that you come up with. I?d love to see any maps that use these ideas. Good luck.
Addendum
There is an alternative method for making ripples that is much simpler. Credit goes to deathz0rz for making this; I don't like it as much but it does save 19 entities:
Delete all of the env_lasers, the env_sprites, the locus_variables and the env_renders (except the "fade" one, which is used for the dust effect).
Select the mm "ripple_mm" and remove all of the keys (except it's targetname). Add:
- render_ripple 0
- ripple_mm 0.4
- Name render_ripple
- Spritename sprites/shockwave.spr
- Color 40 128 255
- Opacity 128
- Duration 8
- Final Radius 140
- Wave height 12
- Distortion 50
- Position shooter_dust
- Centered
- Repeatable