예제 #1
0
        public BattleDecision CalculateAction(Combatant character)
        {
            var decision = new BattleDecision();
            decision.Destination = new Point((int)character.Avatar.Location.X, (int)character.Avatar.Location.Y);

            if (_threat.Count == 0) return decision;

            // find the enemy with the highest threat
            var enemy = (from ckv in _threat orderby ckv.Value descending select ckv.Key).First();

            // find the point that brings you closest to them
            var grid = character.GetMovementGrid(BattleBoard.GetAccessibleGrid(character.Faction));

            var distance = 65535;
            for (var x = 0; x < grid.Size.Width; x++)
            {
                for (var y = 0; y < grid.Size.Height; y++)
                {
                    if (grid.Weight[x, y] != 1) continue;

                    var d = BattleBoard.Sandbag.Pathfind(
                        new Point(x, y),
                        new Point((int)enemy.Avatar.Location.X, (int)enemy.Avatar.Location.Y)
                    ).Count();

                    if (d >= distance || d > 2 || BattleBoard.GetCharacterAt(new Point(x, y)) != null) continue;

                    decision.Destination = new Point(x, y);
                    distance = d;
                }
            }

            var ability = Ability.Factory(_game, "attack");
            ability.Character = character;

            // attack
            decision.Command = new Command
                {
                    Ability = ability,
                    Character = character,
                    Target = new Point((int)enemy.Avatar.Location.X, (int)enemy.Avatar.Location.Y)
                };

            return decision;
        }
예제 #2
0
        /// <summary>
        /// Create a callback function to process if the player chooses to have a character attack. This callback will display the targetting grid
        /// and bind _aimAbility to a function that queues an attack command from the character onto the target.
        /// </summary>
        /// <param name="character">The character whose attack is being chosen.</param>
        /// <param name="ability">The ability currently being aimed.</param>
        /// <returns></returns>
        private void SelectAbilityTarget(Combatant character, Ability ability)
        {
            _state = BattleState.AimingAbility;
            Gui.Screen.Desktop.Children.Remove(_radialMenuControl);

            _battleBoardLayer.SetTargettingGrid(
                ability.Name == "Move" ?
                    character.GetMovementGrid(BattleBoard.GetAccessibleGrid(character.Faction)) :
                    ability.GenerateTargetGrid(BattleBoard.Sandbag.Clone()),
                ability.GenerateImpactGrid()
            );

            _battleBoardLayer.AbilityAim = true;

            _aimAbility = (x, y) =>
                {
                    // only target enemies with angry spells and allies with friendly spells
                    if (!ability.CanTarget(BattleBoard.IsOccupied(new Point(x, y))))
                        return false;

                    character.Avatar.UpdateVelocity(x - character.Avatar.Location.X, y - character.Avatar.Location.Y);
                    character.Avatar.UpdateVelocity(0, 0);

                    // make sure the ability knows who is casting it. this probably shouldn't
                    // be done here, but there are issues doing it elsewhere.
                    ability.Character = character;

                    var command = new Command
                        {
                            Character = character,
                            Target = new Point(x, y),
                            Ability = ability
                        };

                    if(ability.Name == "Move")
                    {
                        ExecuteCommand(command);
                        return true;
                    }

                    character.CanAct = false;
                    QueuedCommands.Add(command);
                    _queuedCommands.UpdateControls();
                    _state = BattleState.Delay;
                    _delayState = BattleState.PlayerTurn;
                    _delayTimer = 0.05F;
                    ResetState();

                    return true;
                };
        }
예제 #3
0
        /// <summary>
        /// Process a character that has been selected by the player, showing a radial menu of options.
        /// </summary>
        /// <param name="character">The character whose options are to be displayed.</param>
        public void SelectCharacter(Combatant character)
        {
            // if they clicked on the character already being shown, assume they want to close the menu
            if (character == _selectedCharacter)
            {
                DeselectCharacter();
                return;
            }

            // you can only click on your characters during your turn
            if (_state != BattleState.PlayerTurn) return;
            if (character.Faction != 0) return;

            if (_radialMenuControl != null)
            {
                Gui.Screen.Desktop.Children.Remove(_radialMenuControl);
                _radialMenuControl = null;
            }

            var menu = new RadialMenuControl(((IInputService)Game.Services.GetService(typeof(IInputService))).GetMouse())
                {
                    CenterX = (int)character.Avatar.Sprite.X + character.Avatar.Sprite.Width/2 - 10,
                    CenterY = (int)character.Avatar.Sprite.Y + character.Avatar.Sprite.Height/2,
                    OnExit = DeselectCharacter
                };

            // move icon, plus event handlers
            var icon = new RadialButtonControl {ImageFrame = "move", Bounds = new UniRectangle(0, 0, 64, 64)};
            if (character.CanMove)
            {
                icon.MouseOver += () =>
                    {
                        if (!character.CanMove) return;

                        _battleBoardLayer.SetTargettingGrid(
                            character.GetMovementGrid(BattleBoard.GetAccessibleGrid(character.Faction)),
                            new Grid(1, 1)
                            );
                    };
                icon.MouseOut += () => { if (_aimAbility == null) _battleBoardLayer.ResetGrid(); };
                icon.MouseClick += () => { SelectAbilityTarget(character, Ability.Factory(Game, "move"));
                                             _aimTime = DateTime.Now;
                };
            }
            else
            {

                // if they can't move, this icon does nothing
                icon.MouseOver = () => { };
                icon.MouseOut = () => { };
                icon.MouseClick = () => { };
                icon.MouseRelease = () => { };
                icon.Enabled = false;
            }

            menu.AddOption("move", icon);

            //// attack icon, plus handlers
            icon = new RadialButtonControl { ImageFrame = "attack", Bounds = new UniRectangle(0, 0, 64, 64) };
            if (character.CanAct)
            {
                var ability = Ability.Factory(Game, "attack");
                ability.Character = character;

                icon.MouseOver += () =>
                    {
                        if (!character.CanAct) return;

                        _battleBoardLayer.SetTargettingGrid(
                            ability.GenerateTargetGrid(BattleBoard.Sandbag.Clone()),
                            new Grid(1, 1)
                            );
                    };
                icon.MouseOut += () => { if (_aimAbility == null) _battleBoardLayer.ResetGrid(); };

                icon.MouseRelease += () => { SelectAbilityTarget(character, ability);
                                               _aimTime = DateTime.Now;
                };
            }
            else
            {
                // if they can't act, this icon does nothing
                icon.MouseOver = () => { };
                icon.MouseOut = () => { };
                icon.MouseClick = () => { };
                icon.MouseRelease = () => { };
                icon.Enabled = false;
            }

            menu.AddOption("attack", icon);

            //// special abilities icon, plus event handlers
            icon = new RadialButtonControl { ImageFrame = "special", Bounds = new UniRectangle(0, 0, 64, 64) };
            if (character.CanAct)
            {
                icon.MouseRelease += () => SelectSpecialAbility(character);
            }
            else
            {
                // if they can't act, this icon does nothing
                icon.MouseOver = () => { };
                icon.MouseOut = () => { };
                icon.MouseClick = () => { };
                icon.MouseRelease = () => { };
                icon.Enabled = false;
            }
            menu.AddOption("special", icon);

            icon = new RadialButtonControl
                {ImageFrame = "item", Bounds = new UniRectangle(0, 0, 64, 64), Enabled = false};
            menu.AddOption("item", icon);

            _radialMenuControl = menu;
            Gui.Screen.Desktop.Children.Add(_radialMenuControl);

            _selectedCharacter = character;
            _state = BattleState.CharacterSelected;
        }