Page 1 of 1

Creating new tasks?

Posted: Wed May 14, 2003 3:14 pm
by Bjarne BZR
I want to make the bots handle an objective that is not planting a bomb.
It is basically "Get to a trigger and trigger it" ( yes, it's the documents again :oops:)...

Sounds a lot less complex than planting a bomb, so now I ask: Can I add ne task types to the bots, and if so: What is the interface to do so ( how do I make the BOT's actually use the new tasks )?

Posted: Wed May 14, 2003 4:08 pm
by jv_map
Yes you can make new tasks. I'll try to give a comprehensable explanation of the task system (I'm not very good at that :oops: ).

All tasks are in the global/jv_bots folder and are prefixed 'task_'. The layout of these scripts is the following:

setup:
end

getpriority:
end (local.priority::local.parm1::local.parm2.....)

evaluate local.parms local.onlyeval:
// necessary since version 1.1
end local.priority

action:
end

These four threads are needed for any task. They have specific functions which I'll explain below.

To make the bots 'use' our new task, you have to 'install' it. This is done in the following manner (you can add this anywhere in your map script):

waitthead global/jv_bots/jv_mp_ai.scr::addtask [taskname] [basepriority]

Although I used [ and ] these parameters are compulsory. [taskname] defines the name of the script file associated with this task, namely 'task_[taskname].scr'. [basepriority] is a priority modifier applied to all output priorities (discussed later). The basepriorities for the existing tasks are (to give you an idea):

follow 1.5
health 10.0 // pickup medkits
attackbomb 1.0
defendbomb 1.0
sniper 0.1
camp 0.1
machinegun 0.5

Since the final priority value is calculated by multiplying the basepriority value with the output priority value, it's not a good idea to use negative priorities for invalid tasks (a double negative value would result in a positive value).

Now I'll try to explain the functions of the threads in the task scripts. The setup: thread is run immediately after you issued the 'addtask' command. It's not run again after a bot restart. The setup thread is the place to start any handler threads that your task may require. It's also generally the place where the 'route tracer' is added, but I'll just skip explaining that one for now :oops: (will do later).

The getpriority: thread is probably the most complicated thread. It's called from the taskhandler for 'free' bots (these bots may choose their own task). The function of the thread is to return the best parameters for the task for this particular bot (self) at this very moment. Moreover a priority value should be returned, which defines the likeliness of the bot to switch to this task.

Let's take a closer look ;):

Code: Select all

// self is the 'free' bot
// just a simple example
// image the bot has to go to the docs
getpriority:
        // if there are multiple docs, find the nearest
 	local.greatest = 0
	local.bestdoc = NULL
	for(local.i = 1; local.i <= $doc.size; local.i++)
	{
		local.doc = $doc[local.i]
		local.dist = vector_length(local.doc.origin - self.origin)
		// always greater than 0
		local.inv_dist = 1.0 / local.dist
		// always greater than 0 again :)
		local.inv_dist > local.greatest)
		{
			local.greatest = local.inv_dist
			local.bestdoc = local.doc
		}
	}
	// likeliness to perform this task only depends on range
	local.priority = local.greatest // the nearer the higher
	local.parm = local.bestdoc // set the parameters (can be any number of parms)
	// need to return this in an array
	local.array[1] = local.priority // compulsory
	local.array[2] = local.parm // optional
	local.array[3] = .... // if you need more parms
	// just return this array, the bot script will take it from here :D
end local.array
This array is returned to the bot script for evaluation. If the priority value is high enough, the bot will switch to this task, entering the action: thread. When entering the action: thread, self.task is set to [taskname] and self.parm[1] is set to the second entry of the array returned by the getpriority thread, self.parm[2] to the third and so on (sorry I know it's confusing :?)

Code: Select all

// actual action code goes here
action:
	// always cast self.parm to local variables, since they may change
	// if the bot switches tasks
	
	local.docs = self.parm[1]
	
	// just run to the docs
	// this thread automatically exits if the task or parms have changed
	self waitthread level.jvbot_main_script::action_go_to_routed local.docs
end
Now there's only one thing left to explain, which is the (new) evaluate thread. This thread is only called from the bot script when a bot is currently executing the task. The evaluate thread is used to decide if the bot should continue doing this task. Usually you can just move some code from the getpriority thread into the evaluate thread to make this work.

Code: Select all

evaluate local.parm local.onlyeval:
	local.doc = local.parm[1]
	local.dist = vector_length(local.doc.origin - self.origin)
	local.inv_dist = 1.0 / local.dist
end local.inv_dist
local.parm contains the entire self.parm array. local.onlyeval is set to 1 if the thread is called from the bot script (this is an optional variable).

Well that's it more or less. I hope I didn't deliver any headaches :?

Posted: Wed May 14, 2003 5:25 pm
by Bjarne BZR
I had a feeling you made your bots widely configurable. Cool work, as always!

If I can get past the "MOHAA faliure" I'll try to make a new tast for your bots :D