ef2gamesource/dlls/game/patrol.cpp

798 lines
18 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /EF2/Code/DLLs/game/patrol.cpp $
// $Revision:: 13 $
// $Author:: Singlis $
// $Date:: 9/26/03 2:36p $
//
// Copyright (C) 2002 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
//
// DESCRIPTION:
// CloseInOnEnemy Implementation
//
// PARAMETERS:
//
//
// ANIMATIONS:
//
//--------------------------------------------------------------------------------
#include "actor.h"
#include "patrol.hpp"
//--------------------------------------------------------------
//
// Class Declaration and Event Registration
//
//--------------------------------------------------------------
CLASS_DECLARATION( Behavior, Patrol, NULL )
{
{ &EV_Behavior_Args, &Patrol::SetArgs },
{ &EV_Behavior_AnimDone, &Patrol::AnimDone },
{ NULL, NULL }
};
//--------------------------------------------------------------
// Name: Patrol()
// Class: Patrol
//
// Description: Constructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
Patrol::Patrol()
{
_anim = "walk";
}
//--------------------------------------------------------------
// Name: ~Patrol()
// Class: Patrol
//
// Description: Destructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
Patrol::~Patrol()
{
}
//--------------------------------------------------------------
// Name: SetArgs()
// Class: Patrol
//
// Description: Sets the arguments of the behavior
//
// Parameters: Event *ev
//
// Returns: None
//--------------------------------------------------------------
void Patrol::SetArgs ( Event *ev)
{
_anim = ev->GetString( 1 );
}
//--------------------------------------------------------------
// Name: AnimDone()
// Class: Patrol
//
// Description: Handles an animation completion
//
// Parameters: Event *ev -- Event holding the completion notification
//
// Returns: None
//--------------------------------------------------------------
void Patrol::AnimDone( Event * )
{
if ( _state == PATROL_WAITING_AT_NODE_FOR_ANIM )
{
_state = PATROL_FIND_NEXT_PATROL_NODE;
}
}
//--------------------------------------------------------------
// Name: Begin()
// Class: Patrol
//
// Description: Begins the Behavior
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::Begin( Actor &self )
{
_init( self );
}
//--------------------------------------------------------------
// Name: _init()
// Class: Patrol
//
// Description: Initializes memeber variables
//
// Parameters: Actor &self -- Actor executing this behavior
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_init( Actor &self )
{
_nextMoveAttempt = 0.0f;
_waitTime = 0.0f;
_moveFailures = 0;
//Setup Torso Anim if appropriate
_torsoAnim = self.combatSubsystem->GetAnimForMyWeapon( "Idle" );
if ( _torsoAnim.length() )
{
self.SetAnim( _torsoAnim, NULL , torso );
}
_state = PATROL_FIND_CLOSEST_PATROL_NODE;
if ( !_setupFindClosestPatrolNode( self ) )
_setupFindClosestPatrolNodeFailed( self );
}
//--------------------------------------------------------------
// Name: Evaluate()
// Class: Patrol
//
// Description: Returns True Or False, and is run every frame
// that the behavior
//
// Parameters: Actor &self
//
// Returns: True or False
//--------------------------------------------------------------
BehaviorReturnCode_t Patrol::Evaluate ( Actor &self )
{
switch ( _state )
{
case PATROL_FIND_CLOSEST_PATROL_NODE:
_findClosestPatrolNode( self );
break;
case PATROL_MOVING_TO_PATROL_NODE:
_moveToPatrolNode( self );
break;
case PATROL_AT_PATROL_NODE:
_atPatrolNode( self );
break;
case PATROL_WAITING_AT_NODE:
_waitAtPatrolNode( self );
break;
case PATROL_WAITING_AT_NODE_FOR_ANIM:
_waitAtPatrolNodeForAnim( self );
break;
case PATROL_FIND_NEXT_PATROL_NODE:
_findNextPatrolNode( self );
break;
case PATROL_HOLD:
_hold( self );
break;
case PATROL_FAILED:
return BEHAVIOR_FAILED;
break;
case PATROL_SUCCESSFUL:
return BEHAVIOR_SUCCESS;
break;
}
return BEHAVIOR_EVALUATING;
}
//--------------------------------------------------------------
// Name: End()
// Class: Patrol
//
// Description: Ends the Behavior
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::End ( Actor & )
{
}
//--------------------------------------------------------------
// Name: _setupFindClosestPatrolNode()
// Class: Patrol
//
// Description: Sets up the behavior for the Find Node State
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupFindClosestPatrolNode( Actor & )
{
_node = NULL;
return true;
}
//--------------------------------------------------------------
// Name: _setupFindClosestPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupFindClosestPatrolNode()
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupFindClosestPatrolNodeFailed( Actor & )
{
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _findClosestPatrolNode
// Class: Patrol
//
// Description: Finds the closest the Patrol Node, and changes
// the behavior's state
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_findClosestPatrolNode( Actor &self )
{
if ( _node )
{
_state = PATROL_MOVING_TO_PATROL_NODE;
if (!_setupMovingToPatrolNode( self ) )
_setupMovingToPatrolNodeFailed( self );
return;
}
_node = HelperNode::FindClosestHelperNode( self , NODETYPE_PATROL , 512.0f, 0 );
if ( !_node )
{
_findClosestPatrolNodeFailed(self);
return;
}
//Now Let's check if we're already "on the path" to help prevent backtracking
str nextNodeTargetName;
nextNodeTargetName = _node->target;
// See if we hit the end of our path
if ( nextNodeTargetName.length() )
{
HelperNode* testNode;
testNode = HelperNode::GetTargetedHelperNode( nextNodeTargetName );
if ( testNode )
{
Vector selfToTestNode = testNode->origin - self.origin;
float selfToTestNodeDist = selfToTestNode.length();
Vector currentNodeToTestNode = testNode->origin - _node->origin;
float currentNodeToTestNodeDist = currentNodeToTestNode.length();
//If we're closer to the next node than the distance between the "closest" node and the next node then
//we'll use the next node instead to prevent backtracking
if ( currentNodeToTestNodeDist > selfToTestNodeDist )
_node = testNode;
}
}
_state = PATROL_MOVING_TO_PATROL_NODE;
if (!_setupMovingToPatrolNode( self ) )
_setupMovingToPatrolNodeFailed( self );
}
//--------------------------------------------------------------
// Name: _findClosestPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _findClosestPatrolNode
//
// Parameters:
//
// Returns:
//--------------------------------------------------------------
void Patrol::_findClosestPatrolNodeFailed( Actor & )
{
SetFailureReason( "Unable to find a patrol node within 512.0 units" );
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _setupMovingToPatrolNode()
// Class: Patrol
//
// Description: Sets up behavior for the Moving To Node State
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupMovingToPatrolNode( Actor &self )
{
//If we have a _lastNode let's run our exit thread
if ( _lastNode )
_lastNode->RunExitThread();
//Setup Torso Anim if appropriate
_torsoAnim = self.combatSubsystem->GetAnimForMyWeapon( "Idle" );
if ( _torsoAnim.length() )
{
self.SetAnim( _torsoAnim, NULL , torso );
}
_gotoHelperNode.SetDistance( 34.0f );
_gotoHelperNode.SetAnim( _anim );
_gotoHelperNode.SetPoint( _node->origin );
_gotoHelperNode.Begin( self );
return true;
}
//--------------------------------------------------------------
// Name: _setupMovingToPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupMovingToPatrolNode()
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupMovingToPatrolNodeFailed( Actor & )
{
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _moveToPatrolNode()
// Class: Patrol
//
// Description: Evaluates the GotoEntity Component Behavior
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_moveToPatrolNode( Actor &self )
{
BehaviorReturnCode_t moveResult;
moveResult = _gotoHelperNode.Evaluate( self );
if ( moveResult == BEHAVIOR_SUCCESS )
{
_nextMoveAttempt = 0.0f;
_moveFailures = 0;
_state = PATROL_AT_PATROL_NODE;
if ( !_setupAtPatrolNode( self ) )
_setupAtPatrolNodeFailed( self );
}
else if ( moveResult == BEHAVIOR_FAILED )
{
_moveToPatrolNodeFailed( self );
}
/*
else if ( moveResult == BEHAVIOR_EVALUATING )
{
//BULLET PROOFING--------------------------------------
//Stupid Check to see if anim got stomped somewhere
//BULLET PROOFING--------------------------------------
str currentAnim = self.animate->GetName();
if ( currentAnim != _anim )
self.SetAnim( _anim, NULL , legs );
}*/
}
//--------------------------------------------------------------
// Name: _moveToPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _moveToPatrolNode
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_moveToPatrolNodeFailed( Actor & )
{
_moveFailures++;
//if ( _moveFailures > 10 )
// {
_state = PATROL_FAILED;
// }
//else
// {
// _state = PATROL_HOLD;
// if ( !_setupHold( self ) )
// _setupHoldFailed( self );
// }
}
//--------------------------------------------------------------
// Name: _setupAtPatrolNode()
// Class: Patrol
//
// Description: Sets behavior up to enter the At Node state
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupAtPatrolNode( Actor & )
{
//self.SetAnim( "walk" );
return true;
}
//--------------------------------------------------------------
// Name: _setupAtPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupAtPatrolNodeFailed
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupAtPatrolNodeFailed( Actor & )
{
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _AtPatrolNode()
// Class: Patrol
//
// Description: Main Function for the At Node State
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_atPatrolNode( Actor &self )
{
str nodeAnim;
nodeAnim = _node->GetAnim();
// Run this thread, if we have one
_node->RunEntryThread();
// First, See if we have a wait time or wait random time
_waitTime = _node->GetWaitTime() + level.time;
if ( _node->isWaitRandom() )
_waitTime = level.time + G_Random( _waitTime ) + 1;
if ( _waitTime > level.time )
{
if ( nodeAnim.length() && self.animate->HasAnim( nodeAnim.c_str() ) )
{
self.ClearLegAnim();
self.ClearTorsoAnim();
self.SetAnim( nodeAnim );
}
else
self.SetAnim( "idle" );
_state = PATROL_WAITING_AT_NODE;
if ( !_setupWaitingAtPatrolNode( self ) )
_setupWaitingAtPatrolNodeFailed( self );
return;
}
// We didn't have a wait time, let's see if we're supposed to wait for an animation
if ( _node->isWaitForAnim() && nodeAnim.length() )
{
self.SetAnim( nodeAnim , EV_Actor_NotifyBehavior);
_state = PATROL_WAITING_AT_NODE_FOR_ANIM;
if ( !_setupWaitingAtPatrolNodeForAnim( self ) )
_setupWaitingAtPatrolNodeForAnimFailed( self );
return;
}
// We're not waiting here, so let's just get the next node
_state = PATROL_FIND_NEXT_PATROL_NODE;
if ( !_setupFindNextPatrolNode( self ) )
_setupFindNextPatrolNodeFailed( self );
}
//--------------------------------------------------------------
// Name: _setupWaitingAtPatrolNode()
// Class: Patrol
//
// Description: Sets Behavior up for Wait State
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupWaitingAtPatrolNode( Actor & )
{
return true;
}
//--------------------------------------------------------------
// Name: _setupWaitingAtPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupWaitingAtPatrol
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupWaitingAtPatrolNodeFailed(Actor & )
{
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _waitAtPatrolNode
// Class: Patrol
//
// Description: Waits at the Patrol Node
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_waitAtPatrolNode(Actor &self )
{
if ( level.time > _waitTime )
{
_state = PATROL_FIND_NEXT_PATROL_NODE;
if ( !_setupFindNextPatrolNode( self ) )
_setupFindNextPatrolNodeFailed( self );
}
}
//--------------------------------------------------------------
// Name: _setupWaitingAtPatrolNodeForAnim()
// Class: Patrol
//
// Description: Sets up behavior to wait for anim
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupWaitingAtPatrolNodeForAnim( Actor &self )
{
self.setAngles(_node->angles);
return true;
}
//--------------------------------------------------------------
// Name: _setupWaitingAtPatrolNodeForAnimFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupWaitingAtPatrolNode()
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupWaitingAtPatrolNodeForAnimFailed( Actor & )
{
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _waitAtPatrolNodeForAnim()
// Class: Patrol
//
// Description: Nothing now, here in case we need it
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_waitAtPatrolNodeForAnim( Actor & )
{
// Transition is handled by the AnimDone Event
}
//--------------------------------------------------------------
// Name: _setupFindNextPatrolNode()
// Class: Patrol
//
// Description: Sets behavior up to find the next patrol node
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupFindNextPatrolNode( Actor & )
{
return true;
}
//--------------------------------------------------------------
// Name: _setupFindNextPatrolNodeFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupFindNextPatrolNode()
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupFindNextPatrolNodeFailed( Actor & )
{
SetFailureReason( "Unable to find the next Node in the patrol path" );
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _findNextPatrolNode()
// Class: Patrol
//
// Description: Finds next patrol node
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_findNextPatrolNode( Actor &self )
{
str nextNodeTargetName;
nextNodeTargetName = _node->target;
// See if we hit the end of our path
if ( !nextNodeTargetName.length() )
{
_state = PATROL_SUCCESSFUL;
return;
}
_lastNode = _node;
_node = HelperNode::GetTargetedHelperNode( nextNodeTargetName );
if ( !_node )
{
_state = PATROL_FAILED;
return;
}
_state = PATROL_MOVING_TO_PATROL_NODE;
if ( !_setupMovingToPatrolNode( self ) )
_setupMovingToPatrolNodeFailed( self );
}
//--------------------------------------------------------------
// Name: _setupHold()
// Class: Patrol
//
// Description: Sets Behavior up to hold
//
// Parameters: Actor &self
//
// Returns: true or false
//--------------------------------------------------------------
bool Patrol::_setupHold( Actor & )
{
_nextMoveAttempt = level.time + 0.5f + G_Random();
return true;
}
//--------------------------------------------------------------
// Name: _setupHoldFailed()
// Class: Patrol
//
// Description: Failure Handler for _setupHold()
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_setupHoldFailed( Actor & )
{
_state = PATROL_FAILED;
}
//--------------------------------------------------------------
// Name: _hold()
// Class: Patrol
//
// Description: Holds the Actor in place for a brief time
//
// Parameters: Actor &self
//
// Returns: None
//--------------------------------------------------------------
void Patrol::_hold( Actor &self )
{
if ( level.time > _nextMoveAttempt )
{
_state = PATROL_MOVING_TO_PATROL_NODE;
if ( !_setupMovingToPatrolNode( self ) )
_setupMovingToPatrolNodeFailed( self );
}
}