void CRoomTemplate::LoadFromKeyValues( const char *pRoomName, KeyValues *pKeyValues ) { m_nTilesX = pKeyValues->GetInt( "TilesX", 1 ); m_nTilesY = pKeyValues->GetInt( "TilesY", 1 ); SetSpawnWeight( pKeyValues->GetInt( "SpawnWeight", MIN_SPAWN_WEIGHT ) ); SetFullName( pRoomName ); Q_strncpy( m_Description, pKeyValues->GetString( "RoomTemplateDescription", "" ), m_nMaxDescriptionLength ); Q_strncpy( m_Soundscape, pKeyValues->GetString( "Soundscape", "" ), m_nMaxSoundscapeLength ); SetTileType( pKeyValues->GetInt( "TileType", ASW_TILETYPE_UNKNOWN ) ); m_Tags.RemoveAll(); // search through all the exit subsections KeyValues *pkvSubSection = pKeyValues->GetFirstSubKey(); bool bClearedExits = false; while ( pkvSubSection ) { // mission details if ( Q_stricmp(pkvSubSection->GetName(), "EXIT")==0 ) { if ( !bClearedExits ) { // if we haven't cleared previous exits yet then do so now m_Exits.PurgeAndDeleteElements(); bClearedExits = true; } CRoomTemplateExit *pExit = new CRoomTemplateExit(); pExit->m_iXPos = pkvSubSection->GetInt("XPos"); pExit->m_iYPos = pkvSubSection->GetInt("YPos"); pExit->m_ExitDirection = (ExitDirection_t) pkvSubSection->GetInt("ExitDirection"); pExit->m_iZChange = pkvSubSection->GetInt("ZChange"); Q_strncpy( pExit->m_szExitTag, pkvSubSection->GetString( "ExitTag" ), sizeof( pExit->m_szExitTag ) ); pExit->m_bChokepointGrowSource = !!pkvSubSection->GetInt("ChokeGrow", 0); // discard exits outside the room bounds if ( pExit->m_iXPos < 0 || pExit->m_iYPos < 0 || pExit->m_iXPos >= m_nTilesX || pExit->m_iYPos >= m_nTilesY ) { delete pExit; } else { m_Exits.AddToTail(pExit); } } else if ( Q_stricmp(pkvSubSection->GetName(), "Tags")==0 && TagList() ) { for ( KeyValues *sub = pkvSubSection->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) { if ( !Q_stricmp( sub->GetName(), "tag" ) ) { AddTag( sub->GetString() ); } } } pkvSubSection = pkvSubSection->GetNextKey(); } }
void CEnvironmentGrid::CreateSquareNebula (SCreateCtx &Ctx, TArray<STileDesc> *retTiles) // CreateSquareNebula // // The nebula is a square: // // center: Ctx.pOrbitDesc position // height: Ctx.rHeight // width: Ctx.rWidth { if (Ctx.pEnv == NULL || Ctx.pOrbitDesc == NULL || Ctx.rWidth == 0.0 || Ctx.rHeight == 0.0) return; CVector vCenter = Ctx.pOrbitDesc->GetObjectPos(); // Compute the bounds of the nebula CVector vUL = vCenter + CVector(-0.5 * Ctx.rWidth, -0.5 * Ctx.rHeight); CVector vLR = vCenter + CVector(0.5 * Ctx.rWidth, 0.5 * Ctx.rHeight); // Now iterate over every tile in bounds and see if it is within // the band that we have defined. int xTileStart, yTileStart, xTileEnd, yTileEnd; VectorToTile(vUL, &xTileStart, &yTileStart); VectorToTile(vLR, &xTileEnd, &yTileEnd); // Set the granularity of the result array (so that we don't keep on // reallocating). if (retTiles) { retTiles->DeleteAll(); int iGranularity = Max(DEFAULT_ARRAY_GRANULARITY, (xTileEnd - xTileStart + 1) * (yTileEnd - yTileStart + 1) / 2); retTiles->SetGranularity(iGranularity); } // Set all tiles int x, y; for (x = xTileStart; x <= xTileEnd; x++) for (y = yTileStart; y <= yTileEnd; y++) { SetTileType(x, y, Ctx.pEnv); // Add to list of tiles if (retTiles) { STileDesc *pNewTile = retTiles->Insert(); pNewTile->x = x; pNewTile->y = y; pNewTile->pEnv = Ctx.pEnv; pNewTile->dwEdgeMask = 0; } } }
void CEnvironmentGrid::ConvertSpaceEnvironmentToPointers (CTileMap &UNIDs) // ConvertSpaceEnvironmentToPointers // // Converts m_pEnvironment to pointers (restore from save file) { m_Map.Init(UNIDs.GetSize(), UNIDs.GetScale()); STileMapEnumerator k; while (UNIDs.HasMore(k)) { DWORD dwTile; int xTile; int yTile; UNIDs.GetNext(k, &xTile, &yTile, &dwTile); CSpaceEnvironmentType *pEnv = g_pUniverse->FindSpaceEnvironment(dwTile); if (pEnv) SetTileType(xTile, yTile, pEnv); } m_iTileCount = m_Map.GetTotalSize(); }
void CEnvironmentGrid::CreateArcNebula (SCreateCtx &Ctx, TArray<STileDesc> *retTiles) // CreateArcNebula // // Creates an arc of nebula { if (Ctx.pEnv == NULL || Ctx.pOrbitDesc == NULL || Ctx.rWidth == 0.0) return; // Compute some constants Metric rHalfWidth = Ctx.rWidth / 2.0; Metric rMaxVariation = Ctx.iWidthVariation * rHalfWidth / 100.0; Metric rHalfVariation = rMaxVariation / 2.0; Metric rHalfSpan = g_Pi * Ctx.iSpan / 360.0; // Shape of the arc CVector vCenter = Ctx.pOrbitDesc->GetFocus(); Metric rArcCenterAngle = Ctx.pOrbitDesc->GetObjectAngle(); Metric rMaxRadius = Ctx.pOrbitDesc->GetSemiMajorAxis() + rHalfWidth; Metric rMinRadius = Ctx.pOrbitDesc->GetSemiMajorAxis() - rHalfWidth; // Shape parameters CWaveGenerator2 OuterWave( 0.75, // Wave 0 amplitude 5.0, // Wave 0 cycles 0.25, // Wave 1 amplitude 11.0 // Wave 1 cycles ); CWaveGenerator2 InnerWave( 0.5, 6.0, 0.5, 15.0 ); // Compute the bounds of the nebula Metric rDiag = rMaxRadius + (GetTileSize() * g_KlicksPerPixel); CVector vUL = vCenter + CVector(-rDiag, rDiag); CVector vLR = vCenter + CVector(rDiag, -rDiag); // Now iterate over every tile in bounds and see if it is within // the band that we have defined. int xTileStart, yTileStart, xTileEnd, yTileEnd; VectorToTile(vUL, &xTileStart, &yTileStart); VectorToTile(vLR, &xTileEnd, &yTileEnd); // Set the granularity of the result array (so that we don't keep on // reallocating). if (retTiles) { retTiles->DeleteAll(); int iGranularity = Max(DEFAULT_ARRAY_GRANULARITY, (xTileEnd - xTileStart + 1) * (yTileEnd - yTileStart + 1) / 2); retTiles->SetGranularity(iGranularity); } // Set all tiles int x, y; for (x = xTileStart; x <= xTileEnd; x++) for (y = yTileStart; y <= yTileEnd; y++) { CVector vTile = TileToVector(x, y); CVector vRadius = vTile - vCenter; // Convert to polar coordinates Metric rRadius; Metric rAngle = VectorToPolarRadians(vRadius, &rRadius); // Skip if outside bounds if (rRadius > rMaxRadius || rRadius < rMinRadius) continue; // Figure out our distance from the center angle Metric rDistAngle = rAngle - rArcCenterAngle; if (rDistAngle > g_Pi) rDistAngle -= 2.0 * g_Pi; else if (rDistAngle < -g_Pi) rDistAngle += 2.0 * g_Pi; Metric rDistAngleAbs = Absolute(rDistAngle); if (rDistAngleAbs > rHalfSpan) continue; // Compute the shape at this angle Metric rMidRadius; Ctx.pOrbitDesc->GetPointAndRadius(rAngle, &rMidRadius); Metric rOuterWave = rHalfVariation * OuterWave.GetValue(rAngle); Metric rInnerWave = rHalfVariation * InnerWave.GetValue(rAngle); // Taper the shape Metric rTaper = 1.0 - (rDistAngleAbs / rHalfSpan); // Calc radius Metric rOuterRadius = rMidRadius + rTaper * (rHalfWidth - rOuterWave); Metric rInnerRadius = rMidRadius - rTaper * (rHalfWidth + rInnerWave); // If we're inside the ring, then put a nebula down if (rRadius > rInnerRadius && rRadius < rOuterRadius) { SetTileType(x, y, Ctx.pEnv); // Add to list of tiles if (retTiles) { STileDesc *pNewTile = retTiles->Insert(); pNewTile->x = x; pNewTile->y = y; pNewTile->pEnv = Ctx.pEnv; pNewTile->dwEdgeMask = 0; } } } }
void CEnvironmentGrid::CreateCircularNebula (SCreateCtx &Ctx, TArray<STileDesc> *retTiles) // CreateCircularNebula // // The nebula is a ring: // // radius: Ctx.pOrbitDesc radius // width of ring: Ctx.rWidth { if (Ctx.pEnv == NULL || Ctx.pOrbitDesc == NULL || Ctx.rWidth == 0.0) return; // Compute some constants Metric rHalfWidth = Ctx.rWidth / 2.0; Metric rMaxVariation = Ctx.iWidthVariation * rHalfWidth / 100.0; Metric rHalfVariation = rMaxVariation / 2.0; // Shape parameters CWaveGenerator2 OuterWave( 0.75, // Wave 0 amplitude 5.0, // Wave 0 cycles 0.25, // Wave 1 amplitude 11.0 // Wave 1 cycles ); CWaveGenerator2 InnerWave( 0.5, 6.0, 0.5, 15.0 ); // The maximum diameter of the ring is the orbit diameter plus half the // width. Metric rMaxRadius = Ctx.pOrbitDesc->GetSemiMajorAxis() + rHalfWidth; CVector vCenter = Ctx.pOrbitDesc->GetFocus(); // Compute the bounds of the nebula Metric rDiag = rMaxRadius + (GetTileSize() * g_KlicksPerPixel); CVector vUL = vCenter + CVector(-rDiag, rDiag); CVector vLR = vCenter + CVector(rDiag, -rDiag); // Now iterate over every tile in bounds and see if it is within // the band that we have defined. int xTileStart, yTileStart, xTileEnd, yTileEnd; VectorToTile(vUL, &xTileStart, &yTileStart); VectorToTile(vLR, &xTileEnd, &yTileEnd); // Set the granularity of the result array (so that we don't keep on // reallocating). if (retTiles) { retTiles->DeleteAll(); int iGranularity = Max(DEFAULT_ARRAY_GRANULARITY, (xTileEnd - xTileStart + 1) * (yTileEnd - yTileStart + 1) / 2); retTiles->SetGranularity(iGranularity); } // Set all tiles int x, y; for (x = xTileStart; x <= xTileEnd; x++) for (y = yTileStart; y <= yTileEnd; y++) { CVector vTile = TileToVector(x, y); CVector vRadius = vTile - vCenter; // Convert to polar coordinates Metric rRadius; Metric rAngle = VectorToPolarRadians(vRadius, &rRadius); // Compute the shape at this angle Metric rMidRadius; Ctx.pOrbitDesc->GetPointAndRadius(rAngle, &rMidRadius); Metric rOuterWave = rHalfVariation * OuterWave.GetValue(rAngle); Metric rInnerWave = rHalfVariation * InnerWave.GetValue(rAngle); Metric rOuterRadius = rMidRadius + rHalfWidth - rOuterWave; Metric rInnerRadius = rMidRadius - rHalfWidth + rInnerWave; // If we're inside the ring, then put a nebula down if (rRadius > rInnerRadius && rRadius < rOuterRadius) { SetTileType(x, y, Ctx.pEnv); // Add to list of tiles if (retTiles) { STileDesc *pNewTile = retTiles->Insert(); pNewTile->x = x; pNewTile->y = y; pNewTile->pEnv = Ctx.pEnv; pNewTile->dwEdgeMask = 0; } } } }