PartitionManager.h 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561
  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: PartitionManager.h //////////////////////////////////////////////////////
  24. //-----------------------------------------------------------------------------
  25. //
  26. // Westwood Studios Pacific.
  27. //
  28. // Confidential Information
  29. // Copyright (C) 2001 - All Rights Reserved
  30. //
  31. //-----------------------------------------------------------------------------
  32. //
  33. // Project: RTS3
  34. //
  35. // File name: PartitionManager.h
  36. //
  37. // Created: Steven Johnson, September 2001
  38. //
  39. // Desc: Partition management, this system will allow us to partition the
  40. // objects in space, iterate objects in specified volumes,
  41. // regions, by types and other properties.
  42. //
  43. //-----------------------------------------------------------------------------
  44. #pragma once
  45. #ifndef __PARTITIONMANAGER_H_
  46. #define __PARTITIONMANAGER_H_
  47. //-----------------------------------------------------------------------------
  48. // Includes
  49. //-----------------------------------------------------------------------------
  50. #include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
  51. #include "GameLogic/ObjectIter.h"
  52. #include "Common/KindOf.h"
  53. #include "Common/Snapshot.h"
  54. #include "Common/Geometry.h"
  55. #include "GameClient/Display.h" // for ShroudLevel
  56. //-----------------------------------------------------------------------------
  57. // defines
  58. //-----------------------------------------------------------------------------
  59. /*
  60. Note, this isn't very accurate currently, so use with caution. (srj)
  61. */
  62. #define PM_CACHE_TERRAIN_HEIGHT
  63. /*
  64. 5% speed improvement, at cost of more memory.
  65. */
  66. #define FASTER_GCO
  67. const Real HUGE_DIST = 1000000.0f;
  68. //-----------------------------------------------------------------------------
  69. // Type Definitions
  70. //-----------------------------------------------------------------------------
  71. struct Coord3D;
  72. class CellAndObjectIntersection;
  73. class Object;
  74. class PartitionManager;
  75. class PartitionData;
  76. class PartitionFilter;
  77. class PartitionCell;
  78. class Player;
  79. class PolygonTrigger;
  80. class Squad;
  81. class Team;
  82. class ThingTemplate;
  83. class GhostObject;
  84. class CommandButton;
  85. enum CommandSourceType;
  86. // ----------------------------------------------------------------------------------------------
  87. enum ValueOrThreat
  88. {
  89. VOT_CashValue = 1,
  90. VOT_ThreatValue,
  91. VOT_NumItems
  92. };
  93. // ----------------------------------------------------------------------------------------------
  94. enum FindPositionFlags
  95. {
  96. FPF_NONE = 0x00000000, // no options, default behavior
  97. FPF_IGNORE_WATER = 0x00000001, // a position found underwater is ok
  98. FPF_WATER_ONLY = 0x00000002, // find positions in the water only
  99. FPF_IGNORE_ALL_OBJECTS = 0x00000004, // ignore all objects, positions inside objects are ok
  100. FPF_IGNORE_ALLY_OR_NEUTRAL_UNITS = 0x00000008, // ignore friendly units (requires relationshipObject)
  101. FPF_IGNORE_ALLY_OR_NEUTRAL_STRUCTURES = 0x00000010, // ignore friendly structures (requires relationshipObject)
  102. FPF_IGNORE_ENEMY_UNITS = 0x00000020, // ignore enemy units (requires relationshipObject)
  103. FPF_IGNORE_ENEMY_STRUCTURES = 0x00000040, // ignore enemy structures (requires relationshipObject)
  104. FPF_USE_HIGHEST_LAYER = 0x00000080, // examine pos on highest layer at given xy (rather than on ground layer)
  105. };
  106. // ----------------------------------------------------------------------------------------------
  107. const Real RANDOM_START_ANGLE = -99999.9f; ///< no start angle (an unlikely number to use for the start angle)
  108. struct FindPositionOptions
  109. {
  110. FindPositionOptions( void )
  111. {
  112. flags = FPF_NONE;
  113. minRadius = 0.0f;
  114. maxRadius = 0.0f;
  115. startAngle = RANDOM_START_ANGLE;
  116. maxZDelta = 1e10f; // ie, any z delta.
  117. ignoreObject = NULL;
  118. sourceToPathToDest = NULL;
  119. relationshipObject = NULL;
  120. };
  121. FindPositionFlags flags; ///< flags for finding the legal position
  122. Real minRadius; ///< min radius to search around
  123. Real maxRadius; ///< max radius to search around
  124. Real startAngle; ///< use this angle to start the search at
  125. Real maxZDelta; ///< maximum delta-z we will allow
  126. const Object *ignoreObject; ///< ignore this object in legal position checks
  127. const Object *sourceToPathToDest; ///< object that must be able to path to the position chosen
  128. const Object *relationshipObject; ///< object to use for relationship tests
  129. };
  130. //=====================================
  131. /** */
  132. //=====================================
  133. enum DistanceCalculationType
  134. {
  135. FROM_CENTER_2D = 0, ///< measure from Object center in 2d.
  136. FROM_CENTER_3D = 1, ///< measure from Object center in 3d.
  137. FROM_BOUNDINGSPHERE_2D = 2, ///< measure from Object bounding sphere in 2d.
  138. FROM_BOUNDINGSPHERE_3D = 3 ///< measure from Object bounding sphere in 3d.
  139. };
  140. //=====================================
  141. /**
  142. a Plain Old Data structure that is used to get optional results from collidesWith().
  143. */
  144. struct CollideLocAndNormal
  145. {
  146. Coord3D loc;
  147. Coord3D normal;
  148. };
  149. //=====================================
  150. /**
  151. PartitionContactList is a utility class used by the Partition Manager
  152. to hold potential collisions as it updates objects in the partition.
  153. It stores pairs of potentially-colliding objects (eliminating duplicates)
  154. for processing after all partitions are updated.
  155. */
  156. //=====================================
  157. class PartitionContactList;
  158. //=====================================
  159. /**
  160. This class (often called COI for short) is the abstraction
  161. of the intersection between an Object and a Partition Cell.
  162. For every Cell that an Object's geometry touches, even partially,
  163. we allocate a COI. This allows us to maintain an efficient two-way
  164. list, such that for every Object, we know the Cells that it touches;
  165. and, for every Cell, we know the Objects that touch it.
  166. */
  167. //=====================================
  168. class CellAndObjectIntersection // not MPO: we allocate these in arrays
  169. {
  170. private:
  171. PartitionCell *m_cell; ///< the cell being touched
  172. PartitionData *m_module; ///< the module (and thus, Object) touching
  173. CellAndObjectIntersection *m_prevCoi, *m_nextCoi; ///< if in use, next/prev in this cell. if not in use, next/prev free in this module.
  174. public:
  175. // Note, we allocate these in arrays, thus we must have a default ctor (and NOT descend from MPO)
  176. CellAndObjectIntersection();
  177. ~CellAndObjectIntersection();
  178. /**
  179. make 'this' refer to the specified cell and module. Normally, this
  180. involves updated the member variables and adding 'this' to the Cell's
  181. list of COIs.
  182. */
  183. void addCoverage(PartitionCell *cell, PartitionData *module);
  184. /**
  185. make 'this' refer to nothing at all. this involves resetting the member
  186. variables to null, and removing 'this' from the Cell's list of COI's.
  187. */
  188. void removeAllCoverage();
  189. /**
  190. return the Cell for this COI (null if the COI is not in use)
  191. */
  192. inline PartitionCell *getCell() { return m_cell; }
  193. /**
  194. return the Module for this COI (null if the COI is not in use)
  195. */
  196. inline PartitionData *getModule() { return m_module; }
  197. /**
  198. return the previous COI in the Cell's list of COIs.
  199. */
  200. inline CellAndObjectIntersection *getPrevCoi() { return m_prevCoi; }
  201. /**
  202. return the next COI in the Cell's list of COIs.
  203. */
  204. inline CellAndObjectIntersection *getNextCoi() { return m_nextCoi; }
  205. // only for use by PartitionCell.
  206. void friend_addToCellList(CellAndObjectIntersection **pListHead);
  207. void friend_removeFromCellList(CellAndObjectIntersection **pListHead);
  208. };
  209. /**
  210. This class encapsulates one area interaction with PartitionCells. The user decides what to do with it.
  211. */
  212. class SightingInfo : public MemoryPoolObject, public Snapshot
  213. {
  214. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( SightingInfo, "SightingInfo" );
  215. public:
  216. SightingInfo();
  217. void reset();
  218. Bool isInvalid() const;
  219. Coord3D m_where;
  220. Real m_howFar;
  221. PlayerMaskType m_forWhom; // ask not for whom the sighting is masked; it masks for thee
  222. UnsignedInt m_data; // Threat and value use as the value. Sighting uses it for a Timestamp
  223. protected:
  224. // snapshot method
  225. virtual void crc( Xfer *xfer );
  226. virtual void xfer( Xfer *xfer );
  227. virtual void loadPostProcess();
  228. };
  229. //=====================================
  230. /**
  231. We sometimes need to save whether or not an area was fogged or permanently revealed through a
  232. script. This helps us do so.
  233. */
  234. //=====================================
  235. enum
  236. {
  237. STORE_DONTTOUCH = 0,
  238. STORE_FOG = 1,
  239. STORE_PERMANENTLY_REVEALED = 2
  240. };
  241. struct ShroudStatusStoreRestore
  242. {
  243. std::vector<UnsignedByte> m_foggedOrRevealed[MAX_PLAYER_COUNT];
  244. Int m_cellsWide; // m_cellsHigh is computed by m_foggedOrRevealed[0].size() / m_cellsWide
  245. };
  246. //=====================================
  247. /**
  248. The world's terrain is partitioned into a large grid of Partition Cells.
  249. The Cell is the fundamental unit of space in the Partition Manager.
  250. */
  251. //=====================================
  252. class PartitionCell : public Snapshot // not MPO: allocated in an array
  253. {
  254. private:
  255. CellAndObjectIntersection* m_firstCoiInCell; ///< list of COIs in this cell (may be null).
  256. ShroudLevel m_shroudLevel[MAX_PLAYER_COUNT];
  257. #ifdef PM_CACHE_TERRAIN_HEIGHT
  258. Real m_loTerrainZ; ///< lowest terrain-pt in this cell
  259. Real m_hiTerrainZ; ///< highest terrain-pt in this cell
  260. #endif
  261. Int m_threatValue[MAX_PLAYER_COUNT];
  262. Int m_cashValue[MAX_PLAYER_COUNT];
  263. Short m_coiCount; ///< number of COIs in this cell.
  264. Short m_cellX; ///< x-coord of this cell within the Partition Mgr coords (NOT in world coords)
  265. Short m_cellY; ///< y-coord of this cell within the Partition Mgr coords (NOT in world coords)
  266. public:
  267. // Note, we allocate these in arrays, thus we must have a default ctor (and NOT descend from MPO)
  268. PartitionCell();
  269. #ifdef PM_CACHE_TERRAIN_HEIGHT
  270. void init(Int x, Int y, Real loZ, Real hiZ) { m_cellX = x; m_cellY = y; m_loTerrainZ = loZ; m_hiTerrainZ = hiZ; }
  271. #else
  272. void init(Int x, Int y) { m_cellX = x; m_cellY = y; }
  273. #endif
  274. ~PartitionCell();
  275. // --------------- inherited from Snapshot interface --------------
  276. void crc( Xfer *xfer );
  277. void xfer( Xfer *xfer );
  278. void loadPostProcess( void );
  279. Int getCoiCount() const { return m_coiCount; } ///< return number of COIs touching this cell.
  280. Int getCellX() const { return m_cellX; }
  281. Int getCellY() const { return m_cellY; }
  282. void addLooker( Int playerIndex );
  283. void removeLooker( Int playerIndex );
  284. void addShrouder( Int playerIndex );
  285. void removeShrouder( Int playerIndex );
  286. CellShroudStatus getShroudStatusForPlayer( Int playerIndex ) const;
  287. // @todo: All of these are inline candidates
  288. UnsignedInt getThreatValue( Int playerIndex );
  289. void addThreatValue( Int playerIndex, UnsignedInt threatValue );
  290. void removeThreatValue( Int playerIndex, UnsignedInt threatValue );
  291. UnsignedInt getCashValue( Int playerIndex );
  292. void addCashValue( Int playerIndex, UnsignedInt cashValue );
  293. void removeCashValue( Int playerIndex, UnsignedInt cashValue );
  294. void invalidateShroudedStatusForAllCois(Int playerIndex);
  295. #ifdef PM_CACHE_TERRAIN_HEIGHT
  296. inline Real getLoTerrain() const { return m_loTerrainZ; }
  297. inline Real getHiTerrain() const { return m_hiTerrainZ; }
  298. #endif
  299. void getCellCenterPos(Real& x, Real& y);
  300. inline CellAndObjectIntersection *getFirstCoiInCell() { return m_firstCoiInCell; }
  301. #ifdef _DEBUG
  302. void validateCoiList();
  303. #endif
  304. // intended only for CellAndObjectIntersection.
  305. void friend_addToCellList(CellAndObjectIntersection *coi);
  306. // intended only for CellAndObjectIntersection.
  307. void friend_removeFromCellList(CellAndObjectIntersection *coi);
  308. };
  309. //=====================================
  310. /**
  311. A PartitionData is the part of an Object that understands
  312. how to maintain the Object in the space partitioning system.
  313. */
  314. //=====================================
  315. class PartitionData : public MemoryPoolObject
  316. {
  317. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(PartitionData, "PartitionDataPool" )
  318. private:
  319. enum DirtyStatus
  320. {
  321. NOT_DIRTY,
  322. NEED_COLLISION_CHECK,
  323. NEED_CELL_UPDATE_AND_COLLISION_CHECK
  324. };
  325. Object *m_object; ///< Object this module is for
  326. GhostObject *m_ghostObject; ///< Temporary object used when real object is gone but player thinks it's there because of fog.
  327. PartitionData *m_next; ///< next module in master list
  328. PartitionData *m_prev; ///< prev module in master list
  329. PartitionData *m_nextDirty;
  330. PartitionData *m_prevDirty;
  331. Int m_coiArrayCount; ///< number of COIs allocated (may be more than are in use)
  332. Int m_coiInUseCount; ///< number of COIs that are actually in use
  333. CellAndObjectIntersection *m_coiArray; ///< The array of COIs
  334. Int m_doneFlag;
  335. DirtyStatus m_dirtyStatus;
  336. ObjectShroudStatus m_shroudedness[MAX_PLAYER_COUNT];
  337. ObjectShroudStatus m_shroudednessPrevious[MAX_PLAYER_COUNT]; ///<previous frames value of m_shroudedness
  338. Bool m_everSeenByPlayer[MAX_PLAYER_COUNT]; ///<whether this object has ever been seen by a given player.
  339. const PartitionCell *m_lastCell; ///< The last cell I thought my center was in.
  340. /**
  341. Given a shape's geometry and size parameters, calculate the maximum number of COIs
  342. that the object could possibly occupy.
  343. */
  344. Int calcMaxCoiForShape(GeometryType geom, Real majorRadius, Real minorRadius, Bool isSmall);
  345. /**
  346. Given an object's geometry and size parameters, calculate the maximum number of COIs
  347. that the object could possibly occupy. (This simply extracts the information from the object
  348. and calls calcMaxCoiForShape.)
  349. */
  350. Int calcMaxCoiForObject();
  351. /**
  352. allocate the array of COIs (m_coiArray) for this module.
  353. */
  354. void allocCoiArray();
  355. /**
  356. free the array of COIs (m_coiArray) for this module (if any).
  357. */
  358. void freeCoiArray();
  359. /**
  360. marks self as touching no cells. (and any previous cells as not touching self!)
  361. */
  362. void removeAllTouchedCells();
  363. /**
  364. this discards all current 'touch' information (via removeAllTouchedCells) and recalculates
  365. the cells touched by this module, based on the object's geometry. this will be called frequently and so
  366. needs to be as efficient as possible.
  367. */
  368. void updateCellsTouched();
  369. /**
  370. If you imagine the array of Partition Cells as pixels, then this method
  371. 'sets' the pixel [cell] at cell coordinate (x, y).
  372. */
  373. void addSubPixToCoverage(PartitionCell *cell);
  374. /**
  375. fill in the pixels covered by the given 'small' shape with the given
  376. center and radius. 'small' shapes are special in that they
  377. are always assumed to cover at most 4 Cells, and so we can use
  378. a more efficient special-purpose filler, rather than a general
  379. rasterizer.
  380. */
  381. void doSmallFill(
  382. Real centerX,
  383. Real centerY,
  384. Real radius
  385. );
  386. /// helper function for doCircleFill.
  387. void hLineCircle(Int x1, Int x2, Int y);
  388. /**
  389. fill in the pixels covered by the given circular shape with the given
  390. center and radius. Note that this is used for both spheres and cylinders.
  391. */
  392. void doCircleFill(
  393. Real centerX,
  394. Real centerY,
  395. Real radius
  396. );
  397. /**
  398. fill in the pixels covered by the given rectangular shape with the given
  399. center, dimensions, and rotation.
  400. */
  401. void doRectFill(
  402. Real centerX,
  403. Real centerY,
  404. Real halfsizeX,
  405. Real halfsizeY,
  406. Real angle
  407. );
  408. /**
  409. do a careful test of the geometries of 'this' and 'that', and return
  410. true iff the geometries touch (or intersect). if true is returned,
  411. loc will be filled in to the collision location, and normal will be
  412. filled in to the normal to the surface of 'this' at the collide location.
  413. */
  414. Bool collidesWith(const PartitionData *that, CollideLocAndNormal *cinfo) const;
  415. public:
  416. PartitionData();
  417. void attachToObject( Object* object );
  418. void detachFromObject( void );
  419. void attachToGhostObject(GhostObject* object);
  420. void detachFromGhostObject(void);
  421. void setNext( PartitionData *next ) { m_next = next; } ///< set next pointer
  422. PartitionData *getNext( void ) { return m_next; } ///< get the next pointer
  423. void setPrev( PartitionData *prev ) { m_prev = prev; } ///< set the prev pointer
  424. PartitionData *getPrev( void ) { return m_prev; } ///< get the prev pointer
  425. /// mark the given module as being "dirty", needing recalcing during next update phase.
  426. // if needToUpdateCells is true, we'll recalc the partition cells it touches and do collision testing.
  427. // if needToUpdateCells is false, we'll just do the collision testing.
  428. void makeDirty(Bool needToUpdateCells);
  429. Bool isInNeedOfUpdatingCells() const { return m_dirtyStatus == NEED_CELL_UPDATE_AND_COLLISION_CHECK; }
  430. Bool isInNeedOfCollisionCheck() const { return m_dirtyStatus != NOT_DIRTY; }
  431. void invalidateShroudedStatusForPlayer(Int playerIndex);
  432. void invalidateShroudedStatusForAllPlayers();
  433. ObjectShroudStatus getShroudedStatus(Int playerIndex);
  434. inline Int wasSeenByAnyPlayers() const ///<check if a player in the game has seen the object but is now looking at fogged version.
  435. {
  436. for (Int i=0; i<MAX_PLAYER_COUNT; i++)
  437. if (m_everSeenByPlayer[i] && m_shroudedness[i] == OBJECTSHROUD_FOGGED)
  438. return i;
  439. return i;
  440. }
  441. Int getControllingPlayerIndex() const;
  442. /**
  443. enumerate the objects that share space with 'this'
  444. (ie, the objects in the same Partition Cells) and
  445. add 'em to the given contact list. also, if self
  446. is intersecting the ground, add it to the list as a possible
  447. collide-with-ground.
  448. */
  449. void addPossibleCollisions(PartitionContactList *ctList);
  450. Object *getObject() { return m_object; } ///< return the Object that owns this module
  451. const Object *getObject() const { return m_object; } ///< return the Object that owns this module
  452. void friend_setObject(Object *object) { m_object = object;} ///< to be used only by the partition manager.
  453. GhostObject *getGhostObject() const { return m_ghostObject; } ///< return the ghost object that serves as fogged memory of object.
  454. void friend_setGhostObject(GhostObject *object) {m_ghostObject=object;} ///<used by ghost object manager to free link to partition data.
  455. void friend_setShroudednessPrevious(Int playerIndex,ObjectShroudStatus status); ///<only used to restore state after map border resizing and/or xfer!
  456. ObjectShroudStatus friend_getShroudednessPrevious(Int playerIndex) {return m_shroudednessPrevious[playerIndex];}
  457. void friend_removeAllTouchedCells() { removeAllTouchedCells(); } ///< this is only for use by PartitionManager
  458. void friend_updateCellsTouched() { updateCellsTouched(); } ///< this is only for use by PartitionManager
  459. Int friend_getCoiInUseCount() { return m_coiInUseCount; } ///< this is only for use by PartitionManager
  460. Bool friend_collidesWith(const PartitionData *that, CollideLocAndNormal *cinfo) const { return collidesWith(that, cinfo); } ///< this is only for use by PartitionContactList
  461. // these are only for use by getClosestObjects.
  462. // (note, if we ever use other bits in this, smarten this up...)
  463. Int friend_getDoneFlag() { return m_doneFlag; }
  464. void friend_setDoneFlag(Int i) { m_doneFlag = i; }
  465. inline Bool isInListDirtyModules(PartitionData* const* pListHead) const
  466. {
  467. Bool result = (*pListHead == this || m_prevDirty || m_nextDirty);
  468. DEBUG_ASSERTCRASH(result == (m_dirtyStatus != NOT_DIRTY), ("dirty flag mismatch"));
  469. return result;
  470. }
  471. inline void prependToDirtyModules(PartitionData** pListHead)
  472. {
  473. DEBUG_ASSERTCRASH((m_dirtyStatus != NOT_DIRTY), ("dirty flag mismatch"));
  474. m_nextDirty = *pListHead;
  475. if (*pListHead)
  476. (*pListHead)->m_prevDirty = this;
  477. *pListHead = this;
  478. }
  479. void removeFromDirtyModules(PartitionData** pListHead)
  480. {
  481. m_dirtyStatus = NOT_DIRTY;
  482. if (m_nextDirty)
  483. m_nextDirty->m_prevDirty = m_prevDirty;
  484. if (m_prevDirty)
  485. m_prevDirty->m_nextDirty = m_nextDirty;
  486. else
  487. *pListHead = m_nextDirty;
  488. m_prevDirty = 0;
  489. m_nextDirty = 0;
  490. }
  491. };
  492. //=====================================
  493. /**
  494. this is an ABC. PartitionData::iterate allows you to pass multiple filters
  495. to filter out objects you don't want. it calls this method on the objects
  496. in question; any that get false returned, are not iterated. Note that
  497. either modMain or posMain will be null, but not both: the filter must be aware
  498. of this, and respond appropriately. (ie, the filter may be used for filtering
  499. against an object, or against a position.)
  500. */
  501. class PartitionFilter
  502. {
  503. public:
  504. virtual Bool allow(Object *objOther) = 0;
  505. #if defined(_DEBUG) || defined(_INTERNAL)
  506. virtual const char* debugGetName() = 0;
  507. #endif
  508. };
  509. //=====================================
  510. /**
  511. Reject any objects that aren't currently flying.
  512. */
  513. class PartitionFilterIsFlying : public PartitionFilter
  514. {
  515. public:
  516. PartitionFilterIsFlying() { }
  517. virtual Bool allow(Object *objOther);
  518. #if defined(_DEBUG) || defined(_INTERNAL)
  519. virtual const char* debugGetName() { return "PartitionFilterIsFlying"; }
  520. #endif
  521. };
  522. //=====================================
  523. class PartitionFilterWouldCollide : public PartitionFilter
  524. {
  525. private:
  526. Coord3D m_position;
  527. GeometryInfo m_geom;
  528. Real m_angle;
  529. Bool m_desiredCollisionResult; // collision must match this for allow to return true
  530. public:
  531. PartitionFilterWouldCollide(const Coord3D& pos, const GeometryInfo& geom, Real angle, Bool desired);
  532. virtual Bool allow(Object *objOther);
  533. #if defined(_DEBUG) || defined(_INTERNAL)
  534. virtual const char* debugGetName() { return "PartitionFilterWouldCollide"; }
  535. #endif
  536. };
  537. //=====================================
  538. /**
  539. Reject any objects that aren't controlled by the same player.
  540. */
  541. class PartitionFilterSamePlayer : public PartitionFilter
  542. {
  543. private:
  544. const Player *m_player;
  545. public:
  546. PartitionFilterSamePlayer(const Player *player) : m_player(player) { }
  547. virtual Bool allow(Object *objOther);
  548. #if defined(_DEBUG) || defined(_INTERNAL)
  549. virtual const char* debugGetName() { return "PartitionFilterSamePlayer"; }
  550. #endif
  551. };
  552. //=====================================
  553. /**
  554. Reject any objects that don't match the alliance
  555. affiliations compared with 'm_obj'. You
  556. may reject objects that are allied, neutral,
  557. or enemy with respect to it.
  558. */
  559. class PartitionFilterRelationship : public PartitionFilter
  560. {
  561. private:
  562. const Object *m_obj;
  563. Int m_flags;
  564. public:
  565. enum
  566. {
  567. ALLOW_ALLIES = (1<<ALLIES), ///< allow objects that m_obj considers allies
  568. ALLOW_ENEMIES = (1<<ENEMIES), ///< allow objects that m_obj considers enemy
  569. ALLOW_NEUTRAL = (1<<NEUTRAL) ///< allow objects that m_obj considers neutral
  570. };
  571. PartitionFilterRelationship(const Object *obj, Int flags) : m_obj(obj), m_flags(flags) { }
  572. virtual Bool allow(Object *objOther);
  573. #if defined(_DEBUG) || defined(_INTERNAL)
  574. virtual const char* debugGetName() { return "PartitionFilterRelationship"; }
  575. #endif
  576. };
  577. //=====================================
  578. /**
  579. Reject any objects that aren't on the specific
  580. team.
  581. */
  582. class PartitionFilterAcceptOnTeam : public PartitionFilter
  583. {
  584. private:
  585. const Team *m_team;
  586. public:
  587. PartitionFilterAcceptOnTeam(const Team *team);
  588. virtual Bool allow(Object *objOther);
  589. #if defined(_DEBUG) || defined(_INTERNAL)
  590. virtual const char* debugGetName() { return "PartitionFilterAcceptOnTeam"; }
  591. #endif
  592. };
  593. //=====================================
  594. /**
  595. Reject any objects that aren't on the specific
  596. squad.
  597. */
  598. class PartitionFilterAcceptOnSquad : public PartitionFilter
  599. {
  600. private:
  601. const Squad *m_squad;
  602. public:
  603. PartitionFilterAcceptOnSquad(const Squad *squad);
  604. virtual Bool allow(Object *objOther);
  605. #if defined(_DEBUG) || defined(_INTERNAL)
  606. virtual const char* debugGetName() { return "PartitionFilterAcceptOnSquad"; }
  607. #endif
  608. };
  609. //=====================================
  610. /**
  611. Reject any objects that are not within clear line-of-sight
  612. of a given object. "Line of sight" takes into account
  613. terrain (ie, no hills between 'em) but does not
  614. yet take into account structures. Note that this
  615. requires more computation that other filters, so
  616. this should generally put toward the end of the filter
  617. list so that simpler filters can reject other (simpler)
  618. cases earlier.
  619. */
  620. class PartitionFilterLineOfSight : public PartitionFilter
  621. {
  622. private:
  623. const Object *m_obj;
  624. public:
  625. PartitionFilterLineOfSight(const Object *obj);
  626. virtual Bool allow(Object *objOther);
  627. #if defined(_DEBUG) || defined(_INTERNAL)
  628. virtual const char* debugGetName() { return "PartitionFilterLineOfSight"; }
  629. #endif
  630. };
  631. //=====================================
  632. /**
  633. Only objects that Can Possibly be attacked by the given object
  634. */
  635. class PartitionFilterPossibleToAttack : public PartitionFilter
  636. {
  637. private:
  638. const Object *m_obj;
  639. CommandSourceType m_commandSource;
  640. AbleToAttackType m_attackType;
  641. public:
  642. PartitionFilterPossibleToAttack(AbleToAttackType t, const Object *obj, CommandSourceType commandSource);
  643. virtual Bool allow(Object *objOther);
  644. #if defined(_DEBUG) || defined(_INTERNAL)
  645. virtual const char* debugGetName() { return "PartitionFilterPossibleToAttack"; }
  646. #endif
  647. };
  648. //=====================================
  649. /**
  650. * Accept only the last object who attacked me. Very fast.
  651. */
  652. class PartitionFilterLastAttackedBy : public PartitionFilter
  653. {
  654. private:
  655. ObjectID m_lastAttackedBy;
  656. public:
  657. PartitionFilterLastAttackedBy(Object *obj);
  658. virtual Bool allow(Object *other);
  659. #if defined(_DEBUG) || defined(_INTERNAL)
  660. virtual const char* debugGetName() { return "PartitionFilterLastAttackedBy"; }
  661. #endif
  662. };
  663. //=====================================
  664. /**
  665. Only objects that match the given masks are accepted.
  666. */
  667. class PartitionFilterAcceptByObjectStatus : public PartitionFilter
  668. {
  669. private:
  670. UnsignedInt m_mustBeSet, m_mustBeClear;
  671. public:
  672. PartitionFilterAcceptByObjectStatus(UnsignedInt mustBeSet, UnsignedInt mustBeClear) : m_mustBeSet(mustBeSet), m_mustBeClear(mustBeClear) { }
  673. virtual Bool allow(Object *objOther);
  674. #if defined(_DEBUG) || defined(_INTERNAL)
  675. virtual const char* debugGetName() { return "PartitionFilterAcceptByObjectStatus"; }
  676. #endif
  677. };
  678. //=====================================
  679. /**
  680. Just like PartitionFilterAcceptByObjectStatus, except that objects
  681. that match the given masks are REJECTED.
  682. */
  683. class PartitionFilterRejectByObjectStatus : public PartitionFilter
  684. {
  685. private:
  686. UnsignedInt m_mustBeSet, m_mustBeClear;
  687. public:
  688. PartitionFilterRejectByObjectStatus(UnsignedInt mustBeSet, UnsignedInt mustBeClear)
  689. : m_mustBeSet(mustBeSet), m_mustBeClear(mustBeClear)
  690. {
  691. }
  692. virtual Bool allow(Object *objOther);
  693. #if defined(_DEBUG) || defined(_INTERNAL)
  694. virtual const char* debugGetName() { return "PartitionFilterRejectByObjectStatus"; }
  695. #endif
  696. };
  697. //=====================================
  698. /**
  699. Objects that are stealthed and not detected or disguised are accepted or rejected based on allow bool.
  700. */
  701. class PartitionFilterStealthedAndUndetected : public PartitionFilter
  702. {
  703. private:
  704. const Object *m_obj;
  705. Bool m_allow;
  706. public:
  707. PartitionFilterStealthedAndUndetected( const Object *obj, Bool allow ) { m_obj = obj; m_allow = allow; }
  708. virtual Bool allow(Object *objOther);
  709. #if defined(_DEBUG) || defined(_INTERNAL)
  710. virtual const char* debugGetName() { return "PartitionFilterStealthedAndUndetected"; }
  711. #endif
  712. };
  713. //=====================================
  714. /**
  715. Only objects that match the given masks are accepted.
  716. */
  717. class PartitionFilterAcceptByKindOf : public PartitionFilter
  718. {
  719. private:
  720. KindOfMaskType m_mustBeSet, m_mustBeClear;
  721. public:
  722. PartitionFilterAcceptByKindOf(const KindOfMaskType& mustBeSet, const KindOfMaskType& mustBeClear) : m_mustBeSet(mustBeSet), m_mustBeClear(mustBeClear) { }
  723. virtual Bool allow(Object *objOther);
  724. #if defined(_DEBUG) || defined(_INTERNAL)
  725. virtual const char* debugGetName() { return "PartitionFilterAcceptByKindOf"; }
  726. #endif
  727. };
  728. //=====================================
  729. /**
  730. Just like PartitionFilterAcceptByKindOf, except that objects
  731. that match the given masks are REJECTED.
  732. */
  733. class PartitionFilterRejectByKindOf : public PartitionFilter
  734. {
  735. private:
  736. KindOfMaskType m_mustBeSet, m_mustBeClear;
  737. public:
  738. PartitionFilterRejectByKindOf(const KindOfMaskType& mustBeSet, const KindOfMaskType& mustBeClear)
  739. : m_mustBeSet(mustBeSet), m_mustBeClear(mustBeClear)
  740. {
  741. }
  742. virtual Bool allow(Object *objOther);
  743. #if defined(_DEBUG) || defined(_INTERNAL)
  744. virtual const char* debugGetName() { return "PartitionFilterRejectByKindOf"; }
  745. #endif
  746. };
  747. //=====================================
  748. /**
  749. * Reject any objects "behind" the given object.
  750. * This is a 3D check.
  751. */
  752. class PartitionFilterRejectBehind: public PartitionFilter
  753. {
  754. private:
  755. Object *m_obj;
  756. public:
  757. PartitionFilterRejectBehind( Object *obj );
  758. virtual Bool allow( Object *other );
  759. #if defined(_DEBUG) || defined(_INTERNAL)
  760. virtual const char* debugGetName() { return "PartitionFilterRejectBehind"; }
  761. #endif
  762. };
  763. //=====================================
  764. /**
  765. * Allow only living victims
  766. */
  767. class PartitionFilterAlive : public PartitionFilter
  768. {
  769. public:
  770. PartitionFilterAlive(void) { }
  771. protected:
  772. virtual Bool allow(Object *objOther);
  773. #if defined(_DEBUG) || defined(_INTERNAL)
  774. virtual const char* debugGetName() { return "PartitionFilterAlive"; }
  775. #endif
  776. };
  777. //=====================================
  778. /**
  779. * If obj is on the map, reject all off-map objects.
  780. * If obj is off the map, reject all on-map objects.
  781. */
  782. class PartitionFilterSameMapStatus : public PartitionFilter
  783. {
  784. private:
  785. const Object *m_obj;
  786. public:
  787. PartitionFilterSameMapStatus(const Object *obj) : m_obj(obj) { }
  788. protected:
  789. virtual Bool allow(Object *objOther);
  790. #if defined(_DEBUG) || defined(_INTERNAL)
  791. virtual const char* debugGetName() { return "PartitionFilterSameMapStatus"; }
  792. #endif
  793. };
  794. //=====================================
  795. /**
  796. * If obj is on the map, accept it.
  797. */
  798. class PartitionFilterOnMap : public PartitionFilter
  799. {
  800. public:
  801. PartitionFilterOnMap() { }
  802. protected:
  803. virtual Bool allow(Object *objOther);
  804. #if defined(_DEBUG) || defined(_INTERNAL)
  805. virtual const char* debugGetName() { return "PartitionFilterOnMap"; }
  806. #endif
  807. };
  808. //=====================================
  809. /**
  810. * Reject buildings, unless they can attack, or
  811. * we are the computer-controlled AI and the building
  812. * is owned by the enemy.
  813. */
  814. class PartitionFilterRejectBuildings : public PartitionFilter
  815. {
  816. private:
  817. const Object *m_self;
  818. Bool m_acquireEnemies;
  819. public:
  820. PartitionFilterRejectBuildings(const Object *o);
  821. protected:
  822. virtual Bool allow( Object *other );
  823. #if defined(_DEBUG) || defined(_INTERNAL)
  824. virtual const char* debugGetName() { return "PartitionFilterRejectBuildings"; }
  825. #endif
  826. };
  827. //=====================================
  828. /**
  829. * Accept/Reject Insignificant buildings
  830. * Note: This will allow things that
  831. */
  832. class PartitionFilterInsignificantBuildings : public PartitionFilter
  833. {
  834. private:
  835. Bool m_allowNonBuildings;
  836. Bool m_allowInsignificant;
  837. public:
  838. PartitionFilterInsignificantBuildings(Bool allowNonBuildings, Bool allowInsignificant) :
  839. m_allowNonBuildings(allowNonBuildings), m_allowInsignificant(allowInsignificant) {}
  840. protected:
  841. virtual Bool allow( Object *other );
  842. #if defined(_DEBUG) || defined(_INTERNAL)
  843. virtual const char* debugGetName() { return "PartitionFilterInsignificantBuildings"; }
  844. #endif
  845. };
  846. //=====================================
  847. /**
  848. * Accept if they are clear, not fogged or shrouded
  849. */
  850. class PartitionFilterFreeOfFog : public PartitionFilter
  851. {
  852. private:
  853. Int m_comparisonIndex;
  854. public:
  855. PartitionFilterFreeOfFog(Int toWhom) :
  856. m_comparisonIndex(toWhom){}
  857. protected:
  858. virtual Bool allow( Object *other );
  859. #if defined(_DEBUG) || defined(_INTERNAL)
  860. virtual const char* debugGetName() { return "PartitionFilterFreeOfFog"; }
  861. #endif
  862. };
  863. //=====================================
  864. /**
  865. * Accept repulsor (enemies, or flagged as repulsor).
  866. */
  867. class PartitionFilterRepulsor : public PartitionFilter
  868. {
  869. private:
  870. const Object *m_self;
  871. public:
  872. PartitionFilterRepulsor(const Object *o) : m_self(o) { }
  873. protected:
  874. virtual Bool allow( Object *other );
  875. #if defined(_DEBUG) || defined(_INTERNAL)
  876. virtual const char* debugGetName() { return "PartitionFilterRepulsor"; }
  877. #endif
  878. };
  879. //=====================================
  880. /**
  881. * Reject all objects outside of the irregularly shaped area defined by the set of points
  882. * passed in at creation. This is done using the even-odd rule against the points, assuming
  883. * that the area is closed.
  884. */
  885. class PartitionFilterIrregularArea : public PartitionFilter
  886. {
  887. private:
  888. Coord3D *m_area;
  889. Int m_numPointsInArea;
  890. public:
  891. PartitionFilterIrregularArea(Coord3D* area, Int numPointsInArea) : m_area(area), m_numPointsInArea(numPointsInArea) {}
  892. protected:
  893. virtual Bool allow( Object *other );
  894. #if defined(_DEBUG) || defined(_INTERNAL)
  895. virtual const char* debugGetName() { return "PartitionFilterIrregularArea"; }
  896. #endif
  897. };
  898. //=====================================
  899. /**
  900. * Reject all objects inside the irregularly trigger area
  901. * passed in at creation. This is done using the even-odd rule against the points, assuming
  902. * that the area is closed.
  903. */
  904. class PartitionFilterPolygonTrigger : public PartitionFilter
  905. {
  906. private:
  907. const PolygonTrigger *m_trigger;
  908. public:
  909. PartitionFilterPolygonTrigger(const PolygonTrigger *trigger) : m_trigger(trigger) {}
  910. protected:
  911. virtual Bool allow( Object *other );
  912. #if defined(_DEBUG) || defined(_INTERNAL)
  913. virtual const char* debugGetName() { return "PartitionFilterPolygonTrigger"; }
  914. #endif
  915. };
  916. //=====================================
  917. /**
  918. * Reject all objects that aren't (or are) the player
  919. * passed in at creation. .
  920. */
  921. class PartitionFilterPlayer : public PartitionFilter
  922. {
  923. private:
  924. const Player *m_player;
  925. Bool m_match;
  926. public:
  927. PartitionFilterPlayer(const Player *player, Bool match) : m_player(player), m_match(match) {}
  928. protected:
  929. virtual Bool allow( Object *other );
  930. #if defined(_DEBUG) || defined(_INTERNAL)
  931. virtual const char* debugGetName() { return "PartitionFilterPlayer"; }
  932. #endif
  933. };
  934. //=====================================
  935. /**
  936. * Allow or reject (based on match) all Objects whose affiliation matches one of those
  937. * specified by
  938. */
  939. class PartitionFilterPlayerAffiliation : public PartitionFilter
  940. {
  941. private:
  942. const Player *m_player;
  943. Bool m_match;
  944. UnsignedInt m_affiliation;
  945. public:
  946. // whichAffiliation should use AllowPlayerRelationship flags specified in PlayerList.h
  947. PartitionFilterPlayerAffiliation(const Player *player, UnsignedInt whichAffiliation, Bool match)
  948. : m_player(player), m_affiliation(whichAffiliation), m_match(match)
  949. {
  950. }
  951. protected:
  952. virtual Bool allow( Object *other );
  953. #if defined(_DEBUG) || defined(_INTERNAL)
  954. virtual const char* debugGetName() { return "PartitionFilterPlayerAffiliation"; }
  955. #endif
  956. };
  957. //=====================================
  958. /**
  959. * Accept all objects that aren't (or are) the thing
  960. * passed in at creation. .
  961. */
  962. class PartitionFilterThing : public PartitionFilter
  963. {
  964. private:
  965. const ThingTemplate *m_tThing;
  966. Bool m_match;
  967. public:
  968. PartitionFilterThing(const ThingTemplate *thing, Bool match) : m_tThing(thing), m_match(match) {}
  969. protected:
  970. virtual Bool allow( Object *other );
  971. #if defined(_DEBUG) || defined(_INTERNAL)
  972. virtual const char* debugGetName() { return "PartitionFilterThing"; }
  973. #endif
  974. };
  975. //=====================================
  976. /**
  977. * Accept all objects that can/cannot be garrisoned by anyone.
  978. */
  979. class PartitionFilterGarrisonable : public PartitionFilter
  980. {
  981. private:
  982. Player *m_player;
  983. Bool m_match;
  984. public:
  985. PartitionFilterGarrisonable( Bool match ) : m_match(match)
  986. {
  987. //Added By Sadullah Nader
  988. //Initializations
  989. m_player = NULL;
  990. //
  991. }
  992. protected:
  993. virtual Bool allow( Object *other );
  994. #if defined(_DEBUG) || defined(_INTERNAL)
  995. virtual const char* debugGetName() { return "PartitionFilterGarrisonable"; }
  996. #endif
  997. };
  998. //=====================================
  999. /**
  1000. * Accept all objects that can/cannot be garrisoned by source *Player*.
  1001. */
  1002. class PartitionFilterGarrisonableByPlayer : public PartitionFilter
  1003. {
  1004. private:
  1005. Player *m_player;
  1006. Bool m_match;
  1007. CommandSourceType m_commandSource;
  1008. public:
  1009. PartitionFilterGarrisonableByPlayer( Player *player, Bool match, CommandSourceType commandSource ):
  1010. m_player(player), m_match(match), m_commandSource(commandSource)
  1011. {
  1012. }
  1013. protected:
  1014. virtual Bool allow( Object *other );
  1015. #if defined(_DEBUG) || defined(_INTERNAL)
  1016. virtual const char* debugGetName() { return "PartitionFilterGarrisonableByPlayer"; }
  1017. #endif
  1018. };
  1019. //=====================================
  1020. /**
  1021. * Accept all objects that are/n't unmanned.
  1022. */
  1023. class PartitionFilterUnmannedObject : public PartitionFilter
  1024. {
  1025. private:
  1026. Bool m_match;
  1027. public:
  1028. PartitionFilterUnmannedObject( Bool match ) : m_match(match) {}
  1029. protected:
  1030. virtual Bool allow( Object *other );
  1031. #if defined(_DEBUG) || defined(_INTERNAL)
  1032. virtual const char* debugGetName() { return "PartitionFilterUnmannedObject"; }
  1033. #endif
  1034. };
  1035. //=====================================
  1036. /**
  1037. * Accept all objects that can/cannot have object X perform a command ability on them
  1038. */
  1039. class PartitionFilterValidCommandButtonTarget : public PartitionFilter
  1040. {
  1041. private:
  1042. Object *m_source;
  1043. const CommandButton *m_commandButton;
  1044. Bool m_match;
  1045. CommandSourceType m_commandSource;
  1046. public:
  1047. PartitionFilterValidCommandButtonTarget( Object *source, const CommandButton *commandButton, Bool match, CommandSourceType commandSource) :
  1048. m_source(source), m_commandButton(commandButton), m_match(match), m_commandSource(commandSource) {}
  1049. protected:
  1050. virtual Bool allow( Object *other );
  1051. #if defined(_DEBUG) || defined(_INTERNAL)
  1052. virtual const char* debugGetName() { return "PartitionFilterValidCommandButtonTarget"; }
  1053. #endif
  1054. };
  1055. //=====================================
  1056. /**
  1057. PartitionManager is the singleton class that manages the entire partition/collision
  1058. system. It maintains the set of PartitionCells that correspond to the world system,
  1059. and updates the PartitionDatas as needed during update phase.
  1060. */
  1061. class PartitionManager : public SubsystemInterface, public Snapshot
  1062. {
  1063. private:
  1064. #ifdef FASTER_GCO
  1065. typedef std::vector<ICoord2D> OffsetVec;
  1066. typedef std::vector<OffsetVec> RadiusVec;
  1067. #endif
  1068. PartitionData *m_moduleList; ///< master partition module list
  1069. Region3D m_worldExtents; ///< should be same as TheTerrainLogic->getExtents()
  1070. Real m_cellSize; ///< edge size of each cell, in world coord space
  1071. Real m_cellSizeInv; ///< 1/cellSize (used for efficiency)
  1072. Int m_cellCountX; ///< number of cells, x
  1073. Int m_cellCountY; ///< number of cells, y
  1074. Int m_totalCellCount; ///< x * y
  1075. PartitionCell* m_cells; ///< array of cells
  1076. PartitionData* m_dirtyModules;
  1077. Bool m_updatedSinceLastReset; ///< Used to force a return of OBJECTSHROUD_INVALID before update has been called.
  1078. std::queue<SightingInfo *> m_pendingUndoShroudReveals; ///< Anything can queue up an Undo to happen later. This is a queue, because "later" is a constant
  1079. #ifdef FASTER_GCO
  1080. Int m_maxGcoRadius;
  1081. RadiusVec m_radiusVec;
  1082. #endif
  1083. protected:
  1084. /**
  1085. This is an internal function that is used to implement the public
  1086. getClosestObject and iterateObjects calls.
  1087. */
  1088. Object *PartitionManager::getClosestObjects(
  1089. const Object *obj,
  1090. const Coord3D *pos,
  1091. Real maxDist,
  1092. DistanceCalculationType dc,
  1093. PartitionFilter **filters,
  1094. SimpleObjectIterator *iter, // if nonnull, append ALL satisfactory objects to the iterator (not just the single closest)
  1095. Real *closestDistArg,
  1096. Coord3D *closestVecArg
  1097. );
  1098. void shutdown( void );
  1099. /// used to validate the positions for findPositionAround family of methods
  1100. Bool tryPosition( const Coord3D *center, Real dist, Real angle,
  1101. const FindPositionOptions *options, Coord3D *result );
  1102. typedef Int (*CellAlongLineProc)(PartitionCell* cell, void* userData);
  1103. Int iterateCellsAlongLine(const Coord3D& pos, const Coord3D& posOther, CellAlongLineProc proc, void* userData);
  1104. // note iterateCellsBreadthFirst returns the cell index that made the CellBreadthFirstProc return
  1105. // non-Zero.
  1106. typedef Int (*CellBreadthFirstProc)(PartitionCell* cell, void* userData);
  1107. Int iterateCellsBreadthFirst(const Coord3D *pos, CellBreadthFirstProc proc, void *userData);
  1108. #ifdef FASTER_GCO
  1109. Int calcMinRadius(const ICoord2D& cur);
  1110. void calcRadiusVec();
  1111. #endif
  1112. // These are all friend functions now. They will continue to function as before, but can be passed into
  1113. // the DiscreteCircle::drawCircle function.
  1114. friend void hLineAddLooker(Int x1, Int x2, Int y, void *playerIndex);
  1115. friend void hLineRemoveLooker(Int x1, Int x2, Int y, void *playerIndex);
  1116. friend void hLineAddShrouder(Int x1, Int x2, Int y, void *playerIndex);
  1117. friend void hLineRemoveShrouder(Int x1, Int x2, Int y, void *playerIndex);
  1118. friend void hLineAddThreat(Int x1, Int x2, Int y, void *threatValueParms);
  1119. friend void hLineRemoveThreat(Int x1, Int x2, Int y, void *threatValueParms);
  1120. friend void hLineAddValue(Int x1, Int x2, Int y, void *threatValueParms);
  1121. friend void hLineRemoveValue(Int x1, Int x2, Int y, void *threatValueParms);
  1122. void processPendingUndoShroudRevealQueue(Bool considerTimestamp = TRUE); ///< keep popping and processing untill you get to one that is in the future
  1123. void resetPendingUndoShroudRevealQueue(); ///< Just delete everything in the queue without doing anything with them
  1124. public:
  1125. PartitionManager( void );
  1126. virtual ~PartitionManager( void );
  1127. // --------------- inherited from Subsystem interface -------------
  1128. virtual void init( void ); ///< initialize
  1129. virtual void reset( void ); ///< system reset
  1130. virtual void update( void ); ///< system update
  1131. // ----------------------------------------------------------------
  1132. // --------------- inherited from Snapshot interface --------------
  1133. void crc( Xfer *xfer );
  1134. void xfer( Xfer *xfer );
  1135. void loadPostProcess( void );
  1136. inline Bool getUpdatedSinceLastReset( void ) const { return m_updatedSinceLastReset; }
  1137. void registerObject( Object *object ); ///< add thing to system
  1138. void unRegisterObject( Object *object ); ///< remove thing from system
  1139. void registerGhostObject( GhostObject* object); ///<recreate partition data needed to hold object (only used to restore after PM reset).
  1140. void unRegisterGhostObject (GhostObject *object); ///< release partition data held for ghost object.
  1141. void processEntirePendingUndoShroudRevealQueue(); ///< process every pending one regardless of timestamp
  1142. /// return the number of PartitionCells in the x-dimension.
  1143. Int getCellCountX() { DEBUG_ASSERTCRASH(m_cellCountX != 0, ("partition not inited")); return m_cellCountX; }
  1144. /// return the number of PartitionCells in the y-dimension.
  1145. Int getCellCountY() { DEBUG_ASSERTCRASH(m_cellCountY != 0, ("partition not inited")); return m_cellCountY; }
  1146. /// return the PartitionCell located at cell coordinates (x,y).
  1147. PartitionCell *getCellAt(Int x, Int y);
  1148. const PartitionCell *getCellAt(Int x, Int y) const;
  1149. /// A convenience funtion to reveal shroud at some location
  1150. // Queueing does not give you control of the timestamp to enforce the queue. I own the delay, you don't.
  1151. void doShroudReveal( Real centerX, Real centerY, Real radius, PlayerMaskType playerMask);
  1152. void undoShroudReveal( Real centerX, Real centerY, Real radius, PlayerMaskType playerMask);
  1153. void queueUndoShroudReveal( Real centerX, Real centerY, Real radius, PlayerMaskType playerMask );
  1154. void doShroudCover( Real centerX, Real centerY, Real radius, PlayerMaskType playerMask);
  1155. void undoShroudCover( Real centerX, Real centerY, Real radius, PlayerMaskType playerMask);
  1156. /// Perform threat map and value map updates.
  1157. void doThreatAffect( Real centerX, Real centerY, Real radius, UnsignedInt threatVal, PlayerMaskType playerMask);
  1158. void undoThreatAffect( Real centerX, Real centerY, Real radius, UnsignedInt threatVal, PlayerMaskType playerMask);
  1159. void doValueAffect( Real centerX, Real centerY, Real radius, UnsignedInt valueVal, PlayerMaskType playerMask);
  1160. void undoValueAffect( Real centerX, Real centerY, Real radius, UnsignedInt valueVal, PlayerMaskType playerMask);
  1161. void getCellCenterPos(Int x, Int y, Real& xx, Real& yy);
  1162. // find the cell that covers the world coords (wx,wy) and return its coords.
  1163. void worldToCell(Real wx, Real wy, Int *cx, Int *cy);
  1164. // given a distance in world coords, return the number of cells needed to cover that distance (rounding up)
  1165. Int worldToCellDist(Real w);
  1166. Object *getClosestObject(
  1167. const Object *obj,
  1168. Real maxDist,
  1169. DistanceCalculationType dc,
  1170. PartitionFilter **filters = NULL,
  1171. Real *closestDist = NULL,
  1172. Coord3D *closestDistVec = NULL
  1173. );
  1174. Object *getClosestObject(
  1175. const Coord3D *pos,
  1176. Real maxDist,
  1177. DistanceCalculationType dc,
  1178. PartitionFilter **filters = NULL,
  1179. Real *closestDist = NULL,
  1180. Coord3D *closestDistVec = NULL
  1181. );
  1182. Real getRelativeAngle2D( const Object *obj, const Object *otherObj );
  1183. Real getRelativeAngle2D( const Object *obj, const Coord3D *pos );
  1184. void getVectorTo(const Object *obj, const Object *otherObj, DistanceCalculationType dc, Coord3D& vec);
  1185. void getVectorTo(const Object *obj, const Coord3D *pos, DistanceCalculationType dc, Coord3D& vec);
  1186. // just like 'getDistance', but return the dist-sqr, meaning we save a sqrt() call if you don't need it.
  1187. Real getDistanceSquared(const Object *obj, const Object *otherObj, DistanceCalculationType dc, Coord3D *vec = NULL);
  1188. Real getDistanceSquared(const Object *obj, const Coord3D *pos, DistanceCalculationType dc, Coord3D *vec = NULL);
  1189. // just like 'getDistanceSquared', but return the dist-sqr where the obj is at goalPos.
  1190. Real getGoalDistanceSquared(const Object *obj, const Coord3D *goalPos, const Object *otherObj, DistanceCalculationType dc, Coord3D *vec = NULL);
  1191. Real getGoalDistanceSquared(const Object *obj, const Coord3D *goalPos, const Coord3D *otherPos, DistanceCalculationType dc, Coord3D *vec = NULL);
  1192. #ifdef PM_CACHE_TERRAIN_HEIGHT
  1193. // note that the 2d positions aren't guaranteed to be the actual spot within the cell where the terrain
  1194. // is lowest or highest.... just the center of the relevant cell. this function is used for rough-n-quick
  1195. // estimates only.
  1196. Bool estimateTerrainExtremesAlongLine(const Coord3D& startWorld, const Coord3D& endWorld, Real* minZ, Real* maxZ, Coord2D* minZPos, Coord2D* maxZPos);
  1197. #endif
  1198. #ifdef DUMP_PERF_STATS
  1199. void getPMStats(double& gcoTimeThisFrameTotal, double& gcoTimeThisFrameAvg);
  1200. #endif
  1201. SimpleObjectIterator *iterateObjectsInRange(
  1202. const Object *obj,
  1203. Real maxDist,
  1204. DistanceCalculationType dc,
  1205. PartitionFilter **filters = NULL,
  1206. IterOrderType order = ITER_FASTEST
  1207. );
  1208. SimpleObjectIterator *iterateObjectsInRange(
  1209. const Coord3D *pos,
  1210. Real maxDist,
  1211. DistanceCalculationType dc,
  1212. PartitionFilter **filters = NULL,
  1213. IterOrderType order = ITER_FASTEST
  1214. );
  1215. SimpleObjectIterator *iterateAllObjects(PartitionFilter **filters = NULL);
  1216. /**
  1217. return the Objects that would (or would not) collide with the given
  1218. geometry.
  1219. */
  1220. SimpleObjectIterator* iteratePotentialCollisions(
  1221. const Coord3D* pos,
  1222. const GeometryInfo& geom,
  1223. Real angle,
  1224. Bool use2D = false
  1225. );
  1226. Bool isColliding( const Object *a, const Object *b ) const;
  1227. /// Checks a geometry against an arbitrary geometry.
  1228. Bool geomCollidesWithGeom( const Coord3D* pos1,
  1229. const GeometryInfo& geom1,
  1230. Real angle1,
  1231. const Coord3D* pos2,
  1232. const GeometryInfo& geom2,
  1233. Real angle2
  1234. ) const;
  1235. /// finding legal positions in the world
  1236. Bool findPositionAround( const Coord3D *center,
  1237. const FindPositionOptions *options,
  1238. Coord3D *result );
  1239. /// return the size of a PartitionCell, in world coords.
  1240. Real getCellSize() { return m_cellSize; } // only for the use of PartitionData!
  1241. /// return (1.0 / getCellSize); this is used frequently, so we cache it for efficiency
  1242. Real getCellSizeInv() { return m_cellSizeInv; }
  1243. /**
  1244. return true iff there is clear line-of-sight between the two positions.
  1245. this only takes terrain into account; it does not consider objects, units,
  1246. trees, buildings, etc.
  1247. */
  1248. Bool isClearLineOfSightTerrain(const Object* obj, const Coord3D& objPos, const Object* other, const Coord3D& otherPos);
  1249. inline Bool isInListDirtyModules(PartitionData* o) const
  1250. {
  1251. return o->isInListDirtyModules(&m_dirtyModules);
  1252. }
  1253. inline void prependToDirtyModules(PartitionData* o)
  1254. {
  1255. o->prependToDirtyModules(&m_dirtyModules);
  1256. }
  1257. inline void removeFromDirtyModules(PartitionData* o)
  1258. {
  1259. o->removeFromDirtyModules(&m_dirtyModules);
  1260. }
  1261. inline void removeAllDirtyModules()
  1262. {
  1263. while (m_dirtyModules)
  1264. {
  1265. PartitionData *tmp = m_dirtyModules;
  1266. removeFromDirtyModules(tmp);
  1267. }
  1268. }
  1269. /**
  1270. Reveals the map for the given player, but does not override Shroud generation. (Script)
  1271. */
  1272. void revealMapForPlayer( Int playerIndex );
  1273. /**
  1274. Reveals the map for the given player, AND permanently disables all Shroud generation (Observer Mode).
  1275. */
  1276. void revealMapForPlayerPermanently( Int playerIndex );
  1277. /**
  1278. Adds a layer of permanent blindness. Used solely to undo the permanent reveal for debugging
  1279. */
  1280. void undoRevealMapForPlayerPermanently( Int playerIndex );
  1281. /**
  1282. Resets the shroud for the given player with passive shroud (can re-explore).
  1283. */
  1284. void shroudMapForPlayer( Int playerIndex );
  1285. /** this doesn't change the actual shroud values in logic, just pushes them
  1286. back out to the display... this should generally only be used when the local
  1287. player changes.
  1288. */
  1289. void refreshShroudForLocalPlayer();
  1290. /**
  1291. Shrouded has no absolute meaning. It only makes sense to say "Shrouded for him".
  1292. */
  1293. CellShroudStatus getShroudStatusForPlayer( Int playerIndex, Int x, Int y ) const;
  1294. CellShroudStatus getShroudStatusForPlayer( Int playerIndex, const Coord3D *loc ) const;
  1295. Real getGroundOrStructureHeight(Real posx, Real posy);
  1296. void getMostValuableLocation( Int playerIndex, UnsignedInt whichPlayerTypes, ValueOrThreat valType, Coord3D *outLocation );
  1297. void getNearestGroupWithValue( Int playerIndex, UnsignedInt whichPlayerTypes, ValueOrThreat valType, const Coord3D *sourceLocation,
  1298. Int valueRequired, Bool greaterThan, Coord3D *outLocation );
  1299. // If saveToFog is true, then we are writing STORE_FOG.
  1300. // If saveToFog is false, then we are writing STORE_PERMENANT_REVEAL
  1301. void storeFoggedCells(ShroudStatusStoreRestore &outPartitionStore, Bool storeToFog) const;
  1302. void restoreFoggedCells(const ShroudStatusStoreRestore &inPartitionStore, Bool restoreToFog);
  1303. }; // end class PartitionManager
  1304. // -----------------------------------------------------------------------------
  1305. inline void PartitionManager::worldToCell(Real wx, Real wy, Int *cx, Int *cy)
  1306. {
  1307. *cx = REAL_TO_INT_FLOOR((wx - m_worldExtents.lo.x) * m_cellSizeInv);
  1308. *cy = REAL_TO_INT_FLOOR((wy - m_worldExtents.lo.y) * m_cellSizeInv);
  1309. }
  1310. //-----------------------------------------------------------------------------
  1311. inline Int PartitionManager::worldToCellDist(Real w)
  1312. {
  1313. return REAL_TO_INT_CEIL(w * m_cellSizeInv);
  1314. }
  1315. //-----------------------------------------------------------------------------
  1316. inline PartitionCell *PartitionManager::getCellAt(Int x, Int y)
  1317. {
  1318. return (x < 0 || y < 0 || x >= m_cellCountX || y >= m_cellCountY) ? NULL : &m_cells[y * m_cellCountX + x];
  1319. }
  1320. //-----------------------------------------------------------------------------
  1321. inline const PartitionCell *PartitionManager::getCellAt(Int x, Int y) const
  1322. {
  1323. return (x < 0 || y < 0 || x >= m_cellCountX || y >= m_cellCountY) ? NULL : &m_cells[y * m_cellCountX + x];
  1324. }
  1325. //-----------------------------------------------------------------------------
  1326. #ifdef FASTER_GCO
  1327. // nothing
  1328. #else
  1329. class CellOutwardIterator
  1330. {
  1331. private:
  1332. PartitionManager *m_mgr;
  1333. Int m_cellCenterX, m_cellCenterY;
  1334. Int m_maxRadius;
  1335. Int m_cellRadius;
  1336. Int m_delta[2];
  1337. Int m_inc;
  1338. Int m_cnt;
  1339. Int m_axis;
  1340. Int m_iter;
  1341. PartitionCell *nextCell(Bool skipEmpties);
  1342. public:
  1343. CellOutwardIterator(PartitionManager *mgr, Int x, Int y);
  1344. ~CellOutwardIterator();
  1345. PartitionCell *next() { return nextCell(false); }
  1346. PartitionCell *nextNonEmpty() { return nextCell(true); }
  1347. Int getCurCellRadius() const { return m_cellRadius; }
  1348. Int getMaxRadius() const { return m_maxRadius; }
  1349. void setMaxRadius(Int max) { m_maxRadius = max; }
  1350. };
  1351. #endif
  1352. //-----------------------------------------------------------------------------
  1353. // Inlining
  1354. //-----------------------------------------------------------------------------
  1355. //-----------------------------------------------------------------------------
  1356. // Externals
  1357. //-----------------------------------------------------------------------------
  1358. extern PartitionManager *ThePartitionManager; ///< object manager singleton
  1359. #endif // __PARTITIONMANAGER_H_