// Creates An Impact Grid Using The Size And Cell Size Of The Given Collision Grid public ImpactGrid(int w, int h) { cellSize = 2 * RTSConstants.IGRID_SIZE; numCells = new Point(w, h); size = new Vector2(numCells.X, numCells.Y) * cellSize; Region = new ImpactRegion[numCells.X, numCells.Y]; ImpactGenerators = new List <RTSBuilding> [numCells.X, numCells.Y]; CellImpact = new int[numCells.X, numCells.Y]; for (int x = 0; x < numCells.X; x++) { for (int y = 0; y < numCells.Y; y++) { Region[x, y] = null; ImpactGenerators[x, y] = new List <RTSBuilding>(); CellImpact[x, y] = 0; } } }
private void SpawnUnits(ImpactRegion r, int level) { // Decide Spawn Cap int spawnCap; if (level == 1) { spawnCap = L1SpawnCap; } else if (level == 2) { spawnCap = L2SpawnCap; } else if (level == 3) { spawnCap = L3SpawnCap; } else { spawnCap = 0; } // Return If Population Count Of Region Is Greater Than The Spawn Cap For The Region if (r.PopCount >= spawnCap) { return; } // Decide On A Starting Point Point start = new Point(-1, -1); foreach (var u in GameState.activeTeams[playerIndex].Team.Units) { Point cc = HashHelper.Hash(u.GridPosition, GameState.CGrid.numCells, GameState.CGrid.size); start = cc; } // Find Possible Spawn Points List<Point> spawnPoints = new List<Point>(); Queue<Point> unvisited = new Queue<Point>(); int width = GameState.CGrid.numCells.X; int height = GameState.CGrid.numCells.Y; bool[,] visited = new bool[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { visited[x, y] = false; } } if (start.X > 0 && start.Y > 0) { unvisited.Enqueue(start); visited[start.X, start.Y] = true; } while (unvisited.Count > 0) { Point at = unvisited.Dequeue(); for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { Point p = new Point(at.X + x, at.Y + y); if ((p.X != at.X || p.Y != at.Y) && p.X > 0 && p.Y > 0 && p.X < width && p.Y < height) { ImpactRegion pr = FindRegion(p); RTSBuilding b = GameState.CGrid.EStatic[p.X, p.Y]; if (pr.Cells.First() == r.Cells.First() && b != null) { bool isOre = b.Data.FriendlyName.Equals(OreData.FriendlyName); bool isTree = b.Data.FriendlyName.Equals(FloraData.FriendlyName); if (isOre || isTree) { spawnPoints.Add(at); } } else if (pr.Cells.First() == r.Cells.First() && b == null && !visited[p.X, p.Y]) { unvisited.Enqueue(p); visited[p.X, p.Y] = true; } } } } } if (spawnPoints.Count > 0) { // Choose A Random Spawn Point int ii = random.Next(spawnPoints.Count); Point spawnPoint = spawnPoints.ElementAt(ii); Vector2 spawnPos = new Vector2(spawnPoint.X, spawnPoint.Y) * GameState.CGrid.cellSize + Vector2.One; // Spawn Environmental Units int numSpawn; int ti = 0; foreach (var spawnType in Spawns) { numSpawn = random.Next(minNumSpawn[level - 1][ti], maxNumSpawn[level - 1][ti]); for (int j = 0; j < numSpawn && r.PopCount < spawnCap; j++) { AddEvent(new SpawnUnitEvent(TeamIndex, spawnType, spawnPos)); r.PopCount++; } ti++; } } SetInitTarget(r); }
private void SetInitTarget(ImpactRegion r) { List<IEntity> selected = r.Selected; // Select Units Not In A Squad AddEvent(new SelectEvent(TeamIndex, selected)); // Set The Target For Those Units IEntity target = null; Vector2 sumPos = Vector2.Zero; foreach(var s in selected) sumPos += s.GridPosition; Vector2 averagePos = new Vector2(sumPos.X / selected.Count, sumPos.Y / selected.Count); foreach(var t in GameState.activeTeams) if(t.Index != TeamIndex) foreach(var u in t.Team.Units) if(target == null || Vector2.Distance(u.GridPosition, averagePos) < Vector2.Distance(u.GridPosition, target.GridPosition)) target = u; AddEvent(new SetTargetEvent(TeamIndex, target)); }
// Natural Disaster That Damages Units private void CreateLightning(ImpactRegion r) { List<LightningParticle> particles = new List<LightningParticle>(); foreach(var ic in r.Cells) { Point c = new Point(ic.X * 2, ic.Y * 2); for(int x = 0; x < 2 && c.X + x < GameState.CGrid.numCells.X; x++) { for(int y = 0; y < 2 && c.Y + y < GameState.CGrid.numCells.Y; y++) { foreach(var u in GameState.CGrid.EDynamic[c.X + x, c.Y + y]) { if(u.Team.Index != Team.Index) { bool takeDamage = (random.Next(100) <= LightningHitP); if(takeDamage) { u.Damage(LightningDamage); bool canSee = GameState.CGrid.GetFogOfWar(u.GridPosition, playerIndex) == FogOfWar.Active; if (canSee) { particles.Add(new LightningParticle(u.WorldPosition, 1, 7, 1, 0.6f, 1, Color.BlueViolet)); } } } } } } } GameState.AddParticles(particles); }
// Natural Disaster That Damages Both Units And Buildings private void CreateFire(ImpactRegion r) { // Find Impact Cell With Highest Impact int i = random.Next(r.Cells.Count); Point highest = r.Cells.ElementAt(i); foreach (var ic in r.Cells) { if (grid.CellImpact[highest.X, highest.Y] > grid.CellImpact[ic.X, ic.Y]) { highest = ic; } } // Use That Impact Cell As A Fire Starting Point FireStarts.Add(highest); }
// Natural Disaster That Damages Buildings private void CreateEarthquake(ImpactRegion r) { List<LightningParticle> particles = new List<LightningParticle>(); foreach(var ic in r.Cells) { Point c = new Point(ic.X * 2, ic.Y * 2); for(int x = 0; x < 2 && c.X + x < GameState.CGrid.numCells.X; x++) { for(int y = 0; y < 2 && c.Y + y < GameState.CGrid.numCells.Y; y++) { RTSBuilding b = GameState.CGrid.EStatic[c.X + x, c.Y + y]; if(b != null && b.Team.Index != Team.Index) { bool takeDamage = (random.Next(100) <= EarthquakeHitP); if(true) { b.Damage(EarthquakeDamage); bool canSee = GameState.CGrid.GetFogOfWar(b.GridPosition, playerIndex) == FogOfWar.Active; if (canSee) { particles.Add(new LightningParticle(b.WorldPosition, 3, 10, 2, 0.6f, 1, Color.Red)); } } } } } } GameState.AddParticles(particles); }