void SpawnEnemy() { Objects.Enemy e = new Objects.Enemy(m_Game, Balance.Waves[m_WaveNumber - 1].Level); SpawnGameObject(e); m_Enemies.Add(e); m_EnemiesThisWave--; // Stop spawning once we hit the limit if (m_EnemiesThisWave == 0) { m_Timer.RemoveTimer("SpawnEnemy"); } }
// Find the closest enemy that's within range public Objects.Enemy GetClosestEnemyInRange(Vector3 vPosition, float fRange) { float fClosest = fRange + 1.0f; Objects.Enemy retVal = null; foreach (Objects.Enemy e in m_Enemies) { float fDist = Vector3.Distance(vPosition, e.Position); if (fDist < fClosest) { retVal = e; fClosest = fDist; } } return(retVal); }
public void RemoveEnemy(Objects.Enemy e, bool bGiveMoney = false) { RemoveGameObject(e, true); m_Enemies.Remove(e); // Give them the well deserved money if (bGiveMoney) { Money += Balance.Enemies[e.Level - 1].Money; } // If there are no enemies left, the wave is over if (m_EnemiesThisWave == 0 && m_Enemies.Count == 0) { m_bWaveActive = false; // If we just finished the last wave, VICTORY!! if (m_WaveNumber == Balance.TotalWaves) { GameOver(true); } else { // If the next wave will have stronger enemies, give a warning if (Balance.Waves[m_WaveNumber].Level == Balance.MaxEnemyLevel) { m_UIGameplay.ShowStatusMessage(Localization.Get().Text("ui_msg_boss"), 2.5f); SoundManager.Get().PlaySoundCue("Alarm"); } else if (Balance.Waves[m_WaveNumber].Level > Balance.Waves[m_WaveNumber - 1].Level) { m_UIGameplay.ShowStatusMessage(Localization.Get().Text("ui_msg_enemiesstronger"), 2.5f); SoundManager.Get().PlaySoundCue("Alarm"); } else { m_UIGameplay.ShowStatusMessage(Localization.Get().Text("ui_msg_waveover"), 2.5f); SoundManager.Get().PlaySoundCue("Victory"); } m_Timer.AddTimer("StartWave", Balance.Waves[m_WaveNumber - 1].NextWaveTime, StartWave, false); } } }
protected void SnareEnemy(Enemy e) { // We want to snare for a little bit longer than the reload time e.Snare(m_TowerData[m_Level - 1].Damage, m_TowerData[m_Level - 1].ReloadTime + 0.1f); }
// Computes the enemy path using A* // Returns true if there is a valid path, false if not. // If the optional parameter is NOT set, it sets the global path that all enemies use by default // otherwise, this function calculates the path only for the passed in Enemy. // This is to allow recalculation of paths for currently active Enemiess. public bool ComputeAStar(Objects.Enemy e = null) { // Clear out the open/closed set from previous paths m_OpenSet.Clear(); m_ClosedSet.Clear(); Objects.Tile StartTile = GlobalStartTile; // If we have a specific Enemy, the starting tile is the one the Enemy is currently at if (e != null) { StartTile = e.CurrentTile; } // We start at the goal node instead of the start node // so that the parent linked list does not need to be reversed once the A* is complete. PathNode node = new PathNode(); node.tile = GlobalGoalTile; node.g = 0.0f; node.h = 0.0f; node.f = 0.0f; // Initialize the A* algorithm PathNode CurrentNode = node; m_ClosedSet.Add(CurrentNode.tile, CurrentNode); do { // Loop through all the nodes adjacent to the current one foreach (Objects.Tile t in CurrentNode.tile.m_Neighbors) { // Is this tile already in the closed set? if (m_ClosedSet.ContainsKey(t)) { // If so, skip. continue; } else if (m_OpenSet.ContainsKey(t)) { // Check if node adoption should occur float test_g = CurrentNode.g + Vector3.Distance(t.Position, CurrentNode.tile.Position); // Is the new g(x) value lower than the current one? node = m_OpenSet[t]; if (test_g < node.g) { // If so, change parent node.parent = CurrentNode; node.g = test_g; node.f = node.g + node.h; } } // Tiles with a building are not passable, so should be ignored... // UNLESS it's the start node, which can happen if this is a Enemy repositioning else if (t.Tower == null || t == StartTile) { // Add a new PathNode to open set with CurrentNode as parent node = new PathNode(); node.parent = CurrentNode; node.tile = t; // Calculate h(x) using Euclidean distance node.h = Vector3.Distance(GlobalGoalTile.Position, t.Position); // Calculate g(x) node.g = node.parent.g + Vector3.Distance(t.Position, node.parent.tile.Position); // f(x) = g(x) + h(x) node.f = node.g + node.h; // Add to open set m_OpenSet.Add(t, node); } } // If the open set is empty, we failed to find a path if (m_OpenSet.Count == 0) { break; } // Search the open set for lowest f(x) cost float lowest_f = 10000000000.0f; foreach (PathNode p in m_OpenSet.Values) { if (p.f < lowest_f) { CurrentNode = p; lowest_f = p.f; } } // Move CurrentNode to closed set m_OpenSet.Remove(CurrentNode.tile); m_ClosedSet.Add(CurrentNode.tile, CurrentNode); }while (CurrentNode.tile != StartTile); // Check to see if we found a path if (CurrentNode.tile == StartTile) { // Set the start of the path to the current node // If there is no Enemy, this is the new global path if (e == null) { GlobalPath = CurrentNode; } else { e.m_Path = CurrentNode; e.ResetPath(true); } return(true); } else { // If there is no Enemy, this is the new global path if (e == null) { GlobalPath = null; } else { e.m_Path = null; e.ResetPath(true); } return(false); } }