/// <summary> /// Fait exploser la bombe, ce qui immobilise et blesse les ennemis proches. /// </summary> private void Explodes() { _hasExplosed = true; var damages = InitialDamages * _owner.SpellPowerRatio(); var actors = CollisionFunctions.GetCollidingActors(Position, ExplosionHitbox); foreach (var actor in actors) { var livingActor = actor as LivingActor; if (EnnemyWith(actor) && livingActor != null) { livingActor.Damages(damages); _owner.Heals(damages * _owner.VampirismRatio()); livingActor.LockMoves(); livingActor.CreateState(States.BombDebuff); } } }
/// <summary> /// Vérifie si le délai est écoulé, auquel cas déclenche l'explosion, ce qui tue l'actor courant (et laisse son /// résidu de mort) et affecte tous les ennemis dans le rayon de l'explosion. /// </summary> /// <param name="ms"> Le temps écoulé en millisecondes </param> public override void Tick(int ms) { base.Tick(ms); if (!((AnimationHandler)SpriteHandler).IsFinished()) { return; } // Si le délai est écoulé var damages = _data.Damage * _owner.SpellPowerRatio(); foreach (var actor in CollisionFunctions.GetCollidingActors(Position, new Circle(_data.Size))) { var livingActor = actor as LivingActor; if (EnnemyWith(actor) && livingActor != null) { livingActor.Damages(damages); _owner.Heals(damages * _owner.VampirismRatio()); _data.Effect?.Invoke(_owner, Position, livingActor); } } Kill(); }
/// <summary> /// Crée un sort qui va infliger des dégâts aux ennemis situés dans un cercle en face du lanceur. /// Certaines données sont écrites par défaut : /// L'animation du posesseur lors de l'incantation du sort est de type Attack, le sort n'a pas de temps de /// recharge, le pourcentage du déclenchement de l'effet est de 1 (ce qui signifie que le sort est lancé à la /// fin de son incantation) et la portée du sort équivaut à deux fois la portée indiquée. /// Ces données prennent en compte les statistiques de son possesseur. /// </summary> /// <param name="damages"> Le sdégâts infligés </param> /// <param name="range"> La distance de l'acteur au cercle d'impact et le rayon de ce cercle </param> /// <param name="castTimeMs"> Le temps d'attaque </param> /// <param name="canMove"> Indique si le lanceur peut se déplacer pendant son attaque </param> public AttackSpellData(int damages, int range, int castTimeMs, bool canMove) : base((caster, target) => { target = caster.Muzzle(range); var livingCaster = caster as LivingActor; var heal = livingCaster?.VampirismRatio() ?? 0.0; var actors = CollisionFunctions.GetCollidingActors(target, new Circle(range)); foreach (var actor in actors) { var livingActor = actor as LivingActor; if (livingActor != null && !caster.FriendWith(actor)) { livingActor.Damages(damages * caster.PhysicalDamagesRatio()); if (heal != 0.0) { livingCaster?.Heals(damages * livingCaster.VampirismRatio()); } } } }, AnimationType.Attack, 0, castTimeMs, 1, canMove, 2, range * 2) { }
/// <summary> /// Récupère les acteurs dans la zone de détection derrière l'acteur associé, et utilise celui qui est le plus /// centré en bas de la zone de détection pour établir la nouvelle opacité. /// </summary> /// <param name="ms"> Le temps écoulé en millisecondes </param> public override void Tick(int ms) { var actors = CollisionFunctions.GetCollidingActors(_owner.Position - new Point(0, (double)_height / 2), new Rectangle(_width * 2, _height * 2)); var opacityMin = 1.0f; foreach (var actor in actors) { // Les acteurs neutres sont ignorés if (actor.Faction == Faction.Neutral) { continue; } var p = actor.Position; var x = Math.Abs(_owner.Position.X - p.X); double y; if (p.Y > _owner.Position.Y) { y = _height + 1; } else { y = Math.Abs(_owner.Position.Y - p.Y); } if ((x > _width) || (y > _height)) { continue; } // Minimise l'opacité lorsque l'acteur est au milieu en abscisse et en bas en ordonnée var x2 = (float)Math.Min(1, x / _width) * (1 - _opacityMin) + _opacityMin; var y2 = (float)Math.Min(1, y / _height) * (1 - _opacityMin) + _opacityMin; opacityMin = Math.Min(Math.Max(x2, y2), opacityMin); } Opacity = opacityMin; }