VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Retreat Controller

The DtRetreatController is a new class that implements the DtRetreatTask to cause an entity to retreat under user defined circumstances


Header file:

/*******************************************************************************
** Copyright (c) 2000 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
//
//class DtRetreatController
//
//The retreating behavior of this controller was not intended to be
//intelligent; it is meant to be an example of a controller invoked by a
//DtUserTask. Because the currentTarget is used to determine which way to
//flee, the behavior is best demonstrated tank vs. tank. Vehicles which do not
//target other vehicles, such as utility vehicles, will simply flee towards
//their current heading. Tanks will not flee from entities which they do
//not target, such as helicopters.
//
//The retreat DtUserTask takes one argument from the "Argument 1" box
//of the DtUserTask dialog. If it is set to "hold ground", entities set to
//retreat will not start moving untill their underFire flag is set.
//
//To enable an entity to retreat, there must be an entry for
//"retreat-controller" in its controller list in the object parameters
//database. The following sample can be used:
//
// (controllers
// ...
// (retreat
// (component-descriptor-type "component-descriptor")
// (component-type "retreat-controller")
// )
// ...
// )
//
// (connections
// ....
// (connect retreat:automotive-control powertrain:automotive-control)
// ...
// )
//
//String which uniquely identifies this controller
const char TestRetreatControllerType[] = "retreat-controller";
{
public:
//constructor
DtSimulationServices * simManager, DtComponentDescriptor* desc = NULL,
DtReaderWriterRegistry * parentRegistry = 0);
//destructor
//copy constructor
//assignment operator
//This returns the string TestRetreatControllerType (defined above),
//used to uniquely identify the type of component.
virtual const char* type() const;
//Register a callback for notification of DtUserTask tasks.
virtual void registerTaskMsgCallbacks();
//Callback function (registered in registerTaskMsgCallbacks()) for
//DtRetreat task messages. Calls processRetreatTask() to actually handle
//the task.
static void retreatTaskCallback(DtSimMessage * msg, void * usr);
//Callback function (registered in registerTaskMsgCallbacks()) for
//DtUserTask messages. Calls processUserTask() to actually handle
//the task.
static void userTaskCallback(DtSimMessage * msg, void * usr);
//Called by retreatTaskCallback() when a new DtRetreatTask message is
//received.
virtual void processRetreatTask(DtSimMessage * msg);
//Called by userTaskCallback() when a new DtRetreatTask message is
//received.
virtual void processUserTask(DtSimMessage * msg);
//Update control values
virtual void tick();
//This is called by the factory
static DtSimComponent* creator(const DtString & name, DtLocalObject* owner,
DtReaderWriterRegistry * parentRegistry);
//Determine which way to flee based on the current target
virtual double getHeading();
//Returns the amount of fuel left. If no fuel left, can no longer retreat
virtual double fuelLeft() const;
protected:
//determined by DtUserTask arg1, see above
};

Implementation:

/*******************************************************************************
** Copyright (c) 2021 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
#include "retreatCtrl.h"
const DtSimTaskMessageType DtRetreatTaskType("retreat-task");
//constructor
DtReaderWriterRegistry * parentRegistry) :
DtGroundAutoControllerComponent(name, owner, simManager, desc,
parentRegistry)
{
myHoldGround = false;
}
//destructor
{
}
//[The type function]
const char* DtRetreatController::type() const
{
//Defined in retreatCtlr.h
}
//[The type function]
//[Registering a callback]
{
//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);
}
}
//[Registering a callback]
//[Checking the task name]
{
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;
};
}
}
//[Checking the task name]
{
const DtSimResource *resource = resourceManager().lookupResource("fuel");
if (resource)
{
DtString resourceType = resource->type();
if (resourceType == DtRealResourceType)
{
const DtRealResource * realResource = (const DtRealResource *)resource;
return realResource->amount();
}
else if (resourceType == DtIntegerResourceType)
{
const DtIntegerResource * intResource = (const DtIntegerResource *)resource;
return (double) intResource->amount();
}
}
//have plenty...
return 1.0E8;
}
//calculate new control values
{
DtPROFILE("DtRetreatController::tick");
if (tasked() && (dT() > 0.0) &&
{
double targetHeading = getHeading();
double localHeading = entity()->heading();
mySteeringPort->setValue(calculateSteering(localHeading, targetHeading));
//if tasked to hold ground, don't start running until under fire
if ((!myHoldGround || entity()->nextFrameUnderFire()) && fuelLeft())
{
}
else
{
}
}
}
DtReaderWriterRegistry* parentRegistry)
{
return
new DtRetreatController(name, owner, simManager, desc, parentRegistry);
}
{
DtVector myPos;
DtVector targetPos;
DtVector vectorFromEntityToTarget;
currentTarget());
if (!target.isValid())
{
}
else
{
myPos = entity()->localPosition();
targetPos = target->localPosition();
DtVecSub(targetPos, myPos, vectorFromEntityToTarget);
myCurrentHeading = atan2(vectorFromEntityToTarget[0],
vectorFromEntityToTarget[1]) + 3.14;
}
}

Document ID: Generated on Wed Mar 27 22:49:11 EDT 2024 from SVN revision 264633
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)