772 lines
18 KiB
C++
772 lines
18 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 : Combat *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/Combat/pathaction.cpp $*
|
||
|
* *
|
||
|
* Author:: Patrick Smith *
|
||
|
* *
|
||
|
* $Modtime:: 11/16/01 1:51p $*
|
||
|
* *
|
||
|
* $Revision:: 18 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include "pathaction.h"
|
||
|
#include "smartgameobj.h"
|
||
|
#include "soldier.h"
|
||
|
#include "doors.h"
|
||
|
#include "humanphys.h"
|
||
|
#include "obbox.h"
|
||
|
#include "path.h"
|
||
|
#include "chunkio.h"
|
||
|
#include "saveload.h"
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////
|
||
|
// Save/Load constants
|
||
|
////////////////////////////////////////////////////////////////
|
||
|
enum
|
||
|
{
|
||
|
CHUNKID_GAMEOBJ_REF = 0x11020954,
|
||
|
CHUNKID_VARIABLES
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
VARID_ELEVATOR_STATE = 0,
|
||
|
VARID_DOOR_STATE,
|
||
|
VARID_STATE,
|
||
|
VARID_TYPE,
|
||
|
VARID_PATH_PTR,
|
||
|
VARID_MECHANISM_PTR,
|
||
|
VARID_DESTINATION,
|
||
|
VARID_FACEPOS,
|
||
|
VARID_GAME_OBJ_PTR,
|
||
|
VARID_LADDER_STATE,
|
||
|
VARID_LADDER_INDEX
|
||
|
};
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////
|
||
|
// Static member initialization
|
||
|
////////////////////////////////////////////////////////////////
|
||
|
DynamicVectorClass<GameObjReference> PathActionClass::LadderList;
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// PathActionClass
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
PathActionClass::PathActionClass (void) :
|
||
|
ElevatorState (ELEVATOR_STATE_NONE),
|
||
|
DoorState (DOOR_STATE_NONE),
|
||
|
LadderState (LADDER_STATE_NONE),
|
||
|
State (STATE_FINISHED),
|
||
|
Type (TYPE_UNKNOWN),
|
||
|
Mechanism (NULL),
|
||
|
GameObj (NULL),
|
||
|
Path (NULL),
|
||
|
LadderIndex (-1),
|
||
|
Destination (0, 0, 0),
|
||
|
FacePos (0, 0, 0),
|
||
|
Timer (0)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// ~PathActionClass
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
PathActionClass::~PathActionClass (void)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Initialize
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Initialize
|
||
|
(
|
||
|
TYPE type,
|
||
|
PathClass * path,
|
||
|
SmartGameObj * game_obj,
|
||
|
StaticPhysClass * mechanism
|
||
|
)
|
||
|
{
|
||
|
Type = type;
|
||
|
GameObj = game_obj;
|
||
|
Mechanism = mechanism;
|
||
|
Path = path;
|
||
|
|
||
|
//
|
||
|
// Reset the states
|
||
|
//
|
||
|
State = STATE_WAITING;
|
||
|
ElevatorState = ELEVATOR_STATE_WAITING;
|
||
|
DoorState = DOOR_STATE_GETTING_IN_POSITION;
|
||
|
LadderState = LADDER_STATE_WAITING;
|
||
|
Timer = 5;
|
||
|
assert(Path != NULL);
|
||
|
assert(Path->Get_Path_Vector_Length() >= Path->Get_Path_Vector_Count());
|
||
|
Path->Get_Action_Entrance (Destination);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Process
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
bool
|
||
|
PathActionClass::Process (void)
|
||
|
{
|
||
|
switch (Type)
|
||
|
{
|
||
|
case TYPE_JUMPING:
|
||
|
Handle_Jump ();
|
||
|
break;
|
||
|
|
||
|
case TYPE_LADDER:
|
||
|
Handle_Ladder ();
|
||
|
break;
|
||
|
|
||
|
case TYPE_ELEVATOR:
|
||
|
Handle_Elevator ();
|
||
|
break;
|
||
|
|
||
|
case TYPE_DOOR:
|
||
|
Handle_Door ();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Set_Finished ();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return (State == STATE_FINISHED);
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Handle_Ladder
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Handle_Ladder (void)
|
||
|
{
|
||
|
SoldierGameObj *soldier = GameObj->As_SoldierGameObj ();
|
||
|
WWASSERT (soldier != NULL);
|
||
|
|
||
|
switch (LadderState)
|
||
|
{
|
||
|
case LADDER_STATE_WAITING:
|
||
|
{
|
||
|
//
|
||
|
// Is there already someone on the ladder?
|
||
|
//
|
||
|
if (Get_Ladder_Occupant (LadderIndex) == NULL) {
|
||
|
Set_Ladder_Occupant (LadderIndex, GameObj);
|
||
|
|
||
|
//
|
||
|
// Get on the ladder
|
||
|
//
|
||
|
soldier->Set_Boolean_Control (ControlClass::BOOLEAN_ACTION);
|
||
|
LadderState = LADDER_STATE_GETTING_ON;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case LADDER_STATE_GETTING_ON:
|
||
|
|
||
|
//
|
||
|
// Have we gotten on yet?
|
||
|
//
|
||
|
if (soldier->Is_On_Ladder ()) {
|
||
|
|
||
|
//
|
||
|
// Start climbing
|
||
|
//
|
||
|
State = STATE_MOVING;
|
||
|
LadderState = LADDER_STATE_CLIMBING;
|
||
|
assert(Path != NULL);
|
||
|
assert(Path->Get_Path_Vector_Length() > Path->Get_Path_Vector_Count());
|
||
|
Path->Get_Action_Destination (Destination);
|
||
|
Path->Set_Movement_Directions (PathClass::MOVE_Z);
|
||
|
} else {
|
||
|
soldier->Set_Boolean_Control (ControlClass::BOOLEAN_ACTION);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case LADDER_STATE_CLIMBING:
|
||
|
|
||
|
//
|
||
|
// Have we finished climbing yet?
|
||
|
//
|
||
|
if (soldier->Is_On_Ladder () == false) {
|
||
|
LadderState = LADDER_STATE_NONE;
|
||
|
Set_Ladder_Occupant (LadderIndex, NULL);
|
||
|
Set_Finished ();
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Get the object's current position
|
||
|
//
|
||
|
Vector3 curr_pos;
|
||
|
GameObj->Get_Position (&curr_pos);
|
||
|
|
||
|
//
|
||
|
// Is the object within a small distance of the destination?
|
||
|
//
|
||
|
float dist = WWMath::Fabs(curr_pos.Z - Destination.Z);
|
||
|
if (dist < 0.25F) {
|
||
|
|
||
|
//
|
||
|
// Tell the object to get off the ladder (he may not be able to
|
||
|
// if someone is blocking his way)
|
||
|
//
|
||
|
soldier->Set_Boolean_Control (ControlClass::BOOLEAN_ACTION);
|
||
|
State = STATE_WAITING;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Handle_Jump
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Handle_Jump (void)
|
||
|
{
|
||
|
//
|
||
|
// Is this a human?
|
||
|
//
|
||
|
SoldierGameObj *soldier_obj = GameObj->As_SoldierGameObj ();
|
||
|
if (soldier_obj != NULL) {
|
||
|
|
||
|
HumanPhysClass *human_phys = soldier_obj->Peek_Physical_Object ()->As_HumanPhysClass ();
|
||
|
if (human_phys != NULL) {
|
||
|
|
||
|
//
|
||
|
// If we are still in the air, then turn to face
|
||
|
// our destination point.
|
||
|
//
|
||
|
if (soldier_obj->Is_Airborne ()) {
|
||
|
Vector3 dest(0,0,0);
|
||
|
assert(Path != NULL);
|
||
|
assert(Path->Get_Path_Vector_Length() > Path->Get_Path_Vector_Count());
|
||
|
Path->Get_Action_Destination (dest);
|
||
|
|
||
|
Vector3 face_pt = dest + Vector3 (0, 0, soldier_obj->Get_Bullseye_Offset_Z() );
|
||
|
soldier_obj->Set_Targeting (face_pt, false);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Revert when we've finished landing
|
||
|
//
|
||
|
if ( human_phys->Has_Just_Jumped () == false &&
|
||
|
soldier_obj->Get_Human_State ()->Get_State () == HumanStateClass::UPRIGHT)
|
||
|
{
|
||
|
Set_Finished ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
Set_Finished ();
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Handle_Elevator
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Handle_Elevator (void)
|
||
|
{
|
||
|
ElevatorPhysClass *elevator = Mechanism->As_ElevatorPhysClass ();
|
||
|
WWASSERT (elevator != NULL);
|
||
|
|
||
|
switch (ElevatorState)
|
||
|
{
|
||
|
case ELEVATOR_STATE_WAITING:
|
||
|
|
||
|
//
|
||
|
// Switch states if the elevator has arrived
|
||
|
//
|
||
|
if (elevator->Can_Object_Enter (GameObj)) {
|
||
|
elevator->Set_Current_Rider (GameObj);
|
||
|
ElevatorState = ELEVATOR_STATE_ENTERING;
|
||
|
State = STATE_MOVING;
|
||
|
|
||
|
//
|
||
|
// Calculate where we want the unit to walk to in order
|
||
|
// to enter the elevator
|
||
|
//
|
||
|
if (elevator->Get_Floor () == 0) {
|
||
|
Get_Elevator_Zone_Pos (ZONE_LOWER_INSIDE, &Destination);
|
||
|
Get_Elevator_Zone_Pos (ZONE_UPPER_CALL, &FacePos);
|
||
|
} else {
|
||
|
Get_Elevator_Zone_Pos (ZONE_UPPER_INSIDE, &Destination);
|
||
|
Get_Elevator_Zone_Pos (ZONE_LOWER_CALL, &FacePos);
|
||
|
}
|
||
|
} else {
|
||
|
elevator->Request_Elevator (GameObj);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case ELEVATOR_STATE_RIDING:
|
||
|
|
||
|
//
|
||
|
// Switch states if the elevator has arrived
|
||
|
//
|
||
|
if (elevator->Can_Object_Exit (GameObj)) {
|
||
|
ElevatorState = ELEVATOR_STATE_EXITING;
|
||
|
State = STATE_MOVING;
|
||
|
Timer = 5.0F;
|
||
|
assert(Path != NULL);
|
||
|
assert(Path->Get_Path_Vector_Length() > Path->Get_Path_Vector_Count());
|
||
|
Path->Get_Action_Destination (Destination);
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Make the unit face the exit
|
||
|
//
|
||
|
GameObj->Set_Targeting (FacePos, false);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case ELEVATOR_STATE_ENTERING:
|
||
|
|
||
|
//
|
||
|
// Switch states if the elevator has started moving
|
||
|
//
|
||
|
if (elevator->Is_Moving ()) {
|
||
|
ElevatorState = ELEVATOR_STATE_RIDING;
|
||
|
State = STATE_WAITING;
|
||
|
} else if (Has_Arrived ()) {
|
||
|
|
||
|
//
|
||
|
// Make the unit face the exit
|
||
|
//
|
||
|
GameObj->Set_Targeting (FacePos, false);
|
||
|
State = STATE_WAITING;
|
||
|
|
||
|
//
|
||
|
// Make the elevator start moving
|
||
|
//
|
||
|
elevator->Request_Elevator (GameObj);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case ELEVATOR_STATE_EXITING:
|
||
|
|
||
|
//
|
||
|
// Has the unit made it through the elevator door, or has time expired?
|
||
|
//
|
||
|
Timer -= TimeManager::Get_Frame_Seconds ();
|
||
|
if (Has_Arrived () || Timer <= 0) {
|
||
|
|
||
|
//
|
||
|
// Let the elevator know that its rider has left
|
||
|
//
|
||
|
if (elevator->Get_Current_Rider () == GameObj) {
|
||
|
elevator->Set_Current_Rider (NULL);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Reset the state
|
||
|
//
|
||
|
ElevatorState = ELEVATOR_STATE_NONE;
|
||
|
Set_Finished ();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Handle_Door
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Handle_Door (void)
|
||
|
{
|
||
|
DoorPhysClass *door = Mechanism->As_DoorPhysClass ();
|
||
|
WWASSERT (door != NULL);
|
||
|
|
||
|
switch (DoorState)
|
||
|
{
|
||
|
case DOOR_STATE_GETTING_IN_POSITION:
|
||
|
{
|
||
|
//
|
||
|
// Has the unit made it into position, or has time expired?
|
||
|
//
|
||
|
Timer -= TimeManager::Get_Frame_Seconds ();
|
||
|
if (Has_Arrived () || Timer <= 0) {
|
||
|
DoorState = DOOR_STATE_WAITING;
|
||
|
State = STATE_WAITING;
|
||
|
} else {
|
||
|
State = STATE_MOVING;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case DOOR_STATE_WAITING:
|
||
|
|
||
|
//
|
||
|
// Keep the door open for as long as we need it
|
||
|
//
|
||
|
door->Request_Door_Open ();
|
||
|
|
||
|
//
|
||
|
// If the door is opened, then move onto the next state
|
||
|
//
|
||
|
if (door->Is_Door_Open ()) {
|
||
|
DoorState = DOOR_STATE_ENTERING;
|
||
|
State = STATE_MOVING;
|
||
|
Timer = 5.0F;
|
||
|
assert(Path != NULL);
|
||
|
assert(Path->Get_Path_Vector_Length() >= Path->Get_Path_Vector_Count());
|
||
|
Path->Get_Action_Destination (Destination);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case DOOR_STATE_ENTERING:
|
||
|
|
||
|
//
|
||
|
// Has the unit made it through the door, or has time expired?
|
||
|
//
|
||
|
Timer -= TimeManager::Get_Frame_Seconds ();
|
||
|
if (Has_Arrived () || Timer <= 0) {
|
||
|
DoorState = DOOR_STATE_NONE;
|
||
|
Set_Finished ();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Has_Arrived
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
bool
|
||
|
PathActionClass::Has_Arrived (void)
|
||
|
{
|
||
|
bool retval = false;
|
||
|
|
||
|
//
|
||
|
// Get the object's current position
|
||
|
//
|
||
|
Vector3 curr_pos;
|
||
|
GameObj->Get_Position (&curr_pos);
|
||
|
|
||
|
//
|
||
|
// Is the object within a small distance of the destination?
|
||
|
//
|
||
|
Vector3 delta = curr_pos - Destination;
|
||
|
delta.Z = 0;
|
||
|
float dist2 = delta.Length2 ();
|
||
|
if (dist2 < 0.0225F) {
|
||
|
retval = true;
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Get_Elevator_Zone_Pos
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Get_Elevator_Zone_Pos (ELEVATOR_ZONE zone_id, Vector3 *position)
|
||
|
{
|
||
|
WWASSERT (position != NULL);
|
||
|
|
||
|
//
|
||
|
// Make sure we have an elevator
|
||
|
//
|
||
|
ElevatorPhysClass *elevator = Mechanism->As_ElevatorPhysClass ();
|
||
|
WWASSERT (elevator != NULL);
|
||
|
|
||
|
//
|
||
|
// Get information about this type of elevator
|
||
|
//
|
||
|
const ElevatorPhysDefClass *definition = elevator->Get_ElevatorPhysDef ();
|
||
|
|
||
|
//
|
||
|
// Transform the requested zone into world-space
|
||
|
//
|
||
|
const Matrix3D &tm = elevator->Get_Transform ();
|
||
|
OBBoxClass zone_box;
|
||
|
OBBoxClass::Transform (tm, definition->Get_Zone (zone_id), &zone_box);
|
||
|
|
||
|
//
|
||
|
// Return the center of the zone to the caller
|
||
|
//
|
||
|
(*position) = zone_box.Center;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Save
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Save (ChunkSaveClass &csave)
|
||
|
{
|
||
|
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||
|
|
||
|
//
|
||
|
// Save each variable to its own microchunk
|
||
|
//
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_ELEVATOR_STATE, ElevatorState);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_DOOR_STATE, DoorState);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_STATE, State);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_TYPE, Type);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_PATH_PTR, Path);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_MECHANISM_PTR, Mechanism);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_DESTINATION, Destination);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_FACEPOS, FacePos);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_GAME_OBJ_PTR, GameObj);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_LADDER_STATE, LadderState);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_LADDER_INDEX, LadderIndex);
|
||
|
|
||
|
csave.End_Chunk ();
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Load
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::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
|
||
|
PathActionClass::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_ELEVATOR_STATE, ElevatorState);
|
||
|
READ_MICRO_CHUNK (cload, VARID_DOOR_STATE, DoorState);
|
||
|
READ_MICRO_CHUNK (cload, VARID_STATE, State);
|
||
|
READ_MICRO_CHUNK (cload, VARID_TYPE, Type);
|
||
|
READ_MICRO_CHUNK (cload, VARID_PATH_PTR, Path);
|
||
|
READ_MICRO_CHUNK (cload, VARID_MECHANISM_PTR, Mechanism);
|
||
|
READ_MICRO_CHUNK (cload, VARID_DESTINATION, Destination);
|
||
|
READ_MICRO_CHUNK (cload, VARID_FACEPOS, FacePos);
|
||
|
READ_MICRO_CHUNK (cload, VARID_GAME_OBJ_PTR, GameObj);
|
||
|
READ_MICRO_CHUNK (cload, VARID_LADDER_STATE, LadderState);
|
||
|
READ_MICRO_CHUNK (cload, VARID_LADDER_INDEX, LadderIndex);
|
||
|
}
|
||
|
|
||
|
cload.Close_Micro_Chunk ();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Request that the mechanism ptr gets remapped
|
||
|
//
|
||
|
if (GameObj != NULL) {
|
||
|
REQUEST_POINTER_REMAP ((void **)&GameObj);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Request that the mechanism ptr gets remapped
|
||
|
//
|
||
|
if (Mechanism != NULL) {
|
||
|
REQUEST_REF_COUNTED_POINTER_REMAP ((RefCountClass **)&Mechanism);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Request that the path ptr gets remapped
|
||
|
//
|
||
|
if (Path != NULL) {
|
||
|
REQUEST_REF_COUNTED_POINTER_REMAP ((RefCountClass **)&Path);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Ladder_Occupant
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Set_Ladder_Occupant (int ladder_index, ScriptableGameObj *object)
|
||
|
{
|
||
|
WWASSERT (ladder_index < 256);
|
||
|
if (ladder_index < 0) {
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Grow the ladder list until it contains enough entries
|
||
|
//
|
||
|
while (ladder_index >= LadderList.Count ()) {
|
||
|
LadderList.Add (NULL);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Fill in this slot in the list
|
||
|
//
|
||
|
LadderList[ladder_index] = object;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Get_Ladder_Occupant
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
ScriptableGameObj *
|
||
|
PathActionClass::Get_Ladder_Occupant (int ladder_index)
|
||
|
{
|
||
|
ScriptableGameObj *object = NULL;
|
||
|
|
||
|
//
|
||
|
// Return the object that's in this slot
|
||
|
//
|
||
|
if (ladder_index >= 0 && ladder_index < LadderList.Count ()) {
|
||
|
object = LadderList[ladder_index];
|
||
|
}
|
||
|
|
||
|
return object;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Reset
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Reset (void)
|
||
|
{
|
||
|
if (GameObj != NULL) {
|
||
|
|
||
|
//
|
||
|
// Check to see if this unit is "reserving" any of the ladders...
|
||
|
//
|
||
|
for (int index = 0; index < LadderList.Count (); index ++) {
|
||
|
if (LadderList[index] == GameObj) {
|
||
|
|
||
|
//
|
||
|
// Clear the ladder reservation
|
||
|
//
|
||
|
LadderList[index] = NULL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GameObj = NULL;
|
||
|
Mechanism = NULL;
|
||
|
Path = NULL;
|
||
|
State = STATE_FINISHED;
|
||
|
Type = TYPE_UNKNOWN;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Finished
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
PathActionClass::Set_Finished (void)
|
||
|
{
|
||
|
State = STATE_FINISHED;
|
||
|
Reset ();
|
||
|
return ;
|
||
|
}
|