Roles
Omni-Bot_Map_Scripting | Roles |
Intro
Bot roles were added in version 0.8 as a method to focus specific bots on specific goals. Any goal that has a role defined will be ignored by bots that do not have the same role defined. This is particularly useful when there are multiple defense points in a map that are simultaneously active or in large dual objective maps.
The Enemy Territory map Radar is one such example as the last stage of the map has two separate objectives for the Allied team to steal; the East and West Radar Parts. The defense has been setup so that one group of defenders will focus on the West Parts and another will focus on the East Parts. Since the defend goals have an equal priority, setting roles ensures that the bots won't be wandering between locations; which results in a much weaker defense.
Another very specific usage of roles is for Covert Ops bots in Enemy Territory that have the ability to steal an enemies uniform. Once in uniform, the bot is automatically assigned an Infiltrator role; which makes certain goals available that normally would not be reachable.
A more common use of roles would be for the Capture the Flag type maps seen in Doom 3 and Quake 4 as there is a need for dedicated base defenders.
Roles however are not limited to the scenarios given. Any time there is a need for specific goals to be limited in usage to one or more bots, setting roles is a simple way to solve the problem.
Setup
Setup requires that both bots and goals are given the desired roles with one of the predefined roles. Valid roles are as follows:
ROLE.ATTACKER
ROLE.ATTACKER1
ROLE.ATTACKER2
ROLE.ATTACKER3
ROLE.OFFENSECAPTAIN
ROLE.DEFENDER
ROLE.DEFENDER1
ROLE.DEFENDER2
ROLE.DEFENDER3
ROLE.DEFENSECAPTAIN
ROLE.TEAMCAPTAIN
ROLE.FIRETEAMCAPTAIN
ROLE.AMBUSHER
ROLE.INFILTRATOR
ROLE.ROAMER
ROLE.SNIPER
ROLE.ESCORT
Goals
Roles can be added to goals either in the editor or in a map script. To add a role in the editor, simply use the following commands:
/bot goal_edit /bot goal_setproperty roles DEFENDER /bot goal_finish
You can set multiple roles on a goal by using the | operator:
/bot goal_setproperty roles DEFENDER|DEFENDER1
Once completed, /bot goal_save will commit the changes to the goals file.
Setting roles in the editor is preferred since it reduces script size, but users wishing to set them in the map script can use the following helper functions:
SetGoalRole( <goal expression>, <roles>, <persistent> );
Util.SetRoleForTable( <goal table>, <roles> );
Util.SetRoleForGroup( <goal group>, <roles> );
ClearGoalRole( <goal expression>, <roles> );
Util.ClearRoleForTable( <goal table>, <roles> );
Util.ClearRoleForGroup( <goal group>, <roles> );
For example:
SetGoalRole("DEFEND_East.*", ROLE.DEFENDER); //set the defender role on goals that have a name starting with DEFEND_East
SetGoalRole("DEFUSE_wall.*", ROLE.DEFENDER2, true); //set role for dynamically created goal
SetGoalRole("MOUNTMG42_bank", { ROLE.DEFENDER2, ROLE.DEFENDER3 }); //set multiple roles to one goal
Util.SetRoleForTable({ "DEFEND_docs.*", "MOUNTMG42_docs" }, ROLE.DEFENDER1); //set role on multiple goals
Priority
Almost every map goal has property RolePriorityBonus which is added to priority if the goal has any role. That's why bots prefer goals which have role. Camp goals (attack/defend/camp/snipe) have RolePriorityBonus only 0.01. Other goals have RolePriorityBonus 0.1.
Sometimes the default RolePriorityBonus is not enough and it's necessary to use function SetGoalPriority to change priorities. For example, if some CHECKPOINT goal without role is active, all DEFEND goals are ignored and all bots go to capture checkpoint. Even if the DEFEND goals have DEFENDER role and some bots have DEFENDER role, nobody will use DEFEND goals if they have default priority.
Bots
The simplest way to assign bot roles is to set up the map script to use the Role Manager. The Role Manager will automatically assign the bots' roles based on a Map.Roles table in the map script.
A commented example of the Role Manager setup:
global Map =
{
Roles =
{
AXIS = // Team
{
AllBots = true, // each bot is considered for a role
DEFENDER = // the DEFENDER role
{
voice = "defend", // signals voice chat to randomly announce
spawnpt = 2, // users of this role will choose spawnpt 2
numbots = 4, // maximum of 4 bots
crucialClass = CLASS.ENGINEER, // class for the first bot
MinBotsForRole = 4, // only assign this role if there are already 4 bots in game
},
ATTACKER =
{
voice = "attack",
numbots = 4,
crucialClass = {CLASS.ENGINEER, CLASS.COVERTOPS}, //the first is engineer, the second is covertops
},
},
ALLIES =
{
AllBots = false, // default: every other bot
DEFENDER =
{
numbots = 3,
},
ATTACKER =
{
numbots = 4,
},
},
},
};
In this example, each team will have bots assigned to two different roles. For each role there can be a maximum number of bots set, a spawn point defined, a crucial class given, and even a voice chat for the bot to randomly use when assigned the role. All of the role flags are optional except for numbots:
numbots - the number of bots the role manager will attempt to keep assigned the role at all times crucialClass - the first bot assigned the role will switch to this class, can be a table of classes for more bots spawnpt - bots with this role will choose this spawn point voice - "attack" and "defend" are the two valid values MinBotsForRole - set the number of bots required to be in game before assigning the role.
Region triggers
If some goals are behind a door or gate which can be opened or destroyed by one team, and closed or rebuilt by the other team, then it is recommended to use region triggers. It will prevent path failed errors. It is usually possible to create one large region which covers entire area behind door (see maps mml_minastirith_fp3, nod_temple). Bots inside the region will have a role, but bots outside the region will not have the role. Goals behind door or gate will have the role only if the door is closed or gate is built.
Rocket_room =
{
Name = "Rocket_room",
TriggerOnClass = CLASS.ANYPLAYER,
OnEnter = function(ent)
{
bot = Util.IsBot(ent);
if(bot){ bot.SetRoles(ROLE.ATTACKER); }
},
OnExit = function(ent)
{
bot = Util.IsBot(ent);
if(bot){ bot.ClearRoles(ROLE.ATTACKER); }
},
},
Door_Open = function( trigger )
{
Util.ClearRoleForTable({ "PLANT_rocket", "ATTACK_rocket.*" }, ROLE.ATTACKER);
},
Door_Close = function( trigger )
{
Util.SetRoleForTable({ "PLANT_rocket", "ATTACK_rocket.*" }, ROLE.ATTACKER);
},
Sometimes it's not possible to create one large region (see map sfx_endor). Then it is necessary to create the first region just behind the gate (OnEnter function sets bot's role) and other regions in front of the gate and at every spawn (OnEnter function clears bot's role).