|
|
|
Optimising
your map for bots
So far, the few
bot tutorials that I've seen have seemed to consist entirely
of:
Run BSPC
on your compiled .bsp to create a bot navigation (.aas)
file.
The End.
Ah, if only it
were that simple.....
|
|
Unless you are extremely
lucky or your map is one box with a rocket launcher and a spawn
point in it, the bots will probably play really dumb. Worse still,
you may encounter 'bot stutter' - an uneven framerate caused by
CPU overload on the bot AI. Now its very easy to say "well,
this map is designed for human players anyway so I'll leave it"
but the sad fact of the matter is that its quite unlikely that your
map will end up on any servers, so its worth making the botplay
as good as possible. Happily there are several things that can be
done to improve matters, and this tutorial is here to tell you what
they are.
However,
before we start there are a few things bots will never, or hardly
ever, do:
a)
Bots will not usually shoot at a shootable trigger or button.
b) Bots will not press a button voluntarily (although
you can make them using an item_botroam - but these are not
conditional, so the bot will carry on trying to activate the
button even if it isn't necessary, and/or won't go for it above
anything else when it is necessary)
c) Bots are pretty rubbish at working out jumps and even
worse at working out rocket jumps and strafe jumps. If an area
of your map can only be reached by jumping don't be surprised
if you can't get the bots to use it.
d)
Bots will only try to get floating items (those flagged as 'suspended')
by using jump-pads and launch-ramps. They won't jump or deliberately
fall off a ledge to get a suspended item.
OK, now that's out of
the way, download a copy of Q3map2Toolz
if you haven't already got it (makes compiling the .aas file
self-explanatory) and let's get on with the optimisations:
1. Simplify the collision
hull with playerclip, weaponclip and botclip.
Bots like simple blocky
shapes to maneouvre round. They especially like blocks which are
axial (parallel to the gridlines). Of course, you could just build
your map out of axial blocks, but it would probably look a bit
pants. This is where our various kinds of clip come in.
Weaponclip blocks
the movement of players, bots and weaponfire. Playerclip blocks
players and bots, but allows weaponfire through. Botclip only
blocks bots.
Important note:
Bots will fire through botclip, but seem to view playerclip as
impenetrable.
The good thing about
botclip is that it does not affect a human player in any way,
so you can stick great big huge axial botclip brushes round more
complicated architecture and no-one will ever know. Except the
bots, who will like you and your map a whole lot better. Oh, and
BSPC which will compile a whole lot faster too.
Remember that the only
way a player will notice a botclip brush is if it stops a bot
from being thrown through an empty space by an explosion, or if
it is really in the way of a normal route round the level. Otherwise,
the bots will just navigate round it and nobody will be any the
wiser.
Stick botclip brushes
everywhere you can get away with it to simplify the collision
hull that the bots see.
Prime
contenders for clip intervention are:
a) Empty spaces
above the players that the bots will never be able to get to
can be botclipped - for example, in Q3DM4 there's a lot of this
because the ceilings are so high.
b) Walls/floors/ceilings
with lots of architectural detail - this kind of thing should
usually be flattened with playerclip because it will probably
get in the way of human players as well. Playerclip also acts
as botclip - you don't need an overlapping botclip brush.
c) Curvy pipes
and suchlike - any complex patchmeshes can complicate the .aas
file unnecessarily. Make them non-solid and encase them in simplified
weaponclip brushes as far as possible.
d)
Any space which cannot be reached in the normal course of play
- doesn't matter if it is just about possible to get there, if
the bots aren't likely to, botclip it off! Look out for small
areas under ledges which the players cannot fit into and things
like that.
Botclip
can also be used to stop the bots doing stupid things like jumping
off the edge of a map, or not giving themselves enough forward thrust
to make a fall from a platform without landing in some hazard. The
latter is acheived by placing a botclip brush next to the edge of
the platform as shown below - now the bots will slide down it (as
long as it's steeper than 45 degrees) and over the hazard, rather
than into it.
Sometimes, you can
use botclip to make an area that the bots keep killing themselves
in more hazardous, so that the bots will realise it's dangerous
and avoid it. For example, bots often think that they can land
on very small or narrow bits of architecture over hazards, when
in actual fact 9 times out of 10 they miss it and fall to their
doom. However, you don't want to stop human players being able
to attempt it. In this case you can use another steeply angled
bit of botclip that makes it impossible for the bots to land on
the offending brush - they would simply slide off. Now the bots
should see the danger and stop acting like lemmings.
2. Where you can't
use botclip, use botdonotenter.
If after all your botclipping
efforts the bots still insist on going places you don't want them
too you can try using botdonotenter brushes instead. In theory,
these create an area which the bots will avoid unless they are
pushed into it or there is a worthwhile goal, such as an item
or flag within it. In practice, the bots sometimes completely
ignore them, so it's just trial and error really. I used a botdonotenter
brush just taller than a player to stop the bots loitering over
the trapdoors in my first map:
I think they thought
they could get down through the trapdoor to the item_botroam I
had placed on the jump-pad below, even though the trapdoor was
one-way and only triggered from below. Luckily, my fix worked,
and didn't stop them using the trapdoor from below and shooting
up through the botdonotenter brush (I guess a trigger_push counts
as being pushed into the area...?)
3. What to do if the
bots won't use certain parts of your map.
First check that there
isn't an error in the .aas file which is causing the bots to see
that area as solid. To do this, load up your map in devmap mode
and type \bot_testsolid 1 into the console. Now you should see
a readout at the top of the screen which says either EMPTY or
SOLID. Go to the part of the map where the problem is and see
if the .aas file is reporting any empty space as solid. If it
is, you will either need to simplify the collision hull in that
part of the map or use the -forcesidesvisible commandline switch
when compiling your .aas file. This should fix any errors but
will take a lot longer and is not recommended.
Another way to test
for this kind of problem is to load up the map in a teamplay mode
and tell one of your team-mate bots to follow you as you go to
the problematic area. If they make it OK, then there probably
isn't an error, and its just the bots being stupid.
If there are no errors
of this type, try placing item_botroam entities in the area. Item_botroams
attract bots in the same way as any other item would, and you
can control how much they attract the bots as compared to other
items by setting the 'weight' key. It's suggested that you keep
the value under 400, but for testing purposes you can go higher
than this, so make it 800 or something like that. Then fire up
the map and see whether the bots go to the area. If they do, then
adjust the weight key so that the bots don't use that area too
much - if the weight is too high then the bots may keep trying
to 'collect' the item_botroam over and over again, because unlike
a regular item it never actually gets picked up.
Important
note: Just got this tip from [AF]haste - if the bots refuse
to use a jump-pad it may be because the target_position at the
end of the jump-pad's trajectory is too close to the floor. On
his map, increasing the gap from 64 to 96 units did the trick.
If they still don't,
and you have already balanced your cluster portals (see 5, below)
then it is probably because they don't see how they can get there
at all (remember they are very stupid), or they think that the
item_botroam is impossible to get to without dying. Jump-pads
which propel the player along a curved surface, like in Flying
Plutonians by nunuk and Scorpion by me, are particular
culprits - especially if they are over a fatal drop. Even placing
an item_botroam on the jump-pad itself will not always persuade
the bots to use it. In my case, I actually had to drop two really
cool double curve jumps from Scorpion because the bots
simply wouldn't use them, no matter what I did. As mentioned before,
you may get similar problems with areas only reachable by jump
or rocketjump.
4. How to 'fake it'
with buttons and triggered doors
I was originally going
to write this bit saying that bots are not clever enough to work
out when an item that is, for example, behind a triggered door,
or over a fatal drop with a triggered bridge, is actually available
and as a general rule will not go for an item that is sometimes
inaccessible. In my experience (which isn't that much admittedly)
this has seemed to be the case. I was then going to suggest some
pretty crude workarounds. (eg hidden trigger_pushes which are
covered with a triggered trapdoor and propel the bots through
the triggered door when it is open. I used this trick in Scorpion
to get the bots through the tail doors)
However, I put together
a small testmap to test the default behaviour and found some interesting
and surprising results:
The testmap consisted
of an empty room with spawnpoints in connected by either triggered
door or bridge over a fatal drop to another room with loads
of goodies in. I tested it both with and without an item_botroam
by the button.
First I tested the
door without an item_botroam - all the bots knew that the goodies
were behind the door and loitered around it acting like idiots.
None of them went anywhere near the button to open it. However,
when I opened it for them they all bundled in and got the goodies.
Next, I tested the
bridge without an item_botroam - all the bots completely ignored
the goodies and ran around shooting each other with machine
guns and ignoring the button. When I raised the bridge for them
they continued to ignore the goodies.
Next I tested the
door with an item_botroam and it worked tolerably well - bots
went for the button and went for the door, and the two coincided
quite a lot allowing the bots to get the goodies, although I
don't think the bots were actually aware of the link between
the button and the door. They were still prone to loiter round
the door when it wasn't open.
Finally,
and strangest of all, I tested the bridge with an item_botroam.
Now when the bridge wasn't there the bots avoided the fatal drop
like they had before, but when they were attracted to the button
by the item_botroam and activated it, they realised that they
could now go across the bridge and get the goodies. This perplexes
me, because simply by adding the item_botroam to the button we
seem to have gained a level of intelligence from the bots regarding
the bridge and the fatal drop. They were now aware of whether
it was safe or not to cross the gap, although again I don't think
they were aware of the link between the button and the bridge.
They also didn't exhibit the loitering behaviour that they had
with the door, making this the most successful test.
Having said all this,
I've yet to see this happen in a custom map, although it does
seem to work in Q3DM7 with the button opening the trapdoor to
the red armor room. I always assumed this was a bit of a coding
hack, but perhaps not. I do vaguely remember reading that one
point release had updated the bots 'button intelligence', so maybe
that explains it. Whether it would still work outside of the very
basic axial architecture of my testmap is, ahem, left to the reader
as an exercise ;)
Ah, clusterportals.
Now we get to the fun part. If your idea of fun is staying up
into the small hours repeatedly recompiling your .aas file. It's
worth noting at this point that you only need to run the BSPand
BSPC stages of the compile to test bot stuff - you can omit VIS
and LIGHT altogether.
First off, you'll need
to know what a cluster is, so here goes....
When BSPC creates
a bot navigation file for your map, it splits the map up into
very small 'reachability areas'. Each reachability area is essentially
a single surface which a bot can move upon during play. Using
the clipping methods described above will reduce the number
of reachability areas in your map and hence reduce the complexity
of the in-game AI calculations. However, if the map is of a
reasonable size and/or geometric complexity there will still
be too many areas to consider at any one time, so BSPC simplifies
the calculations further by dividing the areas into groups called
clusters. The place where two clusters meet is known as a clusterportal.
In an ideal situation, the clusters should be balanced (that
is, each should have approximately the same number of areas)
and there should be under 500 areas in each cluster. This isn't
always possible, especially on very open maps, but the closer
you can get to it, the faster the bot calculations will be,
the better the bots will play, and the less likely it will be
that your map will suffer from the evil that is bot stutter.
Problem is, BSPC doesn't
always split up the clusters very well, unless your map is a mostly
horizontal room-corridor-room-corridor-etc map. When there are
lots of overlapping vertical layers the chances of BSPC working
out the clusters properly are pretty small.
So, what can be done?
First you'll need to see what BSPC has done with your map by default,
so after compiling the .aas file open up the bspc.log file in
your Quake3 root folder. You'll probably see quite a few warning
messages like WARNING: CM_AddFacetBevels... invalid bevel
or AAS_GetFace: face 21271 had degenerate edge 3-4 but
don't be alarmed - more than likely they're just harmless non-fatal
warnings that you don't need to worry about. Scroll down to near
the bottom of the logfile and you should see something like this:
cluster
1 has 301 reachability areas
cluster 2 has 5 reachability areas
cluster 3 has 736 reachability areas
cluster 4 has 10 reachability areas
cluster 5 has 17 reachability areas
cluster 6 has 3 reachability areas
1072 total reachability areas
(this
is from Q3DM7sample.map compiled without clusterportals)
Unsurprisingly, this
is a list of all the clusters and the number of reachability areas
in each. The trick is to balance them up so that each cluster
contains roughly the same number of areas. In the above example
we should be aiming to get rid of some of the very small clusters
and have about 6 clusters containing about 160 reachability areas
each, or 4 clusters containing about 200 areas. But at the moment
you don't even know which cluster refers to which part of your
map, so fire up your map with the devmap command and type \bot_testclusters
1 into the console. Lo and behold you now have a readout saying
which cluster you are in at the top left of the screen. A minus
number indicates you are inside a working clusterportal. Zero
indicates that you are on a trigger_push trajectory.
What you are looking
for are places where you could manually force a clusterportal
to even up the numbers. You do this by using a brush textured
on all sides with the common/clusterportal shader. In room-corridor-room
maps like Q3DM7 the obvious place for clusterportals is in doorways.
In more complex maps you'll have to be a little more creative.
However you can't just stick them in anywhere - there are quite
a few conditions that have to be met before BSPC will accept your
forced clusterportals as valid and include them in its calculations.
Stick to the rules below and you should be OK.
Clusterportals
must completely seal off a section of the map to make
that section a cluster in its own right.
Taking a tip from
a deceased tutorial by Jon Eriksson, I think the best way
to explain this is to look at the section of the map that
you want to become a separate cluster and imagine that you
are filling it completely with water. (Hide any entities,
models and non-solid brushes from the view first as they will
not block our virtual water. Unlike with areaportals, detailbrushes
(as long as they are solid) will block the water)
Now, if any water
can escape into another section of the map without going
through a clusterportal then the cluster will not be created.
Take a look at the screenshots below and imagine we want the
corridor to be cluster 1 and the room to be cluster 2. (The
ceiling has been removed so you can see what's going on)
of course, in reality
it's rarely this simple. But if you understand the principle
you should be able to apply it to more complex spaces. An
important point to remember is that the virtual water will
be able to flow through a teleport, so if we had a teleport
in the room above which led to a destination in the corridor,
cluster 2 would no longer be watertight. A possible solution
to this is to encase the teleport in botclip as far as possible
and then make a clusterportal 'entrance' the bots will have
to go through to get to it. In the above example, this would
cause the room, cluster 2, to be 'watertight' again and cluster
1 would consist of the corridor and the small botclip box
round the teleport.
Clusterportals
will not function if they are crossed by a trigger_push trajectory.
This
is a little known fact (it's not in the Radiant manual) which
caused me no end of headaches when trying to clusterportal Scorpion.
As far as the manual said, I had everything right, but my clusterportals
still weren't working. Thanks to Quakin' for setting me right
on this one... :)
Clusterportals
will not work properly if they can be fallen, rather than walked,
through.
In other words,
clusterportals will only work horizontally. And, yes, that
is rubbish. Strangely, a vertical clusterportal will still
split clusters, but it makes the bots even stupider than they
usually are, so don't do it!
Clusterportals
will not work properly if they have any other brushes intersecting
them.
This is even worse
than no clusterportal, because it may cause the clusterportal
to alternately fail and work in game. Euughhh....
Clusterportals
should be axial as far as possible, and made from a single brush.
If you have an
arched doorway for example, clip the arch with botclip to
make the doorway rectangular, then fill that rectangle with
a clusterportal.
Clusterportals
should always have identically shaped and sized 'entrances'
and 'exits'.
For
example, a doorway in a sloped hall should not be approached
like this:
But
like this:
Clusterportals
should always be surrounded on all sides by solid geometry or
clip.
Well, except the
front and the back of course... All but two sides is more
accurate perhaps.
If a door is already
sealed with an areaportal brush, a clusterportal is not necessary
there.
BSPC uses areaportals
as clusterportals. The reverse is not true.
Clusterportals
should not contain less than 10 areas.
This
is taken from the Radiant manual, but is often very hard to
acheive - even the id sample maps have some tiny 'phantom'
clusters which do not seem to appear anywhere in the map.
It doesn't seem to affect things too badly, but is worth bearing
in mind. What you should be looking out for is small areas
which can be botclipped off - say a gap above a ceiling beam
or something like that....
Clusterportals
should be 16 units thick, or 32 if absolutely necessary.
Clusterportals
must separate no more and no less than 2 clusters.
Clusterportals
should never extend into the void.
6. Clusterportals
in space
This is such an awkward
problem that I thought it deserved its own special section. In
a large space map with lots of jump-pads, placing clusterportals
can be nigh-on impossible, as most of the map is cris-crossed
with trigger_push trajectories, there are no obvious door-type
structures which seal off any area, and there are usually vertical
access points to almost every single part of the map. If the map
is simple enough, you can get away with not adding clusterportals.
This is what id did with Q3DM17 - its just one big cluster with
4 little 'phantom' clusters creeping in there too. However, once
you start adding any fancy architecture (and let's face it - Q3DM17
looks like a dog, even though it plays like a work of art) you'll
have too many areas to get away with this. So, its clusterportal
time for you...
The only way (as far
as I know) to get clusterportals working properly in space comes
courtesy of Raven, who helped me out with this on Scorpion
(Thanks and sorry I forgot you in the readme!) Here goes...
1. Split the
map into approximately equal sized sections using huge botclip
walls, 16 units thick, which go all the way across the skybox
and so completely seal the areas they divide. You'll probably
only need two or three walls, but remember that you cannot have
a trigger_push trajectory going through any of them. Don't worry
about teleports for the moment.
2. Use the
clipper tool to make rectangular 'windows' in these walls where
the bots will need to go through them.
3. Fill the
'windows' with clusterportal brushes.
4. If there
are any teleports which have a destination in another cluster,
make a botclip box round the teleport and put in a clusterportal
'door' for the bots to use.
5. Cross your
fingers and compile the .aas
6. Repeat
until it works. :)
Here's the two walls
I ended up with in Scorpion - I've selected the botclip
and left the clusterportals unselected to make it clearer. (Whoever
it was at id who decided to make botclip and clusterportals almost
the same colour should be remonstrated with most severely. I hope
you're listening Mr. Carmack)
By doing this I managed
to reduce the number of areas in each of the two main clusters
to about 800 - still too high, but it seemed to fix the bot stutter
problem, so I was reasonably happy with it.
Typically enough,
I've just figured out a way I could have split it into 3 and reduced
the number of areas in each.... oh well, it's too late now, and
I wasn't lucky enough to have such a useful bot optimisation tutorial
to hand at the time... so now there's no excuse for any of your
spacemaps to have clusters with more than 500 areas in, OK? ;)
Well, if you haven't
gone to sleep by now, you are probably:
a) on some kind
of amphetamine and
b) a bot optimisation
expert
So go whip those unruly
bots into shape! Good luck!
Thanks
to Raven, Quakin' and Snickelfritz for help and advice on this topic!
If
you have any corrections or additions to this tutorial, please
go right ahead and email them to me at: cardigan@planetquake.com
|
|