/* ** 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 . */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : Commando * * * * $Archive:: /Commando/Code/Combat/repairbaygameobj.cpp $* * * * $Author:: Byon_g $* * * * $Modtime:: 11/15/01 6:37p $* * * * $Revision:: 11 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "repairbaygameobj.h" #include "basecontroller.h" #include "wwhack.h" #include "simpledefinitionfactory.h" #include "persistfactory.h" #include "definitionmgr.h" #include "combatchunkid.h" #include "debug.h" #include "scriptzone.h" #include "wwprofile.h" #include "basecontroller.h" #include "vehicle.h" #include "soldier.h" #include "playertype.h" #include "playerdata.h" #include "mesh.h" #include "meshmdl.h" #include "crandom.h" #include "simplegameobj.h" #include "objlibrary.h" #include "phys.h" #include "hanim.h" #include "combat.h" #include "bitpackids.h" //////////////////////////////////////////////////////////////// // Hacks //////////////////////////////////////////////////////////////// DECLARE_FORCE_LINK (RepairBay) //////////////////////////////////////////////////////////////// // Namespaces //////////////////////////////////////////////////////////////// using namespace BuildingConstants; //////////////////////////////////////////////////////////////// // Constants //////////////////////////////////////////////////////////////// const char *RepairBayGameObj::BoneNames[RepairBayGameObj::BONE_COUNT] = { "BONE02", "BONE03", "BONE04", "BONE05", "BONE06", "BONE07", }; //////////////////////////////////////////////////////////////// // Editable and persist factories //////////////////////////////////////////////////////////////// SimplePersistFactoryClass _RepairBayGameObjDefPersistFactory; SimplePersistFactoryClass _RepairBayGameObjPersistFactory; DECLARE_DEFINITION_FACTORY (RepairBayGameObjDef, CLASSID_GAME_OBJECT_DEF_REPAIR_BAY, "Repair Bay") _RepairBayGameObjDefDefFactory; //////////////////////////////////////////////////////////////// // Save/Load constants //////////////////////////////////////////////////////////////// enum { CHUNKID_DEF_PARENT = 0x02200638, CHUNKID_DEF_VARIABLES, MICROCHUNKID_DEF_REPAIR_PER_SEC = 1, MICROCHUNKID_DEF_REPARING_STATICANIM_DEFID }; enum { CHUNKID_PARENT = 0x0219043, CHUNKID_VARIABLES, MICROCHUNKID_UNUSED = 1, }; //////////////////////////////////////////////////////////////// // // RepairBayGameObjDef // //////////////////////////////////////////////////////////////// RepairBayGameObjDef::RepairBayGameObjDef (void) : RepairPerSec (0), RepairingStaticAnimDefID (0) { // // Editable support // EDITABLE_PARAM (RepairBayGameObjDef, ParameterClass::TYPE_FLOAT, RepairPerSec); #ifdef PARAM_EDITING_ON GenericDefParameterClass *param = new GenericDefParameterClass (&RepairingStaticAnimDefID); param->Set_Class_ID (CLASSID_TILE); param->Set_Name ("Repairing Static Anim Type"); GENERIC_EDITABLE_PARAM (RepairBayGameObjDef, param) #endif //PARAM_EDITING_ON return ; } //////////////////////////////////////////////////////////////// // // ~RepairBayGameObjDef // //////////////////////////////////////////////////////////////// RepairBayGameObjDef::~RepairBayGameObjDef (void) { return ; } //////////////////////////////////////////////////////////////// // // Get_Class_ID // //////////////////////////////////////////////////////////////// uint32 RepairBayGameObjDef::Get_Class_ID (void) const { return CLASSID_GAME_OBJECT_DEF_REPAIR_BAY; } //////////////////////////////////////////////////////////////// // // Create // //////////////////////////////////////////////////////////////// PersistClass * RepairBayGameObjDef::Create (void) const { RepairBayGameObj *building = new RepairBayGameObj; building->Init (*this); return building; } //////////////////////////////////////////////////////////////// // // Save // //////////////////////////////////////////////////////////////// bool RepairBayGameObjDef::Save (ChunkSaveClass &csave) { csave.Begin_Chunk (CHUNKID_DEF_PARENT); BuildingGameObjDef::Save (csave); csave.End_Chunk (); csave.Begin_Chunk (CHUNKID_DEF_VARIABLES); WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_REPAIR_PER_SEC, RepairPerSec); WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_REPARING_STATICANIM_DEFID, RepairingStaticAnimDefID); csave.End_Chunk (); return true; } //////////////////////////////////////////////////////////////// // // Load // //////////////////////////////////////////////////////////////// bool RepairBayGameObjDef::Load (ChunkLoadClass &cload) { while (cload.Open_Chunk ()) { switch (cload.Cur_Chunk_ID ()) { case CHUNKID_DEF_PARENT: BuildingGameObjDef::Load (cload); break; case CHUNKID_DEF_VARIABLES: Load_Variables (cload); break; default: Debug_Say (("Unrecognized RepairBay Def chunkID\n")); break; } cload.Close_Chunk (); } return true; } //////////////////////////////////////////////////////////////// // // Load_Variables // //////////////////////////////////////////////////////////////// void RepairBayGameObjDef::Load_Variables (ChunkLoadClass &cload) { while (cload.Open_Micro_Chunk ()) { switch (cload.Cur_Micro_Chunk_ID ()) { READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_REPAIR_PER_SEC, RepairPerSec); READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_REPARING_STATICANIM_DEFID, RepairingStaticAnimDefID); default: Debug_Say (("Unrecognized RepairBay Def Variable chunkID\n")); break; } cload.Close_Micro_Chunk(); } return ; } //////////////////////////////////////////////////////////////// // // Get_Factory // //////////////////////////////////////////////////////////////// const PersistFactoryClass & RepairBayGameObjDef::Get_Factory (void) const { return _RepairBayGameObjDefPersistFactory; } //////////////////////////////////////////////////////////////// // // RepairBayGameObj // //////////////////////////////////////////////////////////////// RepairBayGameObj::RepairBayGameObj (void) : RepairTimer (0), RepairZone (Vector3 (0, 0, 0), Vector3 (0, 0, 0)), RepairAnimationID (0), IsReparing (false), RepairMesh (NULL) { ::memset (ArcObjects, 0, sizeof (ArcObjects)); for (int index = 0; index < ARC_OBJ_COUNT; index ++) { ArcLifeRemaining[index] = 0; } return ; } //////////////////////////////////////////////////////////////// // // ~RepairBayGameObj // //////////////////////////////////////////////////////////////// RepairBayGameObj::~RepairBayGameObj (void) { for (int index = 0; index < ARC_OBJ_COUNT; index ++) { ArcObjects[index] = NULL; } return ; } //////////////////////////////////////////////////////////////// // // Get_Factory // //////////////////////////////////////////////////////////////// const PersistFactoryClass & RepairBayGameObj::Get_Factory (void) const { return _RepairBayGameObjPersistFactory; } //////////////////////////////////////////////////////////////// // // Init // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Init( void ) { Init( Get_Definition() ); } //////////////////////////////////////////////////////////////// // // Init // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Init (const RepairBayGameObjDef &definition) { BuildingGameObj::Init (definition); return ; } //////////////////////////////////////////////////////////////// // // Get_Definition // //////////////////////////////////////////////////////////////// const RepairBayGameObjDef & RepairBayGameObj::Get_Definition (void) const { return (const RepairBayGameObjDef &)BaseGameObj::Get_Definition (); } //////////////////////////////////////////////////////////////// // // Save // //////////////////////////////////////////////////////////////// bool RepairBayGameObj::Save (ChunkSaveClass &csave) { csave.Begin_Chunk (CHUNKID_PARENT); BuildingGameObj::Save (csave); csave.End_Chunk (); csave.Begin_Chunk (CHUNKID_VARIABLES); csave.End_Chunk (); return true; } //////////////////////////////////////////////////////////////// // // Load // //////////////////////////////////////////////////////////////// bool RepairBayGameObj::Load (ChunkLoadClass &cload) { while (cload.Open_Chunk ()) { switch (cload.Cur_Chunk_ID ()) { case CHUNKID_PARENT: BuildingGameObj::Load (cload); break; case CHUNKID_VARIABLES: Load_Variables (cload); break; default: Debug_Say (("Unrecognized RepairBay chunkID\n")); break; } cload.Close_Chunk(); } return true; } //////////////////////////////////////////////////////////////// // // Load_Variables // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Load_Variables (ChunkLoadClass &cload) { while (cload.Open_Micro_Chunk ()) { /*switch (cload.Cur_Micro_Chunk_ID ()) { default: Debug_Say (("Unrecognized RepairBay Variable chunkID\n")); break; }*/ cload.Close_Micro_Chunk(); } return ; } //////////////////////////////////////////////////////////////// // // CnC_Initialize // //////////////////////////////////////////////////////////////// void RepairBayGameObj::CnC_Initialize (BaseControllerClass *base) { BuildingGameObj::CnC_Initialize (base); // // Get the building's "position" // Vector3 pos; Get_Position (&pos); // // Find the closest repair bay zone to the building // ScriptZoneGameObj *zone = NULL; zone = ScriptZoneGameObj::Find_Closest_Zone (pos, ZoneConstants::TYPE_VEHICLE_REPAIR); if (zone != NULL) { RepairZone = zone->Get_Bounding_Box (); // // Get rid of the zone (if the game doesn't need it anymore) // if (zone->Get_Observers ().Count () == 0) { zone->Set_Delete_Pending (); } } // // Try to find the mesh that contains the // RefMultiListIterator mesh_iterator (&Aggregates); for (mesh_iterator.First (); !mesh_iterator.Is_Done (); mesh_iterator.Next ()) { StaticPhysClass *phys_obj = mesh_iterator.Peek_Obj (); if (phys_obj != NULL && phys_obj->Peek_Model () != NULL) { if (::lstrcmpi (phys_obj->Peek_Model ()->Get_Name (), "rep^NOD_fx") == 0) { RepairMesh = phys_obj; break; } } } // // Find the closest reparing static anim phys // float closest2 = 99999.0F; RefPhysListIterator iterator = PhysicsSceneClass::Get_Instance()->Get_Static_Object_Iterator (); for (iterator.First (); !iterator.Is_Done (); iterator.Next ()) { StaticAnimPhysClass *anim_phys_obj = iterator.Peek_Obj ()->As_StaticAnimPhysClass (); // // Is this a repairing static anim phys? // if ( anim_phys_obj != NULL && anim_phys_obj->Get_Definition ()->Get_ID () == (uint32)Get_Definition ().RepairingStaticAnimDefID) { // // Is this the closest one we've found so far? // Vector3 anim_pos; anim_phys_obj->Get_Position (&anim_pos); float dist2 = (anim_pos - pos).Length2 (); if (dist2 < closest2) { closest2 = dist2; RepairAnimationID = anim_phys_obj->Get_ID (); } } } // // Create the simple game object's that we'll use to display the repair-arc effect // for (int index = 0; index < ARC_OBJ_COUNT; index ++) { ArcObjects[index] = (SimpleGameObj *)ObjectLibraryManager::Create_Object ("Arc Effect"); if ( ArcObjects[index]->Peek_Physical_Object () != NULL && ArcObjects[index]->Peek_Physical_Object ()->Peek_Model () != NULL) { ArcObjects[index]->Peek_Physical_Object ()->Peek_Model ()->Set_Hidden (true); } ArcLifeRemaining[index] = 0; } // // Get information about the model // RenderObjClass *model = ArcObjects[0]->Peek_Physical_Object ()->Peek_Model (); if (model != NULL) { // // Store the original transforms of each bone // for (int index = 0; index < BONE_COUNT; index ++) { Bones[index] = model->Get_Bone_Transform (BoneNames[index]); } // // Lookup the original transform of the end-bone // int end_index = model->Get_Bone_Index ("bone_end"); EndTM = model->Get_Bone_Transform (end_index); } return ; } //////////////////////////////////////////////////////////////// // // Play_Repairing_Animation // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Play_Repairing_Animation (bool onoff) { // // Lookup the static animation object we need to play // StaticPhysClass *static_phys_obj = PhysicsSceneClass::Get_Instance ()->Find_Static_Object (RepairAnimationID); if (static_phys_obj != NULL) { StaticAnimPhysClass *anim_phys_obj = static_phys_obj->As_StaticAnimPhysClass (); if (anim_phys_obj != NULL) { // // Configure the animation // AnimCollisionManagerClass &anim_mgr = anim_phys_obj->Get_Animation_Manager (); anim_mgr.Set_Animation_Mode (AnimCollisionManagerClass::ANIMATE_TARGET); // // Either play the animation forward or backward // if (onoff && anim_mgr.Get_Target_Frame () == 0) { anim_mgr.Set_Target_Frame_End (); } else if (onoff == false && anim_mgr.Get_Target_Frame () != 0) { anim_mgr.Set_Target_Frame (0); } } } return ; } //////////////////////////////////////////////////////////////// // // Think // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Think (void) { WWPROFILE ("Repair Bay Think"); // // Check to see if we should repair the vehicle a little more... // if (IsDestroyed == false) { RepairTimer -= TimeManager::Get_Frame_Seconds (); if (RepairTimer <= 0) { RepairTimer = 0.5F; // // Repair any vehicle that is in our zone // bool is_repairing = Repair_Vehicle (); // // Play the repairing animation // if (is_repairing != IsReparing) { IsReparing = is_repairing; } } if (IsReparing) { Update_Repairing_Animations (); } } // // Hide any arc-effects that have finished // for (int index = 0; index < ARC_OBJ_COUNT; index ++) { if (ArcLifeRemaining[index] > 0) { ArcLifeRemaining[index] -= TimeManager::Get_Frame_Seconds (); if (ArcLifeRemaining[index] <= 0) { PhysClass *phys_obj = ArcObjects[index]->Peek_Physical_Object (); phys_obj->Peek_Model ()->Set_Hidden (true); } } } BuildingGameObj::Think (); return ; } //////////////////////////////////////////////////////////////// // // Repair_Vehicle // //////////////////////////////////////////////////////////////// bool RepairBayGameObj::Repair_Vehicle (void) { bool is_repairing = false; VehicleList.Delete_All (); // // Collect the dynamic physics objects in the repair zone // NonRefPhysListClass objs_to_repair; PhysicsSceneClass::Get_Instance ()->Collect_Objects (RepairZone, false, true, &objs_to_repair); // // Loop over all the objects // NonRefPhysListIterator it (&objs_to_repair); for (it.First (); !it.Is_Done (); it.Next ()) { PhysicalGameObj *gameobj = NULL; // // Get the game object from this physics object // if (it.Peek_Obj()->Get_Observer () != NULL) { gameobj = ((CombatPhysObserverClass *)it.Peek_Obj()->Get_Observer())->As_PhysicalGameObj(); } if (gameobj != NULL) { // // See if this is a vehicle game object // VehicleGameObj *vehicle = gameobj->As_VehicleGameObj (); if (vehicle != NULL) { // // Check to ensure the driver is of the right team // SoldierGameObj *driver = vehicle->Get_Driver (); if ( driver != NULL && driver->Get_Player_Type () == BaseController->Get_Player_Type() ) { PlayerDataClass *player_data = driver->Get_Player_Data (); float shield_max = vehicle->Get_Defense_Object ()->Get_Shield_Strength_Max (); float health_max = vehicle->Get_Defense_Object ()->Get_Health_Max (); float curr_health = vehicle->Get_Defense_Object ()->Get_Health (); float curr_shield = vehicle->Get_Defense_Object ()->Get_Shield_Strength (); // // Avoid divide-by-zero // health_max = max (health_max, WWMATH_EPSILON); shield_max = max (shield_max, WWMATH_EPSILON); // // Calculate how much health and shield to restore and how much it will cost // float vehicle_cost = 1000.0F;//vehicle->Get_Cost (); float repair_rate = (Get_Definition ().RepairPerSec * 0.5F); float total_damage = (health_max - curr_health) + (shield_max - curr_shield); int damage_points = (int)min (repair_rate, total_damage); float repair_cost_per_pt = vehicle_cost / (health_max + shield_max); //int available_funds = 1000; //player_data->Get_Score () #pragma message("(TSS) available_funds = 1000 looks suspect...") int available_funds = 1000; //player_data->Get_Money () int points_restored = int(available_funds / repair_cost_per_pt); points_restored = max (points_restored, 0); points_restored = min (points_restored, damage_points); float total_cost = points_restored * repair_cost_per_pt; int health_restored = min (int(health_max - curr_health), points_restored); int shield_restored = min (int(shield_max - curr_shield), (points_restored - health_restored)); // // Debit the player's account // //player_data->Purchase_Item (total_cost); is_repairing = true; // // Repair the vehicle's health if the player has enough money // if (health_restored > 0) { if (CombatManager::I_Am_Server ()) { vehicle->Get_Defense_Object ()->Add_Health (health_restored); } is_repairing = true; } // // Repair the vehicle's shield if the player has enough money // if (shield_restored > 0) { if (CombatManager::I_Am_Server ()) { vehicle->Get_Defense_Object ()->Add_Shield_Strength (shield_restored); } is_repairing = true; } // // Add this vehicle to the list of vehicles that are being repaired // if (is_repairing) { VehicleList.Add (vehicle); } } } } } return is_repairing; } //////////////////////////////////////////////////////////////// // // Find_Random_Mesh // //////////////////////////////////////////////////////////////// MeshClass * Find_Random_Mesh (RenderObjClass *model) { MeshClass *mesh = NULL; // // Is this model a mesh? // if (mesh == NULL && model->Class_ID () == RenderObjClass::CLASSID_MESH) { mesh = reinterpret_cast (model); } // // Pick a random start index in the list // int count = model->Get_Num_Sub_Objects (); int start_index = FreeRandom.Get_Int ( count ); // // Loop over all the objects // for (int index = 0; mesh == NULL && index < count; index ++) { // // Get a pointer to the current subobject // int real_index = (start_index + index) % count; RenderObjClass *subobj = model->Get_Sub_Object (real_index); if (subobj != NULL) { // // Try to find a mesh inside this object // mesh = Find_Random_Mesh (subobj); REF_PTR_RELEASE (subobj); } } return mesh; } //////////////////////////////////////////////////////////////// // // Update_Repairing_Animations // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Update_Repairing_Animations (void) { // // Loop over all the vehicles that are currently being repaired // for (int index = 0; index < VehicleList.Count (); index ++) { ScriptableGameObj *game_obj = VehicleList[index]; if (game_obj != NULL) { PhysicalGameObj *physical_game_obj = game_obj->As_PhysicalGameObj (); RenderObjClass *model = physical_game_obj->Peek_Model (); if (model != NULL) { // // Randomize the welding-arc's that this vehicle gets // if (FreeRandom.Get_Int (4) == 1) { Emit_Welding_Arc (model); } } } } return ; } //////////////////////////////////////////////////////////////// // // Emit_Welding_Arc // //////////////////////////////////////////////////////////////// void RepairBayGameObj::Emit_Welding_Arc (RenderObjClass *vehicle_model) { if (RepairMesh == NULL) { return ; } // // Pick a random "arc welder" to emit the animation from // Vector3 startpoint (0, 0, 0); Get_Position (&startpoint); // // Pick a random bone to emit the animation from // RenderObjClass *aggregate_model = RepairMesh->Peek_Model (); int count = 8;//aggregate_model->Get_Num_Bones (); int bone_index = FreeRandom.Get_Int (count) + 1; StringClass bone_name; bone_name.Format ("REP^NODRIM_FX%d", bone_index); startpoint = aggregate_model->Get_Bone_Transform (bone_name).Get_Translation (); // // Default the end of the vector to the vehicles start position // Vector3 endpoint = vehicle_model->Get_Transform ().Get_Translation (); // // Find a random mesh inside the vehicle's model // MeshClass *mesh = Find_Random_Mesh (vehicle_model); if (mesh != NULL) { MeshModelClass *mesh_model = mesh->Get_Model (); if (mesh_model != NULL) { // // Get a random vertex inside the model // int vertex_count = mesh_model->Get_Vertex_Count (); int random_vert_index = FreeRandom.Get_Int (vertex_count); if (vertex_count > 0) { endpoint = mesh->Get_Transform () * mesh_model->Get_Vertex_Array ()[random_vert_index]; } REF_PTR_RELEASE (mesh_model); } } // // Try to find an available welding-arc // for (int index = 0; index < ARC_OBJ_COUNT; index ++) { if ((ArcLifeRemaining[index] <= 0) && (FreeRandom.Get_Int (4) == 1)) { // // Get the model of the object we'll be displaying // RenderObjClass *model = ArcObjects[index]->Peek_Physical_Object ()->Peek_Model (); //startpoint.Set (0, 0, 0); //endpoint.Set (0, 0, 10); // // Make the object "look" at its endpoint // Matrix3D start_tm; start_tm.Obj_Look_At (startpoint, endpoint, 0); model->Set_Transform (start_tm); // // Now scale the bone's that control the length of the arc so it // will fit perfectly between the start and endpoints. // for (int bone_index = 0; bone_index < BONE_COUNT; bone_index ++) { float percent = WWMath::Fabs (Bones[bone_index].Get_Translation ().X / EndTM.Get_Translation ().X); Vector3 new_pos = startpoint + (endpoint - startpoint) * percent; // // Calculate the world space position of the bone // Vector3 world_space_pos = start_tm * Bones[bone_index].Get_Translation (); Vector3 world_space_offset = new_pos - world_space_pos; Matrix3D bone_tm (world_space_offset); // // Control the bone // int bone_id = model->Get_Bone_Index (BoneNames[bone_index]); model->Capture_Bone (bone_id); model->Control_Bone (bone_id, bone_tm, true); } // // Calculate the world space position of the endpoint // Vector3 world_space_end_pos = start_tm * EndTM.Get_Translation (); Vector3 world_space_offset = endpoint - world_space_end_pos; Matrix3D end_tm (world_space_offset); // // Control the ending bone // int end_index = model->Get_Bone_Index ("bone_end"); model->Capture_Bone (end_index); model->Control_Bone (end_index, end_tm, true); // // Start the animation // ArcLifeRemaining[index] = 3.0F; HAnimClass *anim = model->Peek_Animation (); if (anim != NULL) { model->Set_Animation (anim, 0, RenderObjClass::ANIM_MODE_ONCE); ArcLifeRemaining[index] = anim->Get_Total_Time (); } // // Show the model // model->Set_Hidden (false); } } return ; } ///////////////////////////////////////////////////////////////////////////// // // Export_Creation // ///////////////////////////////////////////////////////////////////////////// void RepairBayGameObj::Export_Creation (BitStreamClass &packet) { BuildingGameObj::Export_Creation (packet); // // Send the repair zone's position and size // packet.Add (RepairZone.Center.X, BITPACK_WORLD_POSITION_X); packet.Add (RepairZone.Center.Y, BITPACK_WORLD_POSITION_Y); packet.Add (RepairZone.Center.Z, BITPACK_WORLD_POSITION_Z); packet.Add (RepairZone.Extent.X, BITPACK_WORLD_POSITION_X); packet.Add (RepairZone.Extent.Y, BITPACK_WORLD_POSITION_Y); packet.Add (RepairZone.Extent.Z, BITPACK_WORLD_POSITION_Z); // // Send the zone's facing (almost 100% of the time, this zone should // simply be an AABox rotated about its Z-axis). // float facing = RepairZone.Basis.Get_Z_Rotation (); packet.Add (facing); return ; } ///////////////////////////////////////////////////////////////////////////// // // Import_Creation // ///////////////////////////////////////////////////////////////////////////// void RepairBayGameObj::Import_Creation (BitStreamClass &packet) { BuildingGameObj::Import_Creation (packet); // // Get the repair zone's position and size // packet.Get (RepairZone.Center.X, BITPACK_WORLD_POSITION_X); packet.Get (RepairZone.Center.Y, BITPACK_WORLD_POSITION_Y); packet.Get (RepairZone.Center.Z, BITPACK_WORLD_POSITION_Z); packet.Get (RepairZone.Extent.X, BITPACK_WORLD_POSITION_X); packet.Get (RepairZone.Extent.Y, BITPACK_WORLD_POSITION_Y); packet.Get (RepairZone.Extent.Z, BITPACK_WORLD_POSITION_Z); // // Get the zone's facing (almost 100% of the time, this zone should // simply be an AABox rotated about its Z-axis). // float facing = 0; packet.Get (facing); RepairZone.Basis.Rotate_Z (facing); return ; }