2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/ai/aipathdb.h,v 1.27 2000/03/01 13:02:52 bfarquha Exp $
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
);
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
53 mxs_vector intersects
[2];
56 ///////////////////////////////////////////////////////////////////////////////
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
;
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
;
87 struct sFleeRegionData
93 class cFleeRegionsHash
: public cHashSet
<sFleeRegionData
*, const ObjID
, cHashFunctions
>
96 virtual tHashSetKey
GetKey(tHashSetNode p
) const
98 return (tHashSetKey
) ((sFleeRegionData
*)p
)->id
;
106 cZonePairTable m_ZonePairTable
;
109 // array of zones for each cell
110 cAIPathArray
<tAIPathZone
> m_CellZones
;
115 ///////////////////////////////////////////////////////////////////////////////
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;
148 int GetCellEdgeInfo(tAIPathCellID cell
, int index
) const;
150 void GetCellVertexFull(tAIPathCellID cell
, int index
, mxs_vector
* pVertex
, tAIPathVertexID
* pVertexID
) const;
152 BOOL
IsCellEdgeLinked(tAIPathCellID cell
, int index
) const;
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 ////////////////////////////////////
171 void Mark(tAIPathCellID cell
);
172 void Unmark(tAIPathCellID cell
);
173 BOOL
GetMark(tAIPathCellID cell
);
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 ////////////////////////////////////
213 friend BOOL
AIPathFind(const cMxsVector
& fromLocation
, tAIPathCellID startCell
,
214 const cMxsVector
& toLocation
, tAIPathCellID endCell
,
215 cAIPath
* pPath
, tAIPathOkBits OkBits
, tAIPathOkBits okCondBits
= 0);
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
;
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
;
242 // mapping of objects to the cells they've created
243 cAIPathArray
<sAIPathCellObjMap
> m_CellObjMap
;
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
;
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
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) \
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 ///////////////////////////////////////
380 inline int cAIPathDB::GetCellEdgeInfo(tAIPathCellID cell
, int index
) const
382 cAIPathDB_NormalizeVertexIndex(index
);
383 return m_CellVertices
[m_Cells
[cell
].firstVertex
+ index
].edgeInfo
;
386 ///////////////////////////////////////
388 inline BOOL
cAIPathDB::IsCellEdgeLinked(tAIPathCellID cell
, int index
) const
390 return m_CellVertices
[m_Cells
[cell
].firstVertex
+ index
].hasLinks
;
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
);
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()
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
;
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();
486 *(pm
+ *(pid
+ i
)) = FALSE
;
489 ///////////////////////////////////////////////////////////////////////////////
491 inline BOOL
cAIPathDB::CanPathfindBetweenZones(eAIPathZoneType ZoneType
, tAIPathZone zone1
, tAIPathZone zone2
, tAIPathOkBits okBits
)
496 if (zone1
== AI_ZONE_ALL
|| zone2
== AI_ZONE_ALL
)
499 if (zone1
== AI_ZONE_SOLO
|| zone2
== AI_ZONE_SOLO
)
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
))
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
];
521 ////////////////////////////////////////
523 inline tAIPathOkBits
cAIPathDB::GetZoneOkBits(eAIPathZoneType ZoneType
, tAIPathZone zone1
, tAIPathZone zone2
)
525 if (zone1
== AI_ZONE_SOLO
|| zone2
== AI_ZONE_SOLO
)
528 int key
= (zone1
<< 16) | zone2
;
530 sZoneOkBitsMap
*pMap
= m_ZoneDatabases
[ZoneType
].m_ZonePairTable
.Search(key
);
538 ////////////////////////////////////////
540 inline void cAIPathDB::SetZoneOkBits(eAIPathZoneType ZoneType
, tAIPathZone zone1
, tAIPathZone zone2
, tAIPathOkBits okBits
)
542 if (zone1
== AI_ZONE_SOLO
|| zone2
== AI_ZONE_SOLO
)
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 ///////////////////////////////////////////////////////////////////////////////
560 #endif /* !__AIPATHDB_H */