Esempio n. 1
0
        /// <summary>
        /// Completes implicit or explicit target selection with the specified target location.
        /// </summary>
        /// <param name="target">
        /// The coordinates of the selected target <see cref="Site"/>.</param>
        /// <returns>
        /// <c>true</c> if a command was successfully executed; otherwise, <c>false</c>.</returns>
        /// <remarks><para>
        /// <b>Complete</b> calls <see cref="Cancel"/> and fails immediately if the specified
        /// <paramref name="target"/> is not in the <see cref="MapView.SelectedRegion"/> of the
        /// default <see cref="Session.MapView"/>.
        /// </para><para>
        /// Otherwise, if the current <see cref="Session.State"/> equals <see
        /// cref="SessionState.Human"/>, <b>Complete</b> issues either an <see
        /// cref="AttackCommand"/> or a <see cref="MoveCommand"/> with the specified <paramref
        /// name="target"/> site, depending on its contents. <b>Complete</b> then invokes <see
        /// cref="HumanAction.SelectUnit"/> to cycle to the next active unit.
        /// </para><para>
        /// Otherwise, if the current <see cref="Session.State"/> equals <see
        /// cref="SessionState.Selection"/>, <b>Complete</b> issues the pending command with the
        /// specified <paramref name="target"/> site. Depending on the pending command,
        /// <b>Complete</b> then calls <see cref="HumanAction.Build"/> or <see
        /// cref="HumanAction.ManageEntities"/>, allowing the local human player to continue
        /// building or placing entities, respectively.
        /// </para><para>
        /// The execution of any command implicitly resets the <see cref="Session.State"/> to <see
        /// cref="SessionState.Human"/> and calls <see cref="Clear"/> to clear all data managed by
        /// the <see cref="TargetSelection"/> class. Finally, <b>Complete</b> returns the return
        /// value of the <see cref="Session.Executor"/> method invoked for command execution.
        /// </para></remarks>

        public void Complete(PointI target)
        {
            // check for valid target
            if (!Session.MapView.InSelectedRegion(target))
            {
                Cancel();
                return;
            }

            // remember currently selected entity, if any
            string id = MainWindow.Instance.SelectedEntity;

            AsyncAction.BeginRun(delegate {
                Action action            = null;
                SessionExecutor executor = Session.Instance.Executor;
                WorldState world         = Session.Instance.WorldState;

                if (Session.State == SessionState.Human)
                {
                    // issue implicit Attack or Move command, then cycle to next active unit
                    if (this._attackTargets != null && this._attackTargets.Contains(target))
                    {
                        executor.ExecuteAttack(world, this._attackUnits, target);
                        action = () => HumanAction.SelectUnit(id, false, false);
                    }
                    else if (this._moveTargets != null && this._moveTargets.Contains(target))
                    {
                        executor.ExecuteMove(world, this._moveUnits, target);
                        action = () => HumanAction.SelectUnit(id, false, false);
                    }
                }
                else if (Session.State == SessionState.Selection)
                {
                    // issue Build or Place command, then let user build or place more entities
                    if (this._commandType == typeof(BuildCommand))
                    {
                        executor.ExecuteBuildPlace(world, this._entityClass.Id, 1, target);
                        action = HumanAction.Build;
                    }
                    else if (this._commandType == typeof(PlaceCommand))
                    {
                        executor.ExecutePlace(world, this._entities, target);
                        action = () => HumanAction.ManageEntities(Dialog.ShowEntitiesMode.Unplaced);
                    }
                }

                // execute automatic user action, if any
                if (action == null)
                {
                    AsyncAction.EndRun();
                }
                else
                {
                    AsyncAction.BeginInvoke(delegate { action(); AsyncAction.EndRun(); });
                }
            });
        }
Esempio n. 2
0
        /// <summary>
        /// Replay the next history <see cref="Command"/>.</summary>
        /// <returns>
        /// <c>true</c> if interactive replay should continue; <c>false</c> if <see cref="Stop"/>
        /// should be called.</returns>
        /// <exception cref="InvalidCommandException">
        /// The current <see cref="Command"/> contains invalid data.</exception>
        /// <remarks><para>
        /// <b>NextCommand</b> fetches the next history command, validates and executes it, and
        /// increments the command counter as necessary. <b>NextCommand</b> returns <c>false</c> if
        /// the command history has been exhausted.
        /// </para><para>
        /// The <see cref="Command.Source"/> and <see cref="Command.Target"/> sites of each history
        /// command are scrolled into view on the default <see cref="Session.MapView"/> if the <see
        /// cref="Options.ReplayOptions.Scroll"/> property of the current <see
        /// cref="ApplicationOptions"/> instance is <c>true</c>.</para></remarks>

        private bool NextCommand()
        {
            Debug.Assert(this._originalWorldState != null);
            Debug.Assert(this._commandIndex >= 0);
            Debug.Assert(!this._commandSkip);

            // retrieve original command history
            IList <Command> commands = this._originalWorldState.History.Commands;

            // stop replay if history exhausted
            if (this._commandIndex >= commands.Count)
            {
                return(false);
            }

            MapView mapView = Session.MapView;

            // retrieve next command in history
            if (this._command == null)
            {
                this._command = commands[this._commandIndex];

                // validate & show command
                this._command.Validate(Session.Instance.WorldState);
                SessionExecutor.ShowCommand(this._command);

                // scroll sites into view if desired
                PointI source = this._command.Source.Location;
                if (ApplicationOptions.Instance.Game.Replay.Scroll)
                {
                    PointI target = this._command.Target.Location;
                    AsyncAction.Invoke(() => mapView.ScrollIntoView(source, target));
                }

                // highlight valid source site
                if (Finder.MapGrid.Contains(source))
                {
                    AsyncAction.Invoke(() => mapView.SelectedSite = source);

                    // select first entity if specified
                    EntityReference[] entities = this._command.Entities;
                    if (entities != null && entities.Length > 0)
                    {
                        AsyncAction.Invoke(() => MainWindow.Instance.SelectedEntity = entities[0].Id);
                    }

                    return(true); // show source for a while
                }
            }

            // attempt to execute command
            this._command.Execute(new ExecutionContext(
                                      Session.Instance.WorldState, null, SessionExecutor.ShowCommandEvent));

            // check if command cleared by reentrant call
            if (this._command != null)
            {
                // add some delay after commands with message events
                this._commandSkip = this._command.Program.Exists(x => x is MessageInstruction);

                // highlight active faction for Begin/EndTurn, otherwise command target
                if (this._command is BeginTurnCommand || this._command is EndTurnCommand)
                {
                    ShowFaction(this._command.Faction.Value);
                }
                else
                {
                    ShowSite(this._command.Target.Location);
                }

                // ensure command effects are shown
                AsyncAction.Invoke(mapView.Redraw);
            }

            // prepare for next command
            this._command = null;
            ++this._commandIndex;

            return(true);
        }