//----------------------------------------------------------------------------- // // $Logfile:: /EF2/Code/DLLs/game/rotateToEntity.cpp $ // $Revision:: 12 $ // $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: // RotateToEntity Behavior Implementation. // -- Rotates the actor to face an entity. If no entity or entityType is specified, then it // will rotate the actor to face its currentEnemy // // PARAMETERS: // Optional turnspeed // Optional entityType to turn to, either "enemy" (default) or "player" // // ANIMATIONS: // Rotation Animation : Optional //-------------------------------------------------------------------------------- #include "actor.h" #include "rotateToEntity.hpp" //-------------------------------------------------------------- // // Class Declaration and Event Registration // //-------------------------------------------------------------- CLASS_DECLARATION( Behavior, RotateToEntity, NULL ) { { &EV_Behavior_Args, &RotateToEntity::SetArgs }, { NULL, NULL } }; //-------------------------------------------------------------- // Name: RotateToEntity() // Class: RotateToEntity // // Description: Constructor // // Parameters: None // // Returns: None //-------------------------------------------------------------- RotateToEntity::RotateToEntity() { _anim = ""; _turnspeed = 10.0f; _ent = NULL; _entityType = "enemy"; } //-------------------------------------------------------------- // Name: ~RotateToEntity() // Class: RotateToEntity // // Description: Destructor // // Parameters: None // // Returns: None //-------------------------------------------------------------- RotateToEntity::~RotateToEntity() { } //-------------------------------------------------------------- // // Name: SetArgs() // Class: RotateToEntity // // Description: Sets Variables based on arguments inside the event // // Parameters: Event *ev -- Event containing the string // // Returns: None // //-------------------------------------------------------------- void RotateToEntity::SetArgs( Event *ev ) { // The Parmeters we're catching now are for turn speed // and Animation ( both of which are optional ). We do not // catch an entity here, because, I don't think there's a way // to pass in an entity from the state machine. However, other // behaviors CAN set the entity, so the functionality is here // We also now take an entityType to turn to ("player" or "enemy") int parmCount= ev->NumArgs(); if ( parmCount > 0 ) // Grab the turnSpeed _turnspeed = ev->GetFloat( 1 ); if ( parmCount > 1 ) // Grab the animation _anim = ev->GetString( 2 ); if ( parmCount > 2 ) // Grab the type of entity to find _entityType = ev->GetString( 3 ); } //-------------------------------------------------------------- // // Name: Begin() // Class: RotateToEntity // // Description: Initializes the behavior // // Parameters: Actor &self -- The actor executing this behavior // // Returns: None // //-------------------------------------------------------------- void RotateToEntity::Begin( Actor &self ) { // Parameters should be set BEFORE we call begin, either through // the SetArgs() or explicitly set through accessors if ( !_ent ) { if ( _entityType == "enemy" ) { self.enemyManager->FindHighestHateEnemy(); _ent = self.enemyManager->GetCurrentEnemy(); } else { Entity *player = (Entity*)GetPlayer(0); if ( player && !(player->flags & FL_NOTARGET) ) { _ent = player; } } } // Set our Animation if Appropriate if ( _anim.length() && self.animate->HasAnim( _anim.c_str() ) ) self.SetAnim( _anim ); // Set up our turnSpeed _oldTurnSpeed = self.movementSubsystem->getTurnSpeed(); self.movementSubsystem->setTurnSpeed( _turnspeed ); } //-------------------------------------------------------------- // // Name: Evaluate() // Class: RotateToEntity // // Description: Update for this behavior -- called every server frame // // Parameters: Actor &self -- Actor executing this behavior // // Returns: BehaviorReturnCode_t // //-------------------------------------------------------------- BehaviorReturnCode_t RotateToEntity::Evaluate( Actor &self ) { Vector dir; Vector selfToEntity; float yawDiff; if ( !_ent ) { SetFailureReason( "RotateToEntity: Has no Entity to Rotate To" ); //self.SetAnim( "idle" ); return BEHAVIOR_FAILED; } // // Previously, we were just steering towards _ent->centroid. This worked, // however it also has the unfortunate side-effect of pitching the actor // if the entity it is rotating to is above it. This, of course, looks // like poo... So, for an interim fix, we're going to set our target // destination's z value to the actor's centroid z value, this, should // prevent the pitch problem // Vector entityPos; entityPos = _ent->centroid; entityPos.z = self.centroid.z; if ( self.IsEntityAlive( _ent ) ) { dir = self.movementSubsystem->getMoveDir(); self.movementSubsystem->Accelerate( self.movementSubsystem->SteerTowardsPoint( entityPos, vec_zero, dir, 1.0f) ); } // // Here, again, I replaced the _ent->centroid with the z-value modified entityPos // selfToEntity = entityPos - self.centroid; selfToEntity = selfToEntity.toAngles(); yawDiff = selfToEntity[YAW] - self.angles[YAW]; yawDiff = AngleNormalize180(yawDiff); if ( yawDiff > -1.5 && yawDiff < 1.5 ) return BEHAVIOR_SUCCESS; return BEHAVIOR_EVALUATING; } //-------------------------------------------------------------- // // Name: End() // Class: RotateToEntity // // Description: Ends this behavior -- cleans things up // // Parameters: Actor &self -- Actor executing this behavior // // Returns: None // //-------------------------------------------------------------- void RotateToEntity::End(Actor &self) { self.movementSubsystem->setTurnSpeed( _oldTurnSpeed ); }