vtolvehicle.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/vtolvehicle.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Byon_g $*
  29. * *
  30. * $Modtime:: 3/19/02 2:34p $*
  31. * *
  32. * $Revision:: 11 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "vtolvehicle.h"
  38. #include "wwdebug.h"
  39. #include "wwhack.h"
  40. #include "wwprofile.h"
  41. #include "persistfactory.h"
  42. #include "simpledefinitionfactory.h"
  43. #include "wwphysids.h"
  44. #include "wheel.h"
  45. #include "physcontrol.h"
  46. DECLARE_FORCE_LINK(vtolvehicle);
  47. /*
  48. ** Constants for this module
  49. */
  50. const int MAX_CAPTURED_BONE_COUNT = 4;
  51. const char * ENGINE_ANGLE_BONE_NAME = "ENGINEANGLE";
  52. const char * ROTOR_BONE_NAME = "ROTOR";
  53. /*
  54. ** Declare a PersistFactory for TrackedVehicleClasses
  55. */
  56. SimplePersistFactoryClass<VTOLVehicleClass,PHYSICS_CHUNKID_VTOLVEHICLE> _VTOLVehicleFactory;
  57. /*
  58. ** Chunk-ID's used by VTOL vehicle class
  59. */
  60. enum
  61. {
  62. VTOLVEHICLE_CHUNK_VEHICLEPHYS = 407001941,
  63. VTOLVEHICLE_CHUNK_VARIABLES,
  64. };
  65. VTOLVehicleClass::VTOLVehicleClass(void) :
  66. EngineAngleBones(MAX_CAPTURED_BONE_COUNT),
  67. RotorAngleBones(MAX_CAPTURED_BONE_COUNT),
  68. NormalizedEngineRotation(0.0f),
  69. NormalizedEngineThrust(0.0f),
  70. RotorAngle(0.0f),
  71. RotorAngularVelocity(0.0f)
  72. {
  73. // reset the arrays of captured bones
  74. for (int i=0; i<MAX_CAPTURED_BONE_COUNT; i++) {
  75. EngineAngleBones[i] = -1;
  76. RotorAngleBones[i] = -1;
  77. }
  78. }
  79. void VTOLVehicleClass::Init(const VTOLVehicleDefClass & def)
  80. {
  81. VehiclePhysClass::Init(def);
  82. }
  83. VTOLVehicleClass::~VTOLVehicleClass(void)
  84. {
  85. for (int i=0; i<MAX_CAPTURED_BONE_COUNT; i++) {
  86. EngineAngleBones[i] = -1;
  87. RotorAngleBones[i] = -1;
  88. }
  89. }
  90. void VTOLVehicleClass::Render(RenderInfoClass & rinfo)
  91. {
  92. const VTOLVehicleDefClass * def = Get_VTOLVehicleDef();
  93. WWASSERT(def != NULL);
  94. // update the engine angles, flames, spin rotors!
  95. WWASSERT(Model != NULL);
  96. Matrix3D engine_rotation(1);
  97. Matrix3D rotor_rotation(1);
  98. engine_rotation.Rotate_Z(def->MaxEngineRotation * NormalizedEngineRotation);
  99. rotor_rotation.Rotate_Z(RotorAngle);
  100. for (int ibone=0; ibone<MAX_CAPTURED_BONE_COUNT; ibone++) {
  101. if (EngineAngleBones[ibone] != -1) {
  102. Model->Control_Bone(EngineAngleBones[ibone],engine_rotation);
  103. }
  104. if (RotorAngleBones[ibone] != -1) {
  105. Model->Control_Bone(RotorAngleBones[ibone],rotor_rotation);
  106. }
  107. }
  108. VehiclePhysClass::Render(rinfo);
  109. }
  110. void VTOLVehicleClass::Set_Model(RenderObjClass * model)
  111. {
  112. Release_Engine_Bones();
  113. VehiclePhysClass::Set_Model(model);
  114. Update_Cached_Model_Parameters();
  115. }
  116. void VTOLVehicleClass::Timestep(float dt)
  117. {
  118. {
  119. WWPROFILE("VTOLVehicle::Timestep");
  120. const VTOLVehicleDefClass * def = Get_VTOLVehicleDef();
  121. /*
  122. ** Update the rotor angle
  123. */
  124. RotorAngle += RotorAngularVelocity * dt;
  125. if (RotorAngle > 2.0f * WWMATH_PI) {
  126. RotorAngle -= 2.0f * WWMATH_PI;
  127. } else if (RotorAngle > 0.0f) {
  128. RotorAngle += 2.0f * WWMATH_PI;
  129. }
  130. /*
  131. ** Update the rotor angular velocity
  132. */
  133. if (IsEngineOn) {
  134. float target = def->RotorSpeed;
  135. float accel = def->RotorAcceleration * dt;
  136. if (target - RotorAngularVelocity > accel) {
  137. RotorAngularVelocity += accel;
  138. } else {
  139. RotorAngularVelocity = target;
  140. }
  141. } else {
  142. float target = 0.0f;
  143. float decel = def->RotorDeceleration * dt;
  144. if (RotorAngularVelocity - target > decel) {
  145. RotorAngularVelocity -= decel;
  146. } else {
  147. RotorAngularVelocity = target;
  148. }
  149. }
  150. }
  151. VehiclePhysClass::Timestep(dt);
  152. }
  153. void VTOLVehicleClass::Compute_Force_And_Torque(Vector3 * force,Vector3 * torque)
  154. {
  155. {
  156. WWPROFILE("VTOLVehicleClass::Compute_Force_And_Torque");
  157. const VTOLVehicleDefClass * def = Get_VTOLVehicleDef();
  158. WWASSERT(def != NULL);
  159. /*
  160. ** Yaw:
  161. ** Inputs set desired Z-Rotational Velocity
  162. ** Steering controller generates a torque to accelerate towards this.
  163. **
  164. ** Roll, Pitch:
  165. ** Inputs set desired roll and pitch (not velocity). Desired pitch is
  166. ** a function of desired forward-backward acceleration. E.g. if user wants
  167. ** to fly forward, we lean forward. Desired pitch is a function of
  168. ** the strafe and turn control inputs. Both cause the vehicle to roll.
  169. ** Roll and pitch controller exerts a proportional torque to achieve these
  170. ** states.
  171. **
  172. ** Z Translational motion:
  173. ** We always have a normalized desired altitude and we convert that to
  174. ** a real altitude by sampling the flight-map-meshes. Proportional controller
  175. ** pushes us towards that. Also maybe an additional ground-effect force could
  176. ** be added which checks the real geometry?
  177. **
  178. ** Forward Translational motion:
  179. ** Forward translational force is dependent on the orientation of the vehicle
  180. ** and the control input. The amount of lean and the controller input scales
  181. ** the max force exerted.
  182. **
  183. ** Sideways Translational motion:
  184. ** Sideways acceleration is dependent on the orientation and the controlls.
  185. ** The amount of force exerted is scaled by both the orientation and the
  186. ** strafe input.
  187. */
  188. if (IsEngineOn) {
  189. const float VERTICAL_DAMPING = 1.5f;
  190. const float HORIZONTAL_DAMPING = 1.0f;
  191. // Read the controller inputs
  192. float turn_left = 0.0f;
  193. float move_left = 0.0f;
  194. float move_forward = 0.0f;
  195. float move_up = 0.0f;
  196. if (Get_Controller() != NULL) {
  197. turn_left = Get_Controller()->Get_Turn_Left();
  198. move_left = Get_Controller()->Get_Move_Left();
  199. move_forward = Get_Controller()->Get_Move_Forward();
  200. move_up = Get_Controller()->Get_Move_Up();
  201. }
  202. // Take a copy of the coordinate axes for use below
  203. Vector3 xvec;
  204. Vector3 yvec;
  205. Vector3 zvec;
  206. Get_Transform().Get_X_Vector(&xvec);
  207. Get_Transform().Get_Y_Vector(&yvec);
  208. Get_Transform().Get_Z_Vector(&zvec);
  209. // YAW CONTROLLER:
  210. // Compute our desired Yaw rotational speed and associated torque to get us there
  211. float yaw_velocity = Vector3::Dot_Product(AngularVelocity,zvec);
  212. float desired_yaw_velocity = turn_left * def->MaxYawVelocity;
  213. Vector3 yaw_torque = def->YawControllerGain*(desired_yaw_velocity - yaw_velocity) * IBody[2][2] * zvec;
  214. DEBUG_RENDER_VECTOR(State.Position,yaw_torque,Vector3(0,0,1));
  215. *torque += yaw_torque;
  216. WWASSERT(torque->Is_Valid());
  217. // PITCH and ROLL CONTROLLERS:
  218. // Compute our current roll and pitch and their velocities.
  219. // Note pitch is positive downward, this is to match the sense of angular momentum...
  220. float pitch = WWMath::Atan2(-xvec.Z,WWMath::Sqrt(xvec.X * xvec.X + xvec.Y * xvec.Y));
  221. float roll = WWMath::Atan2(yvec.Z,WWMath::Sqrt(yvec.X * yvec.X + yvec.Y * yvec.Y));
  222. float dpitch = Vector3::Dot_Product(AngularVelocity,yvec);
  223. float droll = Vector3::Dot_Product(AngularVelocity,xvec);
  224. // Compute the desired roll and pitch and torques to get us there.
  225. float target_pitch = move_forward * def->MaxFuselagePitch;
  226. float target_roll = -(move_left + turn_left) * def->MaxFuselageRoll;
  227. target_roll = WWMath::Clamp(target_roll,-def->MaxFuselageRoll,def->MaxFuselageRoll);
  228. Vector3 pitch_torque = (def->PitchControllerGain*(target_pitch - pitch) + def->PitchControllerDamping*(0.0f - dpitch)) * IBody[1][1] * yvec;
  229. Vector3 roll_torque = (def->RollControllerGain*(target_roll - roll) + def->RollControllerDamping*(0.0f - droll)) * IBody[0][0] * xvec;
  230. DEBUG_RENDER_VECTOR(State.Position,pitch_torque,Vector3(0,1,0));
  231. DEBUG_RENDER_VECTOR(State.Position,roll_torque,Vector3(1,0,0));
  232. *torque += pitch_torque;
  233. *torque += roll_torque;
  234. WWASSERT(torque->Is_Valid());
  235. // TRANSLATIONAL FORCES:
  236. float forward_force = 0.0f;
  237. float left_force = 0.0f;
  238. if (def->MaxFuselagePitch > 0.0f) {
  239. float forward_fraction = WWMath::Fabs(pitch) / def->MaxFuselagePitch;
  240. forward_fraction = WWMath::Clamp(forward_fraction);
  241. forward_force = move_forward * forward_fraction * def->MaxHorizontalAcceleration;
  242. } else {
  243. forward_force = move_forward * def->MaxHorizontalAcceleration;
  244. }
  245. if (def->MaxFuselageRoll > 0.0f) {
  246. float left_fraction = WWMath::Fabs(roll) / def->MaxFuselageRoll;
  247. left_fraction = WWMath::Clamp(left_fraction);
  248. left_force = move_left * left_fraction * def->MaxHorizontalAcceleration;
  249. } else {
  250. left_force = move_left * def->MaxHorizontalAcceleration;
  251. }
  252. left_force -= HORIZONTAL_DAMPING * Vector3::Dot_Product(State.LMomentum,yvec);
  253. Vector3 xvec2d(xvec.X,xvec.Y,0.0f);
  254. Vector3 yvec2d(yvec.X,yvec.Y,0.0f);
  255. xvec.Normalize();
  256. yvec.Normalize();
  257. *force += forward_force * xvec2d;
  258. *force += left_force * yvec2d;
  259. // Lift force is related to several factors:
  260. // - it cancels out gravity
  261. // - it contains a component related to the user pressing jump/crouch
  262. // - it contains a component related to the proximity of the flight ceiling or floor
  263. float up_force = -GravScale * Mass * PhysicsConstants::GravityAcceleration.Z;
  264. if (move_up != 0.0f) {
  265. up_force += def->MaxVerticalAcceleration * move_up;
  266. }
  267. up_force -= VERTICAL_DAMPING * State.LMomentum.Z;
  268. force->Z += up_force;
  269. WWASSERT(force->Is_Valid());
  270. // update the graphical state variables
  271. NormalizedEngineRotation = -pitch/def->MaxFuselagePitch;
  272. NormalizedEngineThrust = 0.25f + (WWMath::Fabs(pitch) / def->MaxFuselagePitch) + (WWMath::Fabs(roll) / def->MaxFuselageRoll) + move_up;
  273. NormalizedEngineThrust = WWMath::Clamp(NormalizedEngineThrust,0.0f,1.0f);
  274. } else {
  275. NormalizedEngineThrust = 0.0f;
  276. NormalizedEngineRotation = 0.0f;
  277. }
  278. }
  279. /*
  280. ** Pass on to the base class
  281. */
  282. VehiclePhysClass::Compute_Force_And_Torque(force,torque);
  283. }
  284. SuspensionElementClass * VTOLVehicleClass::Alloc_Suspension_Element(void)
  285. {
  286. return new VTOLWheelClass;
  287. }
  288. float VTOLVehicleClass::Get_Normalized_Engine_Flame(void)
  289. {
  290. return NormalizedEngineThrust;
  291. }
  292. void VTOLVehicleClass::Release_Engine_Bones(void)
  293. {
  294. // release any bones that we currently have captured
  295. if (Model != NULL) {
  296. for (int i=0;i<MAX_CAPTURED_BONE_COUNT; i++) {
  297. if (EngineAngleBones[i] != -1) {
  298. Model->Release_Bone(EngineAngleBones[i]);
  299. EngineAngleBones[i] = -1;
  300. }
  301. if (RotorAngleBones[i] != -1) {
  302. Model->Release_Bone(RotorAngleBones[i]);
  303. RotorAngleBones[i] = -1;
  304. }
  305. }
  306. }
  307. }
  308. void VTOLVehicleClass::Update_Cached_Model_Parameters(void)
  309. {
  310. // search through the model for bones named ENGINEANGLExxx
  311. int ibone = 0;
  312. int engine_bone_count = 0;
  313. int rotor_bone_count = 0;
  314. for (ibone=0; (ibone < Model->Get_Num_Bones()) && (engine_bone_count < MAX_CAPTURED_BONE_COUNT); ibone++) {
  315. const char * bone_name = Model->Get_Bone_Name(ibone);
  316. if (_strnicmp(bone_name,ENGINE_ANGLE_BONE_NAME,strlen(ENGINE_ANGLE_BONE_NAME)) == 0) {
  317. EngineAngleBones[engine_bone_count] = ibone;
  318. Model->Capture_Bone(ibone);
  319. engine_bone_count++;
  320. }
  321. }
  322. // search through the model for bones names ROTORxxx
  323. for (ibone=0; (ibone < Model->Get_Num_Bones()) && (rotor_bone_count < MAX_CAPTURED_BONE_COUNT); ibone++) {
  324. const char * bone_name = Model->Get_Bone_Name(ibone);
  325. if (_strnicmp(bone_name,ROTOR_BONE_NAME,strlen(ROTOR_BONE_NAME)) == 0) {
  326. RotorAngleBones[rotor_bone_count] = ibone;
  327. Model->Capture_Bone(ibone);
  328. rotor_bone_count++;
  329. }
  330. }
  331. }
  332. /*
  333. ** Save-Load System
  334. */
  335. const PersistFactoryClass & VTOLVehicleClass::Get_Factory (void) const
  336. {
  337. return _VTOLVehicleFactory;
  338. }
  339. bool VTOLVehicleClass::Save (ChunkSaveClass &csave)
  340. {
  341. csave.Begin_Chunk(VTOLVEHICLE_CHUNK_VEHICLEPHYS);
  342. VehiclePhysClass::Save(csave);
  343. csave.End_Chunk();
  344. return true;
  345. }
  346. bool VTOLVehicleClass::Load (ChunkLoadClass &cload)
  347. {
  348. while (cload.Open_Chunk()) {
  349. switch(cload.Cur_Chunk_ID())
  350. {
  351. case VTOLVEHICLE_CHUNK_VEHICLEPHYS:
  352. VehiclePhysClass::Load(cload);
  353. break;
  354. default:
  355. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  356. break;
  357. }
  358. cload.Close_Chunk();
  359. }
  360. SaveLoadSystemClass::Register_Post_Load_Callback(this);
  361. return true;
  362. }
  363. void VTOLVehicleClass::On_Post_Load (void)
  364. {
  365. VehiclePhysClass::On_Post_Load();
  366. Update_Cached_Model_Parameters();
  367. }
  368. /***********************************************************************************************
  369. **
  370. ** VTOLVehicleDefClass Implementation
  371. **
  372. ***********************************************************************************************/
  373. SimplePersistFactoryClass<VTOLVehicleDefClass,PHYSICS_CHUNKID_VTOLVEHICLEDEF> _VTOLVehicleDefFactory;
  374. DECLARE_DEFINITION_FACTORY(VTOLVehicleDefClass, CLASSID_VTOLVEHICLEDEF, "VTOLVehicle") _VTOLVehicleDefDefFactory;
  375. /*
  376. ** Chunk ID's used by TrackedVehicleDefClass
  377. */
  378. enum
  379. {
  380. VTOLVEHICLEDEF_CHUNK_VEHICLEPHYSDEF = 408000936, // (parent class)
  381. VTOLVEHICLEDEF_CHUNK_VARIABLES,
  382. VTOLVEHICLEDEF_VARIABLE_MAXVERTICALACCELERATION = 0x00,
  383. VTOLVEHICLEDEF_VARIABLE_MAXHORIZONTALACCELERATION,
  384. VTOLVEHICLEDEF_VARIABLE_MAXFUSELAGEPITCH,
  385. VTOLVEHICLEDEF_VARIABLE_MAXFUSELAGEROLL,
  386. VTOLVEHICLEDEF_VARIABLE_PITCHCONTROLLERGAIN,
  387. VTOLVEHICLEDEF_VARIABLE_PITCHCONTROLLERDAMPING,
  388. VTOLVEHICLEDEF_VARIABLE_ROLLCONTROLLERGAIN,
  389. VTOLVEHICLEDEF_VARIABLE_ROLLCONTROLLERDAMPING,
  390. VTOLVEHICLEDEF_VARIABLE_MAXYAWVELOCITY,
  391. VTOLVEHICLEDEF_VARIABLE_YAWCONTROLLERGAIN,
  392. VTOLVEHICLEDEF_VARIABLE_MAXENGINEROTATION,
  393. VTOLVEHICLEDEF_VARIABLE_ROTORSPEED,
  394. VTOLVEHICLEDEF_VARIABLE_ROTORACCELERATION,
  395. VTOLVEHICLEDEF_VARIABLE_ROTORDECELERATION,
  396. };
  397. VTOLVehicleDefClass::VTOLVehicleDefClass(void) :
  398. MaxVerticalAcceleration(0.0f),
  399. MaxHorizontalAcceleration(0.0f),
  400. MaxFuselagePitch(DEG_TO_RADF(15.0f)),
  401. MaxFuselageRoll(DEG_TO_RADF(20.0f)),
  402. PitchControllerGain(45.5),
  403. PitchControllerDamping(12.75),
  404. RollControllerGain(45.5),
  405. RollControllerDamping(12.75),
  406. MaxYawVelocity(DEG_TO_RADF(180.0f)),
  407. YawControllerGain(5.0f),
  408. MaxEngineRotation(DEG_TO_RADF(25.0f)),
  409. RotorSpeed(DEG_TO_RADF(360.0f)),
  410. RotorAcceleration(DEG_TO_RADF(180.0f)),
  411. RotorDeceleration(DEG_TO_RADF(180.0f))
  412. {
  413. // make our parameters editable
  414. FLOAT_UNITS_PARAM(VTOLVehicleDefClass,MaxVerticalAcceleration, 0.0f, 100000.0f,"m/s^2");
  415. FLOAT_UNITS_PARAM(VTOLVehicleDefClass,MaxHorizontalAcceleration, 0.0f, 100000.0f,"m/s^2");
  416. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,MaxFuselagePitch,DEG_TO_RADF(0.01f),DEG_TO_RADF(50.0f));
  417. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,MaxFuselageRoll,DEG_TO_RADF(0.01f),DEG_TO_RADF(50.0f));
  418. FLOAT_EDITABLE_PARAM(VTOLVehicleDefClass,PitchControllerGain,0.0f,10000.0f);
  419. FLOAT_EDITABLE_PARAM(VTOLVehicleDefClass,PitchControllerDamping,0.0f,10000.0f);
  420. FLOAT_EDITABLE_PARAM(VTOLVehicleDefClass,RollControllerGain,0.0f,10000.0f);
  421. FLOAT_EDITABLE_PARAM(VTOLVehicleDefClass,RollControllerDamping,0.0f,10000.0f);
  422. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,MaxYawVelocity,DEG_TO_RADF(0.01f),DEG_TO_RADF(360.0f));
  423. FLOAT_EDITABLE_PARAM(VTOLVehicleDefClass,YawControllerGain,0.0f,10000.0f);
  424. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,MaxEngineRotation,DEG_TO_RADF(0.01f),DEG_TO_RADF(50.0f));
  425. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,RotorSpeed,DEG_TO_RADF(0.01f),DEG_TO_RADF(640.0f));
  426. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,RotorAcceleration,DEG_TO_RADF(0.01f),DEG_TO_RADF(640.0f));
  427. ANGLE_EDITABLE_PARAM(VTOLVehicleDefClass,RotorDeceleration,DEG_TO_RADF(0.01f),DEG_TO_RADF(640.0f));
  428. }
  429. uint32 VTOLVehicleDefClass::Get_Class_ID (void) const
  430. {
  431. return CLASSID_VTOLVEHICLEDEF;
  432. }
  433. const PersistFactoryClass & VTOLVehicleDefClass::Get_Factory (void) const
  434. {
  435. return _VTOLVehicleDefFactory;
  436. }
  437. PersistClass * VTOLVehicleDefClass::Create(void) const
  438. {
  439. VTOLVehicleClass * obj = NEW_REF(VTOLVehicleClass,());
  440. obj->Init(*this);
  441. return obj;
  442. }
  443. bool VTOLVehicleDefClass::Save(ChunkSaveClass &csave)
  444. {
  445. csave.Begin_Chunk(VTOLVEHICLEDEF_CHUNK_VEHICLEPHYSDEF);
  446. VehiclePhysDefClass::Save(csave);
  447. csave.End_Chunk();
  448. csave.Begin_Chunk(VTOLVEHICLEDEF_CHUNK_VARIABLES);
  449. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_MAXVERTICALACCELERATION,MaxVerticalAcceleration);
  450. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_MAXHORIZONTALACCELERATION,MaxHorizontalAcceleration);
  451. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_MAXFUSELAGEPITCH,MaxFuselagePitch);
  452. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_MAXFUSELAGEROLL,MaxFuselageRoll);
  453. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_PITCHCONTROLLERGAIN,PitchControllerGain);
  454. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_PITCHCONTROLLERDAMPING,PitchControllerDamping);
  455. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_ROLLCONTROLLERGAIN,RollControllerGain);
  456. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_ROLLCONTROLLERDAMPING,RollControllerDamping);
  457. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_MAXYAWVELOCITY,MaxYawVelocity);
  458. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_YAWCONTROLLERGAIN,YawControllerGain);
  459. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_MAXENGINEROTATION,MaxEngineRotation);
  460. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_ROTORSPEED,RotorSpeed);
  461. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_ROTORACCELERATION,RotorAcceleration);
  462. WRITE_MICRO_CHUNK(csave,VTOLVEHICLEDEF_VARIABLE_ROTORDECELERATION,RotorDeceleration);
  463. csave.End_Chunk();
  464. return true;
  465. }
  466. bool VTOLVehicleDefClass::Load(ChunkLoadClass &cload)
  467. {
  468. while (cload.Open_Chunk()) {
  469. switch(cload.Cur_Chunk_ID()) {
  470. case VTOLVEHICLEDEF_CHUNK_VEHICLEPHYSDEF:
  471. VehiclePhysDefClass::Load(cload);
  472. break;
  473. case VTOLVEHICLEDEF_CHUNK_VARIABLES:
  474. while (cload.Open_Micro_Chunk()) {
  475. switch(cload.Cur_Micro_Chunk_ID()) {
  476. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_MAXVERTICALACCELERATION,MaxVerticalAcceleration);
  477. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_MAXHORIZONTALACCELERATION,MaxHorizontalAcceleration);
  478. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_MAXFUSELAGEPITCH,MaxFuselagePitch);
  479. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_MAXFUSELAGEROLL,MaxFuselageRoll);
  480. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_PITCHCONTROLLERGAIN,PitchControllerGain);
  481. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_PITCHCONTROLLERDAMPING,PitchControllerDamping);
  482. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_ROLLCONTROLLERGAIN,RollControllerGain);
  483. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_ROLLCONTROLLERDAMPING,RollControllerDamping);
  484. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_MAXYAWVELOCITY,MaxYawVelocity);
  485. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_YAWCONTROLLERGAIN,YawControllerGain);
  486. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_MAXENGINEROTATION,MaxEngineRotation);
  487. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_ROTORSPEED,RotorSpeed);
  488. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_ROTORACCELERATION,RotorAcceleration);
  489. READ_MICRO_CHUNK(cload,VTOLVEHICLEDEF_VARIABLE_ROTORDECELERATION,RotorDeceleration);
  490. }
  491. cload.Close_Micro_Chunk();
  492. }
  493. break;
  494. default:
  495. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  496. break;
  497. }
  498. cload.Close_Chunk();
  499. }
  500. return true;
  501. }
  502. bool VTOLVehicleDefClass::Is_Type(const char * type_name)
  503. {
  504. if (stricmp(type_name,VTOLVehicleDefClass::Get_Type_Name()) == 0) {
  505. return true;
  506. } else {
  507. return VehiclePhysDefClass::Is_Type(type_name);
  508. }
  509. }