PartitionManager.h 54 KB

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