convert line ends
[canaan.git] / prj / cam / src / ai / aipathdb.h
blob2c0869c2ef8bde47fd9910c8793132f4165332f2
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/ai/aipathdb.h,v 1.27 2000/03/01 13:02:52 bfarquha Exp $
8 //
9 //
12 #ifndef __AIPATHDB_H
13 #define __AIPATHDB_H
15 #include <aipthbas.h>
16 #include <aipthzon.h>
17 #include <aiokbits.h>
19 #include <dbmem.h>
21 #pragma pack(1)
22 #pragma once
24 #define HUGE_Z ((float)5.10)
26 // Anything less than 2 feet high will use SmallCreature links.
27 #define AIPATHDB_SmallCreatureHeight 0.5
30 F_DECLARE_INTERFACE(ITagFile);
31 class cAIPath;
33 ///////////////////////////////////////////////////////////////////////////////
35 BOOL AIPathFindDBBuild();
37 void AIPathFindUpdate();
39 void AIPathFindMTWaypointHit(ObjID movingTerrain, ObjID waypoint);
40 void AIPathFindMTWaypointLeft(ObjID movingTerrain);
42 void AIPathFindRead(ITagFile *);
43 void AIPathFindWrite(ITagFile *);
45 // Given flee point, return flee region, else -1.
46 int AIGetFleeRegion(ObjID id);
48 ///////////////////////////////////////////////////////////////////////////////
50 struct sAICellLineIntersect
52 unsigned n;
53 mxs_vector intersects[2];
56 ///////////////////////////////////////////////////////////////////////////////
58 struct sAIExternCell
60 struct sPlane
62 mxs_vector normal;
63 float constant;
66 sPlane plane;
67 unsigned nVertices;
68 mxs_vector vertices[1];
71 inline sAIExternCell * AINewExternCell(unsigned nVertices)
73 sAIExternCell * p = (sAIExternCell *)malloc(sizeof(sAIExternCell) + sizeof(mxs_vector) * nVertices);
74 p->nVertices = nVertices;
75 return p;
78 inline sAIExternCell * AINewExternCell(const mxs_vector & normal, float constant, unsigned nVertices)
80 sAIExternCell * p = AINewExternCell(nVertices);
81 p->plane.normal = normal;
82 p->plane.constant = constant;
83 return p;
87 struct sFleeRegionData
89 int nRegionId;
90 ObjID id;
93 class cFleeRegionsHash : public cHashSet<sFleeRegionData *, const ObjID, cHashFunctions>
95 public:
96 virtual tHashSetKey GetKey(tHashSetNode p) const
98 return (tHashSetKey) ((sFleeRegionData *)p)->id;
104 struct sZoneDatabase
106 cZonePairTable m_ZonePairTable;
107 int m_nZones;
109 // array of zones for each cell
110 cAIPathArray<tAIPathZone> m_CellZones;
115 ///////////////////////////////////////////////////////////////////////////////
117 // CLASS: cAIPathDB
120 class cAIPathDB
122 public:
124 cAIPathDB();
126 void Init();
127 void Term();
129 ////////////////////////////////////
131 unsigned NumCells() const;
133 const sAIPathCell * GetCell(const tAIPathCellID cell) const;
134 sAIPathCell * AccessCell(const tAIPathCellID cell);
135 const sAIPathCellLink * GetCellLink(tAIPathCell2CellLinkID linkId) const;
137 const mxs_vector & GetCenter(const tAIPathCellID cell, mxs_vector * pCenter) const;
138 const mxs_vector & GetCenter(const tAIPathCellID cell) const;
140 const sAIPathCellPlane * GetCellPlane(const tAIPathCellID cell) const;
141 const sAIPathCellPlane * GetCellPlane(const sAIPathCell * pCell) const;
143 ////////////////////////////////////
145 const mxs_vector & GetCellVertex(tAIPathCellID cell, int index) const;
146 tAIPathVertexID GetCellVertexID(tAIPathCellID cell, int index) const;
147 #if 0
148 int GetCellEdgeInfo(tAIPathCellID cell, int index) const;
149 #endif
150 void GetCellVertexFull(tAIPathCellID cell, int index, mxs_vector * pVertex, tAIPathVertexID * pVertexID) const;
151 #if 0
152 BOOL IsCellEdgeLinked(tAIPathCellID cell, int index) const;
153 #endif
154 const mxs_vector & GetVertex(tAIPathVertexID id) const;
155 int GetVertexInfo(tAIPathVertexID id) const;
157 ////////////////////////////////////
159 ObjID GetCellDoor(tAIPathCellID cell);
161 ////////////////////////////////////
163 sbool IsUnpathable(tAIPathCellID cell);
164 sbool IsBelowDoor(tAIPathCellID cell);
165 sbool IsBlockedOBB(tAIPathCellID cell);
166 sbool IsActiveMovingTerrain(tAIPathCellID cell);
168 ////////////////////////////////////
170 void MarkBegin();
171 void Mark(tAIPathCellID cell);
172 void Unmark(tAIPathCellID cell);
173 BOOL GetMark(tAIPathCellID cell);
174 void MarkEnd();
176 ////////////////////////////////////
178 // wsf: doen't use condition bits for zones.
179 BOOL CanPathfindBetweenZones(eAIPathZoneType ZoneType, tAIPathZone zone1, tAIPathZone zone2, tAIPathOkBits okBits);
181 tAIPathZone GetCellZone(eAIPathZoneType ZoneType, tAIPathCellID cell);
182 tAIPathOkBits GetZoneOkBits(eAIPathZoneType ZoneType, tAIPathZone zone1, tAIPathZone zone2);
183 void SetZoneOkBits(eAIPathZoneType ZoneType, tAIPathZone zone1, tAIPathZone zone2, tAIPathOkBits okBits);
185 ////////////////////////////////////
187 float GetZAtXY(const sAIPathCell * pCell, const mxs_vector & pt) const;
188 float GetZAtXY(const tAIPathCellID cell, const mxs_vector & pt) const;
190 float GetHighestZ(tAIPathCellID cell) const;
191 float GetLowestZ(tAIPathCellID cell) const;
193 ////////////////////////////////////
195 float ComputeArea(tAIPathCellID cell) const;
197 ////////////////////////////////////
199 void DeleteCell(tAIPathCellID cell);
200 void GetCell(tAIPathCellID cell, sAIExternCell **);
201 BOOL AddOBBCell(sAIExternCell *, tAIPathCellID cell = 0, BOOL movable = FALSE);
203 int GetLineIntersections(tAIPathCellID cell, const mxs_vector & line1, const mxs_vector & line2, sAICellLineIntersect * pIntersect) const;
204 BOOL SplitCellByLine(tAIPathCellID cell, const mxs_vector & line1, const mxs_vector & line2);
205 BOOL SplitCell(tAIPathCellID cell, const mxs_vector & pt1, const mxs_vector & pt2);
207 // @TBD (toml 08-24-98): void Compact();
209 ////////////////////////////////////
211 private:
213 friend BOOL AIPathFind(const cMxsVector & fromLocation, tAIPathCellID startCell,
214 const cMxsVector & toLocation, tAIPathCellID endCell,
215 cAIPath * pPath, tAIPathOkBits OkBits, tAIPathOkBits okCondBits = 0);
217 public:
218 // array of cells
219 cAIPathArray<sAIPathCell> m_Cells; // 1..count, zero is invalid
220 tAIPathCellID m_nCells;
222 // array of cell plane info
223 cAIPathArray<sAIPathCellPlane> m_Planes;
224 tAIPathCellID m_nPlanes;
226 // array of links between cells
227 cAIPathArray<sAIPathCellLink> m_Links; // 1..count, zero is invalid
228 tAIPathCell2CellLinkID m_nLinks;
230 // array of vertices
231 cAIPathArray<sAIPathVertex> m_Vertices; // 1..count, zero is invalid
232 tAIPathVertexID m_nVertices;
234 // array of vertices owned by cells
235 cAIPathArray<sAIPathCell2VertexLink> m_CellVertices;// 1..count, zero is invalid
236 tAIPathCell2VertexLinkID m_nCellVertices;
238 // array of object hints
239 cAIPathArray<tAIPathCellID> m_ObjHints;
240 int m_nObjHints;
242 // mapping of objects to the cells they've created
243 cAIPathArray<sAIPathCellObjMap> m_CellObjMap;
244 int m_nCellObjMaps;
246 sZoneDatabase m_ZoneDatabases[kAIZone_Num];
248 // Cell to door mapping
249 cAICellDoorTable m_CellToDoorsTable;
250 cAIPathArray<sAICellDoor> m_CellDoors;
252 // List of all movable cells
253 cDynClassArray<sAIMovableCell> m_MovableCells;
255 // scratch arrays for database searching/traversing
256 cAIPathArray<sbool> m_Marks;
257 cDynArray_<tAIPathCellID, 128> m_MarkedCells;
258 int m_nMarkedCells;
259 cAIPathArray<ushort> m_BestCostToReach;
261 cFleeRegionsHash m_FleeRegions;
262 int m_nNumFleeRegions;
265 extern cAIPathDB g_AIPathDB;
267 ///////////////////////////////////////////////////////////////////////////////
269 inline unsigned cAIPathDB::NumCells() const
271 return m_nCells;
274 ///////////////////////////////////////
276 inline const sAIPathCell * cAIPathDB::GetCell(const tAIPathCellID cell) const
278 return &m_Cells[cell];
281 ///////////////////////////////////////
283 inline const sAIPathCellLink * cAIPathDB::GetCellLink(tAIPathCell2CellLinkID linkId) const
285 return &m_Links[linkId];
288 ///////////////////////////////////////
290 inline sAIPathCell * cAIPathDB::AccessCell(const tAIPathCellID cell)
292 return &m_Cells[cell];
295 ///////////////////////////////////////
297 inline const mxs_vector & cAIPathDB::GetCenter(const tAIPathCellID cell, mxs_vector * pCenter) const
299 return (*pCenter = m_Cells[cell].center);
302 ///////////////////////////////////////
304 inline const mxs_vector & cAIPathDB::GetCenter(const tAIPathCellID cell) const
306 return m_Cells[cell].center;
309 ///////////////////////////////////////
311 inline const sAIPathCellPlane * cAIPathDB::GetCellPlane(const tAIPathCellID cell) const
313 return &m_Planes[m_Cells[cell].plane];
316 ///////////////////////////////////////
318 inline const sAIPathCellPlane * cAIPathDB::GetCellPlane(const sAIPathCell * pCell) const
320 return &m_Planes[pCell->plane];
323 ///////////////////////////////////////
325 inline float cAIPathDB::GetZAtXY(const sAIPathCell * pCell, const mxs_vector & pt) const
327 const sAIPathCellPlane * pPlane = &m_Planes[pCell->plane];
328 return ((-pPlane->constant - pPlane->normal.x * pt.x - pPlane->normal.y * pt.y) / pPlane->normal.z);
331 ///////////////////////////////////////
333 inline float cAIPathDB::GetZAtXY(const tAIPathCellID cell, const mxs_vector & pt) const
335 return GetZAtXY(&m_Cells[cell], pt);
338 ///////////////////////////////////////
340 // Normalize a vertex index.
341 #define cAIPathDB_NormalizeVertexIndex(i) \
343 const int _nVertices = m_Cells[cell].vertexCount; \
345 if (index == _nVertices) \
346 index = 0; \
347 else if (index > _nVertices) \
348 index %= _nVertices; \
349 else if (index < 0) \
350 index = _nVertices + (index % _nVertices); \
353 ///////////////////////////////////////
355 inline const mxs_vector & cAIPathDB::GetCellVertex(tAIPathCellID cell, int index) const
357 cAIPathDB_NormalizeVertexIndex(index);
358 return m_Vertices[m_CellVertices[m_Cells[cell].firstVertex + index].id].pt;
361 ///////////////////////////////////////
363 inline tAIPathVertexID cAIPathDB::GetCellVertexID(tAIPathCellID cell, int index) const
365 cAIPathDB_NormalizeVertexIndex(index);
366 return m_CellVertices[m_Cells[cell].firstVertex + index].id;
369 ///////////////////////////////////////
371 inline void cAIPathDB::GetCellVertexFull(tAIPathCellID cell, int index, mxs_vector * pVertex, tAIPathVertexID * pVertexID) const
373 cAIPathDB_NormalizeVertexIndex(index);
374 *pVertexID = m_CellVertices[m_Cells[cell].firstVertex + index].id;
375 *pVertex = m_Vertices[*pVertexID].pt;
378 ///////////////////////////////////////
379 #if 0
380 inline int cAIPathDB::GetCellEdgeInfo(tAIPathCellID cell, int index) const
382 cAIPathDB_NormalizeVertexIndex(index);
383 return m_CellVertices[m_Cells[cell].firstVertex + index].edgeInfo;
385 #endif
386 ///////////////////////////////////////
387 #if 0
388 inline BOOL cAIPathDB::IsCellEdgeLinked(tAIPathCellID cell, int index) const
390 return m_CellVertices[m_Cells[cell].firstVertex + index].hasLinks;
392 #endif
393 ///////////////////////////////////////
395 inline const mxs_vector & cAIPathDB::GetVertex(tAIPathVertexID id) const
397 return m_Vertices[id].pt;
400 ///////////////////////////////////////
402 inline int cAIPathDB::GetVertexInfo(tAIPathVertexID id) const
404 return m_Vertices[id].ptInfo;
407 ///////////////////////////////////////
409 inline ObjID cAIPathDB::GetCellDoor(tAIPathCellID cell)
411 sAICellDoor * pCellDoor = m_CellToDoorsTable.Search(cell);
412 if (!pCellDoor)
413 return OBJ_NULL;
414 return pCellDoor->door;
417 ///////////////////////////////////////
419 inline sbool cAIPathDB::IsUnpathable(tAIPathCellID cell)
421 return (m_Cells[cell].pathFlags & kAIPF_Unpathable);
424 ///////////////////////////////////////
426 inline sbool cAIPathDB::IsBelowDoor(tAIPathCellID cell)
428 return (m_Cells[cell].pathFlags & kAIPF_BelowDoor);
431 ///////////////////////////////////////
433 inline sbool cAIPathDB::IsBlockedOBB(tAIPathCellID cell)
435 return (m_Cells[cell].pathFlags & kAIPF_BlockingOBB);
438 ///////////////////////////////////////
440 inline sbool cAIPathDB::IsActiveMovingTerrain(tAIPathCellID cell)
442 return (m_Cells[cell].pathFlags & kAIPF_ActiveMovingTerrain);
445 ///////////////////////////////////////
447 inline void cAIPathDB::MarkBegin()
449 m_nMarkedCells = 0;
452 ///////////////////////////////////////
454 inline void cAIPathDB::Mark(tAIPathCellID cell)
456 m_Marks[cell] = TRUE;
457 if (m_MarkedCells.Size() == m_nMarkedCells)
458 m_MarkedCells.Grow(16);
459 m_MarkedCells[m_nMarkedCells] = cell;
460 m_nMarkedCells++;
463 ///////////////////////////////////////
465 inline void cAIPathDB::Unmark(tAIPathCellID cell)
467 m_Marks[cell] = FALSE;
470 ///////////////////////////////////////
472 inline BOOL cAIPathDB::GetMark(tAIPathCellID cell)
474 return m_Marks[cell];
477 ///////////////////////////////////////
479 inline void cAIPathDB::MarkEnd()
481 register int i = m_nMarkedCells;
482 register sbool * const pm = m_Marks.AsPointer();
483 register const tAIPathCellID * const pid = m_MarkedCells.AsPointer();
485 while (--i >= 0)
486 *(pm + *(pid + i)) = FALSE;
489 ///////////////////////////////////////////////////////////////////////////////
491 inline BOOL cAIPathDB::CanPathfindBetweenZones(eAIPathZoneType ZoneType, tAIPathZone zone1, tAIPathZone zone2, tAIPathOkBits okBits)
493 if (zone1 == zone2)
494 return TRUE;
496 if (zone1 == AI_ZONE_ALL || zone2 == AI_ZONE_ALL)
497 return TRUE;
499 if (zone1 == AI_ZONE_SOLO || zone2 == AI_ZONE_SOLO)
500 return FALSE;
502 // the okbits must satisfy all okbits between the zones
503 tAIPathOkBits zoneOkBits = GetZoneOkBits(ZoneType, zone1, zone2);
505 if ((zoneOkBits != 0) && ((zoneOkBits & okBits & kNoConditionMask) == zoneOkBits))
506 return TRUE;
507 else
508 return FALSE;
511 ////////////////////////////////////////
513 inline tAIPathZone cAIPathDB::GetCellZone(eAIPathZoneType ZoneType, tAIPathCellID cell)
515 if (cell < m_ZoneDatabases[ZoneType].m_CellZones.Size())
516 return m_ZoneDatabases[ZoneType].m_CellZones[cell];
517 else
518 return 0;
521 ////////////////////////////////////////
523 inline tAIPathOkBits cAIPathDB::GetZoneOkBits(eAIPathZoneType ZoneType, tAIPathZone zone1, tAIPathZone zone2)
525 if (zone1 == AI_ZONE_SOLO || zone2 == AI_ZONE_SOLO)
526 return 0;
528 int key = (zone1 << 16) | zone2;
530 sZoneOkBitsMap *pMap = m_ZoneDatabases[ZoneType].m_ZonePairTable.Search(key);
532 if (pMap == NULL)
533 return 0;
534 else
535 return pMap->okBits;
538 ////////////////////////////////////////
540 inline void cAIPathDB::SetZoneOkBits(eAIPathZoneType ZoneType, tAIPathZone zone1, tAIPathZone zone2, tAIPathOkBits okBits)
542 if (zone1 == AI_ZONE_SOLO || zone2 == AI_ZONE_SOLO)
543 return;
545 sZoneOkBitsMap *pMap = new sZoneOkBitsMap;
547 pMap->key = (zone1 << 16) | zone2;
548 pMap->okBits = okBits;
550 m_ZoneDatabases[ZoneType].m_ZonePairTable.RemoveByKey(pMap->key);
551 m_ZoneDatabases[ZoneType].m_ZonePairTable.Insert(pMap);
554 ///////////////////////////////////////////////////////////////////////////////
556 #pragma pack()
558 #include <undbmem.h>
560 #endif /* !__AIPATHDB_H */