/// <summary> /// Mets à jour l'aggro de l'Datacenter. /// </summary> void UpdateAggro() { EntityCollection entitiesInRange = GameServer.GetMap().Entities.GetAliveEntitiesInRange(this.Position, AttackRange); // Si la cible sort de l'aggro : on annule l'agro. if (m_currentAgro != null) { if (m_currentAgro.IsDead || Vector2.DistanceSquared(m_currentAgro.Position, Position) > AttackRange * AttackRange) { m_currentAgro = null; } } // Si la tour n'a pas d'aggro : on cherche la première unité Virus en range if (m_currentAgro == null) { EntityType ennemyVirus = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyVirus, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityBase nearestEnnemyVirus = entitiesInRange.GetEntitiesByType(ennemyVirus).NearestFrom(this.Position); m_currentAgro = nearestEnnemyVirus; } // Si on n'en trouve pas : on cherche le premier héros en range. if (m_currentAgro == null) { EntityType ennemyHero = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyPlayer, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityCollection ennemyHeroes = entitiesInRange.GetEntitiesByType(ennemyHero); EntityBase nearestEnnemyHero = ennemyHeroes.NearestFrom(this.Position); m_currentAgro = nearestEnnemyHero; } if (m_currentAgro != null && !m_currentAgro.Type.HasFlag(EntityType.Player)) { // Si la cible a déjà l'aggro sur quelqu'un et que ce n'est pas un héros, // on vérifie qu'un des alliés n'est pas attaqué par un héros adverse. // Si un allié est attaqué par un héros, la tour aggro le héros qui l'a attaquée. EntityType allyHeroType = EntityTypeConverter.ToAbsolute(EntityTypeRelative.AllyPlayer, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityType ennemyHeroType = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyPlayer, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityCollection allyHeroes = entitiesInRange.GetEntitiesByType(allyHeroType); // Pour tous les héros alliés, on regarde s'ils n'ont pas été attaqués recemment par des héros // ennemis. foreach (var kvp in allyHeroes) { EntityBase allyHero = kvp.Value; EntityCollection aggressiveHeros = allyHero.GetRecentlyAgressiveEntities(1.0f).GetEntitiesByType(ennemyHeroType); if (aggressiveHeros.Count != 0) { EntityBase aggressiveHero = aggressiveHeros.First().Value; m_currentAgro = aggressiveHero; } } } }
/// <summary> /// Mets à jour l'aggro du Virus. /// </summary> void UpdateAggro(GameTime time) { // Vérification du délai d'update // Ce délai est mis en place pour des questions de performances. __updateAgroDelay -= (float)time.ElapsedGameTime.TotalSeconds; if (__updateAgroDelay > 0) { return; } // Mise à jour du délai d'update float margin = AggroUpdateDelay * AggroUpdateDelayMargin; __updateAgroDelay = AggroUpdateDelay + ((float)s_random.NextDouble() - 0.5f) * margin; // Commencement de l'update. EntityCollection entitiesInRange = GameServer.GetMap().Entities.GetAliveEntitiesInRange(this.Position, AttackRange).GetEntitiesInSight(Type & EntityType.Teams); EntityBase oldAggro = m_currentAgro; if (m_currentAgro != null && (m_currentAgro.IsDead || !HasSightOn(m_currentAgro))) { m_currentAgro = null; } // Si la Virus n'a pas d'aggro : on cherche la première unité Virus en range EntityType ennemyVirusType = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyVirus, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityBase nearestEnnemyVirus = entitiesInRange.GetEntitiesByType(ennemyVirusType).NearestFrom(this.Position); if (nearestEnnemyVirus != null) { m_currentAgro = nearestEnnemyVirus; } // S'il n'y a pas de Virus ennemi en range, on regarde si il y a une tour en range. EntityType ennemyTower = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyTower, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityBase nearestTower = entitiesInRange.GetEntitiesByType(ennemyTower).NearestFrom(this.Position); if (nearestTower != null) { m_currentAgro = nearestTower; } // Datacenter EntityType ennemyDatacenter = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyDatacenter, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityBase nearestDatacenter = entitiesInRange.GetEntitiesByType(ennemyDatacenter).NearestFrom(this.Position); if (nearestDatacenter != null) { m_currentAgro = nearestDatacenter; } // Si on n'en trouve pas : on cherche le premier héros en range. EntityType ennemyHero = EntityTypeConverter.ToAbsolute(EntityTypeRelative.EnnemyPlayer, this.Type & (EntityType.Team1 | EntityType.Team2)); EntityBase nearestEnnemyHero = entitiesInRange.GetEntitiesByType(ennemyHero).NearestFrom(this.Position); if (nearestEnnemyHero != null) { m_currentAgro = nearestEnnemyHero; } // Avance au checkpoint suivant si on a atteint le précédent ou qu'on a rien trouvé à aggro. if (m_currentAgro == null || (m_currentAgro.Type.HasFlag(EntityType.Checkpoint) && HasReachedPosition(m_currentAgro.Position, time, GetMoveSpeed()))) { //bool __debugPositionReached = HasReachedPosition(m_currentAgro.Position, time, GetMoveSpeed()); EntityType allycp = EntityTypeConverter.ToAbsolute(EntityTypeRelative.AllyCheckpoint, this.Type); EntityCollection checkpoints = GameServer.GetMap().Entities.GetEntitiesByType(allycp); // Obtient le checkpoint suivant le plus proche. float minDistanceSqr = float.MaxValue; EntityBase next = m_currentAgro; foreach (var kvp in checkpoints) { EntityCheckpoint cp = (EntityCheckpoint)kvp.Value; // On ne considère pas les checkpoints qui ne sont pas dans notre rangée. if (cp.CheckpointRow != Row) { continue; } // On prend le + proche des checkpoints suivants. float dstSqr = Vector2.DistanceSquared(cp.Position, Position); if ((cp.CheckpointID > m_currentCheckpointId || (m_currentAgro == null && cp.CheckpointID >= m_currentCheckpointId)) && dstSqr < minDistanceSqr) { minDistanceSqr = dstSqr; next = cp; } } if (next != null) { m_currentCheckpointId = ((EntityCheckpoint)next).CheckpointID; } m_currentAgro = next; } // Si l'aggro bouge, on recalcule l'A*. if (m_currentAgro != null && Vector2.DistanceSquared(m_currentAgro.Position, m_currentAggroOldPos) > 1) { m_currentAggroOldPos = m_currentAgro.Position; ComputePath(); } // Si on change d'aggro, retourne le chemin vers la tour la plus proche. if (m_currentAgro != oldAggro) { ComputePath(); } }