This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Combat/vehicledriver.cpp

979 lines
No EOL
25 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : LevelEdit *
* *
* $Archive:: /Commando/Code/Combat/vehicledriver.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 2/22/02 7:13p $*
* *
* $Revision:: 43 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "vehicledriver.h"
#include "smartgameobj.h"
#include "matrix3d.h"
#include "movephys.h"
#include "vehiclephys.h"
#include "path.h"
#include "pscene.h"
#include "vehicle.h"
#include "soldier.h"
#include "combat.h"
#include "chunkio.h"
#include <windows.h>
#include "vehiclecurve.h"
////////////////////////////////////////////////////////////////
// Save/Load constants
////////////////////////////////////////////////////////////////
enum
{
CHUNKID_VARIABLES = 0x11040454,
};
enum
{
VARID_CURRENT_DEST = 1,
VARID_FINAL_DEST,
VARID_MAX_SPEED,
VARID_SPEED_FACTOR,
VARID_LAST_POS,
VARID_BAD_PROGRESS_COUNT,
VARID_IS_BACKING_UP,
VARID_IS_BACKUP_LOCKED,
VARID_TURN_OFF_ENGINE,
VARID_PATH_PTR,
VARID_GAME_OBJ_PTR,
VARID_ARRIVED_DIST
};
////////////////////////////////////////////////////////////////
//
// VehicleDriverClass
//
////////////////////////////////////////////////////////////////
VehicleDriverClass::VehicleDriverClass (void)
: m_CurrentDest (0, 0, 0),
m_FinalDest (0, 0, 0),
m_CurrentPath (NULL),
m_GameObj (NULL),
m_IsBackingUp (false),
m_MaxSpeed (20.0F),
m_SpeedFactor (1.0F),
m_LastPos (0, 0, 0),
m_BadProgressCount (0),
m_IsBackupLocked (false),
m_TurnOffEngineWhenDone (false),
m_ArrivedDist (1.0F),
m_BrakingDist (0),
m_LastFrameExpectedVelocity (0)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ~VehicleDriverClass
//
////////////////////////////////////////////////////////////////
VehicleDriverClass::~VehicleDriverClass (void)
{
Free();
}
////////////////////////////////////////////////////////////////
//
// Get_Velocity
//
// Returns the object-space velocity vector
//
////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Get_Velocity (const Matrix3D &tm, Vector3 &vel_vector)
{
//
// Get a pointer to the physics object for this vehicle
//
MoveablePhysClass *phys_obj = m_GameObj->Peek_Physical_Object()->As_MoveablePhysClass ();
if (phys_obj != NULL) {
//
// Get the world-space velocity vector for this vehicle and transform
// it into object space.
//
Vector3 vel_vector_world;
phys_obj->Get_Velocity (&vel_vector_world);
Matrix3D::Inverse_Rotate_Vector (tm, vel_vector_world, &vel_vector);
} else {
vel_vector.Set (0, 0, 0);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Initialize
//
////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Initialize (SmartGameObj *game_obj, PathClass *path)
{
m_GameObj = game_obj;
//
// If the game object is driving a vehicle, then get the vehicle instead
//
SoldierGameObj *soldier_game_obj = game_obj->As_SoldierGameObj ();
if (soldier_game_obj != NULL) {
VehicleGameObj *vehicle_game_obj = soldier_game_obj->Get_Profile_Vehicle ();
if (vehicle_game_obj != NULL) {
m_GameObj = vehicle_game_obj;
}
}
m_CurrentPath = path;
m_FinalDest = path->Get_Dest_Pos ();
m_CurrentDest = path->Get_Dest_Pos ();
m_BrakingDist = 0;
m_LastFrameExpectedVelocity = 0;
//
// Determine if this game object is a vehicle or not (it better be...)
//
VehicleGameObj *vehicle = m_GameObj->As_VehicleGameObj ();
if (vehicle != NULL) {
//
// Start this vehicle's engine's running
//
if (vehicle->Is_Engine_Enabled () == false) {
vehicle->Enable_Engine (true);
m_TurnOffEngineWhenDone = true;
} else {
m_TurnOffEngineWhenDone = false;
}
}
return ;
}
///////////////////////////////////////////////////////////////////////////
//
// Find_Tangent_Angle
//
///////////////////////////////////////////////////////////////////////////
static float
Find_Tangent_Angle
(
const Vector2 & center,
float radius,
const Vector2 & point,
bool clockwise
)
{
float angle = 0;
//
// Calculate the distance from the point to the center of the circle
//
float delta_x = point.X - center.X;
float delta_y = point.Y - center.Y;
float dist = ::sqrt (delta_x * delta_x + delta_y * delta_y);
if (dist == 0) {
dist = 0.0001F;
}
//
// Determine the offset angle (from the line between the point and center)
// where the 2 tangent points lie.
//
float angle_offset = WWMath::Fast_Acos (radius / dist);
float base_angle = WWMath::Atan2 (delta_x, -delta_y);
base_angle = WWMath::Wrap (base_angle, 0, WWMATH_PI * 2);
//
// Return which ever tangent point we would come across first, depending
// on our orientation
//
if (clockwise) {
angle = (WWMATH_PI * 3) - (base_angle + angle_offset);
} else {
angle = base_angle - angle_offset;
}
angle = WWMath::Wrap (angle, 0, WWMATH_PI * 2);
if (dist < radius) {
angle = DEG_TO_RADF (360.0F);
}
return angle;
}
////////////////////////////////////////////////////////////////
//
// Drive
//
////////////////////////////////////////////////////////////////
bool
VehicleDriverClass::Drive (void)
{
bool retval = false;
//
// Get the turn radius of the current vehicle
//
PathObjectClass path_obj;
m_CurrentPath->Get_Path_Object (path_obj);
float turn_radius = path_obj.Get_Turn_Radius ();
//
// Drive either using wheeled vehicle logic or tracked vehicle logic
//
if (turn_radius != 0) {
retval = Drive_Wheeled ();
} else {
retval = Drive_Tracked ();
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Drive_Wheeled
//
////////////////////////////////////////////////////////////////
bool
VehicleDriverClass::Drive_Wheeled (void)
{
//
// Convert the destinations from world to object space
//
Matrix3D tm = m_GameObj->Get_Transform ();
Vector3 pos = tm.Get_Translation ();
float facing = tm.Get_Z_Rotation ();
tm.Make_Identity ();
tm.Set_Translation (pos);
tm.Rotate_Z (facing);
/*PhysClass *phys_obj = m_GameObj->Peek_Physical_Object ();
RenderObjClass *model = phys_obj->Peek_Model ();
AABoxClass bounding_box;
bounding_box = model->Get_Bounding_Box ();
Vector3 offset;
Matrix3D::Rotate_Vector (tm, Vector3 (bounding_box.Extent.X, 0, 0), &offset);
tm.Set_Translation (tm.Get_Translation () - offset);
PhysicsSceneClass::Get_Instance ()->Add_Debug_AABox (AABoxClass (tm.Get_Translation (), Vector3 (0.5F,0.5F,0.5F)), Vector3 (1, 0, 1));*/
//
// Make sure we have the final destination point
//
if (m_CurrentPath != NULL) {
m_FinalDest = m_CurrentPath->Get_Dest_Pos ();
}
float max_speed = m_MaxSpeed * m_SpeedFactor;
float curve_modifier = 1.0F;
//
// Modify some of our parameters if we are force moving backwards
//
if (m_IsBackupLocked) {
tm.Rotate_Z (DEG_TO_RADF (180));
//curve_modifier = 2.0F;
}
//
// Convert the current and final destination points into object space
//
Vector3 final_dest;
Vector3 current_dest;
Matrix3D::Inverse_Transform_Vector (tm, m_FinalDest, &final_dest);
Matrix3D::Inverse_Transform_Vector (tm, m_CurrentDest, &current_dest);
final_dest.Z = 0;
current_dest.Z = 0;
//
// Get the vehicle's current position
//
Vector3 curr_pos;
m_GameObj->Get_Position (&curr_pos);
//
// Calculate the distance to the destination
//
float dist_on_path = m_CurrentPath->Get_Remaining_Path_Length ();
float dist_to_goal = (current_dest.Length () + dist_on_path);
//
// Are we there yet?
//
bool is_complete = (dist_to_goal <= m_ArrivedDist);
if (is_complete) {
dist_to_goal = 0;
}
if (is_complete == false) {
//
// Get the sharpness of the curve from the path object
//
Vector3 curve_pos (0, 0, 0);
float curve_sharpness = m_CurrentPath->Get_Curve_Sharpness (&curve_pos);
//
// Take into account the distance to the curve
//
float curve_dist = (curve_pos - tm.Get_Translation ()).Length ();
curve_sharpness *= 1.0F - WWMath::Clamp (curve_dist / max_speed, 0, 1.0F);
curve_sharpness *= curve_modifier;
//
// Calculate what the angle is between us and the next destination point
//
float turn_angle = WWMath::Atan2 (current_dest.Y, current_dest.X);
turn_angle = WWMath::Wrap (turn_angle, DEG_TO_RADF(-180), DEG_TO_RADF(180));
//
// Calculate how sharp we need to turn based on the sharpness of the curve
//
float max_angle = DEG_TO_RADF (10.0F) + (1.0F - curve_sharpness) * DEG_TO_RADF (30.0F);
float turn_accel = turn_angle / max_angle;
/*PathObjectClass path_obj;
m_CurrentPath->Get_Path_Object (path_obj);
float turn_radius = path_obj.Get_Turn_Radius ();*/
/*if ((turn_radius * turn_radius) > current_dest.Length2 () && WWMath::Fabs (turn_angle) > DEG_TO_RADF (60.0F)) {
m_IsBackingUp = true;
}*/
//
// Calculate our (current) normalized speed
//
Vector3 vel_vector;
Get_Velocity (tm, vel_vector);
float speed = vel_vector.X;
float norm_speed = speed / max_speed;
//
// Calculate how fast we should accelerate
//
float expected_velocity = 1.0F - (0.3F * curve_sharpness);
//
// Take into account the braking speed as we approach the goal
//
float brake_velocity = Calculate_Brake (dist_to_goal, expected_velocity, speed, max_speed);
expected_velocity = min (brake_velocity, expected_velocity);
//
// Calculate how far off our last velocity request was
//
float vel_factor = 1.0F;
if (norm_speed != 0) {
vel_factor = m_LastFrameExpectedVelocity / WWMath::Fabs (norm_speed);
}
//
// Try to account for our last velocity request error
//
m_LastFrameExpectedVelocity = WWMath::Fabs (expected_velocity);
float forward_accel = (expected_velocity - norm_speed) * vel_factor;
/*StringClass message;
message.Format ("forward accel = %f\n", forward_accel);
WWDEBUG_SAY (((const char *)message));*/
//
// Invert everything if we are locked in driving backwards mode
//
if (m_IsBackupLocked) {
forward_accel = -forward_accel;
turn_accel = -turn_accel;
}
//
// Handle the case where we are backing up
//
/*if (m_IsBackingUp) {
//
// Switch out of backup mode if we have a pretty good facing on the
// destination or we got stuck while backing up.
//
if (WWMath::Fabs (turn_angle) < DEG_TO_RADF (25.0F) || Are_We_Stuck (vel_vector)) {
m_IsBackingUp = false;
m_BadProgressCount = 0;
} else {
//
// Backup and turn in the opposite direction
//
forward_accel = -forward_accel;
turn_accel = -turn_accel;
}
} else if (Are_We_Stuck (vel_vector)) {
m_IsBackingUp = true;
m_BadProgressCount = 0;
}*/
//
// Clamp the analog controls to -1 and 1
//
turn_accel = WWMath::Clamp (turn_accel, -1.0F, 1.0F);
forward_accel = WWMath::Clamp (forward_accel, -1.0F, 1.0F);
//
// Pass the controls onto the vehicle
//
Apply_Controls (forward_accel, turn_accel);
} else {
//
// Calculate our (current) normalized speed
//
Vector3 vel_vector;
Get_Velocity (tm, vel_vector);
float speed = vel_vector.X;
float norm_speed = speed / max_speed;
//
// Try to zero out our forward movement
//
float forward_accel = WWMath::Clamp (-norm_speed * 5.0F, -1.0F, 1.0F);
if (m_GameObj->Peek_Physical_Object ()->As_VTOLVehicleClass ()) {
forward_accel = WWMath::Clamp (-norm_speed * 5.0F, -1.0F, 1.0F);
}
//
// Invert everything if we are locked in driving backwards mode
//
if (m_IsBackupLocked) {
forward_accel = -forward_accel;
}
//
// Try to hover about the point
//
Apply_Controls (forward_accel, 0);
//
// We aren't really done unless we've stopped most motion
//
if (m_GameObj->Peek_Physical_Object ()->As_VTOLVehicleClass ()) {
is_complete = (WWMath::Fabs (norm_speed) < 0.0001F);
}
//
// Do we need to turn off the engine?
//
if (is_complete && m_TurnOffEngineWhenDone) {
//
// Turn off the engine if we are finished moving
//
VehicleGameObj *vehicle = m_GameObj->As_VehicleGameObj ();
if (vehicle != NULL) {
Apply_Controls (0, 0);
vehicle->Enable_Engine (false);
}
}
}
return is_complete;
}
////////////////////////////////////////////////////////////////
//
// Calculate_Brake
//
////////////////////////////////////////////////////////////////
float
VehicleDriverClass::Calculate_Brake
(
float dist_to_goal,
float expected_velocity,
float curr_speed,
float max_speed
)
{
float brake_velocity = expected_velocity;
//
// Handle VTOL's differently
//
if (m_GameObj->Peek_Physical_Object ()->As_VTOLVehicleClass () == NULL) {
//
// Start braking when the vehicle is 1 second away from its destination
//
if (m_BrakingDist == 0 && dist_to_goal < curr_speed) {
m_BrakingDist = curr_speed;
}
//
// Calculate what speed we should be given the distance to the destination
//
if (m_BrakingDist > 0) {
float end_velocity = (0.5F / max_speed);
float percent = WWMath::Clamp (dist_to_goal / (m_BrakingDist - m_ArrivedDist), -1.0F, 1.0F);
brake_velocity = ((1.0F - percent) * end_velocity) + (percent * expected_velocity);
}
} else {
//
// Start braking when the vehicle is 3 seconds away from its destination
//
if (m_BrakingDist == 0 && dist_to_goal < max_speed * 3) {
m_BrakingDist = max_speed * 3;
}
//
// Calculate what speed we should be given the distance to the destination
//
if (m_BrakingDist > 0) {
float percent = WWMath::Clamp (dist_to_goal / (m_BrakingDist - m_ArrivedDist), -1.0F, 1.0F);
float end_velocity = WWMath::Clamp ((-(curr_speed / max_speed) * 5.0F) + (0.75F / max_speed), -1.0F, 1.0F);
brake_velocity = ((1.0F - percent) * end_velocity) + (percent * expected_velocity);
}
}
return brake_velocity;
}
////////////////////////////////////////////////////////////////
//
// Drive_Tracked
//
////////////////////////////////////////////////////////////////
bool
VehicleDriverClass::Drive_Tracked (void)
{
//
// Convert the destinations from world to object space
//
Matrix3D tm = m_GameObj->Get_Transform ();
Vector3 pos = tm.Get_Translation ();
float facing = tm.Get_Z_Rotation ();
tm.Make_Identity ();
tm.Set_Translation (pos);
tm.Rotate_Z (facing);
float max_speed = m_MaxSpeed * m_SpeedFactor;
//
// Let the path know how fast we are moving
//
Vector3 vel_vector;
Get_Velocity (tm, vel_vector);
m_CurrentPath->Set_Velocity (WWMath::Fabs (vel_vector.X));
//
// Make sure we have the final destination point
//
if (m_CurrentPath != NULL) {
m_FinalDest = m_CurrentPath->Get_Dest_Pos ();
m_CurrentDest = m_CurrentPath->Get_Next_Pos ();
}
//
// Modify some of our parameters if we are force moving backwards
//
if (m_IsBackupLocked) {
tm.Rotate_Z (DEG_TO_RADF (180));
}
//
// Convert the current and final destination points into object space
//
Vector3 final_dest;
Vector3 current_dest;
Matrix3D::Inverse_Transform_Vector (tm, m_FinalDest, &final_dest);
Matrix3D::Inverse_Transform_Vector (tm, m_CurrentDest, &current_dest);
final_dest.Z = 0;
current_dest.Z = 0;
//
// Get the vehicle's current position
//
Vector3 curr_pos;
m_GameObj->Get_Position (&curr_pos);
//
// Calculate the distance to the destination
//
float dist_on_path = m_CurrentPath->Get_Remaining_Path_Length ();
float dist_to_goal = (current_dest.Length () + dist_on_path);
//
// Are we there yet?
//
bool is_complete = (dist_to_goal <= m_ArrivedDist);
if (is_complete) {
dist_to_goal = 0;
}
if (is_complete == false) {
//
// Calculate what the angle is between us and the next destination point
//
float turn_angle = WWMath::Atan2 (current_dest.Y, current_dest.X);
turn_angle = WWMath::Wrap (turn_angle, DEG_TO_RADF(-180), DEG_TO_RADF(180));
//StringClass message;
// message.Format ("turn_angle = %f\n", turn_angle * 180 / 3.1415926F);
//WWDEBUG_SAY (((const char *)message));
//
// Calculate how sharp we need to turn based on the sharpness of the curve
//
float turn_accel = turn_angle / DEG_TO_RADF (45.0F);
//
// Calculate our (current) normalized speed
//
float speed = vel_vector.X;
float norm_speed = speed / max_speed;
//
// Calculate how fast we should accelerate
//
float expected_velocity = 1.0F;
//
// Start braking when the vehicle is 1 second away from its destination
//
if (m_BrakingDist == 0 && dist_to_goal < speed) {
m_BrakingDist = speed;
}
if (m_BrakingDist > 0) {
float end_velocity = (0.5F / max_speed);
float percent = WWMath::Clamp (dist_to_goal / (m_BrakingDist - m_ArrivedDist), -1.0F, 1.0F);
float braking_vel = ((1.0F - percent) * end_velocity) + (percent * expected_velocity);
expected_velocity = min (expected_velocity, braking_vel);
}
float forward_accel = expected_velocity - norm_speed;
//
// Make tracked vehicles turn in place
//
if (WWMath::Fabs (turn_angle) > DEG_TO_RADF (10.0F)) {
forward_accel /= 4.0F;
}
//
// Invert everything if we are locked in driving backwards mode
//
if (m_IsBackupLocked) {
forward_accel = -forward_accel;
}
//
// Clamp the analog controls to -1 and 1
//
turn_accel = WWMath::Clamp (turn_accel, -1.0F, 1.0F);
forward_accel = WWMath::Clamp (forward_accel, -1.0F, 1.0F);
//
// Pass the controls onto the vehicle
//
Apply_Controls (forward_accel, turn_accel);
} else {
//
// Calculate our (current) normalized speed
//
Vector3 vel_vector;
Get_Velocity (tm, vel_vector);
float speed = vel_vector.X;
float norm_speed = speed / max_speed;
//
// Try to zero out our forward movement
//
float forward_accel = WWMath::Clamp (-norm_speed * 2, -1.0F, 1.0F);
//
// Invert everything if we are locked in driving backwards mode
//
if (m_IsBackupLocked) {
forward_accel = -forward_accel;
}
//
// Try to hover about the point
//
Apply_Controls (forward_accel, 0);
//
// Do we need to turn off the engine?
//
if (m_TurnOffEngineWhenDone) {
//
// Turn off the engine if we are finished moving
//
VehicleGameObj *vehicle = m_GameObj->As_VehicleGameObj ();
if (vehicle != NULL) {
Apply_Controls (0, 0);
vehicle->Enable_Engine (false);
}
}
}
return is_complete;
}
////////////////////////////////////////////////////////////////
//
// Apply_Controls
//
////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Apply_Controls
(
float forward_accel,
float left_accel
)
{
if (!WWMath::Is_Valid_Float(forward_accel)) {
#ifdef WWDEBUG
const char* name = m_GameObj->Peek_Physical_Object()->Peek_Model()->Get_Name();
WWDEBUG_SAY(("VehicleDriverClass::Apply_Controls - BAD FLOAT forward_access = %f - Model name = %s\n", forward_accel, name));
#endif //WWDEBUG
forward_accel = 0.0f;
}
if (!WWMath::Is_Valid_Float(left_accel)) {
#ifdef WWDEBUG
const char* name = m_GameObj->Peek_Physical_Object()->Peek_Model()->Get_Name();
WWDEBUG_SAY(("VehicleDriverClass::Apply_Controls - BAD FLOAT left_access = %f - Model name = %s\n", left_accel, name));
#endif //WWDEBUG
left_accel = 0.0f;
}
//
// Now pass the controls onto the game object
//
m_GameObj->Set_Analog_Control (ControlClass::ANALOG_MOVE_FORWARD, forward_accel);
m_GameObj->Set_Analog_Control (ControlClass::ANALOG_TURN_LEFT, left_accel);
m_GameObj->Set_Analog_Control (ControlClass::ANALOG_MOVE_LEFT, 0);
return ;
}
////////////////////////////////////////////////////////////////
//
// Force_Backup
//
////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Force_Backup (bool onoff)
{
//
// Simply set these flags, the Drive method will
// make use of them.
//
m_IsBackingUp = onoff;
m_IsBackupLocked = onoff;
return ;
}
////////////////////////////////////////////////////////////////
//
// Are_We_Stuck
//
////////////////////////////////////////////////////////////////
bool
VehicleDriverClass::Are_We_Stuck (const Vector3 &vel_vector)
{
//
// Determine if we are not making significant progress
//
if (WWMath::Fabs (vel_vector.X) < (m_MaxSpeed * m_SpeedFactor) / 10.0F) {
m_BadProgressCount ++;
} else {
m_BadProgressCount = 0;
}
//
// If we aren't making progress for 30 frames in a row,
// then assume we are stuck
//
return bool(m_BadProgressCount > 30);
}
////////////////////////////////////////////////////////////////////////////////////////////
//
// Save
//
////////////////////////////////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_VARIABLES);
//
// Save each variable to its own microchunk
//
WRITE_MICRO_CHUNK (csave, VARID_CURRENT_DEST, m_CurrentDest);
WRITE_MICRO_CHUNK (csave, VARID_FINAL_DEST, m_FinalDest);
WRITE_MICRO_CHUNK (csave, VARID_MAX_SPEED, m_MaxSpeed);
WRITE_MICRO_CHUNK (csave, VARID_SPEED_FACTOR, m_SpeedFactor);
WRITE_MICRO_CHUNK (csave, VARID_LAST_POS, m_LastPos);
WRITE_MICRO_CHUNK (csave, VARID_BAD_PROGRESS_COUNT, m_BadProgressCount);
WRITE_MICRO_CHUNK (csave, VARID_IS_BACKING_UP, m_IsBackingUp);
WRITE_MICRO_CHUNK (csave, VARID_IS_BACKUP_LOCKED, m_IsBackupLocked);
WRITE_MICRO_CHUNK (csave, VARID_TURN_OFF_ENGINE, m_TurnOffEngineWhenDone);
WRITE_MICRO_CHUNK (csave, VARID_PATH_PTR, m_CurrentPath);
WRITE_MICRO_CHUNK (csave, VARID_GAME_OBJ_PTR, m_GameObj);
WRITE_MICRO_CHUNK (csave, VARID_ARRIVED_DIST, m_ArrivedDist);
csave.End_Chunk ();
return ;
}
////////////////////////////////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ()) {
case CHUNKID_VARIABLES:
Load_Variables (cload);
break;
}
cload.Close_Chunk ();
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Variables
//
///////////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Load_Variables (ChunkLoadClass &cload)
{
//
// Loop through all the microchunks that define the variables
//
while (cload.Open_Micro_Chunk ()) {
switch (cload.Cur_Micro_Chunk_ID ()) {
READ_MICRO_CHUNK (cload, VARID_CURRENT_DEST, m_CurrentDest);
READ_MICRO_CHUNK (cload, VARID_FINAL_DEST, m_FinalDest);
READ_MICRO_CHUNK (cload, VARID_MAX_SPEED, m_MaxSpeed);
READ_MICRO_CHUNK (cload, VARID_SPEED_FACTOR, m_SpeedFactor);
READ_MICRO_CHUNK (cload, VARID_LAST_POS, m_LastPos);
READ_MICRO_CHUNK (cload, VARID_BAD_PROGRESS_COUNT, m_BadProgressCount);
READ_MICRO_CHUNK (cload, VARID_IS_BACKING_UP, m_IsBackingUp);
READ_MICRO_CHUNK (cload, VARID_IS_BACKUP_LOCKED, m_IsBackupLocked);
READ_MICRO_CHUNK (cload, VARID_TURN_OFF_ENGINE, m_TurnOffEngineWhenDone);
READ_MICRO_CHUNK (cload, VARID_PATH_PTR, m_CurrentPath);
READ_MICRO_CHUNK (cload, VARID_GAME_OBJ_PTR, m_GameObj);
READ_MICRO_CHUNK (cload, VARID_ARRIVED_DIST, m_ArrivedDist);
}
cload.Close_Micro_Chunk ();
}
//
// Request that the game object ptr gets remapped
//
if (m_GameObj != NULL) {
REQUEST_POINTER_REMAP ((void **)&m_GameObj);
}
//
// Request that the path ptr gets remapped
//
if (m_CurrentPath != NULL) {
REQUEST_REF_COUNTED_POINTER_REMAP ((RefCountClass **)&m_CurrentPath);
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Reset
//
///////////////////////////////////////////////////////////////////////
void
VehicleDriverClass::Reset (void)
{
m_CurrentPath = NULL;
m_GameObj = NULL;
m_BrakingDist = 0;
m_LastFrameExpectedVelocity = 0;
m_TurnOffEngineWhenDone = false;
m_BadProgressCount = 0;
return ;
}