/************************************************************************************************ * * Copyright (C) 2001-2002 Raven Software * * RM_Path.h * ************************************************************************************************/ #pragma once #if !defined(RM_PATH_H_INC) #define RM_PATH_H_INC #ifdef DEBUG_LINKING #pragma message("...including RM_Path.h") #endif #if !defined(CM_RANDOMTERRAIN_H_INC) #include "../qcommon/cm_randomterrain.h" #endif #include class CRMPathManager; // directions you can proceed from cells enum ERMDir { DIR_FIRST= 0, DIR_N = 0, DIR_NE, DIR_E , DIR_SE, DIR_S , DIR_SW, DIR_W , DIR_NW, DIR_MAX, DIR_ALL = 255 }; #define HALF_DIR_MAX (DIR_MAX/2) class CRMNode { private: string mName; // name of node - "" if not used yet vec3_t mPos; // where node is int mPathID[DIR_MAX]; // path id's that lead from this node bool mAreaPointPlaced; // false if no area point here yet. int mFlattenHeight; public: CRMNode ( ); bool IsLocation() {return strlen(mName.c_str())>0;}; const char* GetName ( ) { return mName.c_str(); } vec3_t& GetPos ( ) { return mPos; } const float PathExist( const int dir) { return (mPathID[dir % DIR_MAX] != -1); }; const float GetPath ( const int dir) { return mPathID[dir % DIR_MAX]; }; bool AreaPoint() {return mAreaPointPlaced;}; void SetName ( const char* name ) { mName = name; } void SetPos ( const vec3_t& v ) { VectorCopy ( v, mPos ); } void SetPath( const int dir, const int id) { mPathID[dir % DIR_MAX] = id; }; void SetAreaPoint(bool ap) {mAreaPointPlaced = ap;}; void SetFlattenHeight(int flattenHeight) {mFlattenHeight = flattenHeight; } int GetFlattenHeight() {return mFlattenHeight; } }; typedef vector rmNodeVector_t; // named spots on the map, should be placed into nodes class CRMLoc { private: string mName; // name of location int mMinDepth; int mMaxDepth; int mMinPaths; int mMaxPaths; bool mPlaced; // location has been placed at a node public: CRMLoc (const char *name, const int min_depth, const int max_depth, const int min_paths =1, const int max_paths=1 ) : mMinDepth(min_depth), mMaxDepth(max_depth), mPlaced(false), mMinPaths(min_paths), mMaxPaths(max_paths) { mName = name; }; const char* GetName ( ) { return mName.c_str(); } void SetName ( const char* name ) { mName = name; } int MinDepth() {return mMinDepth;}; void SetMinDepth(const int deep) {mMinDepth = deep;}; int MaxDepth() {return mMaxDepth;}; void SetMaxDepth(const int deep) {mMaxDepth = deep;}; int MinPaths() {return mMinPaths;}; void SetMinPaths(const int paths) {mMinPaths = paths;}; int MaxPaths() {return mMaxPaths;}; void SetMaxPaths(const int paths) {mMaxPaths = paths;}; bool Placed() { return mPlaced; }; void SetPlaced(bool p) { mPlaced = p;}; }; typedef vector rmLocVector_t; // cells are used for figuring out node connections / paths struct CRMCell { private: int border; int wall; public: CRMCell() { border = 0; wall = DIR_ALL; }; int Border() {return border;}; int Wall() {return wall;}; bool Border(const int dir) { return (border & (1< rmCellVector_t; class CRMPathManager { public: int mXNodes; // number of nodes in the x dimension int mYNodes; // number of nodes in the y dimension private: rmLocVector_t mLocations; // location, named spots to be placed at nodes rmNodeVector_t mNodes; // nodes, spots on map that *may* be connected by paths rmCellVector_t mCells; // array of cells for doing path generation int mPathCount; int mRiverCount; int mMaxDepth; // deepest any location wants to be int mDepth; // current depth bool mCrossed; // used to indicate if paths crossed the imaginary diagonal that cuts symmetric maps in half // path style int mPathPoints; float mPathMinWidth; float mPathMaxWidth; float mPathDepth; float mPathDeviation; float mPathBreadth; // river style int mRiverDepth; int mRiverPoints; float mRiverMinWidth; float mRiverMaxWidth; float mRiverBedDepth; float mRiverDeviation; float mRiverBreadth; string mRiverBridge; vec3_t mRiverPos; static int neighbor_x[DIR_MAX]; static int neighbor_y[DIR_MAX]; CRandomTerrain* mTerrain; public: CRMPathManager ( CRandomTerrain* terrain ); ~CRMPathManager ( ); void ClearCells (int x_nodes, int y_nodes); bool CreateArray ( const int x_nodes, const int y_nodes ); CRMNode* FindNodeByName ( const char* name ); CRMNode* Node ( const int x, const int y ) {return mNodes[x + y*mXNodes];}; void CreateLocation ( const char* name, const int min_depth, int max_depth, const int min_paths =1, int max_paths =1 ); vec3_t& GetNodePos ( const int x, const int y ) { return mNodes[x + y*mXNodes]->GetPos(); }; void SetNodePos ( const int x, const int y, const vec3_t& pos) { mNodes[x + y*mXNodes]->SetPos(pos); }; int GetPathCount () {return mPathCount;}; int GetRiverCount () {return mRiverCount;}; float GetRiverDepth () {return mRiverBedDepth;}; float GetPathDepth () {return mPathDepth;}; const char *GetBridgeName () {return mRiverBridge.c_str();}; vec3_t& GetRiverPos ( const int x, const int y ); CRMCell& Cell ( const int x, const int y ) {return mCells[x + y*mXNodes];}; CRMCell& RiverCell ( const int x, const int y ) {return mCells[x + y*(mXNodes+1)];}; void PlaceLocation ( const int x, const int y ); void PathVisit ( const int x, const int y ); void RiverVisit ( const int x, const int y ); void SetPathStyle ( const int points = 10, const float minwidth = 0.01f, const float maxwidth = 0.05f, const float depth = 0.3f, const float deviation = 0.2f, const float breadth = 5); void SetRiverStyle ( const int depth = 5, const int points = 10, const float minwidth = 0.01, const float maxwidth = 0.03, const float beddepth = 0.0f, const float deviation = 0.25f, const float breadth = 7, string bridge_name = ""); void GeneratePaths ( symmetry_t symmetric = SYMMETRY_NONE ); void GenerateRivers ( ); }; #endif