TerrainLogic.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. ** Command & Conquer Generals(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: TerrainLogic.h ///////////////////////////////////////////////////////////////////////////
  24. // Logical terrain representation for the game logic side
  25. // Author: Colin Day, April 2001
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __TERRAINLOGIC_H_
  29. #define __TERRAINLOGIC_H_
  30. #include "Common/GameMemory.h"
  31. #include "Common/Snapshot.h"
  32. #include "Common/STLTypedefs.h"
  33. #include "GameClient/TerrainRoads.h"
  34. typedef std::vector<ICoord2D> VecICoord2D;
  35. class DataChunkInput;
  36. struct DataChunkInfo;
  37. class MapObject;
  38. class Object;
  39. class Dict;
  40. class PolygonTrigger;
  41. class ThingTemplate;
  42. class Vector3;
  43. class Drawable;
  44. class Matrix3D;
  45. class WaterHandle;
  46. class Xfer;
  47. enum WaypointID
  48. {
  49. INVALID_WAYPOINT_ID = 0x7FFFFFFF
  50. };
  51. //-------------------------------------------------------------------------------------------------
  52. // Waypoint
  53. /** Helper class for waypoint info in terrain logic.
  54. */
  55. class Waypoint : public MemoryPoolObject
  56. {
  57. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Waypoint, "Waypoint")
  58. // friends do not play well with MPO (srj)
  59. //friend class TerrainLogic;
  60. public:
  61. Waypoint(WaypointID id, AsciiString name, const Coord3D *pLoc, AsciiString label1,
  62. AsciiString label2, AsciiString label3, Bool biDirectional);
  63. //~Waypoint();
  64. enum {MAX_LINKS=8};
  65. protected:
  66. WaypointID m_id; ///< Unique integer identifier.
  67. AsciiString m_name; ///< Name.
  68. Coord3D m_location; ///< Location.
  69. Waypoint* m_pNext; ///< Linked list of all waypoints.
  70. Waypoint* m_links[MAX_LINKS]; ///< Directed graph of waypoints.
  71. Int m_numLinks; ///< Number of links in m_links.
  72. AsciiString m_pathLabel1;
  73. AsciiString m_pathLabel2;
  74. AsciiString m_pathLabel3;
  75. Bool m_biDirectional;
  76. public:
  77. // should be protected, but friendly access needed (srj)
  78. void setNext(Waypoint *pNext) {m_pNext = pNext; }
  79. //void setLink(Int ndx, Waypoint *pLink)
  80. //{
  81. // if (ndx>=0 && ndx <=MAX_LINKS) m_links[ndx] = pLink;
  82. //}
  83. void addLink(Waypoint* pLink)
  84. {
  85. if (m_numLinks < MAX_LINKS)
  86. {
  87. m_links[m_numLinks] = pLink;
  88. ++m_numLinks;
  89. }
  90. }
  91. public:
  92. /// Enumerate all waypoints using getNext.
  93. Waypoint *getNext(void) const {return m_pNext; }
  94. /// Enumerate the directed links from a waypoint using this,a nd getLink.
  95. Int getNumLinks(void) const {return m_numLinks; }
  96. /// Get the n'th directed link. (May be NULL).
  97. Waypoint *getLink(Int ndx) const {if (ndx>=0 && ndx <= MAX_LINKS) return m_links[ndx]; return NULL; }
  98. /// Get the waypoint's name.
  99. AsciiString getName(void) const {return m_name; }
  100. /// Get the integer id.
  101. WaypointID getID(void) const {return m_id; }
  102. /// Get the waypoint's position
  103. const Coord3D *getLocation( void ) const { return &m_location; }
  104. /// Get the waypoint's first path label
  105. AsciiString getPathLabel1( void ) const { return m_pathLabel1; }
  106. /// Get the waypoint's second path label
  107. AsciiString getPathLabel2( void ) const { return m_pathLabel2; }
  108. /// Get the waypoint's third path label
  109. AsciiString getPathLabel3( void ) const { return m_pathLabel3; }
  110. /// Get bi-directionality.
  111. Bool getBiDirectional( void ) const { return m_biDirectional; }
  112. void setLocationZ(Real z) { m_location.z = z; }
  113. };
  114. //-------------------------------------------------------------------------------------------------
  115. // Bridge
  116. /** Helper class for bridge info in terrain logic.
  117. */
  118. class BridgeInfo
  119. {
  120. public:
  121. BridgeInfo();
  122. public:
  123. Coord3D from, to; /// The points that the bridge was drawn using.
  124. Real bridgeWidth; /// Width of the bridge.
  125. Coord3D fromLeft, fromRight, toLeft, toRight; /// The 4 corners of the rectangle that the bridge covers.
  126. Int bridgeIndex; ///< The index to the drawable bridges.
  127. BodyDamageType curDamageState;
  128. ObjectID bridgeObjectID;
  129. ObjectID towerObjectID[ BRIDGE_MAX_TOWERS ];
  130. Bool damageStateChanged;
  131. };
  132. //-------------------------------------------------------------------------------------------------
  133. // Bridge
  134. /** Helper class for bridge info in terrain logic.
  135. */
  136. struct TBridgeAttackInfo
  137. {
  138. public:
  139. Coord3D attackPoint1, attackPoint2; /// The points that can be attacked..
  140. };
  141. //-------------------------------------------------------------------------------------------------
  142. //-------------------------------------------------------------------------------------------------
  143. class Bridge : public MemoryPoolObject
  144. {
  145. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Bridge, "Bridge")
  146. // friends do not play well with MPO (srj)
  147. //friend class TerrainLogic;
  148. public:
  149. public: // ctor/dtor.
  150. Bridge(BridgeInfo &theInfo, Dict *props, AsciiString bridgeTemplateName);
  151. Bridge(Object *bridgeObj);
  152. //~Bridge();
  153. protected:
  154. Bridge* m_next; ///< Link for traversing all bridges in the current map.
  155. AsciiString m_templateName; ///< bridge template name
  156. BridgeInfo m_bridgeInfo;
  157. Region2D m_bounds; /// 2d bounds for quick screening.
  158. PathfindLayerEnum m_layer; ///< Pathfind layer for this bridge.
  159. public:
  160. // should be protected, but friendly access needed (srj)
  161. void setNext(Bridge *pNext) {m_next = pNext; }
  162. Object *createTower( Coord3D *worldPos, BridgeTowerType towerPos,
  163. const ThingTemplate *towerTemplate, Object *bridge );
  164. public:
  165. /// return the bridge template name
  166. AsciiString getBridgeTemplateName( void ) { return m_templateName; }
  167. /// Enumerate all bridges using getNext;
  168. Bridge *getNext(void) {return m_next; }
  169. /// Get the height for an object on bridge. Note - assumes object is on bridge. Use isPointOnBridge to check.
  170. Real getBridgeHeight(const Coord3D *pLoc, Coord3D* normal);
  171. /// Get the bridges logical info.
  172. void getBridgeInfo(class BridgeInfo *pInfo) {*pInfo = m_bridgeInfo; }
  173. /// See if the point is on the bridge.
  174. Bool isPointOnBridge(const Coord3D *pLoc);
  175. Drawable *pickBridge(const Vector3 &from, const Vector3 &to, Vector3 *pos);
  176. void updateDamageState(void); ///< Updates a bridge's damage info.
  177. inline const BridgeInfo *peekBridgeInfo(void) const {return &m_bridgeInfo;}
  178. inline PathfindLayerEnum getLayer(void) const {return m_layer;}
  179. inline void setLayer(PathfindLayerEnum layer) {m_layer = layer;}
  180. const Region2D *getBounds(void) const {return &m_bounds;}
  181. Bool isCellOnEnd(const Region2D *cell); // Is pathfind cell on the sides of the bridge
  182. Bool isCellOnSide(const Region2D *cell); // Is pathfind cell on the end of the bridge
  183. Bool isCellEntryPoint(const Region2D *cell); // Is pathfind cell an entry point to the bridge
  184. inline void setBridgeObjectID( ObjectID id ) { m_bridgeInfo.bridgeObjectID = id; }
  185. inline void setTowerObjectID( ObjectID id, BridgeTowerType which ) { m_bridgeInfo.towerObjectID[ which ] = id; }
  186. };
  187. //-------------------------------------------------------------------------------------------------
  188. /** Device independent implementation for some functionality of the
  189. * logical terrain singleton */
  190. //-------------------------------------------------------------------------------------------------
  191. class TerrainLogic : public Snapshot,
  192. public SubsystemInterface
  193. {
  194. public:
  195. TerrainLogic();
  196. virtual ~TerrainLogic();
  197. virtual void init( void ); ///< Init
  198. virtual void reset( void ); ///< Reset
  199. virtual void update( void ); ///< Update
  200. virtual Bool loadMap( AsciiString filename, Bool query );
  201. virtual void newMap( Bool saveGame ); ///< Initialize the logic for new map.
  202. virtual Real getGroundHeight( Real x, Real y, Coord3D* normal = NULL ) const;
  203. virtual Real getLayerHeight(Real x, Real y, PathfindLayerEnum layer, Coord3D* normal = NULL, Bool clip = true) const;
  204. virtual void getExtent( Region3D *extent ) const { DEBUG_CRASH(("not implemented")); } ///< @todo This should not be a stub - this should own this functionality
  205. virtual void getExtentIncludingBorder( Region3D *extent ) const { DEBUG_CRASH(("not implemented")); } ///< @todo This should not be a stub - this should own this functionality
  206. virtual void getMaximumPathfindExtent( Region3D *extent ) const { DEBUG_CRASH(("not implemented")); } ///< @todo This should not be a stub - this should own this functionality
  207. virtual Coord3D findClosestEdgePoint( const Coord3D *closestTo ) const ;
  208. virtual Coord3D findFarthestEdgePoint( const Coord3D *farthestFrom ) const ;
  209. virtual Bool isClearLineOfSight(const Coord3D& pos, const Coord3D& posOther) const;
  210. virtual AsciiString getSourceFilename( void ) { return m_filenameString; }
  211. virtual PathfindLayerEnum alignOnTerrain( Real angle, const Coord3D& pos, Bool stickToGround, Matrix3D& mtx);
  212. virtual Bool isUnderwater( Real x, Real y, Real *waterZ = NULL, Real *terrainZ = NULL ); ///< is point under water
  213. virtual Bool isCliffCell( Real x, Real y) const; ///< is point cliff cell
  214. virtual const WaterHandle* getWaterHandle( Real x, Real y ); ///< get water handle at this location
  215. virtual const WaterHandle* getWaterHandleByName( AsciiString name ); ///< get water handle by name
  216. virtual Real getWaterHeight( const WaterHandle *water ); ///< get height of water table
  217. virtual void setWaterHeight( const WaterHandle *water,
  218. Real height,
  219. Real damageAmount,
  220. Bool forcePathfindUpdate ); ///< set height of water table
  221. virtual void changeWaterHeightOverTime( const WaterHandle *water,
  222. Real finalHeight,
  223. Real transitionTimeInSeconds,
  224. Real damageAmount );///< change water height over time
  225. virtual Waypoint *getFirstWaypoint(void) { return m_waypointListHead; }
  226. /// Return the waypoint with the given name
  227. virtual Waypoint *getWaypointByName( AsciiString name );
  228. /// Return the waypoint with the given ID
  229. virtual Waypoint *getWaypointByID( UnsignedInt id );
  230. /// Return the closest waypoint on the labeled path
  231. virtual Waypoint *getClosestWaypointOnPath( const Coord3D *pos, AsciiString label );
  232. /// Return true if the waypoint path containint pWay is labeled with the label.
  233. virtual Bool isPurposeOfPath( Waypoint *pWay, AsciiString label );
  234. /// Return the trigger area with the given name
  235. virtual PolygonTrigger *getTriggerAreaByName( AsciiString name );
  236. ///Gets the first bridge. Traverse all bridges using bridge->getNext();
  237. virtual Bridge *getFirstBridge(void) const { return m_bridgeListHead; }
  238. /// Find the bridge at a location. NULL means no bridge.
  239. virtual Bridge *findBridgeAt(const Coord3D *pLoc) const;
  240. /// Find the bridge at a location. NULL means no bridge. Note that the layer value will be used to resolve crossing bridges.
  241. virtual Bridge *findBridgeLayerAt(const Coord3D *pLoc, PathfindLayerEnum layer, Bool clip = true) const;
  242. /// Returns true if the object is close enough to interact with the bridge for pathfinding.
  243. virtual Bool objectInteractsWithBridgeLayer(Object *obj, Int layer, Bool considerBridgeHealth = true) const;
  244. /// Returns true if the object is close to one or the other end of the bridge.
  245. virtual Bool objectInteractsWithBridgeEnd(Object *obj, Int layer) const;
  246. virtual Drawable *pickBridge(const Vector3 &from, const Vector3 &to, Vector3 *pos);
  247. virtual void addBridgeToLogic(BridgeInfo *pInfo, Dict *props, AsciiString bridgeTemplateName); ///< Adds a bridge's logical info.
  248. virtual void addLandmarkBridgeToLogic(Object *bridgeObj); ///< Adds a bridge's logical info.
  249. virtual void deleteBridge( Bridge *bridge ); ///< remove a bridge
  250. virtual void updateBridgeDamageStates(void); ///< Updates bridge's damage info.
  251. Bool anyBridgesDamageStatesChanged(void) {return m_bridgeDamageStatesChanged; } ///< Bridge damage states updated.
  252. Bool isBridgeRepaired(const Object *bridge); ///< Is bridge repaired?
  253. Bool isBridgeBroken(const Object *bridge); ///< Is bridge Broken?
  254. void getBridgeAttackPoints(const Object *bridge, TBridgeAttackInfo *info); ///< Get bridge attack points.
  255. PathfindLayerEnum getLayerForDestination(const Coord3D *pos);
  256. // this is just like getLayerForDestination, but always return the highest layer that will be <= z at that point
  257. // (unlike getLayerForDestination, which will return the closest layer)
  258. PathfindLayerEnum getHighestLayerForDestination(const Coord3D *pos, Bool onlyHealthyBridges = false);
  259. void enableWaterGrid( Bool enable ); ///< enable/disable the water grid
  260. // This is stuff to get the currently active boundary information
  261. Int getActiveBoundary(void) { return m_activeBoundary; }
  262. void setActiveBoundary(Int newActiveBoundary);
  263. void flattenTerrain(Object *obj); ///< Flatten the terrain under a building.
  264. protected:
  265. // snapshot methods
  266. virtual void crc( Xfer *xfer );
  267. virtual void xfer( Xfer *xfer );
  268. virtual void loadPostProcess( void );
  269. /// Chunk parser callback.
  270. static Bool parseWaypointDataChunk(DataChunkInput &file, DataChunkInfo *info, void *userData);
  271. /// Chunk parser callback.
  272. Bool parseWaypointData(DataChunkInput &file, DataChunkInfo *info, void *userData);
  273. /// Add a waypoint to the list.
  274. void addWaypoint(MapObject *pMapObj);
  275. /// Add a directed link between waypoints.
  276. void addWaypointLink(Int id1, Int id2);
  277. /// Deletes all waypoints.
  278. void deleteWaypoints(void);
  279. /// Deletes all bridges.
  280. void deleteBridges(void);
  281. /// find the axis aligned region bounding the water table
  282. void findAxisAlignedBoundingRect( const WaterHandle *waterHandle, Region3D *region );
  283. UnsignedByte *m_mapData; ///< array of height samples
  284. Int m_mapDX; ///< width of map samples
  285. Int m_mapDY; ///< height of map samples
  286. VecICoord2D m_boundaries;
  287. Int m_activeBoundary;
  288. Waypoint *m_waypointListHead;
  289. Bridge *m_bridgeListHead;
  290. Bool m_bridgeDamageStatesChanged;
  291. AsciiString m_filenameString; ///< filename for terrain data
  292. Bool m_waterGridEnabled; ///< TRUE when water grid is enabled
  293. static WaterHandle m_gridWaterHandle; ///< water handle for the grid water (we only presently have one)
  294. //
  295. // we will force a limit of MAX_DYNAMIC_WATER as the max dynamically changable water
  296. // tables for a map. We could use a list, but eh, this is fine and small anyway
  297. //
  298. enum { MAX_DYNAMIC_WATER = 64 };
  299. struct DynamicWaterEntry
  300. {
  301. const WaterHandle *waterTable; ///< handle to water table to edit
  302. Real changePerFrame; ///< how much height to add to the water each frame (negative=lowering)
  303. Real targetHeight; ///< the target height we want to be at
  304. Real damageAmount; ///< amount of damage to do to objects that are underwater
  305. Real currentHeight; ///< we need to keep track of this ourselves cause some water height are represented with ints
  306. } m_waterToUpdate[ MAX_DYNAMIC_WATER ]; ///< water tables to dynamicall update
  307. Int m_numWaterToUpdate; ///< how many valid entries are in m_waterToUpdate
  308. }; // end class TerrainLogic
  309. // EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
  310. extern TerrainLogic *TheTerrainLogic; ///< singleton definition
  311. extern void makeAlignToNormalMatrix( Real angle, const Coord3D& pos, const Coord3D& normal, Matrix3D& mtx);
  312. extern Bool LineInRegion( const Coord2D *p1, const Coord2D *p2, const Region2D *clipRegion );
  313. #endif // end __TERRAINLOGIC_H_