public override void Boot(ActionArguments args, WarUnit doer, Action finished) { var situation = args.Situation; var movableArea = situation.Map.MoveCalculator.CalcMovableArea(situation.Map, doer, doer.Location); _scope.CurrentMovableArea = movableArea; base.Boot(args, doer, finished); }
public virtual void Boot(ActionArguments args, WarUnit doer, Action finished) { var warAdapter = args.Model; IEnumerable<Point2> rangePoints; var validRangePoints = Scope.GetValidRangeScope(args.Situation, doer, out rangePoints).ToArray(); if (validRangePoints.Length <= 0) { // HACK: メッセージボックス表示ルーチンの記述場所 MessageBox.Show("射程内に有効な対象が存在しません."); args.Model.InvokeCancelEvent(); return; } // スコープの位置に選択肢があれば、ユーザーに選択させる if (Scope.ExistChoice) { var pScope = new PrintableScope(Scope, rangePoints.ToArray(), validRangePoints, args.Situation, doer); // スコープを選択した際のイベント Action<Point2> selectMapChip = null; // スコープ選択状態を解除するデリゲート Action resetSelectScopeMode = () => { warAdapter.Scope = null; warAdapter.SelectMapChipEvent -= selectMapChip; }; // スコープを選択した際のイベントの定義 selectMapChip = p => { if (warAdapter.Scope.ValidRangeChips.Contains(p)) { // スコープ選択状態を解除 resetSelectScopeMode(); Execute(args, doer, p, finished); } }; // スコープの表示 warAdapter.Scope = pScope; // スコープを選択した際のイベントを追加 warAdapter.SelectMapChipEvent += selectMapChip; // キャンセルをした際のイベントを追加 warAdapter.CancelCommandStack.Push(delegate { resetSelectScopeMode(); return false; // 次のキャンセル処理へ続く }); } else { Execute(args, doer, validRangePoints[0], finished); } }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); // 攻撃アニメーションとその後の処理を予約する IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine); yield return 0; // エフェクト表示 // 洪水処理 var map = args.Situation.Map; var width = map.Width; var height = map.Height; var enableDamageAnimation = false; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var land = map[x, y]; if (land.Height <= TARGET_HEIGHT) { var taker = land.Unit; if (taker != null && _attackType != AttackType.なし) { AdditionalEffect cond; var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond); BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine); enableDamageAnimation = true; } // マップの更新 if (brinkNames.Contains(land.Info.Name)) { map[x, y] = new Land(land.Height - TARGET_HEIGHT, land.Landform, null); } else { map[x, y] = new Land(land.Height - TARGET_HEIGHT, _brinkLandform, null); } } } } if (enableDamageAnimation) yield return 0; // ダメージ表示 finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); // 攻撃アニメーションとその後の処理を予約する IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine); yield return 0; // エフェクト表示 foreach (var p in validPoints) { var taker = args.Situation.Map[p].Unit; taker.Conditions.Add(_cond, args.Situation); } finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); Debug.Assert(args.Situation.Map[center].Unit != null, "選択位置にユニットが存在しません."); var taker = args.Situation.Map[center].Unit; var doerAttack = doer.Status.DefaultAttacks.Select(atk => new { Doer = doer, Taker = taker, atk.Type, atk.Power }); var takerAttack = taker.Status.DefaultAttacks.Select(atk => new { Doer = taker, Taker = doer, atk.Type, atk.Power }); var source = doerAttack.AlternatelyConcat(takerAttack) .Where(info => info.Type != AttackType.なし); foreach (var info in source) { // ローカル変数にも代入しておく(ごっちゃにならないように) doer = info.Doer; taker = info.Taker; // アニメーション中は、マップ上のユニット表示をオフにする doer.Visible = false; // 攻撃アニメーションとその後の処理を予約する args.Model.SetContinuouslyMovingAnimationOnMap( doer.ChipImage, new[] { doer.Location, taker.Location, doer.Location }, args.Model.ATTACK_EFFECT_TIME, 0, doCoroutine); yield return 0; // エフェクト表示 doer.Visible = true; AdditionalEffect cond; var damage = BattleActionUtil.GetDamage(doer, taker, info.Power, info.Type, out cond); BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine); yield return 0; // ダメージ表示 // どちらかが死亡したら処理を中断 if (!doer.Alive || !taker.Alive) break; } finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); var times = XMath.Center(doer.SkillTimes, 1, _maxTimes); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, times, (times_, maxTimes_) => { foreach (var p in validPoints) { var taker = args.Situation.Map[p].Unit; AdditionalEffect cond; var value = BattleActionUtil.GetSkillValue(doer, taker, _power, _attackType, _atkDependency, _defDependency, out cond); var action = times_ < maxTimes_ ? doCoroutine.GetNOP() : doCoroutine; if (_attackType != AttackType.体力回復 && _attackType != AttackType.魔力回復) { BattleActionUtil.RunAttackRoutine(args, doer, taker, value, cond, action); } else { if (_attackType == AttackType.体力回復) taker.HealHP(args.Situation, doer, value); else taker.HealMP(args.Situation, doer, value); // 回復値の表示 args.Model.SetHealAnimationOnMap(value, doer.Location, action); } } }); yield return 0; // 最後のダメージ表示 finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); // 攻撃アニメーションとその後の処理を予約する IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine); yield return 0; // エフェクト表示 foreach (var p in validPoints) { Debug.Assert(args.Situation.Map[p].Unit == null); var unit = WarGlobal.UnitBuilder.Create(new Unit(_unit), doer.Side, null); args.Situation.Units.AddUnit(unit); args.Situation.Map.Deploy(unit, p); } finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); // 攻撃アニメーションとその後の処理を予約する IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine); yield return 0; // エフェクト表示 // 対象内の壁を破壊 var map = args.Situation.Map; var enableDamageAnimation = false; foreach (var p in areaPoints) { var land = map[p]; if (land.Construct != null && land.Construct.Info.Name == "壁") { map[p] = new Land(land.Height, land.Landform, null); if (land.Unit != null && _attackType != AttackType.なし) { var taker = land.Unit; AdditionalEffect cond; var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond); BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine); enableDamageAnimation = true; } } } if (enableDamageAnimation) yield return 0; // ダメージ表示 finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); // 攻撃アニメーションとその後の処理を予約する IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine); yield return 0; // エフェクト表示 foreach (var p in validPoints) { var taker = args.Situation.Map[p].Unit; if (!AttackTypes.Heal.Contains(_attackType)) { AdditionalEffect cond; var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond); BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine); } else { var value = BattleActionUtil.GetMagicHeal(doer, taker, _power); if (_attackType == AttackType.体力回復) taker.HealHP(args.Situation, doer, value); else taker.HealMP(args.Situation, doer, value); // 回復値の表示 args.Model.SetHealAnimationOnMap(value, doer.Location, doCoroutine); } } yield return 0; // ダメージ表示 finished(); }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // キャンセル処理のために記憶する var oldLocation = doer.Location; var resetCommandState = doer.SaveCommandState(); // 移動アニメーション用に経路を生成する var movePoints = new Stack<Point2>(); var movePoint = _scope.CurrentMovableArea.Find(p => p.Point == center); while (movePoint != null) { movePoints.Push(movePoint.Point); movePoint = movePoint.From; } // アニメーション中は、マップ上のユニット表示をオフにする doer.Visible = false; // 移動アニメーションのセット args.Model.SetContinuouslyMovingAnimationOnMap(doer.ChipImage, movePoints, 150, 20, doCoroutine); yield return 0; // 移動アニメーションの表示 // アニメーション後に元に戻す doer.Visible = true; args.Situation.Map.MoveUnit(doer, center); // アクション終了の通知 finished(); // 移動前に戻すキャンセル処理の追加 args.Model.CancelCommandStack.Push( () => { args.Situation.Map.MoveUnit(doer, oldLocation); resetCommandState(); return false; // キャンセル処理の続行 }); }
public virtual void BootAI(ActionArguments args, WarUnit doer, Action finished) { //わざと何も処理してません //何か処理したければオーバーライドしてください }
/// <summary> /// 行為が発動可能かどうかチェックする /// </summary> /// <param name="args">アクションの引数</param> /// <param name="doer">行為者</param> /// <returns> /// 発動可能かどうか /// </returns> public override bool CanBoot(ActionArguments args, WarUnit doer) { return _cost.CanExpend(doer) && args.Situation.Units.Alive.Any(unit_ => unit_.IsUndead); }
protected abstract IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine);
public override void Execute(ActionArguments args, WarUnit doer, Point2 center, Action finished) { IEnumerator<int> enumerator = null; enumerator = GetCoroutine(args, doer, center, finished, () => enumerator.MoveNext()).GetEnumerator(); enumerator.MoveNext(); }
public static void RunAttackRoutine(ActionArguments args, WarUnit doer, WarUnit taker, int value, AdditionalEffect effect, Action finishAnimation) { switch (effect) { case AdditionalEffect.なし: break; case AdditionalEffect.毒: taker.Conditions.Add(new PoisonCondition(), args.Situation); break; case AdditionalEffect.石化: taker.Conditions.Add(new PetrifactionCondition(), args.Situation); break; case AdditionalEffect.麻痺: taker.Conditions.Add(new ParalysisCondition(), args.Situation); break; case AdditionalEffect.眠り: taker.Conditions.Add(new SleepCondition(), args.Situation); break; case AdditionalEffect.幻想: // TODO: 実装 break; case AdditionalEffect.死: taker.Die(args.Situation, doer); break; case AdditionalEffect.吸収: // 回復値の表示 doer.HealHP(args.Situation, doer, value); args.Model.SetHealAnimationOnMap(value, doer.Location, null); break; default: throw new ArgumentOutOfRangeException("effect"); } // ダメージの表示要請 taker.DamageHP(args.Situation, doer, value); args.Model.SetDamageAnimationOnMap(value, taker.Location, finishAnimation); }
public void Execute(ActionArguments args, WarUnit doer, Action finished) { args.Situation.PhaseManager.ExitPhase(args.Situation); finished(); }
public override bool CanBoot(ActionArguments args, WarUnit doer) { return _cost.CanExpend(doer); }
public abstract bool CanBoot(ActionArguments args, WarUnit doer);
public bool CanExecute(ActionArguments args, WarUnit doer) { return _action.CanBoot(args, doer); }
public override bool CanBoot(ActionArguments args, WarUnit doer) { return _cost.CanExpend(doer) && args.Situation.Map.Any(land_ => brinkNames.Contains(land_.Info.Name)); }
public void Execute(ActionArguments args, WarUnit doer, Action finished) { _action.Boot(args, doer, finished); }
public abstract void Execute(ActionArguments args, WarUnit doer, Point2 center, Action finished);
private Button GetButton(IBattleCommand cmd) { Button btn; if (!buttons.TryGetValue(cmd, out btn)) { // クリックしたときに実行されるコマンド // 作成されるボタン btn = new Button { Margin = new Padding(0), Size = new Size(48, 48), Image = cmd.Image, Text = cmd.Image == null ? cmd.Name : "", }; buttons[cmd] = btn; // マウスオーバーで表示される文字 toolTip.SetToolTip(btn, cmd.Description); // クリック時のイベントを設定 btn.Click += delegate { flowLayoutPanel.Enabled = false; var doer = Situation.ActiveUnit; // キャンセル時の処理はGUIの実装に依存するためここに記述 Action finished = () => { doer.ChangeCommandState(cmd); ResetCommandButtons(); flowLayoutPanel.Enabled = true; }; model.CancelCommandStack.Push(() => { ResetCommandButtons(); flowLayoutPanel.Enabled = true; return true; // キャンセル処理の完了 }); var arc = new ActionArguments(Situation, model); cmd.Execute(arc, doer, finished); }; } return btn; }
protected override IEnumerable<int> GetCoroutine(ActionArguments args, WarUnit doer, Point2 center, Action finished, Action doCoroutine) { // 行為のキャンセルの不許可 args.Model.CancelCommandStack.Clear(); // コストの消費 _cost.Expend(args.Situation, doer); // 攻撃アニメーションとその後の処理を予約する IEnumerable<Point2> areaPoints; var validPoints = _scope.GetValidAreaScope(args.Situation, doer, center, out areaPoints); _screenEffect.SetScreenEffect(args, doer, center, areaPoints, validPoints, doCoroutine); yield return 0; // エフェクト表示 var lf = WarGlobal.Landforms; var landforms = new[,] { { lf[152], lf[143], lf[143], lf[143], lf[143], lf[153], null, null, null, null, null, }, { lf[159], lf[172], lf[163], lf[163], lf[163], lf[172], lf[158], null, null, null, null, }, { lf[159], lf[179], lf[172], lf[163], lf[163], lf[173], lf[178], lf[158], null, null, null, }, { lf[159], lf[179], lf[179], lf[172], lf[163], lf[173], lf[178], lf[178], lf[158], null, null, }, { lf[159], lf[179], lf[179], lf[179], lf[141], lf[141], lf[178], lf[178], lf[178], lf[158], null, }, { lf[144], lf[164], lf[164], lf[164], lf[141], lf[141], lf[141], lf[165], lf[165], lf[165], lf[145], }, { null, lf[156], lf[176], lf[176], lf[176], lf[141], lf[141], lf[177], lf[177], lf[177], lf[157], }, { null, null, lf[156], lf[176], lf[176], lf[174], lf[162], lf[175], lf[177], lf[177], lf[157], }, { null, null, null, lf[156], lf[176], lf[174], lf[162], lf[162], lf[175], lf[177], lf[157], }, { null, null, null, null, lf[156], lf[174], lf[162], lf[162], lf[162], lf[175], lf[157], }, { null, null, null, null, null, lf[154], lf[142], lf[142], lf[142], lf[142], lf[155], }, }; var heights = new[,] { { 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, }, { 4, 5, 5, 5, 5, 5, 4, 0, 0, 0, 0, }, { 4, 5, 6, 6, 6, 6, 5, 4, 0, 0, 0, }, { 4, 5, 6, 7, 7, 7, 6, 5, 4, 0, 0, }, { 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 0, }, { 4, 5, 6, 7, 8, 8, 8, 7, 6, 5, 4, }, { 0, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, }, { 0, 0, 4, 5, 6, 7, 7, 7, 6, 5, 4, }, { 0, 0, 0, 4, 5, 6, 6, 6, 6, 5, 4, }, { 0, 0, 0, 0, 4, 5, 5, 5, 5, 5, 4, }, { 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, }, }; // 地形書き換え処理 var map = args.Situation.Map; var sx = center.X - 5; var sy = center.Y - 5; foreach (var p in validPoints) { var taker = args.Situation.Map[p].Unit; AdditionalEffect cond; var damage = BattleActionUtil.GetMagicDamage(doer, taker, _power, _attackType, out cond); BattleActionUtil.RunAttackRoutine(args, doer, taker, damage, cond, doCoroutine); } foreach (var p in areaPoints) { // マップの更新 map[p] = new Land(heights[p.Y - sy, p.X - sx], landforms[p.Y - sy, p.X - sx], null); } yield return 0; // ダメージ表示 finished(); }
public bool CanExecute(ActionArguments args, WarUnit doer) { return false; }
public override bool CanBoot(ActionArguments args, WarUnit doer) { return true; }
public void Execute(ActionArguments args, WarUnit doer, Action finished) { finished(); }
/// <summary> /// このウインドウを表示する /// </summary> /// <param name="model"></param> /// <param name="doer"></param> /// <param name="finished"></param> /// <param name="index">魔法の属性を示すインデックス値</param> public void Show(WarPresentationModel model, WarUnit doer, Action finished, int index) { Debug.Assert(0 <= index && index <= 5, "予期せぬindex値を受け取りました: " + index); _model = model; var situation = model.Situation; // ボタンの全消去 flowButtonPanel.Controls.Clear(); // ボタンの追加 var magicDatasList = _magicCommands[index, doer.MagicLevels[magicAttributes[index]]]; for (int j = 0; j < magicDatasList.Count; j++) { var magicDatas = magicDatasList[j]; for (int i = 0; i < magicDatas.Count; i++) { var magicData = magicDatas[i]; var arc = new ActionArguments(situation, model); var button = new Button { Enabled = magicData.Action.CanBoot(arc, doer), Text = magicData.Name + (i + 1), }; button.Click += (sender_, e_) => { Visible = false; model.CancelCommandStack.Push(delegate { Visible = true; return true; // キャンセル処理の完了 }); magicData.Action.Boot(arc, doer, finished); }; button.MouseEnter += delegate { PointingMagic = magicData; }; button.MouseLeave += delegate { PointingMagic = null; }; flowButtonPanel.Controls.Add(button); } } SetDetail(null); Text = doer.Name; Visible = true; }
protected virtual void CreateInitiativePhase(WarPresentationModel model, List<List<WarUnit>> friendUnits, List<WarUnit> enemyUnits, MainWindow mainWindow) { Phases.InitiativePhase.Start = situation_ => { model.MapWindow.Refresh(); if (situation_.ActiveUnit.Side.IsPlayer) { // ユニットのコマンド状態を初期化する situation_.ActiveUnit.ResetCommandState(); } else { #region AI var doer = situation_.ActiveUnit; var ar = new ActionArguments(situation_, model); var actionEnumrator = new AI.AI().GetActionWithCoroutine(situation_); Action actionCoroutine = null; // AIの行動選択と実行のコルーチン actionCoroutine = () => { // 非同期実行のためのAIの行動選択デリゲートの生成 Func<bool> selectNextAction = actionEnumrator.MoveNext; var asyncResult = selectNextAction.BeginInvoke(null, null); // TaskList にAIの行動選択完了後の、戦闘行動実行を予約する // TaskList を使うことで、ウィンドウメッセージ処理のスレッドによる同期実行が行われる TaskList<int>.Task task = null; task = (taskArgs_, time_) => { // 非同期実行が完了するまでは何もしない if (!asyncResult.IsCompleted) return; // 非同期実行が完了すれば、戻り値を取得する if (selectNextAction.EndInvoke(asyncResult)) { // AIが選択したActionが存在する var battleAction = actionEnumrator.Current.Item1; battleAction.BootAI(ar, doer, Delegates.NOP); battleAction.Execute(ar, doer, actionEnumrator.Current.Item2, actionCoroutine); } else { // AIが選択したActionが存在しないので、ユニットの行動終了 situation_.PhaseManager.ExitPhase(situation_); } // タスクリストからこのデリゲートを削除する Global.MainLoop.TickEvents.Remove(task); }; Global.MainLoop.TickEvents.Add(Double.MinValue, task); }; // AIの行動選択と実行のコルーチンを実行 actionCoroutine(); #endregion } }; Phases.InitiativePhase.Exit = situation_ => { var friends = situation_.Sides.Single(side => side.IsPlayer); var enemies = situation_.Sides.Single(side => !side.IsPlayer); _result = checkBattleEnd(situation_, friends, enemies); if (_result != BattleResult.None) { situation_.PhaseManager.ExitPhase(situation_); return; } model.CancelCommandStack.Clear(); situation_.ActiveUnit.Side.UpdateForceAndBrave(situation_.Units.Alive); var unit = situation_.TurnManager.GetInitiativeUnit(situation_); if (unit != null) { situation_.ActiveUnit = unit; situation_.PhaseManager.StartPhase(situation_, Phases.InitiativePhase); } else { situation_.PhaseManager.ExitPhase(situation_); } }; }