public static List<IBattleCommand> Load(IList<Skill> skills) { var results = new List<IBattleCommand>(skills.Count) { new DisableCommand("特技", "なし", Properties.Resources.w_skill), }; foreach (var skill in skills) { IScreenEffect screenEffect = null; string path = null; foreach(var dir in Global.CharDirs) { path = Path.Combine(dir, skill.Name + ".bmp"); if (File.Exists(path)) break; } var surfaces = WarGlobal.BmpManager.GetSurfaces(path, skill.SideSize, skill.SideSize, fpath => BitmapUtil.Load(fpath, Color.Black), (bmp, w, h) => bmp.SplitToBitmaps(w, h, skill.ImageCount)); var maxTimes = 1; var targetType = TargetType.ENEMY; var createFunc = DefaultCreator; switch (skill.ScopeType) { case ScopeType.Arrow: screenEffect = new ArrowAnimation(surfaces); maxTimes = 3; break; case ScopeType.Breath: screenEffect = new ChipFrameAnimation(surfaces); maxTimes = 3; break; case ScopeType.Heal: screenEffect = new ChipFrameAnimation(surfaces); targetType = TargetType.FRIEND; break; case ScopeType.Magic: screenEffect = new ChipFrameAnimation(surfaces); break; case ScopeType.WallBreak: screenEffect = new ChipFrameAnimation(surfaces); createFunc = WallCrashCreator; break; case ScopeType.Unknown: screenEffect = new ChipFrameAnimation(surfaces); break; case ScopeType.SixWay: screenEffect = new ChipFrameAnimation(surfaces); break; case ScopeType.BlackDragonSword: screenEffect = new ChipFrameAnimation(surfaces); break; default: break; } // 行為の範囲や対象を設定する IScope scope; if (skill.Range < 0) scope = new StraightScope(skill.Area, targetType); else if (skill.Area != 0) scope = new DefaultScope(skill.Range, skill.Area, targetType); else scope = new WholeScope(targetType); var action = createFunc(scope, skill, maxTimes, screenEffect); var command = new SingleActionCommand(skill.Name, skill.Name, Properties.Resources.w_skill, action); results.Add(command); } return results; }
public IEnumerator<Tuple<ChipTargetAction, Point2>> GetActionWithCoroutine(Situation situation) { WarUnit doer = situation.ActiveUnit; IEnumerable<Point2> enumPoint; ChipTargetAction bestBattleAction = null; Point2 bestp = doer.Location; IScope scope; int bestrank = 0; #region 死にそうな敵がいる所を見つけるアルゴリズム { scope = new StraightScope(1, TargetType.ENEMY); IEnumerable<Point2> around = scope.GetValidRangeScope(situation, doer, out enumPoint); foreach (Point2 q in around) { WarUnit unit = situation.Map[q].Unit; if (unit != null) { bestrank += unit.Status.HP; } } if (bestrank == 0) bestrank = 500; } MoveScope movescope = new MoveScope(); movescope.CurrentMovableArea = situation.Map.MoveCalculator.CalcMovableArea(situation.Map, doer, bestp); foreach (Point2 p in movescope.GetValidRangeScope(situation, doer, out enumPoint)) { scope = new StraightScope(1, TargetType.ENEMY); IEnumerable<Point2> around = scope.GetValidRangeScope(situation, doer, out enumPoint); int rank = 0; foreach (Point2 q in around) { WarUnit unit = situation.Map[q].Unit; if (unit != null) { rank += unit.Status.HP; } } if (rank == 0) rank = 500; if (rank < bestrank) { bestrank = rank; bestp = p; } } #endregion #region 行動範囲内に敵がいなかったら、一番近くの敵に移動する if (bestp == doer.Location) { double min = Double.MaxValue; Vector2 diff = new Vector2(); foreach (WarUnit unit in situation.Units.WarUnits) { if (situation.Sides[0].IsPlayer && unit.Side == situation.Sides[0]) { Vector2 bufdiff = unit.Location - doer.Location; double r = bufdiff.X * bufdiff.X + bufdiff.Y * bufdiff.Y; if (r < min) { min = r; diff = bufdiff; } } } for (double d = 1.0; d > 0; d -= 0.1) { Point2 arrive = new Point2((int)(doer.Location.X + diff.X * d), (int)(doer.Location.Y + diff.Y * d)); if (situation.Map.IsValidPoint(arrive) && situation.Map[arrive].Unit == null && situation.Map[arrive].Construct == null) { if (movescope.GetValidRangeScope(situation, doer, out enumPoint).Contains(arrive)) { bestp = arrive; break; } } } } #endregion if (bestp != doer.Location) yield return new Tuple<ChipTargetAction, Point2>(new MoveAction(), bestp); bestrank = Int32.MaxValue; bestBattleAction = null; scope = new StraightScope(1, TargetType.ENEMY); IEnumerable<Point2> validRange = scope.GetValidRangeScope(situation, doer, out enumPoint); if (validRange.Count() != 0) { bestBattleAction = new NormalAttackAction(); foreach (Point2 p in scope.GetValidRangeScope(situation, doer, out enumPoint)) { WarUnit unit = situation.Map[p].Unit; if (unit != null && unit.Status.HP < bestrank) { bestrank = unit.Status.HP; bestp = p; } } } //TODO: 魔法等の検討 if(bestBattleAction != null) yield return new Tuple<ChipTargetAction, Point2>(bestBattleAction, bestp); yield break; #region 参考にするために一応保持 //int bestrank = 0; //{ // doer.DefaultAttacks[0]. // List<Point2> validRangePoints = doer.AdditionalEffect.ReadyAI(doer, mapControl, out areaPoints); // if(validRangePoints != null) // { // foreach(Point2 rangePoint in validRangePoints) // { // List<Point2> targets = new List<Point2>(); // foreach(Point2 q in areaPoints) // { // targets.Add(rangePoint + q); // } // int rank = doer.AdditionalEffect.BootAI(mapControl, doer, targets); // if(bestrank < rank) // { // bestrank = rank; // bestp = rangePoint; // bestBattleAction = doer.AdditionalEffect; // } // } // } //} //foreach(Magic magic_ in doer.GetMagicList(0)) //{ // IDefaultBattleAction battleAction = magic_.BattleAction; // List<Point2> validRangePoints = battleAction.ReadyAI(doer, mapControl, out areaPoints); // if(validRangePoints != null) // { // foreach(Point2 rangePoint in validRangePoints) // { // List<Point2> targets = new List<Point2>(); // foreach(Point2 q in areaPoints) // { // targets.Add(rangePoint + q); // } // int rank = battleAction.BootAI(mapControl, doer, targets); // if(bestrank < rank) // { // bestrank = rank; // bestp = rangePoint; // bestBattleAction = battleAction; // } // } // } //} //if(bestrank > 0) //{ // bestBattleAction.ReadyAI(doer, mapControl, out areaPoints); // if(areaPoints == null) // { // FinishAct(); // } // else // { // List<Point2> targets = new List<Point2>(); // foreach(Point2 q in areaPoints) // { // targets.Add(bestp + q); // } // bestBattleAction.Boot(mapControl, doer, targets, actionManager); // } //} //else //{ // FinishAct(); //} #endregion }