/************************************************************************************************ * CRMInstance::PreSpawn * Prepares the instance for spawning by flattening the ground under it * * inputs: * landscape: landscape the instance will be spawned on * * return: * true: spawn preparation successful * false: spawn preparation failed * ************************************************************************************************/ bool CRMInstance::PreSpawn ( CRandomTerrain* terrain, qboolean IsServer ) { vec3_t origin; CArea area; VectorCopy(GetOrigin(), origin); if (mMirror) { origin[0] = TheRandomMissionManager->GetLandScape()->GetBounds()[0][0] + TheRandomMissionManager->GetLandScape()->GetBounds()[1][0] - origin[0]; origin[1] = TheRandomMissionManager->GetLandScape()->GetBounds()[0][1] + TheRandomMissionManager->GetLandScape()->GetBounds()[1][1] - origin[1]; } const vec3_t& terxelSize = terrain->GetLandScape()->GetTerxelSize ( ); const vec3pair_t& bounds = terrain->GetLandScape()->GetBounds(); // Align the instance to the center of a terxel origin[0] = bounds[0][0] + (int)((origin[0] - bounds[0][0] + terxelSize[0] / 2) / terxelSize[0]) * terxelSize[0]; origin[1] = bounds[0][1] + (int)((origin[1] - bounds[0][1] + terxelSize[1] / 2) / terxelSize[1]) * terxelSize[1]; // This is BAD - By copying the mirrored origin back into the instance, you've now mirrored the original instance // so when anything from this point on looks at the instance they'll be looking at a mirrored version but will be expecting the original // so later in the spawn functions the instance will be re-mirrored, because it thinks the mInstances have not been changed // VectorCopy(origin, GetOrigin()); // Flatten the area below the instance if ( GetFlattenRadius() ) { area.Init( origin, GetFlattenRadius(), 0.0f, AT_NONE, 0, 0 ); terrain->GetLandScape()->FlattenArea( &area, mFlattenHeight | (mSurfaceSprites?0:0x80), false, true, true ); } return true; }
void CRMPathManager::RiverVisit(const int c_x, const int c_y) { // does this cell have any neighbors with all walls intact? int i,off; // look at neighbors in random order off = TheRandomMissionManager->GetLandScape()->irand(DIR_FIRST, DIR_MAX-1); ++mDepth; // track our depth of recursion for (i = DIR_FIRST; i<DIR_MAX && mDepth <= mMaxDepth; i+=2) { int d = (i + off) % DIR_MAX; if ( !Cell(c_x, c_y).Border(d) ) { // we can move this way, since no border int new_c_x = c_x + neighbor_x[d]; int new_c_y = c_y + neighbor_y[d]; if (RiverCell(new_c_x,new_c_y).Wall() == DIR_ALL) { // we have a new cell that has not been visited! int new_dir; // d is the direction relative to the current cell // new_dir is the direction relative to the next cell (N becomes S, NE becomes SW, etc...) if( d < HALF_DIR_MAX ) { new_dir = d + HALF_DIR_MAX; } else { new_dir = d - HALF_DIR_MAX; } // knock down walls RiverCell(c_x,c_y).RemoveWall(d); RiverCell(new_c_x,new_c_y).RemoveWall(new_dir); //DIR_MAX - d); // create river between cells mTerrain->CreatePath ( mPathCount++, -1, 0, mRiverPoints, GetRiverPos(c_x,c_y)[0], GetRiverPos(c_x,c_y)[1], GetRiverPos(new_c_x,new_c_y)[0], GetRiverPos(new_c_x,new_c_y)[1], mRiverMinWidth, mRiverMaxWidth, mRiverBedDepth, mRiverDeviation, mRiverBreadth ); // flatten a small spot CArea area; float flat_radius = mRiverMinWidth * fabs(TheRandomMissionManager->GetLandScape()->GetBounds()[1][0] - TheRandomMissionManager->GetLandScape()->GetBounds()[0][0]); area.Init( GetRiverPos(c_x,c_y), flat_radius, 0.0f, AT_NONE, 0, 0 ); TheRandomMissionManager->GetLandScape()->FlattenArea (&area, 255 * mRiverBedDepth, false, true, true ); // recurse RiverVisit(new_c_x, new_c_y); } } } // --mDepth; }
/************************************************************************************************ * CRMPathManager::PathVisit * This method is called recursively to create a network of nodes connected with paths. * * inputs: * c_x, c_y - cell to visit * * return: * none * ************************************************************************************************/ void CRMPathManager::PathVisit(const int c_x, const int c_y) { // does this cell have any neighbors with all walls intact? int i,off; // look at neighbors in random order off = TheRandomMissionManager->GetLandScape()->irand(DIR_FIRST, DIR_MAX-1); ++mDepth; // track our depth of recursion for (i = DIR_FIRST; i<DIR_MAX && mDepth <= mMaxDepth; i++) { int d = (i + off) % DIR_MAX; if ( !Cell(c_x, c_y).Border(d) ) { // we can move this way, since no border int new_c_x = c_x + neighbor_x[d]; int new_c_y = c_y + neighbor_y[d]; if (Cell(new_c_x,new_c_y).Wall() == DIR_ALL) { // we have a new cell that has not been visited! int new_dir; // d is the direction relative to the current cell // new_dir is the direction relative to the next cell (N becomes S, NE becomes SW, etc...) if( d < HALF_DIR_MAX ) { new_dir = d + HALF_DIR_MAX; } else { new_dir = d - HALF_DIR_MAX; } // knock down walls Cell(c_x,c_y).RemoveWall(d); Cell(new_c_x,new_c_y).RemoveWall(new_dir); //DIR_MAX - d); // set path id Node(c_x, c_y)->SetPath(d, mPathCount); Node(new_c_x, new_c_y)->SetPath(new_dir, mPathCount); //DIR_MAX - d, mPathCount); // create path between cells mTerrain->CreatePath( mPathCount++, -1, 0, mPathPoints, GetNodePos(c_x,c_y)[0], GetNodePos(c_x,c_y)[1], GetNodePos(new_c_x,new_c_y)[0], GetNodePos(new_c_x,new_c_y)[1], mPathMinWidth, mPathMaxWidth, mPathDepth, mPathDeviation, mPathBreadth ); // flatten a small spot CArea area; float flat_radius = mPathMaxWidth * fabs(TheRandomMissionManager->GetLandScape()->GetBounds()[1][0] - TheRandomMissionManager->GetLandScape()->GetBounds()[0][0]); area.Init( GetNodePos(c_x,c_y), flat_radius, 0.0f, AT_NONE, 0, 0 ); TheRandomMissionManager->GetLandScape()->FlattenArea(&area, 255 * mPathDepth, false, true, true ); // recurse PathVisit(new_c_x, new_c_y); } } } --mDepth; // NOTE: *whoop* hack alert, the first time this is reached, it should be the very last placed node. if( !mCrossed && TheRandomMissionManager->GetMission()->GetSymmetric() && TheRandomMissionManager->GetMission()->GetBackUpPath() ) { mCrossed = true; int directionSet[3][3] = {DIR_NW,DIR_W,DIR_SW,DIR_N,-1,DIR_S,DIR_NE,DIR_E,DIR_SE}; int ncx = (mXNodes-1)-c_x; int ncy = (mYNodes-1)-c_y; int x_delta = ncx - c_x; int y_delta = ncy - c_y; if( x_delta < -1 ) { x_delta = -1; } else if( x_delta > 1 ) { x_delta = 1; } if( y_delta < -1 ) { y_delta = -1; } else if( y_delta > 1 ) { y_delta = 1; } // make sure the mirror is actually in a different position than then un-mirrored node if( x_delta || y_delta ) { int d = directionSet[x_delta][y_delta]; int new_dir; // d is the direction relative to the current cell // new_dir is the direction relative to the next cell (N becomes S, NE becomes SW, etc...) if( d < HALF_DIR_MAX ) { new_dir = d + HALF_DIR_MAX; } else { new_dir = d - HALF_DIR_MAX; } //NOTE: Knocking down these walls will cause instances to be created on this new artificial path // Since this path could span more than just the normal 1 cell, these walls being knocked down are not exactly correct... but get the job done // knock down walls Cell(c_x,c_y).RemoveWall(d); Cell(ncx,ncy).RemoveWall(new_dir); //DIR_MAX - d); // set path id Node(c_x, c_y)->SetPath(d, mPathCount); Node(ncx, ncy)->SetPath(new_dir, mPathCount); //DIR_MAX - d, mPathCount); // create an artificial path that crosses over to connect the symmetric and non-symmetric map parts mTerrain->CreatePath( mPathCount++, -1, 0, mPathPoints, GetNodePos(c_x,c_y)[0], GetNodePos(c_x,c_y)[1], GetNodePos(ncx,ncy)[0], GetNodePos(ncx,ncy)[1], mPathMinWidth, mPathMaxWidth, mPathDepth, mPathDeviation, mPathBreadth ); } } PlaceLocation(c_x, c_y); }