Ejemplo n.º 1
0
 // コマンドを実行し、実行後のEventDataLine#IDを返す
 public int Exec()
 {
     SRC.LogDebug(Name.ToString(), args.Select(x => x.strArg).ToArray());
     try
     {
         return(ExecInternal());
     }
     catch (EventErrorException ex)
     {
         Event.DisplayEventErrorMessage(ex?.EventData.ID ?? EventData.ID, ex.Message);
         return(-1);
     }
     catch (NotImplementedException ex)
     {
         SRC.Log.LogWarning("NotImplemented: " + EventData.Data);
         return(EventData.NextID);
     }
     catch (Exception ex)
     {
         SRC.Log.LogError(ex.Message, ex);
         if (Strings.LCase(GeneralLib.ListIndex(EventData.Data, 1)) == "talk")
         {
             Event.DisplayEventErrorMessage(EventData.ID, "Talkコマンド実行中に不正な処理が行われました。" + "MIDIがソフトウェアシンセサイザで演奏されているか、" + "フォントキャッシュが壊れている可能性があります。" + "詳しくはSRC公式ホームページの「よくある質問集」をご覧下さい。");
         }
         else if (Strings.LCase(GeneralLib.ListIndex(EventData.Data, 1)) == "autotalk")
         {
             Event.DisplayEventErrorMessage(EventData.ID, "AutoTalkコマンド実行中に不正な処理が行われました。" + "MIDIがソフトウェアシンセサイザで演奏されているか、" + "フォントキャッシュが壊れている可能性があります。" + "詳しくはSRC公式ホームページの「よくある質問集」をご覧下さい。");
         }
         else
         {
             Event.DisplayEventErrorMessage(EventData.ID, "イベントデータが不正です");
         }
         return(-1);
     }
 }
Ejemplo n.º 2
0
        public string SearchFile(string name)
        {
            var path = ImageFilders()
                       .Select(x => SRC.FileSystem.PathCombine(x, name))
                       .FirstOrDefault(x => SRC.FileSystem.FileExists(x));

            SRC.LogDebug($"{name} -> {path}");
            return(path);
        }
Ejemplo n.º 3
0
        // イベントの実行
        public void HandleEvent(params string[] Args)
        {
            SRC.LogDebug(">", Args);

            // 画面入力をロック
            var prev_is_gui_locked = GUI.IsGUILocked;

            if (!GUI.IsGUILocked)
            {
                GUI.LockGUI();
            }

            // 現在選択されているユニット&ターゲットをイベント用に設定
            // (SearchLabel()実行時の式計算用にあらかじめ設定しておく)
            SelectedUnitForEvent = Commands.SelectedUnit;
            // 引数に指定されたユニットを優先
            if (Args.Length > 1)
            {
                if (SRC.PList.IsDefined(Args[1]))
                {
                    var p = SRC.PList.Item(Args[1]);
                    if (p.Unit is object)
                    {
                        SelectedUnitForEvent = p.Unit;
                    }
                }
            }
            SelectedTargetForEvent = Commands.SelectedTarget;

            // イベントキューを作成
            // XXX キューをいつ処理しきるのか?
            //event_que_idx = Information.UBound(EventQue);
            switch (Args[0])
            {
            case "プロローグ":
            {
                EventQue.Enqueue("プロローグ");
                SRC.Stage = "プロローグ";
                break;
            }

            case "エピローグ":
            {
                EventQue.Enqueue("エピローグ");
                SRC.Stage = "エピローグ";
                break;
            }

            case "破壊":
            {
                EventQue.Enqueue("破壊 " + Args[1]);
                var p      = SRC.PList.Item(Args[1]);
                var uparty = p.Party;
                if (p.Unit != null)
                {
                    var u = p.Unit;
                    // 格納されていたユニットも破壊しておく
                    while (u.CountUnitOnBoard() > 0)
                    {
                        var onBoardUnit = u.UnitOnBoards.First();
                        onBoardUnit.UnloadUnit(onBoardUnit.ID);
                        onBoardUnit.Status = "破壊";
                        onBoardUnit.HP     = 0;
                        EventQue.Enqueue("マップ攻撃破壊 " + onBoardUnit.MainPilot().ID);
                    }
                    uparty = u.Party0;
                }

                // 全滅の判定
                var flag = false;
                foreach (Unit currentU in SRC.UList.Items)
                {
                    if ((currentU.Party0 ?? "") == (uparty ?? "") &&
                        currentU.Status == "出撃" &&
                        !currentU.IsConditionSatisfied("憑依"))
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    EventQue.Enqueue("全滅 " + uparty);
                }
                break;
            }

            case "マップ攻撃破壊":
            {
                EventQue.Enqueue("マップ攻撃破壊 " + Args[1]);
                var p      = SRC.PList.Item(Args[1]);
                var uparty = p.Party;
                if (p.Unit != null)
                {
                    var u = p.Unit;
                    // 格納されていたユニットも破壊しておく
                    while (u.CountUnitOnBoard() > 0)
                    {
                        var onBoardUnit = u.UnitOnBoards.First();
                        onBoardUnit.UnloadUnit(onBoardUnit.ID);
                        onBoardUnit.Status = "破壊";
                        onBoardUnit.HP     = 0;
                        EventQue.Enqueue("マップ攻撃破壊 " + onBoardUnit.MainPilot().ID);
                    }
                    uparty = u.Party0;
                }

                // XXX 全滅の処理どこでやってんの?

                break;
            }

            case "ターン":
                EventQue.Enqueue(string.Join(" ", "ターン ", "全", Args[2]));
                EventQue.Enqueue(string.Join(" ", "ターン ", Args[1], Args[2]));
                break;

            case "損傷率":
                EventQue.Enqueue(string.Join(" ", "損傷率", Args[1], Args[2]));
                break;

            case "攻撃":
                EventQue.Enqueue(string.Join(" ", "攻撃", Args[1], Args[2]));
                break;

            case "攻撃後":
                EventQue.Enqueue(string.Join(" ", "攻撃後", Args[1], Args[2]));
                break;

            case "会話":
                EventQue.Enqueue(string.Join(" ", "会話", Args[1], Args[2]));
                break;

            case "接触":
                EventQue.Enqueue(string.Join(" ", "接触", Args[1], Args[2]));
                break;

            case "進入":
                EventQue.Enqueue(string.Join(" ", "進入", Args[1], Args[2], Args[3]));
                EventQue.Enqueue(string.Join(" ", "進入", Args[1], Map.Terrain(Conversions.ToInteger(Args[2]), Conversions.ToInteger(Args[3])).Name));
                if (Conversions.ToInteger(Args[2]) == 1)
                {
                    EventQue.Enqueue(string.Join(" ", "脱出", Args[1], "W"));
                }
                else if (Conversions.ToInteger(Args[2]) == Map.MapWidth)
                {
                    EventQue.Enqueue(string.Join(" ", "脱出", Args[1], "E"));
                }
                else if (Conversions.ToInteger(Args[3]) == 1)
                {
                    EventQue.Enqueue(string.Join(" ", "脱出", Args[1], "N"));
                }
                else if (Conversions.ToInteger(Args[3]) == Map.MapHeight)
                {
                    EventQue.Enqueue(string.Join(" ", "脱出", Args[1], "S"));
                }
                break;

            case "収納":
                EventQue.Enqueue(string.Join(" ", "収納", Args[1]));
                break;

            case "使用":
                EventQue.Enqueue(string.Join(" ", "使用", Args[1], Args[2]));
                break;

            case "使用後":
                EventQue.Enqueue(string.Join(" ", "使用後", Args[1], Args[2]));
                break;

            case "行動終了":
                EventQue.Enqueue(string.Join(" ", "行動終了", Args[1]));
                break;

            case "ユニットコマンド":
                var cmd1 = string.Join(" ", "ユニットコマンド", Args[1], Args[2]);
                if (IsEventDefined(cmd1))
                {
                    EventQue.Enqueue(cmd1);
                }
                else
                {
                    var cmd2 = string.Join(" ", "ユニットコマンド", Args[1], SRC.PList.Item(Args[2]).Unit.Name);
                    EventQue.Enqueue(cmd2);
                }
                break;

            default:
                EventQue.Enqueue(string.Join(" ", Args));
                break;
            }

            if (CallDepth > MaxCallDepth)
            {
                GUI.ErrorMessage("サブルーチンの呼び出し階層が" + SrcFormatter.Format(MaxCallDepth) + "を超えているため、イベントの処理が出来ません");
                CallDepth = MaxCallDepth;
                return;
            }

            // 現在の状態を保存
            ArgIndexStack[CallDepth] = ArgIndex;
            VarIndexStack[CallDepth] = VarIndex;
            ForIndexStack[CallDepth] = ForIndex;
            SaveBasePoint();

            // 呼び出し階層数をインクリメント
            var prev_call_depth = CallDepth;

            CallDepth = (CallDepth + 1);

            // 各イベントを発生させる
            // XXX キューのスキップすんの?
            //i = event_que_idx;
            SRC.IsCanceled = false;
            while (EventQue.Count > 0)
            {
                var eventItem = EventQue.Dequeue();
                SRC.LogDebug("EventQue.Dequeue", eventItem);

                // 前のイベントで他のユニットが出現している可能性があるので
                // 本当に全滅したのか判定
                if (GeneralLib.LIndex(eventItem, 1) == "全滅")
                {
                    var uparty = GeneralLib.LIndex(eventItem, 2);
                    if (SRC.UList.Items.Any(u => u.Party0 == uparty &&
                                            u.Status == "出撃" &&
                                            !u.IsConditionSatisfied("憑依")))
                    {
                        continue;
                    }
                }

                CurrentLabel = -1;
                var ret             = -1;
                var main_event_done = false;
                while (true)
                {
                    // 現在選択されているユニット&ターゲットをイベント用に設定
                    // SearchLabel()で入れ替えられる可能性があるので、毎回設定し直す必要あり
                    SelectedUnitForEvent = Commands.SelectedUnit;
                    // 引数に指定されたユニットを優先
                    if (Args.Length > 1)
                    {
                        if (SRC.PList.IsDefined(Args[1]))
                        {
                            var p = SRC.PList.Item(Args[1]);
                            if (p.Unit is object)
                            {
                                SelectedUnitForEvent = p.Unit;
                            }
                        }
                    }
                    SelectedTargetForEvent = Commands.SelectedTarget;

                    // 実行するイベントラベルを探す
                    do
                    {
                        if (Information.IsNumeric(eventItem))
                        {
                            // 数値の場合はラベルの示す位置が指定されたとみなす
                            // (マップコマンド、ユニットコマンド)
                            if (CurrentLabel < 0)
                            {
                                ret = Conversions.ToInteger(eventItem);
                            }
                            else
                            {
                                ret = -1;
                            }
                        }
                        else
                        {
                            // 数値以外はラベルを探す
                            ret = SearchLabel(eventItem, CurrentLabel + 1);
                        }

                        // ラベルが見つからなければ終わり
                        if (ret < 0)
                        {
                            break;
                        }

                        CurrentLabel = ret;
                        if (!EventData[ret].IsAlwaysEventLabel)
                        {
                            // 常時イベントではないイベントは1度しか実行しない
                            if (main_event_done)
                            {
                                ret = -1;
                            }
                            else
                            {
                                main_event_done = true;
                            }
                        }
                    }while (ret < 0);

                    if (ret < 0)
                    {
                        break;
                    }

                    // 戦闘後のイベント実行前にはいくつかの後始末が必要
                    if (!EventData[ret].IsAlwaysEventLabel)
                    {
                        if (Args[0] == "破壊" ||
                            Args[0] == "損傷率" ||
                            Args[0] == "攻撃後" ||
                            Args[0] == "全滅")
                        {
                            // 画面をクリア
                            if (GUI.MainFormVisible)
                            {
                                Status.ClearUnitStatus();
                                GUI.RedrawScreen();
                            }

                            // メッセージウィンドウを閉じる
                            if (GUI.MessageFormVisible)
                            {
                                GUI.CloseMessageForm();
                            }
                        }
                    }

                    // ラベルの行は実行しても無駄なので
                    ret = ret + 1;
                    GUI.DoEvents();

                    // イベントの各コマンドを実行
                    do
                    {
                        CurrentLineNum = ret;
                        if (CurrentLineNum >= EventCmd.Count)
                        {
                            break;
                        }

                        ret = EventCmd[CurrentLineNum].Exec();
                    }while (ret > 0);

                    // ステージが終了 or キャンセル?
                    if (SRC.IsScenarioFinished || SRC.IsCanceled)
                    {
                        break;
                    }
                }
                // ステージが終了 or キャンセル?
                if (SRC.IsScenarioFinished || SRC.IsCanceled)
                {
                    break;
                }
            }
            ;

            if (CallDepth >= 0)
            {
                // 呼び出し階層数を元に戻す
                // (サブルーチン内でExitが呼ばれることがあるので単純に-1出来ない)
                CallDepth = prev_call_depth;

                // イベント実行前の状態に復帰
                ArgIndex = ArgIndexStack[CallDepth];
                VarIndex = VarIndexStack[CallDepth];
                ForIndex = ForIndexStack[CallDepth];
            }
            else
            {
                ArgIndex = 0;
                VarIndex = 0;
                ForIndex = 0;
            }

            //// イベントキューを元に戻す
            //Array.Resize(EventQue, GeneralLib.MinLng(event_que_idx - 1, Information.UBound(EventQue)) + 1);

            // フォント設定をデフォルトに戻す
            // XXX 位置はリセットしない?
            GUI.ResetDrawString();
            GUI.PermanentStringMode = false;
            GUI.KeepStringMode      = false;

            // オブジェクト色をデフォルトに戻す
            // XXX これはEventsが持ってていいのか?
            ObjColor      = Color.White;
            ObjFillColor  = Color.White;
            ObjFillStyle  = FillStyle.VbFSTransparent;
            ObjDrawWidth  = 1;
            ObjDrawOption = "";

            // 描画の基準座標位置を元に戻す
            RestoreBasePoint();

            // 画面入力のロックを解除
            if (!prev_is_gui_locked)
            {
                GUI.UnlockGUI();
            }
        }
Ejemplo n.º 4
0
        // ラベルの検索
        public int SearchLabel(string lname, int start = -1)
        {
            // ラベルの各要素をあらかじめ解析
            // XXX Indexがずれていて辛い。
            string[] litem;
            int      llen = GeneralLib.ListSplit(lname, out litem);

            // XXX 死にたい
            litem = (new string[] { "" }).Concat(litem).ToArray();

            // ラベルの種類を判定
            LabelType ltype;
            var       lnum         = new string[5];
            var       is_unit      = new bool[5];
            var       is_num       = new bool[5];
            var       is_condition = new bool[5];
            var       revrersible  = false;

            switch (litem[1] ?? "")
            {
            case "プロローグ":
            {
                ltype = LabelType.PrologueEventLabel;
                break;
            }

            case "スタート":
            {
                ltype = LabelType.StartEventLabel;
                break;
            }

            case "エピローグ":
            {
                ltype = LabelType.EpilogueEventLabel;
                break;
            }

            case "ターン":
                ltype = LabelType.TurnEventLabel;
                if (Information.IsNumeric(litem[2]))
                {
                    is_num[2] = true;
                }
                lnum[2] = GeneralLib.StrToLng(litem[2]).ToString();
                break;

            case "損傷率":
                ltype      = LabelType.DamageEventLabel;
                is_unit[2] = true;
                is_num[3]  = true;
                lnum[3]    = GeneralLib.StrToLng(litem[3]).ToString();
                break;

            case "破壊":
            case "マップ攻撃破壊":
                ltype      = LabelType.DestructionEventLabel;
                is_unit[2] = true;
                break;

            case "全滅":
                ltype = LabelType.TotalDestructionEventLabel;
                break;

            case "攻撃":
                ltype       = LabelType.AttackEventLabel;
                revrersible = true;
                is_unit[2]  = true;
                is_unit[3]  = true;
                break;

            case "攻撃後":
                ltype       = LabelType.AfterAttackEventLabel;
                revrersible = true;
                is_unit[2]  = true;
                is_unit[3]  = true;
                break;

            case "会話":
                ltype      = LabelType.TalkEventLabel;
                is_unit[2] = true;
                is_unit[3] = true;
                break;

            case "接触":
                ltype       = LabelType.ContactEventLabel;
                revrersible = true;
                is_unit[2]  = true;
                is_unit[3]  = true;
                break;

            case "進入":
                ltype      = LabelType.EnterEventLabel;
                is_unit[2] = true;
                if (llen == 4)
                {
                    is_num[3] = true;
                    is_num[4] = true;
                    lnum[3]   = GeneralLib.StrToLng(litem[3]).ToString();
                    lnum[4]   = GeneralLib.StrToLng(litem[4]).ToString();
                }
                break;

            case "脱出":
                ltype      = LabelType.EscapeEventLabel;
                is_unit[2] = true;
                break;

            case "収納":
                ltype      = LabelType.LandEventLabel;
                is_unit[2] = true;
                break;

            case "使用":
                ltype      = LabelType.UseEventLabel;
                is_unit[2] = true;
                break;

            case "使用後":
                ltype      = LabelType.AfterUseEventLabel;
                is_unit[2] = true;
                break;

            case "変形":
                ltype      = LabelType.TransformEventLabel;
                is_unit[2] = true;
                break;

            case "合体":
                ltype      = LabelType.CombineEventLabel;
                is_unit[2] = true;
                break;

            case "分離":
                ltype      = LabelType.SplitEventLabel;
                is_unit[2] = true;
                break;

            case "行動終了":
                ltype      = LabelType.FinishEventLabel;
                is_unit[2] = true;
                break;

            case "レベルアップ":
                ltype      = LabelType.LevelUpEventLabel;
                is_unit[2] = true;
                break;

            case "勝利条件":
                ltype = LabelType.RequirementEventLabel;
                break;

            case "再開":
                ltype = LabelType.ResumeEventLabel;
                break;

            case "マップコマンド":
                ltype           = LabelType.MapCommandEventLabel;
                is_condition[3] = true;
                break;

            case "ユニットコマンド":
                ltype           = LabelType.UnitCommandEventLabel;
                is_condition[4] = true;
                break;

            case "特殊効果":
                ltype = LabelType.EffectEventLabel;
                break;

            default:
                ltype = LabelType.NormalLabel;
                break;
            }

            // 各ラベルについて一致しているかチェック
            foreach (LabelData lab in colEventLabelList.List)
            {
                // ラベルの種類が一致している?
                if (ltype != lab.Name)
                {
                    continue;
                }

                // ClearEventされていない?
                if (!lab.Enable)
                {
                    continue;
                }

                // 検索開始行より後ろ?
                if (lab.EventDataId < start)
                {
                    continue;
                }

                // パラメータ数が一致している?
                if (llen != lab.CountPara())
                {
                    if (ltype != LabelType.MapCommandEventLabel && ltype != LabelType.UnitCommandEventLabel)
                    {
                        continue;
                    }
                }

                // 各パラメータが一致している?
                var reversed = false;
                var isMatch  = IsMatch(ltype, lab, litem, lnum, is_unit, is_num, is_condition, reversed);
                if (!isMatch && revrersible)
                {
                    // 対象と相手を入れ替えたイベントラベルが存在するか判定
                    var lname2 = litem[1] + " " + GeneralLib.ListIndex(lab.Data, 3) + " " + GeneralLib.ListIndex(lab.Data, 2);
                    if (lab.AsterNum > 0)
                    {
                        lname2 = "*" + lname2;
                    }

                    if (FindLabel(lname2) == 0)
                    {
                        // 対象と相手を入れ替えて判定し直す
                        reversed = true;
                        isMatch  = IsMatch(ltype, lab, litem, lnum, is_unit, is_num, is_condition, reversed);
                    }
                }
                if (!isMatch)
                {
                    continue;
                }

                // ここまでたどり付けばラベルは一致している
                SRC.LogDebug("Found", lab.Name.ToString(), lab.Data);

                // 対象と相手を入れ替えて一致した場合はグローバル変数も入れ替え
                if (reversed)
                {
                    var tmp_u = SelectedUnitForEvent;
                    SelectedUnitForEvent   = SelectedTargetForEvent;
                    SelectedTargetForEvent = tmp_u;
                }

                return(lab.EventDataId);
            }

            return(-1);
        }