/// <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(); }); } }); }
/// <summary> /// Cancels <see cref="SessionState.Selection"/> mode without completing the pending /// command.</summary> /// <remarks><para> /// <b>Cancel</b> resets the current <see cref="Session.State"/> to <see /// cref="SessionState.Human"/> which implicitly calls <see cref="Clear"/> to clear all data /// managed by the <see cref="TargetSelection"/> class. /// </para><para> /// If the pending command was a <see cref="BuildCommand"/> or a <see cref="PlaceCommand"/>, /// <b>Cancel</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> /// <b>Cancel</b> does nothing if the current <see cref="Session.State"/> does not equal /// <see cref="SessionState.Selection"/>. Thus, implicit target selection is unaffected. /// </para></remarks> public void Cancel() { // check for active Selection mode if (Session.State != SessionState.Selection) { return; } // remember command type for continuation Type commandType = this._commandType; // cancel explicit Selection mode Session.State = SessionState.Human; // let user build or place more entities if (commandType == typeof(BuildCommand)) { HumanAction.Build(); } else if (commandType == typeof(PlaceCommand)) { HumanAction.ManageEntities(Dialog.ShowEntitiesMode.Unplaced); } }