public override void Run(RoleBase caster, Space space, MagicArgs args)
 {
     double angle = GlobalMethod.GetAngle(GlobalMethod.GetRadian(args.Position, args.Destination)) + 180;
     double singleAngle = 10;
     double startAngle = angle - ((args.Number - 1) / 2 * singleAngle);
     double endAngle = angle + ((args.Number - 1) / 2 * singleAngle);
     for (int i = 0; i < args.Number; i++) {
         double otherAngle = startAngle + singleAngle * i;
         Bullet bullet = new Bullet(new BulletDatas() { Code = args.ResCode, Type = BulletTypes.Common }) {
             SpaceLayer = caster.SpaceLayer,
             Z = (int)args.Destination.Y,
         };
         double offsetX = bullet.Source.PixelWidth * bullet.Scale;
         double offsetStartY = (caster.State == States.Riding ? (caster.Profession == Professions.Taoist ? 130 : 110) : 60) * bullet.Scale;
         double offsetEndY = 80 * bullet.Scale;
         EventHandler handler = null;
         bullet.MoveCompleted += handler = delegate {
             bullet.MoveCompleted -= handler;
             space.RemoveUIElement(bullet);
         };
         space.AddUIElement(bullet);
         Point p = new Point(args.Destination.X + args.Radius * Math.Cos(GlobalMethod.GetRadian(otherAngle)), args.Destination.Y + args.Radius * Math.Sin(GlobalMethod.GetRadian(otherAngle)));
         bullet.Move(new Point(args.Position.X - offsetX, args.Position.Y - offsetStartY), new Point(p.X - offsetX, p.Y - offsetEndY), 0.6 / bullet.Scale, MoveModes.Normal);
     }
     double s0 = 0, s1 = 1, e0 = 0, e1 = 0;
     if (startAngle < 180 && endAngle > 180) {
         s0 = startAngle; e0 = 180; s1 = -180; e1 = endAngle - 360;
     } else if (startAngle >= 180) {
         s0 = startAngle - 360; e0 = endAngle - 360;
     } else {
         s0 = startAngle; e0 = endAngle;
     }
     for (int i = space.AllRoles().Count - 1; i >= 0; i--) {
         RoleBase target = space.AllRoles()[i];
         if (caster.IsHostileTo(target)) {
             double tempAngle = GlobalMethod.GetAngle(GlobalMethod.GetRadian(target.Position, args.Position));
             if ((tempAngle >= s0 && tempAngle <= e0) || (tempAngle >= s1 && tempAngle <= e1) || target.InCircle(args.Position, 50)) {
                 caster.CastingToEffect(target, args);
             }
         }
     }
 }
 void CreateSubMagic(RoleBase caster, Space space, MagicArgs args)
 {
     Bullet bullet = new Bullet(new BulletDatas() { Code = args.ResCode, Type = BulletTypes.Animation,Loop = true }) {
         SpaceLayer = caster.SpaceLayer,
         Z = (int)args.Destination.Y,
     };
     double offsetX = bullet.Offset.X * bullet.Scale;
     double offsetStartY = (caster.State == States.Riding ? (caster.Profession == Professions.Taoist ? 130 : 110) : 60) * bullet.Scale;
     double offsetEndY = (targets[index].State == States.Riding ? 100 : 70) * bullet.Scale;
     EventHandler handler = null;
     bullet.MoveCompleted += handler = delegate {
         bullet.MoveCompleted -= handler;
         space.RemoveUIElement(bullet);
         if (caster.IsHostileTo(targets[index])) { caster.CastingToEffect(targets[index], args); }
         index++;
         if (index == targets.Count) {
             targets.Clear();
         } else {
             CreateSubMagic(caster, space, args);
         }
     };
     space.AddUIElement(bullet);
     bullet.Move(new Point((index == 0 ? args.Position.X : targets[index - 1].Position.X) - offsetX, (index == 0 ? args.Position.Y : targets[index - 1].Position.Y) - offsetStartY), new Point(targets[index].Position.X - offsetX, targets[index].Position.Y - offsetEndY), 0.9 / bullet.Scale, MoveModes.Normal);
 }
 /// <summary>
 /// 在空间中战斗
 /// </summary>
 /// <param name="space">所处空间</param>
 public void DoAttackIn(Space space)
 {
     if (Target != null) {
         switch (weapon.AttackType) {
             case AttackTypes.Close:
                 AttackToHurt(Target);
                 break;
             case AttackTypes.LongRange:
                 Bullet bullet = new Bullet(weapon.BulletData) {
                     SpaceLayer = this.SpaceLayer,
                     Z = Target.Z,
                 };
                 double offsetX = bullet.Source.PixelWidth * bullet.Scale;
                 double offsetStartY = (this.State == States.Riding ? (this.Profession == Professions.Taoist ? 130 : 110) : 60) * bullet.Scale;
                 double offsetEndY = (Target.State == States.Riding ? 100 : 70) * bullet.Scale;
                 EventHandler handler = null;
                 bullet.MoveCompleted += handler = delegate {
                     bullet.MoveCompleted -= handler;
                     if (Target != null) {
                         double range = 10 * bullet.Scale;
                         //达到目标时如果在10*10范围内则算命中产生伤害
                         if (Target.Position.X - offsetX - range < bullet.Position.X && Target.Position.X - offsetX + range > bullet.Position.X && Target.Position.Y - offsetEndY - range < bullet.Position.Y && Target.Position.Y - offsetEndY + range > bullet.Position.Y) {
                             AttackToHurt(Target);
                         } else {
                             Target.ChangeLife(0, ValueEffects.Failure);
                         }
                     }
                     space.RemoveUIElement(bullet);
                 };
                 space.AddUIElement(bullet);
                 bullet.Move(new Point(this.Position.X - offsetX, this.Position.Y - offsetStartY), new Point(Target.Position.X - offsetX, Target.Position.Y - offsetEndY), weapon.BulletData.Speed / bullet.Scale, MoveModes.Normal);
                 break;
         }
     }
 }