With the release of ShootMania comes a brand new feature: Bots ! This post will give you all information you need to use your custom bots in your title packs. To help you understand this feature, please download the Horde mode's data here : http://files.maniaplanet.com/botdata/BotExample.zip
. Horde is a Shootmania mode created specifically to give you an example of what can be done with Maniaplanet bots.
Important note : This feature is meant to be used in your custom title packs
. The reason is that if you use custom bots (model, skins), the player who wants to play your mode will need the assets to load the bots. If a player install your title pack he will automatically download these assets. In this tutorial though, we explain how to test custom bots in Storm. You shouldn't set up a Storm dedicated server with a mode or with maps that use bots. For more informations about title packs, please read this thread
(and particularly this post
--- QUICK TEST SECTION ---
Here we will explain you how to create maps for this Horde mode.
1) Install the bot files
You first have to install the specific kind of bots used by Horde mode (a creature that looks like a toad):
- Copy the item file OrganicSmall.Item.gbx
(create folders if necessary)
- Copy the skin file OrganicSmall.zip
(create folders if necessary)
2) Install the script files
You also have to install the mode itself, which consists of two scripts:
- Copy the maptype file HordeArena.Script.txt
(create folders if necessary)
- Copy the mode file Horde.Script.txt
(create folders if necessary)
3) How to place bots in a map
(If you don't want to create your own maps, just use the maps mentionned at the end of step 4 and go to step 5)
Open the map editor (in advanced mode) and create a new map.
There are two ways to place bots in your map:
3.a) Autonomous bots
Switch to Item Mode (by clicking on the tree-shaped icon at the bottom of the screen) and select the bot you have installed in step 1.
You can place it on the map with left click, turn it with right click, remove it by clicking on it while holding "X" key, etc. just as you do when you place blocks in Block Mode.
The bots you place with this method will appear in any mode, even if the mode is not supposed to handle bots. They defend the zone where they were placed. They attack players who come too close but stop following them if they leave the zone. These bots have two points of armor, and respawn automatically a little while after they are eliminated.
3.b) Script-managed bots
Switch to Item Mode (by clicking on the tree-shaped icon at the bottom of the screen) and select the bot you have installed in step 1. Then click on the icon that has appeared at the bottom left corner of the screen (just above the "Save" icon) to switch to Path Mode.
You can create a new path with RIGHT CLICK, and then add points to this path with left clicks. You can also select an existing path by holding "Ctrl" key while you click or remove some points with "X" + click.
This method creates paths, not bots. Bots will appear in game only if the mode script decides to spawn bots on the paths of the map (as Horde mode do).
4) How to create a Horde map
Create a new map. Click on the script name at the top left corner of the screen and select HordeArena (the map type script you have intsalled at step 2).
Then build your map, keeping in mind that you must place one spawn (where the player(s) will appear) and at least one pole (that the player(s) will have to defend).
Place some PATHS in the map as described in the 3-b) section. All paths should end near a pole
You can define the Map Objectives by clicking on the little hammer on the bottom-right corner of the screen and clicking on Set Map Objectives. In this mode, the map objectives are times (in milliseconds) that players have to reach to earn medals (just like TrackMania).
Here are some examples of Horde maps (copy them into MyDocuments\ManiaPlanet\Maps\My Maps)
- A single player map: Horde_Single.Map.Gbx
- A two players map (best players can try it alone ^^): Horde_Double.Map.Gbx
5) Let's play Horde!
While you are in the map editor, you can test your map simply by clicking on the green flag at the bottom right corner of the screen (if it is not green, it means that you forgot to place one spawn and a pole in your map).
The other way to play is to create a server in your local network:
- select the Storm station
- select "Local Play" and then "Create"
- choose the script "Horde" and click on "Launch"
- choose the maps you have created or the ones provided in the .zip file
- if you play with other players, make sure everyone has put the files in the places described in step 1.
In this mode, the players have to cooperate to defend their poles from waves of toads (bots) that spawns in the map (in the maps provided in the .zip file, they spawn next to the cristals). Each time a wave of bots spawns, the difficulty increases, making the toads more powerful (first gaining speed, then gaining armor). After 12 waves, the Insane mode is activated, making the bots spawn continuously. The game ends once 10 bots have reached the Poles. All players have the Laser. If you hit 10 toads without failing a laser, you enter in Frenzy during 10 seconds, increasing your reload rate. The goal is to defend the poles during as long as possible. Your time then grants you a medal determined by the ones stored in the map.
--- ADVANCED SECTION ---
This section is for advanced players who want to create their own bot skins or their own modes using bots.
1) Create new bot skins
2) Use bots in your own mode
This part will explain you how to use the ManiaScript API to customize your bots.To understand how bots are managed in script, you should take a look at the script "Horde.Script" given in the .zip file (cf the beginning of this thread).
Tell the game you are going to use bots
Place the following instruction at the beginning of the main function (StartServer section if your script extends ModeBase.Script.txt) :
Prepare the model
Before the Mode::LoadMap call, you need to tell the game that you wish to use a custom bot. For this purpose, call the ItemList_Add() function with the path to your file (e.g., in our case, ItemList_Add("Characters/OrganicSmall.Item.gbx")). This function returns an Ident that you need to store somewhere, in order to use it when you spawn a bot of this kind.
Spawn a bot
To spawn a bot from the script, you need to use the CreateBotPlayer
function. This function takes five arguments:
- [Ident] the model of the bot which you have stored from ItemList_Add (0 for the StormMan)
- [Integer] the team of the bot
- [Integer] the armor of the bot
- [CSmLandmark] element of the BotPaths array, which represents the path of the bot (the bot spawns on the first point of the path)
- [Integer] Time of activation
It returns a CSmPlayer
pointer to your bot, just like the function SpawnPlayer
would have done for a human player. The difference is that the bot's Driver component (type CSmPlayerDriver
) is not Null. This Driver is what defines what the bot does.
The bot's Driver contains all the parameters you can tweak to customize your bot. First, let's see the parameters to define the bot's behaviour against potential targets :
(Real): distance from which the bot attacks its target
(Real): when the bot is further than this distance from its initial point, it retreats. During its retreat the bot doesn't attack anyone.
(Real): Real between 0 and 1 that defines the efficiency of the bot (1 means he always shoots straight at its target)
(Integer): Time the bot takes before handling its target
(Integer): Minimum time between two shots
(Integer): Maximum time between two shots
(enum CSmPlayerDriver::ESmAttackFilter): Defines what kind of players the bot needs to attack
- OppositePlayers: only players of the opposite team
- OppositeBots: only bots of the opposite team
- AllOpposite: players and bots of the opposite team
- AllPlayers: players of both teams
- AllBots: bots of both teams
- All: everyone
: Whatever the current behaviour is, the bot will start chasing the target defined in this variable (CSmPlayer class) and won't stop untill this variable is set to Null.
Now that we have seen how the bot can handle a target, let's see how it can move. There are three predefined behaviours, stored in the Behaviour
member (enum CSmPlayerDriver::ESmDriverBehaviour
The bot doesn't move. It will fire at the targets in its AggroRadius
The bot wanders in a zone defined by a point and a radius. More precisely, the bot goes to a random location in this zone, then waits, and chooses another point in the same zone (and loops on this pattern). Use the following Driver's parameters to customize this behaviour :
- Saunter_AnchorPoint (Vec3) -> Center of the zone
- Saunter_Radius (Real) -> Radius of the zone
- Saunter_BaseChillingTime (Integer) -> Time between two moves (in ms)
- Saunter_ChillingDeltaTime (Integer) -> Used to add some randomness in the chilling time. For example, if the BaseChillingTime is 1000 and ChillingDeltaTime is 300, the chilling time will be a random value between 0.7 and 1.3 second.
The bot will engage the targets within its AggroRadius
, following them and shooting at them until they are out of sight or until the distance between the bot and its AnchorPoint
is above its DisengageDistance
. The bot then disengages and goes back in a random point in its zone.
The bot follows the path bound to the BotPath object it was attached to. The only parameter you need to modify is named Patrol_Mode
(enum CSmPlayerDriver::ESmDriverPatrolMode). There are three values:
- OneTrip (default one) -> the bots stops at the end of the path
- BackAndForth -> the bot goes back and forth between the first and last points, always following the defined path
- Loop -> When it reaches the end of the path, the bot returns to the first point of the path by the shortest way possible
The bot will engage the targets within its AggroRadius
, following them and shooting at them until they are out of sight or until the distance between the bot and the point where he engaged the target is above its DisengageDistance
. The bot then disengages and goes back to the closest point on its Path
, resuming its Patrol.
Unspawning a bot doesn't require anything special, but once it is unspawned, you should call the DestroyBotPlayer procedure
- The number of bots spawned at the same time should be limited, for performance issues. Keep in mind that there can't be more than 256 players on a map, bots included.
3) Different behaviours for different paths
In some cases, you might want to create different categories of BotPaths. For instance, if you do a team mode, you might want to have some paths for Blue bots and some others for Red bots. When you create a BotPath in the editor, use the spacebar to change the color of the path. This changes the Clan variable of the BotPath in the script. You can then use this variable to determine what you want to do with this BotPath.
This API will be completed in future updates, with more behaviours and more possibilities. Don't hesitate to ask questions if some parts remain unclear, and please give us your feedback on this feature. Horde is of course just a very simple example of a solo/co-op experience that you can create with this feature, and we can't wait to see your creations !
Have fun !
Edit : Update 24/04/2013
- Fixed an issue with bots movements in Saunter mode, they shouldn't be stuck anymore.
- Changed the way a bot disengages an enemy while in Patrol mode : they joins the path as fast as possible, instead of cutting to the next waypoint on their path. This partially fixes an issue with the bots not engaging sometimes, although there seems to be some situations where it still happens. We are still investigating on this issue.
- You can now change the zone in which the bot wanders while in Saunter mode with the variable Saunter_AnchorPoint (Vec3) in the bot's Driver.
- There is a new variable in the Driver called Target (CSmPlayer), which stores the current target of the bot. This target is the closest player on which the bot can shoot (i.e. in the Line of Sight, within the AggroRadius, and that matches the AttackFilter). Note that there is no point in trying to set this target in the script, it is recomputed by the game engine when the bot is updated.
- New AttackFilter value : Nobody. This enables you to create peaceful bots without having to tweak other variables like AggroRadius.
- You can define a set of players that the bot should not target, with the Driver's variable TargetsToAvoid (an array of CSmPlayer).
- New predefined Behaviour : Escape. The bot doesn't attack, it only flees when an enemy is too close, and keeps its current position otherwise. When the distance between an enemy and the bot is lower than Escape_DistanceSafe, the bot chooses a random point located between Escape_DistanceMinEscape and Escape_DistanceMaxEscape meters from its current location.
- You can now move a point of a path by left-clicking on it and dragging it to another location.
- You can now add a point between two other points by left-clicking on the path between these two points and dragging it to another location.
Edit : Update 16/05/2013
- Before, when you wanted to respawn a bot, you had to destroy it and create it back. You can now respawn a bot like you would respawn a human player, with the function SpawnBotPlayer. This function takes the same arguments as SpawnPlayer, except that the Player has to be a bot and the spawn location doesn't have to be a CSmBlockSpawn, it can be any CSmScriptLandmark (including CSmScriptBotPath). Please note that you still have to call CreateBotPlayer for the first spawn, and you still need to destroy a bot when you don't use it anymore.
- Fixed some issues that could occure while changing the Behaviour of the bot.
- Fixed the bug that made rockets disappear when the bot who shot them was destroyed (should fix the bug of the non-appearing +1 as well)
- Fixed some issues that could occure when a bot was in Patrol mode and was returning to its Path
- New variable Path in CSmScriptBotPath, to access the points defined in the map editor (read-only)
- New variable IsStuck in the Driver, to know if the bot can't move (this variable is True when the bot didn't move for 1 sec or more, when he is supposed to move)
- New API to control the bot entirely with the script. The corresponding Behaviour enum is called Scripted. Here's the list of available functions:
- ScriptedBot_Move(CSmPlayer Bot, Vec3 Position) : Moves the bot to the given position
- ScriptedBot_MoveDelta(CSmPlayer Bot, Vec3 Delta) : Same as the previous function, but with a position depending on the current position
- ScriptedBot_Aim(CSmPlayer Bot, Vec3 Position) : Aims at the given position
- ScriptedBot_AimDelta(CSmPlayer Bot, Real DYaw, Real DPitch) : Turns the bot's aim with the given angles
- ScriptedBot_MoveAndAim(CSmPlayer Bot, Vec3 Position) : Same as calling ScriptedBot_Move followed by ScriptedBot_Aim
- ScriptedBot_RequestAction(CSmPlayer Bot) : Makes the bot use its current action (right click)
- ScriptedBot_RequestGunTrigger(CSmPlayer Bot) : Makes the bot fire
- Boolean variable Scripted_ForceAimInMoveDir in the Driver : Forces the bot to aim in the direction he is moving (just as he does when he is in a predefined mode). False by default.
Edit : Update 22/05/2013
- Crashfix : Game could crash when the bot engaged an enemy while not moving
- Crashfix : Restarting server (Del) while bots were being destructed resulted in a crash
- Crashfix : ForcedTarget could contain an invalid pointer
- Bugfix : when a bot's AmmoGain variable was not set in the script, it took a random value (which could lead to the bot running quickly out of ammo or having infinite ammo)
- Bugfix : the bot could sometimes run in circle while trying to reach a point
- Bugfix : the bot could sometimes ignore targets
- Bugfix : there were several issues when using the Patrol behaviour with a one-point Path
- Bugfix : in Patrol behaviour, BackAndForth mode, the bot could go in the wrong direction when disengaging
Edit : Update 02/07/2013
- Crashfix/Bugfix : The game could crash when using a bot in Saunter or Escape behaviour
- Bugfix : Bots could go in the wrong way when disengaging in Patrol behaviour using the Loop mode between the last point and the first point
- Bugfix : Bots have less trouble with slopes
- Bugfix : Bots could act strangely after being respawned in certain cases
- New Feature : You can now set the Field of View of the Bot. This is an angle in radians (in other words a real between 0 and 2Pi) that defines the area in which a Target is considered as visible. The default value is 2Pi/3 (which was also the setting used in previous versions)
- New Feature : Bots now take bumpers into account. They don't realize that bumpers make them go faster, but they understand bumpers can help them reach otherwise unreachable points. Bots don't use air control though, so they will always land in the same area (you can use the helpers available in the Block Property mode in the editor)