#pragma once #include "aas2file/aastraversalchaindata.h" #include "framework/resource.h" #include "idlib/bv/bounds.h" #include "idlib/containers/list.h" #include "idlib/math/plane.h" #include "idlib/text/str.h" #include class idFile; class idLexer; template class idTypedResourceList; enum aas2TravelFlag_t : int { AAS_TFL_INVALID = 0x1, AAS_TFL_INVALID_TEAM1 = 0x2, AAS_TFL_INVALID_TEAM2 = 0x4, AAS_TFL_AIR = 0x8, AAS_TFL_WATER = 0x10, AAS_TFL_WALK = 0x20, AAS_TFL_WALKOFFLEDGE = 0x40, AAS_TFL_WALKOFFBARRIER = 0x80, AAS_TFL_BARRIERJUMP = 0x100, AAS_TFL_JUMP = 0x200, AAS_TFL_LADDER = 0x400, AAS_TFL_SWIM = 0x800, AAS_TFL_TELEPORT = 0x1000, AAS_TFL_ELEVATOR = 0x2000, AAS_TFL_CROUCH = 0x4000, AAS_TFL_LEAP = 0x8000, AAS_TFL_TRAVERSAL_CLASS_A = 0x10000, AAS_TFL_TRAVERSAL_CLASS_B = 0x20000, AAS_TFL_TRAVERSAL_CLASS_C = 0x40000, AAS_TFL_TRAVERSAL_EVASION = 0x80000, AAS_TFL_CLIMB = 0x100000, AAS_TFL_FLY = 0x200000, AAS_TFL_TRAVERSAL_EMERGENCY = 0x400000, AAS_TFL_TRAVERSAL_CLASS_D = 0x800000, AAS_TFL_TRAVERSAL_CLASS_E = 0x1000000, AAS_TFL_TRAVERSAL_COMBAT = 0x2000000, AAS_TFL_BLOCK_PLAYER = 0x4000000, AAS_TFL_MELEE = 0x8000000, AAS_TFL_MAX = 0x8000001, AAS_TFL_VALID_TEAM1 = static_cast(0xFFFFFFFCu), AAS_TFL_VALID_TEAM2 = static_cast(0xFFFFFFFAu), AAS_TFL_VALID_BOTH_TEAMS = static_cast(0xFFFFFFFEu), AAS_TFL_VALID_WALK_TEAM1 = 0x3C, AAS_TFL_VALID_WALK_TEAM2 = 0x3A, AAS_TFL_VALID_WALK_BOTH_TEAMS = 0x3E, AAS_TFL_TRAVERSAL_ANY_CLASS = 0x1870000 }; enum aas2AreaFlag_t : int { AAS_AREA_LEDGE = 0x1, AAS_AREA_REACHABLE_WALK = 0x2, AAS_AREA_OUTSIDE = 0x4, AAS_AREA_HIGH_CEILING = 0x8, AAS_AREA_NOPUSH = 0x10, AAS_AREA_CONTENTS_SOLID = 0x100, AAS_AREA_CONTENTS_WATER = 0x200, AAS_AREA_CONTENTS_CLUSTERPORTAL = 0x400, AAS_AREA_CONTENTS_OBSTACLE = 0x800, AAS_AREA_FAKE = 0x1000, AAS_AREA_CONTENTS_FLY = 0x2000, AAS_AREA_FLOOD_VISITED = 0x8000, AAS_AREA_MAX = 0x8001 }; enum aas2EdgeFlag_t : int { AAS_EDGE_WALL = 0x1, AAS_EDGE_LEDGE = 0x2, AAS_EDGE_WALL_CORNER = 0x4, AAS_EDGE_LEDGE_CORNER = 0x8, AAS_EDGE_STEP_TOP = 0x10, AAS_EDGE_STEP_BOTTOM = 0x20, AAS_EDGE_VERTICAL = 0x40, AAS_EDGE_WATER = 0x80, AAS_EDGE_LADDER = 0x100, AAS_EDGE_STEP_SIDE = 0x200, AAS_EDGE_WALL_CORNER_V0 = 0x400, AAS_EDGE_WALL_CORNER_V1 = 0x800, AAS_EDGE_FAKE = 0x1000, AAS_EDGE_MAX = 0x1001 }; enum aas2CoverFlag_t : int { AAS_COVERFLAG_CROUCH = 0x1, AAS_COVERFLAG_LEANLEFT = 0x2, AAS_COVERFLAG_LEANRIGHT = 0x4, AAS_COVERFLAG_STEPLEFT = 0x8, AAS_COVERFLAG_STEPRIGHT = 0x10, AAS_COVERFLAG_FIREOVER = 0x20, AAS_COVERFLAG_FIRELEANLEFT = 0x40, AAS_COVERFLAG_FIRELEANRIGHT = 0x80, AAS_COVERFLAG_FIRESTEPLEFT = 0x100, AAS_COVERFLAG_FIRESTEPRIGHT = 0x200, AAS_COVERFLAG_EXPOSED = 0x400, AAS_COVERFLAG_EXPLICIT = 0x800, AAS_COVERFLAG_FORCE = 0x1000, AAS_COVERFLAG_INVALID = 0x2000, AAS_COVERFLAG_TRANSITION_APPROACH_FORWARD = 0x4000, AAS_COVERFLAG_TRANSITION_APPROACH_LEFT = 0x8000, AAS_COVERFLAG_TRANSITION_APPROACH_TURN_AROUND_LEFT = 0x10000, AAS_COVERFLAG_TRANSITION_APPROACH_WRAP_AROUND_LEFT = 0x20000, AAS_COVERFLAG_TRANSITION_APPROACH_RIGHT = 0x40000, AAS_COVERFLAG_TRANSITION_APPROACH_TURN_AROUND_RIGHT = 0x80000, AAS_COVERFLAG_TRANSITION_APPROACH_WRAP_AROUND_RIGHT = 0x100000, AAS_COVERFLAG_TRANSITION_APPROACH_JUMPOVER = 0x200000, AAS_COVERFLAG_AVOID = 0x400000, AAS_COVERFLAG_TRANSITION_ALL = 0x3FC000 }; class idAAS2Settings { public: enum type_t : int { AAS_PLAYER = 0, AAS_MONSTER = 1, AAS_VEHICLE = 2, AAS_MAX = 3 }; enum aasPrimitiveMode_t : int { AAS_PRIMITIVE_MODE_DEFAULT = 0, AAS_PRIMITIVE_MODE_NEVER = 1, AAS_PRIMITIVE_MODE_ALWAYS = 2 }; idAAS2Settings(); bool ParseInt(idLexer& source, int& value); bool ParseFloat(idLexer& source, float& value); bool ParseVector(idLexer& source, idVec3& vector); bool ParseBounds(idLexer& source, idBounds& bounds); bool ValidForBounds(const idBounds& bounds) const; bool ReadFromFile(idLexer& source); bool WriteToFileBinary(idFile& file) const; bool ReadFromFileBinary(idFile& file); type_t type; idStr fileExtensionAAS; idStr groupName; idStr explicitGroupName; idBounds boundingBox; int primitiveModeBrush; int primitiveModePatch; int primitiveModeModel; idVec3 gravityDir; float gravityValue; float maxStepHeight; float maxBarrierHeight; float maxWaterJumpHeight; float maxFallHeight; float minFloorCos; float minHighCeiling; float groundSpeed; float waterSpeed; float ladderSpeed; float wallCornerEdgeRadius; float ledgeCornerEdgeRadius; float obstaclePVSRadius; float wallCornerReachabilityBackoff; float highQualityReachabilityBackoff; float minCrouchingCoverHeight; float minStandingCoverHeight; float crouchingFireHeight; float standingFireHeight; float minWallWidth; float maxWallWidth; float minDoorWidth; float maxDoorWidth; float coverCornerDistance; float coverWallDistance; float chokePointWidth; int tt_barrierJump; int tt_waterJump; int tt_startWalkOffLedge; int tt_startLadderClimb; }; struct aas2Edge_t { int vertexNum[2]; int flags; }; struct aas2Node_t { std::uint32_t planeNum; std::uint32_t flags; int children[2]; }; struct aas2Portal_t { std::uint16_t areaNum; std::int16_t clusters[2]; std::uint16_t clusterAreaNum[2]; std::uint16_t maxAreaTravelTime; }; struct aas2Cluster_t { int numAreas; int numReachableAreas; int numPortals; int firstPortal; }; struct aas2Name_t { char name[128]; int index; }; struct aas2AnimName_t { char name[128]; }; struct aas2DependencyName_t { char name[128]; }; struct aas2InteractionEntityName_t { char name[128]; }; struct aas2TraversalEntityName_t { char name[128]; }; struct aas2AreaBounds_t { std::int16_t min[3]; std::int16_t max[3]; }; struct aas2Reachability_t { std::uint32_t travelFlags; std::uint16_t travelTime; std::uint16_t fromAreaNum; std::uint16_t toAreaNum; std::uint16_t padding; std::int16_t start[3]; std::int16_t end[3]; std::uint32_t areaTTOfsAndNumber; idIndex next; idIndex rev_next; idVec3 Start() const { return idVec3(float(start[0]), float(start[1]), float(start[2])); } idVec3 End() const { return idVec3(float(end[0]), float(end[1]), float(end[2])); } }; struct aas2Area_t { std::uint32_t travelFlags; std::uint16_t flags; std::int16_t numEdges; int firstEdge; std::int16_t cluster; std::uint16_t clusterAreaNum; std::uint32_t obstaclePVSOffset; idIndex reach; idIndex rev_reach; std::uint16_t firstChokePoint; std::int16_t numChokePoints; std::uint16_t firstCover; std::uint16_t numCover; std::uint16_t firstTraversal; std::uint16_t numTraversals; std::uint16_t firstHintNode; std::uint16_t numHintNodes; aas2Area_t(); }; struct aas2Cover_t { idVec3 origin; idVec3 dir; std::int16_t areaNum; std::int16_t flags; int numTouching; int firstTouching; float durationSec; float minRange; float maxRange; int reservedBy; int usableTime; aas2Cover_t(); }; struct aas2ChokePoint_t { idVec3 points[2]; std::uint16_t rooms[2]; }; struct aas2HintNode_t { enum hintNodeType_t : int { HINT_NODE_TYPE_SEARCH_AUTO = 0, HINT_NODE_TYPE_SEARCH_ANIMATION = 1, HINT_NODE_TYPE_GRENADE = 2 }; idVec3 origin; std::int16_t areaNum; std::int16_t radius; std::uint8_t hintType; std::uint8_t orientation; std::uint8_t dirFlags; std::uint8_t grouping; int hintData; aas2HintNode_t(); void GetOrientationVector(idVec3& direction) const; }; struct aas2Trace_t { int flags; int travelFlags; int maxAreas; int getOutOfSolid; float fraction; idVec3 endpos; int planeNum; int lastAreaNum; int blockingAreaNum; int numAreas; int* areas; idVec3* points; }; struct aas2TraceHeight_t { int maxPoints; int numPoints; idVec3* points; }; struct aas2EdgeCrossed_t { int toAreaNum; int edgeNum; idVec3 edgePoint; }; struct aas2TraceFloor_t { float fraction; idVec3 endpos; int lastAreaNum; aas2EdgeCrossed_t firstEdge; aas2EdgeCrossed_t lastEdge; int maxAreas; int numAreas; int maxReachIndices; int numReachIndices; int* areas; idIndex* reachIndices; }; class idAAS2File : public idResource { public: struct bspTree_t { idVec3 floorNormal; int headNode; int firstArea; int lastArea; }; struct bestReachableArea_t { float bboxHeight; float maxEdgeDist; int areaFlags; int excludeTravelFlags; int pointAreaNum; float pointAreaFloorDist; int boundsAreaNum; float boundsAreaFloorDist; }; struct floorEdgeSplitPoint_t { idVec3 point; float dist; int edgeNum; }; idAAS2File(); ~idAAS2File() override; void LoadResource() override; bool ReloadIfStale() override; idResourceList* GetResourceList() override; void Clear(); void MakeDefault(); unsigned int MemorySize() const; bool LoadBinary(const char* fileName, const char* binaryFileName, std::uint32_t mapFileCRC, std::uint32_t sourceTimestamp); bool WriteBinary(const char* fileName, const char* binaryFileName, std::uint32_t mapFileCRC, std::uint32_t sourceTimestamp); bool GetAASAnim(idIndex index, const aas2AnimName_t** value) const; idIndex GetAASAnimIndexByName(const char* name) const; bool GetAASDependency(idIndex index, const aas2DependencyName_t** value) const; idIndex GetAASDependencyIndexByName(const char* name) const; bool GetAASInteractionEntity(idIndex index, const aas2InteractionEntityName_t** value) const; idIndex GetAASInteractionEntityIndexByName(const char* name) const; bool GetAASTraversalNameIndex(idIndex index, const aas2TraversalEntityName_t** value) const; idIndex GetAASTraversalNameIndexByName(const char* name) const; int GetAASTraversalIndexByNameIndex(idIndex index) const; bool SetTraversalFlag(int index, int flags); bool ClearTraversalFlag(int index, int flags); bool GetAASTraversalAreas(int index, int& startArea, int& goalArea) const; idIndex FindReachabilityByName(const char* name) const; int GetTraversalsForReachability(idIndex reachIndex, idList& traversals) const; int GetTraversalsForInteractableEntity(idIndex index, idList& traversals) const; void FlagNoPushAreas(); void ResetCover(); idIndex GetTreeForFloorNormal(const idVec3& normal) const; idIndex GetTreeForArea(int areaNum) const; int GetNumAreasInTree(idIndex treeNum) const; const idVec3* GetFloorNormalForArea(int areaNum) const; const idVec3* GetFloorNormalForTree(idIndex treeNum) const; idVec3 AreaCenter(int areaNum) const; idBounds EdgeBounds(int edgeNum) const; idBounds AreaBounds(int areaNum) const; int PointAreaNum(int tree, const idVec3& origin) const; int BoundsAreaNums(int tree, const idBounds& bounds, int* outputAreas, int maxAreas) const; void FlagBoundsAreas(int tree, const idBounds& bounds, bool* areasTouched) const; int BoundsReachableAreaNum(int tree, const idBounds& bounds, std::uint16_t areaFlags, int excludeTravelFlags) const; bool TraceHeight(int tree, aas2TraceHeight_t& trace, const idVec3& start, const idVec3& end) const; bool GetFloorEdgeSplitPoints(floorEdgeSplitPoint_t& nearest, floorEdgeSplitPoint_t& furthest, int areaNum, const idPlane& pathPlane, const idPlane& nearPlane) const; int MaxTreeDepth(int tree) const; bool Trace(int tree, aas2Trace_t& trace, const idVec3& start, const idVec3& end) const; int GetObstaclePVSWallEdges(int areaNum, int edgeFlags, int* outputEdges, int maxEdges) const; void ClipGridToAreas(const idVec3& startOrigin, int startAreaNum, int travelFlags, unsigned int cellSize, int dimension, std::uint8_t* reachable) const; float GetFloorDistance(int areaNum, const idPlane& floorPlane, const idVec3& point, float bboxHeight, float maxEdgeDist) const; int PointReachableAreaNum(idIndex tree, const idVec3& origin, int areaFlags, int excludeTravelFlags) const; bool PushPointIntoAreaNum(int areaNum, idVec3& point) const; bool TraceFloor(aas2TraceFloor_t& trace, const idVec3& start, int startAreaNum, const idVec3& end, int endAreaNum, int travelFlags, bool allowFloorNormalChange, bool ignoreGravityDirectionDistance, bool ignoreSameArea) const; void FloodAddVisitedArea(int areaNum); void FloodClearVisitedAreas(int offset); static idTypedResourceList resourceList; std::uint32_t crc; std::uint32_t timestamp; idList visitedAreas; idAAS2Settings settings; int major; int minor; int firstFakeVertex; int firstFakeEdge; int firstFakeEdgeIndex; int firstFakeArea; idList trees; idList planes; idList vertices; idList edges; idList edgeIndex; idList reachabilities; idList areas; idList nodes; idList portals; idList portalIndex; idList clusters; idList obstaclePVS; idList reachabilityNames; idList animNames; idList dependencyNames; idList interactionEntityNames; idList traversalEntityNames; idList cover; idList areaCoverIndex; idList touchingCoverIndex; idList chokePoints; idList traversalPoints; idList hintNodes; idList areaBounds; private: bool LoadText(const char* fileName, std::uint32_t sourceTimestamp); bool ParseIndex(idLexer& source, idList& indexes); bool ParseNames(idLexer& source, idList& names); template bool ParseInteractionEntityNames(idLexer& source, idList& names); bool ParseVertices(idLexer& source); bool ParseEdges(idLexer& source); bool ParseNodes(idLexer& source); bool ParsePortals(idLexer& source); bool ParseClusters(idLexer& source); bool ParseObstaclePVS(idLexer& source); bool ParsePlanes(idLexer& source); bool ParseReachabilities(idLexer& source); bool ParseAreas(idLexer& source); bool ParseCover(idLexer& source); bool ParseTraversalPoints(idLexer& source); bool ParseHintNodes(idLexer& source); bool ParseTrees(idLexer& source); void CalculateAreaBounds(); void BuildReachabilityChains(); void PointBestReachableAreaNum(int tree, const idVec3& origin, bestReachableArea_t& bestArea) const; void BoundsBestReachableAreaNum(int tree, const idBounds& bounds, const idVec3& origin, bestReachableArea_t& bestArea) const; void MaxTreeDepth_r(int nodeNum, int depth, int& maxDepth) const; }; #if INTPTR_MAX == INT32_MAX static_assert(sizeof(idAAS2Settings) == 268, "Recovered idAAS2Settings ABI changed"); static_assert(sizeof(aas2Edge_t) == 12, "Recovered aas2Edge_t ABI changed"); static_assert(sizeof(aas2Node_t) == 16, "Recovered aas2Node_t ABI changed"); static_assert(sizeof(aas2Portal_t) == 12, "Recovered aas2Portal_t ABI changed"); static_assert(sizeof(aas2Reachability_t) == 32, "Recovered aas2Reachability_t ABI changed"); static_assert(sizeof(aas2Area_t) == 40, "Recovered aas2Area_t ABI changed"); static_assert(sizeof(aas2Cover_t) == 56, "Recovered aas2Cover_t ABI changed"); static_assert(sizeof(aas2ChokePoint_t) == 28, "Recovered aas2ChokePoint_t ABI changed"); static_assert(sizeof(aas2HintNode_t) == 24, "Recovered aas2HintNode_t ABI changed"); static_assert(sizeof(aas2Trace_t) == 56, "Recovered aas2Trace_t ABI changed"); static_assert(sizeof(aas2TraceFloor_t) == 84, "Recovered aas2TraceFloor_t ABI changed"); static_assert(sizeof(idAAS2File) == 736, "Recovered idAAS2File ABI changed"); #endif