Fritzbot Map Scripting

From Bots-United Wiki

Jump to: navigation, search

Contents

[hide]

Intro

This article will provide some general knowledge of ET map scripting and how to utilize the tools available for supporting FritzBots.

General ET Map Scripting

An ET map script gets called every time an event (i.e. construct built) happens during the course of a game. A maps script can be found inside the maps pk3 file (mapname.script). The first event is always the map load. For that reason, every ET map script starts with a basic layout:

 game_manager
 {
     spawn
     {
 
     }
 }

'game_manager' defines a script block and 'spawn' defines a sub routine within the script block. Each of these must start with a { and end with a }.

When the round starts, it triggers the game_manager script block and because it's a spawn event it will load the spawn sub routine within the game_manager block. Other entities are handled with the same general principals:

 game_manager
 {
     spawn
     {
 
     }
 }
 
 construct_example
 {
     spawn
     {
 
     }
 
     buildstart final
     {
 
     }
 
     built final
     {
 
     }
 
     decayed final
     {
 
     }
   
     death final
     {
 
     }
   
 }

A construct script block has been added to the map script. It is used by any entity in the map with the scriptname construct_example. If an event happens to our construct, the map script is referenced, the script block is called, and the instructions within the corresponding events sub routine are executed.

These script blocks can be created for any entity with a 'scriptname' defined. The only required sub routine in a script block is for the spawn event.

For a list of map scripting commands, Chruker has a good reference page here. A less detailed reference from Splash Damage is reproduced here.

There is also a pdf ( Map Scripting 4 Newbies ) that can be helpful to understanding script file contents. Please note it was written for noob map creators not waypointers.

ET Pro Map Script Support

The ET Pro Team created a map script command called 'create' to give the ability to add entities to maps. FritzBot uses the create command as well. The create command is used in the spawn sub routine of the game_manager script block:

 game_manager
 {
     spawn
     {
 
       create
       {
 
       }
 
     }
 }

When the map is loaded, the games initial spawn event is called, then the create command is used to place the new entities in the map.

General Information about Et Pro map scripting can be found here.

Usage Examples

Fritzbot_Fake_Brushes

FritzBot_Buttons_And_Levers

Creating_a_fake_toi


ET Map Entities

All objects in the map are entities. Some entities you can see (i.e. a flag) and some entities are invisible (func_explosive). A detailed explanation of entities is outside the scope of this document, but for a general understanding you can visit this site.


Each entity must have certain properties defined. Some of the important ones for creating entities with ET Pro map scripting are:

classname -> what type of entity is it (trigger_objective_info, func_explosive, etc.)

target -> if this entity is used, what entity should it trigger

targetname -> used with target, the targetname is what target looks for

origin -> the position of the entity

mins -> minimum x,y.z properties in relation to the origin

maxs -> maximum x,y.z properties in relation to the origin

scriptname -> for use with the map script (not always defined)

spawnflags -> bitset value depending on type of entity (see below)

eflags -> Entity Flags. only worry about eflags 65536

track -> use with the "you are near" message for toi's

shortname -> the short name for this entity


spawnflags bitsets for func_constructible's

 CONSTRUCTIBLE_START_BUILT	1
 CONSTRUCTIBLE_INVULNERABLE	2
 AXIS_CONSTRUCTIBLE			4
 ALLIED_CONSTRUCTIBLE		8
 CONSTRUCTIBLE_BLOCK_PATHS_WHEN_BUILD	16
 CONSTRUCTIBLE_NO_AAS_BLOCKING			32
 CONSTRUCTIBLE_AAS_SCRIPTED				64
 

spawnflags bitsets for func_explosive's

 EXPLOSIVE_START_INVIS		1
 EXPLOSIVE_TOUCHABLE			2
 EXPLOSIVE_USESHADER			4
 EXPLOSIVE_LOWGRAV			8
 EXPLOSIVE_NO_AAS_BLOCKING	16
 EXPLOSIVE_TANK				32

In most cases, you can use an example entity from existing map scripts or using entity properties found with Hobbit's BSP reader (in the waypoint tool).

Finding Entity Properties

Finding properties of entities in a map can be done with Hobbit's Waypoint Tool. In the Utility section, there is a BSP reader. Simply extract the maps .bsp and load it with the reader. You can then browse all of the entities or search for specific entity types:

Image:Bsp_reader.gif

Setting Existing Entity Properties

The 2.60 patch for ET implemented an ET Pro command that allows for changing some of the properties of existing or map-created entities. This can be useful for FritzBot in cases where triggers for script movers are too small. The set command is used in the spawn sub routine of the entities script block:

 example_entity
 {
     spawn
     {
 
       set
       {
           
       }
 
     }
 }

An example of creating a larger move trigger for a tank would be:

 tank_trigger 
 {
 	spawn
 	{
 		set //make the move trigger larger
 		{
 			mins "-1000 -1000 -1000"
 			maxs "1000 1000 1000"
 		}
 
 	}
 
 }

These are the documented (from etpro forums) properties that can be used with the set command:

mins A point describing the location of the lower corner of the bounding box. (ent->r.mins)

maxs A point describing the location of the upper corner of the bounding box. (ent->r.maxs)

contents Contents flags - description above (ent->r.contents)

svflags Server flags (ent->r.svFlags)

clipmask Brush content types to collide with. (ent->clipmask)

count2 entity-specific (ent->count2)

eflags Entity flags (ent->s.eFlags)

pos_trType Position trajectory type (ent->s.pos.trType)

pos_trDelta Position trajectory delta Δ (ent->s.pos.trType)

apos_trType Angle trajectory type (ent->s.apos.trType)

pos_trDelta Angle trajectory delta Δ (ent->s.apos.trType)

classname_nospawn Changes the class name, but doesn't re-spawn the entity. (ent->classname)

customaxisimage Custom command map image for the Axis team

customalliesimage

customalliedimage Custom command map image for the Allied team

allowteams Teams allowed to use an entity (ent->allowteams)

target and targetname seem to work as well.

The set { } command may also work in other non-spawn sub routines (To be verified).

Barrier Removal

Some obstacles in maps are difficult for the bots to navigate around. The barrierRemove command can be used in cases where the entities to be removed do not have a scriptname:

 game_manager
 {
     spawn
     {
 
       barrierRemove
       {
           xxx //the entity number of the barrier to remove
       }
 
     }
 }

This should only be used in cases where the bots cannot destroy the barrier themselves and the entity does not have a scriptname.

More about the barrierRemove command can be found here.

In cases where the entity has a script name, the remove command can be used in the spawn event of the entities script block:

 example_entity //the scriptname
  {
 
     spawn
     {
       remove
     }
 
   }

Here's an example of Removing_a_Door.

Changing Team Spawn points

FritzBots do not have the inherent ability to choose a spawn point. On some maps, the spawning has been randomized in the code to select between default spawn points. Battery is an example of this; the Allied bots will spawn at both positions. For maps that are waypointed after the final release of FritzBot, there is still some control for bots spawn locations with map scripting. The simplest form of control is the setautospawn command.

The syntax and placement of the setautospawn command is fairly simple. There will always be an instance of it in the game_manager script block and possibly in other sections where a map event effects spawn locations (i.e. a spawn flag). Here's an example of a typical spawn setup in the game_manager block:

 game_manager
 {
   spawn
   {
       ...snip...
       setautospawn "Allied West Beach" 1
       setautospawn "West Bunker" 0
       ...snip...
     }
   }

The syntax for the command is setautospawn "<description>" <Team>

Team is defined as 1 = Allies, 0 = Axis

The description used is the description defined in the team_Wolf_objective entity. In some cases (especially custom maps) you will need to use the bsp reader to find the correct description to use:

Image:Spawn description.gif

The bots will always spawn at the setautospawn value (if enough spawns are available), so we have the ability to change their spawning by changing it in the map script. An example of this is in the Frostbite map script. When the documents are stolen, the Axis bots will spawn closer to the deliver point. If the documents are recovered, they will spawn closer to the documents:

 docs
 {
       trigger stolen 
       { 
          //wm_announce "Allies have stolen the Supply Documents!" 
          setstate docs_cm_marker invisible
 	   
 	   // modified for Fritzbot -Crapshoot
 	   setautospawn "Axis Garage" 0 
 
 	   // bots don't anticipate yet, so compensate w/ spawn time -Crapshoot
 	   wm_axis_respawntime	   5
       } 
 
       trigger returned 
       { 
          //wm_announce "Supply Documents returned!" 
          setstate docs_cm_marker default 
 
 	   // modified for Fritzbot -Crapshoot
 	   setautospawn "Axis Barracks" 0
 
 	   // set the spawn back to default -Crapshoot
 	   wm_axis_respawntime	   20
       } 
 
       trigger captured 
       { 
       } 
 }

Creating New Spawns For Testing

One of the difficult parts of waypoint testing is evaluating a part of the paths which are rarely used. This can be a path that is only available late in the game, or is far from an objective or spawn. And you want to know that the bots will use the path successfully without killing themselves, getting stuck or going around in circles. What you would like is to simply tell the bot to teleport to that point and then follow that path. In a way you can by adding a single spawn pad at that point and wait for a bot to spawn there after dying. The method is described in detail here:Test_spawns_for_Waypoint_tests

Once you can handle placing a test spawn you know what is needed to create new spawns and pads anywhere on the map to improve the gameplay (e.g. the garage spawns in fueldump). A spacing of pads on a grid of 75-160 is typical.

AI Script Basic Principals

This section will describe the basic principles of how an AI script works. If you are looking for detailed information about keywords and structure, look here.

FritzBot relies on map events to manage node connections and actions. The AI script gives instructions to be executed when certain map events occur. Action numbers are used to associate map events with AI script instructions:

 action 1 // a dynamite-able wall
 {
     node_connect 1 2 true //connect the nodes
 }

Action 1 is defined as a dynamite action in our nav file. Once the wall is dynamited, that map event triggers a call to the AI script. The AI script then looks for an action test associated with the map event. Because we have set action 1's entity number to the trigger_objective_info entity number of the wall, the association is made between the action test and the map event.

Each time a supported map event occurs for an entity, the action test for that entity is called in the AI script.

Interacting with the AI Script

Relying on default map events to control the actions of the bots limits the ability to manage the flow of the game on more complex maps. Creating entities and generating map events at certain points of the map script gives us the ability to better manage the bots on the complex maps.

There are currently two methods in which we can create map events from the map script for use in the AI Script; action_event_explode and using the construct command for a fake constructible.

Action_Event_Explode

Action_Event_Explode is a defined action type in FritzBot (#34). It is used with the entity type func_explosive. An example of its usage is the sewer gate on Fueldump:

 action 38 // sewer gate explode action
 {
 
   // connect the nodes
   node_connect 105 669 true
 
   // activate some allied actions
   activateAction_Group 7
 
   // activate alt_roam in sewer for axis
   activateAction 55
 
 }

When the tank destroys the sewer gate, the map event calls the AI script and looks for the action test above.

By creating a func_explosive in a map with etpro map scripting, we can do the same thing almost anywhere in a map script. Func_explosive's can only be used once in a map, so they are best used with actions that are not toggled on and off.

An example of a created func_explosive:

 		create
 		{
 			scriptname "position1"
 			classname "func_explosive"
 			targetname "position1"
 			origin "2029 3821 -159"
 			mins "-63 -10 0"
 			maxs "63 10 128"
                       health 1000000
 			spawnflags 1	// EXPLOSIVE_START_INVIS(1)
 			eflags 65536	// EF_FAKEBMODEL
 			svflags 1	// SVF_NOCLIENT
 		}

Now we need to trigger the map event where we want to in the map script. For this example, it's going to be triggered when a tank gets to a certain position:

 	trigger run_1
 	{
 		trigger self tracks_forward
 		trigger game_manager allies_steal_tank
 
 		accum 1 bitset 2
 		followspline 0 spln3 50 wait length 32
 		accum 1 bitreset 2
 
 		//trigger the aiscript by removing the created func_explosive
 		alertentity position1
 
 		trigger self run_continue
 
 	}

The alertentity (alertentity <targetname of func_explosive>) command is used to remove our func_explosive; which in turn calls our aiscript:

 action 1 // action_event_explode for when the tank gets to spline 1
 {
 
 //tank is at spline 1, so move the bots to the next phase
 deactivateAction_Group 1
 activateAction_Group 2
 
 }

In cases where we want to be able to call the same action test in the AI script multiple times, it's best to use a created func_constructible.

Fake Construct's

The premise of the fake construct is simple; we want to create one action test in our AI script for multiple map events. FritzBot has a limit of 16 action tests in an AI script. The problem was that some maps require more than 16 action tests to be waypointed properly. By combining action tests, the 16 action test limit can be avoided.

First we need to create the fake construct:

 game_manager
 {
 	spawn
 	{  
   		create
 		{
 			objflags "2"
 			scriptName "helper_ent_obj"
 			classname "trigger_objective_info"
 			targetname "helper_ent_obj"
 			target "helper_ent"
 			origin "-2433 4800 1543"
 			mins "-63 -10 0"
 			maxs "63 10 128"
 			health 1000000
 			//spawnflags 17	// AXIS_OBJECTIVE(1) | CUSTOMIMAGE
 			track "helper_ent"
 			shortname "helper_ent"
 			eflags 65536
 			//customaxisimage "gfx/limbo/cm_radar_maindoor"
 			//model "*16"
 		}
 
 		create
 		{
 			classname "func_constructible"
 			spawnflags "4"
 			scriptname "helper_ent"
 			targetname "helper_ent"
 			origin "-2433 4800 1543"
  			mins "-63 -10 0"
 			maxs "63 10 128"
 			eflags 65536
 			svflags 1
 			model "*24"
 		}
               // rest of game_manager block is here // 
 }

Now we need to set up the points where we want to use the action test in the map script. This method takes advantage of the construct command used in et map scripting:

 flag1
 {
 	trigger axis_capture
 	{
 		construct helper_ent //call the aiscript -crapshoot
 		trigger game_manager flag1red
 	}
 
 	trigger allied_capture
 	{
 		construct helper_ent //call the aiscript -crapshoot
 		trigger game_manager flag1blue
 	}
 	
 	trigger del
 	{
 		remove
 	}
 }
 
 defense2
 {
 	...snip...
 	built final
 	{
 		construct helper_ent //call the aiscript -crapshoot
 		setstate defense2 default
 		setstate defense2_materials invisible
 		setstate defense2_materials_clip invisible
 		setstate defense2_flag invisible
 
 		wm_announce	"the canyon rope bridge has been constructed"
 
 	}
 
 	death
 	{
 		construct helper_ent //call the aiscript -crapshoot
 		setstate defense2 invisible
 
 		setstate defense2_materials default
 		setstate defense2_materials_clip default
 		setstate defense2_flag default
 
 		wm_announce	"the canyon rope bridge has been destroyed"
 
 	}
 }

Now we have the map script set up to call our helper entity (fake construct) when anything happens to the flag and the defense2 constructible. At this point, you save the map script and open your nav file within the Fritz Editor. Find the entity number of the fake construct with the command /faketois. You should see it listed with the name helper_ent_obj (the toi for our helper). Create a construct action anywhere in the map. Give it a goal number of 999 and set the entity number.

Next, we create regular actions for each of the objectives we will use with our helper action test; i.e. set up the flag action and defense2 construction normally.

Creating the action test in the AI script is the last step:

 action 1 // our helper entity
 {
   //FLAG TESTS
   if_fda_owner_allies 2
       activateAction_Group 1
   if_fda_owner_axis 2
       deactivateAction_Group 1
 
   //DEFENSE2 TESTS
   if_construct_built_true 3
       activateAction_Group 2
   if_construct_built_false 3
       deactivateAction_Group 3
 
 }

So we have just combined two scriptable map events into one action test. Remember that each time an event happens, all tests in this action test will be run. It's very important to make sure that you combine the right action tests or you use extra checks (AND / OR) in your action test. Usage of g_action_info is recommended to test that actions are being toggled correctly in all cases. You can combine as many action tests as you want / need as long as you are within the 64 keyword limit per action test.

Some maps have no room for adding the trigger_objective_info entity required for this method. As long as there is a health and/or ammo cabinet with a TOI and scriptname, it still can be done. Simply don't add the trigger_objective_info entity from the example above (just add the func_constructible). Find the scriptname of the cabinet with Hobbit's BSP reader and change the target for it to targetname of your created func_constructible:

 // max trigger_objective_info's, so let's hijack a cabinet -crapshoot
 
 campo_hacabinet_toi //the scriptname of the cabinet we are using
 {
 
       spawn
 
       {
 
             set
 
             {
 
                   target "helper_ent"
 
             }
 
       }
 
 }

The above example was used in Venice. Be sure to set up the construct action using the TOI of the cabinet for this. Everything else is done the same as above.

Alternatives to Fake Constructs

If there are no available trivial TOIs like health and ammo cabinets and you can't add any more scripted TOIs you might still have an option. In a sense you can time share a TOI. For example if you are scripting in fake func_explosives for feedback on the position of a vehicle then you may be able to free up some of their TOIs. Say the map has a constructible like an MG tower that is in an area that loses strategic value later in the match. And there is a spline which was to be scripted with a faketoi that is triggered late in the match. Then when your vehicle reaches that spot, script in the removal of the MG tower. Now instead of adding action_event_explode actions in the nav file for that spline, you will add an action_event_expire action. So in your aiscript there will be the action test for the construct and there will be an action test for the action_event_expire that you added. As long as nothing else invokes the total removal of the tower it should work out OK. This method is used in the eagles_2way_b3 waypoints to detect when the bus reaches the hangar.

Similarly you might be able to construct and immediately make invisible a real construction that is no longer useful or available after a point in a map. For example, early on in the italyfp2 map, the market gate construction materials disappear when the jeep passes. Now the toi for this gate construction is not removed (unlike other maps like goldrush). This makes it possible to reconstruct the gate to trigger an aiscript action test for the position of the jeep after that point. The caveat is that construct-ing a real construction brings it back physically and runs its related script trigger. We deal with the latter by adding an accumulator that is used to see if the jeep has passed and if so aborts the built event script block. And for the former, to remove the physical construction we immediately set its state (setstate) to off (invisible) every time we "construct" it.

Things You Can Do With Fake Constructs

Some of the things you can do with fake constructs include

  • Helper ents combining 2 different actions inside the same action test (See the temple_final example above).
  • Helper ents to handle complex logic that can't be done easily in the aiscript or for which space is not available. For instance if the logic requires counting, or access to system variables then the aiscript can not handle it directly.
  • Provide feedback for buttons, levers or other things operated by "floor triggers". (See FritzBot_Buttons_And_Levers).
  • Provide a trigger to make all classes of bots react to an event not covered in the aiscript language. For example only the defending engineer bots respond to a "dynamite planted event". But communicate the dynamited event back and the aiscript can direct the other classes of either team to new camp or roam actions before the dynamite blows. (See Making_Bots_Respond_To_Dynamite_Planted_Events.)
  • Communicate to the aiscript when a Tram, Cable car, Elevator, Glider or other re-usable mover is in position to allow bots to get on or off (Example: The monorail car in Northpole).

Permanent link to this page

Retrieved from "Fritzbot_Map_Scripting"