Locomotor.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: Locomotor.h /////////////////////////////////////////////////////////////////////////////////
  24. // Author: Steven Johnson, Feb 2002
  25. // Desc: Locomotor Descriptions
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __Locomotor_H_
  29. #define __Locomotor_H_
  30. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  31. #include "Common/NameKeyGenerator.h"
  32. #include "Common/Override.h"
  33. #include "Common/Snapshot.h"
  34. #include "GameLogic/Damage.h"
  35. #include "GameLogic/LocomotorSet.h"
  36. // FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
  37. class Locomotor;
  38. class LocomotorTemplate;
  39. class INI;
  40. class PhysicsBehavior;
  41. enum BodyDamageType;
  42. enum PhysicsTurningType;
  43. // if we ever re-enable jets circling for landing, we need this. so keep in around just in case. (srj)
  44. #define NO_CIRCLE_FOR_LANDING
  45. //-------------------------------------------------------------------------------------------------
  46. enum LocomotorAppearance
  47. {
  48. LOCO_LEGS_TWO,
  49. LOCO_WHEELS_FOUR,
  50. LOCO_TREADS,
  51. LOCO_HOVER,
  52. LOCO_THRUST,
  53. LOCO_WINGS,
  54. LOCO_CLIMBER, // human climber - backs down cliffs.
  55. LOCO_OTHER,
  56. LOCO_MOTORCYCLE
  57. };
  58. enum LocomotorPriority
  59. {
  60. LOCO_MOVES_BACK=0, // In a group, this one moves toward the back
  61. LOCO_MOVES_MIDDLE=1, // In a group, this one stays in the middle
  62. LOCO_MOVES_FRONT=2 // In a group, this one moves toward the front of the group
  63. };
  64. #ifdef DEFINE_LOCO_APPEARANCE_NAMES
  65. static const char *TheLocomotorAppearanceNames[] =
  66. {
  67. "TWO_LEGS",
  68. "FOUR_WHEELS",
  69. "TREADS",
  70. "HOVER",
  71. "THRUST",
  72. "WINGS",
  73. "CLIMBER",
  74. "OTHER",
  75. "MOTORCYCLE",
  76. NULL
  77. };
  78. #endif
  79. //-------------------------------------------------------------------------------------------------
  80. enum LocomotorBehaviorZ
  81. {
  82. Z_NO_Z_MOTIVE_FORCE, // does whatever physics tells it, but has no z-force of its own.
  83. Z_SEA_LEVEL, // keep at surface-of-water level
  84. Z_SURFACE_RELATIVE_HEIGHT, // try to follow a specific height relative to terrain/water height
  85. Z_ABSOLUTE_HEIGHT, // try follow a specific height regardless of terrain/water height
  86. Z_FIXED_SURFACE_RELATIVE_HEIGHT, // stays fixed at surface-rel height, regardless of physics
  87. Z_FIXED_ABSOLUTE_HEIGHT, // stays fixed at absolute height, regardless of physics
  88. Z_RELATIVE_TO_GROUND_AND_BUILDINGS, // stays fixed at surface-rel height including buildings, regardless of physics
  89. Z_SMOOTH_RELATIVE_TO_HIGHEST_LAYER // try to follow a height relative to the highest layer.
  90. };
  91. #ifdef DEFINE_LOCO_Z_NAMES
  92. static const char *TheLocomotorBehaviorZNames[] =
  93. {
  94. "NO_Z_MOTIVE_FORCE",
  95. "SEA_LEVEL",
  96. "SURFACE_RELATIVE_HEIGHT",
  97. "ABSOLUTE_HEIGHT",
  98. "FIXED_SURFACE_RELATIVE_HEIGHT",
  99. "FIXED_ABSOLUTE_HEIGHT",
  100. "FIXED_RELATIVE_TO_GROUND_AND_BUILDINGS",
  101. "RELATIVE_TO_HIGHEST_LAYER",
  102. NULL
  103. };
  104. #endif
  105. //-------------------------------------------------------------------------------------------------
  106. class LocomotorTemplate : public Overridable
  107. {
  108. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( LocomotorTemplate, "LocomotorTemplate" )
  109. friend class Locomotor;
  110. public:
  111. LocomotorTemplate();
  112. /// field table for loading the values from an INI
  113. const FieldParse* getFieldParse() const;
  114. void friend_setName(const AsciiString& n) { m_name = n; }
  115. void validate();
  116. protected:
  117. private:
  118. /**
  119. Units check:
  120. -- Velocity: dist/frame
  121. -- Acceleration: dist/(frame*frame)
  122. -- Forces: (mass*dist)/(frame*frame)
  123. */
  124. AsciiString m_name;
  125. LocomotorSurfaceTypeMask m_surfaces; ///< flags indicating the kinds of surfaces we can use
  126. Real m_maxSpeed; ///< max speed
  127. Real m_maxSpeedDamaged; ///< max speed when "damaged"
  128. Real m_minSpeed; ///< we should never brake past this
  129. Real m_maxTurnRate; ///< max rate at which we can turn, in rads/frame
  130. Real m_maxTurnRateDamaged; ///< max turn rate when "damaged"
  131. Real m_acceleration; ///< max acceleration
  132. Real m_accelerationDamaged; ///< max acceleration when damaged
  133. Real m_lift; ///< max lifting acceleration (flying objects only)
  134. Real m_liftDamaged; ///< max lift when damaged
  135. Real m_braking; ///< max braking (deceleration)
  136. Real m_minTurnSpeed; ///< we must be going >= this speed in order to turn
  137. Real m_preferredHeight; ///< our preferred height (if flying)
  138. Real m_preferredHeightDamping; ///< how aggressively to adjust to preferred height: 1.0 = very much so, 0.1 = gradually, etc
  139. Real m_circlingRadius; ///< for flying things, the radius at which they circle their "maintain" destination. (pos = cw, neg = ccw, 0 = smallest possible)
  140. Real m_speedLimitZ; ///< try to avoid going up or down at more than this speed, if possible
  141. Real m_extra2DFriction; ///< extra 2dfriction to apply (via Physics)
  142. Real m_maxThrustAngle; ///< THRUST locos only: how much we deflect our thrust angle
  143. LocomotorBehaviorZ m_behaviorZ; ///< z-axis behavior
  144. LocomotorAppearance m_appearance; ///< how we should diddle the Drawable to imitate this motion
  145. LocomotorPriority m_movePriority; ///< Where we move - front, middle, back.
  146. Real m_accelPitchLimit; ///< Maximum amount we will pitch up under acceleration (including recoil.)
  147. Real m_decelPitchLimit; ///< Maximum amount we will pitch down under deceleration (including recoil.)
  148. Real m_bounceKick; ///< How much simulating rough terrain "bounces" a wheel up.
  149. Real m_pitchStiffness; ///< How stiff the springs are forward & back.
  150. Real m_rollStiffness; ///< How stiff the springs are side to side.
  151. Real m_pitchDamping; ///< How good the shock absorbers are.
  152. Real m_rollDamping; ///< How good the shock absorbers are.
  153. Real m_pitchByZVelCoef; ///< How much we pitch in response to z-speed.
  154. Real m_thrustRoll; ///< Thrust roll around X axis
  155. Real m_wobbleRate; ///< how fast thrust things "wobble"
  156. Real m_minWobble; ///< how much thrust things "wobble"
  157. Real m_maxWobble; ///< how much thrust things "wobble"
  158. Real m_forwardVelCoef; ///< How much we pitch in response to speed.
  159. Real m_lateralVelCoef; ///< How much we roll in response to speed.
  160. Real m_forwardAccelCoef; ///< How much we pitch in response to acceleration.
  161. Real m_lateralAccelCoef; ///< How much we roll in response to acceleration.
  162. Real m_uniformAxialDamping; ///< For Attenuating the pitch and roll rates
  163. Real m_turnPivotOffset; ///< should we pivot around noncenter? (-1.0 = rear, 0.0 = center, 1.0 = front)
  164. Int m_airborneTargetingHeight; ///< The height transition at witch I should mark myself as a AA target.
  165. Real m_closeEnoughDist; ///< How close we have to approach the end of a path before stopping
  166. Bool m_isCloseEnoughDist3D; ///< And is that calculation 3D, for very rare cases that need to move straight down.
  167. Real m_ultraAccurateSlideIntoPlaceFactor; ///< how much we can fudge turning when ultra-accurate
  168. Bool m_locomotorWorksWhenDead; ///< should locomotor continue working even when object is "dead"?
  169. Bool m_allowMotiveForceWhileAirborne; ///< can we apply motive when airborne?
  170. Bool m_apply2DFrictionWhenAirborne; // apply "2d friction" even when airborne... useful for realistic-looking movement
  171. Bool m_downhillOnly; // pinewood derby, moves only by gravity pulling downhill
  172. Bool m_stickToGround; // if true, can't leave ground
  173. Bool m_canMoveBackward; // if true, can move backwards.
  174. Bool m_hasSuspension; ///< If true, calculate 4 wheel independent suspension values.
  175. Real m_maximumWheelExtension; ///< Maximum distance wheels can move down. (negative value)
  176. Real m_maximumWheelCompression; ///< Maximum distance wheels can move up. (positive value)
  177. Real m_wheelTurnAngle; ///< How far the front wheels can turn.
  178. // Fields for wander locomotor
  179. Real m_wanderWidthFactor;
  180. Real m_wanderLengthFactor;
  181. Real m_wanderAboutPointRadius;
  182. Real m_rudderCorrectionDegree;
  183. Real m_rudderCorrectionRate;
  184. Real m_elevatorCorrectionDegree;
  185. Real m_elevatorCorrectionRate;
  186. };
  187. typedef OVERRIDE<LocomotorTemplate> LocomotorTemplateOverride;
  188. // ---------------------------------------------------------
  189. class Locomotor : public MemoryPoolObject, public Snapshot
  190. {
  191. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Locomotor, "Locomotor" )
  192. friend class LocomotorStore;
  193. public:
  194. void setPhysicsOptions(Object* obj);
  195. void locoUpdate_moveTowardsPosition(Object* obj, const Coord3D& goalPos,
  196. Real onPathDistToGoal, Real desiredSpeed, Bool *blocked);
  197. void locoUpdate_moveTowardsAngle(Object* obj, Real angle);
  198. /**
  199. Kill any current (2D) velocity (but stay at current position, or as close as possible)
  200. return true if we can maintain the position without being called every frame (eg, we are
  201. resting on the ground), false if not (eg, we are hovering or circling)
  202. */
  203. Bool locoUpdate_maintainCurrentPosition(Object* obj);
  204. Real getMaxSpeedForCondition(BodyDamageType condition) const; ///< get max speed given condition
  205. Real getMaxTurnRate(BodyDamageType condition) const; ///< get max turning rate given condition
  206. Real getMaxAcceleration(BodyDamageType condition) const; ///< get acceleration given condition
  207. Real getMaxLift(BodyDamageType condition) const; ///< get acceleration given condition
  208. Real getBraking() const; ///< get braking given condition
  209. inline Real getPreferredHeight() const { return m_preferredHeight;} ///< Just return preferredheight, no damage consideration
  210. inline void restorePreferredHeightFromTemplate() { m_preferredHeight = m_template->m_preferredHeight; };
  211. inline Real getPreferredHeightDamping() const { return m_preferredHeightDamping;}
  212. inline LocomotorAppearance getAppearance() const { return m_template->m_appearance; }
  213. inline LocomotorPriority getMovePriority() const { return m_template->m_movePriority; }
  214. inline LocomotorSurfaceTypeMask getLegalSurfaces() const { return m_template->m_surfaces; }
  215. inline AsciiString getTemplateName() const { return m_template->m_name;}
  216. inline Real getMinSpeed() const { return m_template->m_minSpeed;}
  217. inline Real getAccelPitchLimit() const { return m_template->m_accelPitchLimit;} ///< Maximum amount we will pitch up or down under acceleration (including recoil.)
  218. inline Real getDecelPitchLimit() const { return m_template->m_decelPitchLimit;} ///< Maximum amount we will pitch down under deceleration (including recoil.)
  219. inline Real getBounceKick() const { return m_template->m_bounceKick;} ///< How much simulating rough terrain "bounces" a wheel up.
  220. inline Real getPitchStiffness() const { return m_template->m_pitchStiffness;} ///< How stiff the springs are forward & back.
  221. inline Real getRollStiffness() const { return m_template->m_rollStiffness;} ///< How stiff the springs are side to side.
  222. inline Real getPitchDamping() const { return m_template->m_pitchDamping;} ///< How good the shock absorbers are.
  223. inline Real getRollDamping() const { return m_template->m_rollDamping;} ///< How good the shock absorbers are.
  224. inline Real getPitchByZVelCoef() const { return m_template->m_pitchByZVelCoef;} ///< How much we pitch in response to speed.
  225. inline Real getThrustRoll() const { return m_template->m_thrustRoll; } ///< Thrust roll
  226. inline Real getWobbleRate() const { return m_template->m_wobbleRate; } ///< how fast thrust things "wobble"
  227. inline Real getMaxWobble() const { return m_template->m_maxWobble; } ///< how much thrust things "wobble"
  228. inline Real getMinWobble() const { return m_template->m_minWobble; } ///< how much thrust things "wobble"
  229. inline Real getForwardVelCoef() const { return m_template->m_forwardVelCoef;} ///< How much we pitch in response to speed.
  230. inline Real getLateralVelCoef() const { return m_template->m_lateralVelCoef;} ///< How much we roll in response to speed.
  231. inline Real getForwardAccelCoef() const { return m_template->m_forwardAccelCoef;} ///< How much we pitch in response to acceleration.
  232. inline Real getLateralAccelCoef() const { return m_template->m_lateralAccelCoef;} ///< How much we roll in response to acceleration.
  233. inline Real getUniformAxialDamping() const { return m_template->m_uniformAxialDamping;} ///< How much we roll in response to acceleration.
  234. inline Real getTurnPivotOffset() const { return m_template->m_turnPivotOffset;}
  235. inline Bool getApply2DFrictionWhenAirborne() const { return m_template->m_apply2DFrictionWhenAirborne; }
  236. inline Bool getIsDownhillOnly() const { return m_template->m_downhillOnly; }
  237. inline Bool getAllowMotiveForceWhileAirborne() const { return m_template->m_allowMotiveForceWhileAirborne; }
  238. inline Int getAirborneTargetingHeight() const { return m_template->m_airborneTargetingHeight; }
  239. inline Bool getLocomotorWorksWhenDead() const { return m_template->m_locomotorWorksWhenDead; }
  240. inline Bool getStickToGround() const { return m_template->m_stickToGround; }
  241. inline Real getCloseEnoughDist() const { return m_closeEnoughDist; }
  242. inline Bool isCloseEnoughDist3D() const { return getFlag(IS_CLOSE_ENOUGH_DIST_3D); }
  243. inline Bool hasSuspension() const {return m_template->m_hasSuspension;}
  244. inline Bool canMoveBackwards() const {return m_template->m_canMoveBackward;}
  245. inline Real getMaxWheelExtension() const {return m_template->m_maximumWheelExtension;}
  246. inline Real getMaxWheelCompression() const {return m_template->m_maximumWheelCompression;}
  247. inline Real getWheelTurnAngle() const {return m_template->m_wheelTurnAngle;}
  248. inline Real getRudderCorrectionDegree() const { return m_template->m_rudderCorrectionDegree;} ///< How much we roll in response to acceleration.
  249. inline Real getRudderCorrectionRate() const { return m_template->m_rudderCorrectionRate;} ///< How much we roll in response to acceleration.
  250. inline Real getElevatorCorrectionDegree() const { return m_template->m_elevatorCorrectionDegree;} ///< How much we roll in response to acceleration.
  251. inline Real getElevatorCorrectionRate() const { return m_template->m_elevatorCorrectionRate;} ///< How much we roll in response to acceleration.
  252. inline Real getWanderWidthFactor() const {return m_template->m_wanderWidthFactor;}
  253. inline Real getWanderAboutPointRadius() const {return m_template->m_wanderAboutPointRadius;}
  254. Real calcMinTurnRadius(BodyDamageType condition, Real* timeToTravelThatDist) const;
  255. /// this is handy for doing things like forcing helicopters to crash realistically: cut their lift.
  256. inline void setMaxLift(Real lift) { m_maxLift = lift; }
  257. inline void setMaxSpeed(Real speed)
  258. {
  259. DEBUG_ASSERTCRASH(!(speed <= 0.0f && m_template->m_appearance == LOCO_THRUST), ("THRUST locos may not have zero speeds!\n"));
  260. m_maxSpeed = speed;
  261. }
  262. inline void setMaxAcceleration(Real accel) { m_maxAccel = accel; }
  263. inline void setMaxBraking(Real braking) { m_maxBraking = braking; }
  264. inline void setMaxTurnRate(Real turn) { m_maxTurnRate = turn; }
  265. inline void setAllowInvalidPosition(Bool allow) { setFlag(ALLOW_INVALID_POSITION, allow); }
  266. inline void setCloseEnoughDist( Real dist ) { m_closeEnoughDist = dist; }
  267. inline void setCloseEnoughDist3D( Bool setting ) { setFlag(IS_CLOSE_ENOUGH_DIST_3D, setting); }
  268. inline Bool isInvalidPositionAllowed() const { return getFlag( ALLOW_INVALID_POSITION ); }
  269. inline void setPreferredHeight( Real height ) { m_preferredHeight = height; }
  270. #ifdef CIRCLE_FOR_LANDING
  271. /**
  272. if we are climbing/diving more than this, circle as needed rather
  273. than just diving or climbing directly. (only useful for Winged things)
  274. */
  275. inline void setAltitudeChangeThresholdForCircling(Real a) { m_circleThresh = a; }
  276. #endif
  277. /**
  278. when off (the default), things get to adjust their z-pos as their
  279. loco says (in particular, airborne things tend to try to fly at a preferred height).
  280. when on, they do their best to reach the specified zpos, even if it's not at their preferred height.
  281. this is used mainly for force missiles to swoop in on their target, and to force airplane takeoff/landing
  282. to go smoothly.
  283. */
  284. inline void setUsePreciseZPos(Bool u) { setFlag(PRECISE_Z_POS, u); }
  285. /**
  286. when off (the default), units slow down as they approach their target.
  287. when on, units go full speed till the end, and may overshoot their target.
  288. this is useful mainly in some weird, temporary situations where we know we are
  289. going to follow this move with another one... or for carbombs.
  290. */
  291. inline void setNoSlowDownAsApproachingDest(Bool u) { setFlag(NO_SLOW_DOWN_AS_APPROACHING_DEST, u); }
  292. /**
  293. when off (the default), units do their normal stuff.
  294. when on, we cheat and make very precise motion, regardless of loco settings.
  295. this is accomplished by cranking up the unit's turning rate, friction, lift (for airborne things),
  296. and possibly other things. This is useful mainly when doing maneuvers where precision
  297. is VITAL, such as airplane takeoff/landing.
  298. For ground units, it also allows units to have a destination off of a pathfing grid.
  299. */
  300. inline void setUltraAccurate(Bool u) { setFlag(ULTRA_ACCURATE, u); }
  301. inline Bool isUltraAccurate() const { return getFlag(ULTRA_ACCURATE); }
  302. inline Bool isMovingBackwards(void) const {return getFlag(MOVING_BACKWARDS);}
  303. void startMove(void); ///< Indicates that a move is starting, primarily to reset the donut timer. jba.
  304. protected:
  305. void moveTowardsPositionLegs(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  306. void moveTowardsPositionLegsWander(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  307. void moveTowardsPositionClimb(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  308. void moveTowardsPositionWheels(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  309. void moveTowardsPositionTreads(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  310. void moveTowardsPositionOther(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  311. void moveTowardsPositionHover(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  312. void moveTowardsPositionThrust(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  313. void moveTowardsPositionWings(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
  314. void maintainCurrentPositionThrust(Object* obj, PhysicsBehavior *physics);
  315. void maintainCurrentPositionOther(Object* obj, PhysicsBehavior *physics);
  316. void maintainCurrentPositionLegs(Object* obj, PhysicsBehavior *physics) { maintainCurrentPositionOther(obj, physics); }
  317. void maintainCurrentPositionWheels(Object* obj, PhysicsBehavior *physics) { maintainCurrentPositionOther(obj, physics); }
  318. void maintainCurrentPositionTreads(Object* obj, PhysicsBehavior *physics) { maintainCurrentPositionOther(obj, physics); }
  319. void maintainCurrentPositionHover(Object* obj, PhysicsBehavior *physics);
  320. void maintainCurrentPositionWings(Object* obj, PhysicsBehavior *physics);
  321. PhysicsTurningType rotateTowardsPosition(Object* obj, const Coord3D& goalPos, Real *relAngle=NULL);
  322. /*
  323. return true if we can maintain the position without being called every frame (eg, we are
  324. resting on the ground), false if not (eg, we are hovering or circling)
  325. */
  326. Bool handleBehaviorZ(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos);
  327. PhysicsTurningType rotateObjAroundLocoPivot(Object* obj, const Coord3D& goalPos, Real maxTurnRate, Real *relAngle = NULL);
  328. Real getSurfaceHtAtPt(Real x, Real y);
  329. Real calcLiftToUseAtPt(Object* obj, PhysicsBehavior *physics, Real curZ, Real surfaceAtPt, Real preferredHeight);
  330. Bool fixInvalidPosition(Object* obj, PhysicsBehavior *physics);
  331. protected:
  332. // snapshot methods
  333. virtual void crc( Xfer *xfer );
  334. virtual void xfer( Xfer *xfer );
  335. virtual void loadPostProcess( void );
  336. protected:
  337. Locomotor(const LocomotorTemplate* tmpl);
  338. // Note, "Law of the Big Three" applies here
  339. //Locomotor(); -- nope, we don't have a default ctor. (srj)
  340. Locomotor(const Locomotor& that);
  341. Locomotor& operator=(const Locomotor& that);
  342. //~Locomotor();
  343. private:
  344. //
  345. // Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
  346. // existing values!
  347. //
  348. enum LocoFlag
  349. {
  350. IS_BRAKING = 0,
  351. ALLOW_INVALID_POSITION,
  352. MAINTAIN_POS_IS_VALID,
  353. PRECISE_Z_POS,
  354. NO_SLOW_DOWN_AS_APPROACHING_DEST,
  355. OVER_WATER, // To allow things to move slower/faster over water and do special effects
  356. ULTRA_ACCURATE,
  357. MOVING_BACKWARDS, // If we are moving backwards.
  358. DOING_THREE_POINT_TURN, // If we are doing a 3 pt turn.
  359. CLIMBING, // If we are in the process of climbing.
  360. IS_CLOSE_ENOUGH_DIST_3D,
  361. OFFSET_INCREASING
  362. };
  363. inline Bool getFlag(LocoFlag f) const { return (m_flags & (1 << f)) != 0; }
  364. inline void setFlag(LocoFlag f, Bool b) { if (b) m_flags |= (1<<f); else m_flags &= ~(1<<f); }
  365. LocomotorTemplateOverride m_template; ///< the kind of Locomotor this is
  366. Coord3D m_maintainPos;
  367. Real m_brakingFactor;
  368. Real m_maxLift;
  369. Real m_maxSpeed;
  370. Real m_maxAccel;
  371. Real m_maxBraking;
  372. Real m_maxTurnRate;
  373. Real m_closeEnoughDist;
  374. #ifdef CIRCLE_FOR_LANDING
  375. Real m_circleThresh;
  376. #endif
  377. UnsignedInt m_flags;
  378. Real m_preferredHeight;
  379. Real m_preferredHeightDamping;
  380. Real m_angleOffset;
  381. Real m_offsetIncrement;
  382. UnsignedInt m_donutTimer; ///< Frame time to keep units from doing the donut. jba.
  383. };
  384. //-------------------------------------------------------------------------------------------------
  385. /**
  386. The "store" used to hold all the LocomotorTemplates in existence. This is usually used when creating
  387. an Object, but can be used at any time after that. (It is explicitly
  388. OK to swap an Object's Locomotor out at any given time.)
  389. */
  390. //-------------------------------------------------------------------------------------------------
  391. class LocomotorStore : public SubsystemInterface
  392. {
  393. public:
  394. LocomotorStore();
  395. ~LocomotorStore();
  396. void init() { };
  397. void reset();
  398. void update();
  399. /**
  400. Find the LocomotorTemplate with the given name. If no such LocomotorTemplate exists, return null.
  401. */
  402. const LocomotorTemplate* findLocomotorTemplate(NameKeyType namekey) const;
  403. LocomotorTemplate* findLocomotorTemplate(NameKeyType namekey);
  404. inline Locomotor* newLocomotor(const LocomotorTemplate *tmpl) const
  405. {
  406. return newInstance(Locomotor)(tmpl); // my, that was easy
  407. }
  408. // locoTemplate is who we're overriding
  409. LocomotorTemplate *newOverride(LocomotorTemplate *locoTemplate);
  410. static void parseLocomotorTemplateDefinition(INI* ini);
  411. protected:
  412. private:
  413. typedef std::map< NameKeyType, LocomotorTemplate*, std::less<NameKeyType> > LocomotorTemplateMap;
  414. LocomotorTemplateMap m_locomotorTemplates;
  415. };
  416. // EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
  417. extern LocomotorStore *TheLocomotorStore;
  418. #endif // __Locomotor_H_