VR-Forces 5.0.3 Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Add Task (addTaskSim)

Table of Contents

The Add Task example adds a new kind of task - retreat - to the list of entity tasks.

The method of doing so is to add a new task and controller which will receive and implement the new DtRetreatTask. The example demonstrates:

If you want to derive a new task from DtSimTask, you have to complete the following general steps:

The first step in creating a new task type is to create a new scripted task from the meta data dialog. You will need to assign an ID to the task, and, also register for this id in the controller that will process it. As part of the scripted task you will add:

Once you have defined a new task, add a new controller to the entity to carry out the action described by the task. To do this, you must derive a new controller from DtTaskControllerComponent. (For details, please see Controller Components. The new controller must have a unique string type and must be registered with the corresponding component factory.

In your new task controller component, you must override registerTaskMsgCallbacks() to register your callback function for handling the new task. Once it is registered, your callback function will be called when a message of the new derived type is received on its radio net. In your callback (actually, in a virtual member function of your controller, called from the static callback), extract the necessary data from the task message parameters and start executing the task.

In the addTask example, the creator function for the controller (DtRetreatController) is registered with its factory in the DtInitializeVrfPlugin module of plugin.cxx:

DT_VRF_DLL_PLUGIN bool DtInitializeVrfPlugin(DtCgf* cgf)
{
//Register the creator function for the controller
return true;
}

Adding a Controller for a Task

You need to add a new controller to an entity to carry out the task contained by the DtUserTask. Since the retreat behavior is just a variation on behaviors already present in DtGroundAutoControllerComponent, we derive the new controller from DtGroundAutoControllerComponent, and register for a DtUserTask message. To do this, override registerTaskMsgCallbacks() to register an interest in incoming DtUserTask messages.

The type() Function

To uniquely identify the new controller, the type() member function must be overridden to provide a unique string name for the new component. In our example, we used the const TestRetreatControllerType and the string "retreat-controller." Default component names in VR Forces are defined in compTypes.h.

const char* DtRetreatController::type() const
{
//Defined in retreatCtlr.h
}

Registering a Callback on the User Task

This code shows how to register for the DtUserTask message on our radio net, providing a callback function for handling DtUserTask messages.

{
//Register for any task messsages required by the base class
//Specify the task type, the callback function, and user data.
//Specify the task type, the callback function, and user data.
addTaskProcessorCallback(DtRetreatTaskType, retreatTaskCallback, (void *) this);
}
void * usrData)
{
DtRetreatController * controller = (DtRetreatController *) usrData;
if (controller)
{
//Call processRetreatTask to handle the incoming retreat task message.
controller->processRetreatTask(msg);
}
}
void * usrData)
{
DtRetreatController * controller = (DtRetreatController *) usrData;
if (controller)
{
//Call processUserTask to handle the incoming user task message.
controller->processUserTask(msg);
}
}

Checking the Task Name

In the callback processing function, some additional checking is required to see if the message contained inside the DtUserTask is actually the task we are looking for. The DtUserTask message can be used for any number of different user-defined tasks, so we need to check the userTaskName() in the callback to determine if the message is really the kind we are looking for.

{
if (msg)
{
//Retrieve the task from the task message.
DtTaskMessage * tm = (DtTaskMessage *) msg;
DtScriptedTaskTask * retreatTask = dynamic_cast<DtScriptedTaskTask*>(tm->task());
if (retreatTask)
{
const DtRwInt* value = dynamic_cast<const DtRwInt*>(
retreatTask->variables().findVariableBinding("retreat"));
if (value && (*value == 1))
{
myHoldGround = true;
}
}
}
}
{
if (msg)
{
//Retrieve the task from the task message.
DtTaskMessage * tm = (DtTaskMessage *) msg;
DtUserTask * userTask = (DtUserTask *) tm->task();
//Check to see if the task is a user-defined retreat task. This
//is the string that is matched against the User Task dialog.
if(userTask->userTaskName() != "retreat")
{
taskComplete(false);
return;
}
//Extract parameters from arguments
if (userTask->arg1Text() == "hold ground")
{
myHoldGround = true;
};
}
}

The tick() Function

If you define a tick() member function for your component, it gets placed on a tick list for the entity, and is called periodically. You can use this member function to update the control values for the retreat task here. Check the ‘tasked’ state (myTasked member variable) to see if the controller is currently being tasked to determine if updates need to be made.

For examples of how the tick() member function works in controllers, please see Controller Components.

Since this example is loaded as a plugin, it can be used in conjunction with the released VR-Forces application

Simulation Model Set

In order for the new controller to be created for a given entity type, it must be added to the movement system for that entity. The addTask example comes with a SMS which is located in .sms. In this SMS, the retreat controller is added to the M1A2. In data\simulationModelSets\developer_toolkit_examples\addTask\vrfSim\systems\movement\ground-tracked-default.sysdef the system is defined as:

      (retreat 
         (component-descriptor-type "component-descriptor")
         (component-type  "retreat-controller")
         (min-tick-period  -1.000000)
         (min-tick-period-variance  -1.000000)
         (process-state-repository-name  "")
         (process-state-repository-type  "")
      )

How to Run the Example

This example demonstrates how to add a new kind of task (retreat).

Usage

In the Launcher, click the Plug-ins button to bring up the Plug-ins Selection dialog. Enable the plugin.

To view the new behavior:

  1. Start VR-Forces GUI and SIM.
  2. Load the scenario userData\scenarios\developer_toolkit_examples\addTask\addTask.scnx. The scenario references the custom SMS data\simulationModelSets\developer_toolkit_examples\addTask.sms.
  3. Play the scenario.
  4. Entities tasked to "retreat immediately" will move at full speed in the opposite direction from enemy entities.
  5. Entities tasked to "hold ground" will stay still until they determine themselves to be "under fire," at which point they will retreat at full speed in the opposite direction from enemy entities.

Classes

DtRetreatControllerThe subclass of DtGroundAutoControllerComponent implements the retreat task.

Plugin Entry Points

/*******************************************************************************
** Copyright (c) 2011 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
#include "retreatCtrl.h"
#include "vrfcgf/cgf.h"
extern "C" {
{
info.pluginName = "Add TaskSim";
info.pluginVersion = "1.00";
info.pluginCreator = "MAK Technologies";
info.pluginCreatorEmail = "sales@mak.com";
info.pluginContactWebPage = "www.mak.com";
info.pluginContactMailingAddress = "10 Fawcett Street, Suite 204, Cambridge, MA 02138 USA";
info.pluginContactPhone = "(617) 876 8085";
}
//[Registering creator methods]
DT_VRF_DLL_PLUGIN bool DtInitializeVrfPlugin(DtCgf* cgf)
{
//Register the creator function for the controller
return true;
}
//[Registering creator methods]
}

Document ID: Generated on Thu Jun 1 17:58:13 EDT 2023 from SVN revision 255404
Copyright © 2005-2021 MAK Technologies. All Rights Reserved (www.mak.com)