예제 #1
0
 private static int movePointExpense(List<Outcome> outcomes, IUnitController unitController) {
     int sum = 0;
     foreach (Outcome outcome in outcomes) {
         sum += UnitBaseStats.TerrainCost(unitController.UnitType, outcome.position.Terrain);
     }
     return sum;
 }
예제 #2
0
        public List <Outcome> SimulatePush(IUnitController target, Vector2 pushDirection, int pushAmount)
        {
            List <Outcome> outcomes = new List <Outcome>();

            //outcomes.Add(new Outcome(target, target.SimPosition)); // Add current hex for interpreter convenience

            if (pushAmount > 0)
            {
                for (int i = 1; i <= pushAmount; i++)
                {
                    if (!scenarioLoader.HexGrid.ContainsKey(pushDirection + target.SimPosition.BoardPos))
                    {
                        break;
                    }
                    HexEntry nextHex = scenarioLoader.HexGrid[pushDirection + target.SimPosition.BoardPos];
                    if (nextHex.SimOccupant != null)
                    {
                        break;
                    }
                    if (UnitBaseStats.TerrainCost(target.UnitType, nextHex.Terrain) == 0)
                    {
                        break;
                    }
                    target.SimPosition = nextHex;
                    List <AttackResult> combat = target.Weapon.CombatResults(target.SimRecentPath);
                    outcomes.Add(new Outcome(target, nextHex, false, combat));
                }
            }

            return(outcomes);
        }
예제 #3
0
        // Update the actual game state after a commitment to a certain move
        public void ExecuteMoves(List <Outcome> outcomes, IUnitController unitSpendingMoves = null)
        {
            foreach (Outcome outcome in outcomes)
            {
                if (outcome.activeUnit == unitSpendingMoves)
                {
                    //Deduct zone of control and movement costs before moving onto a hex
                    outcome.activeUnit.MovesRemaining -= UnitBaseStats.TerrainCost(outcome.activeUnit.UnitType, outcome.position.Terrain);
                    if (DefaultPathGenerator.IsEnemyNeighbor(outcome.activeUnit.Position, outcome.activeUnit.PlayerOwner))
                    {
                        outcome.activeUnit.ZoCRemaining -= 1;
                        if (outcome.activeUnit.ZoCRemaining < 0)
                        {
                            throw new System.Exception("This should not have happened");
                        }
                        else if (outcome.activeUnit.ZoCRemaining == 0)
                        {
                            outcome.activeUnit.MovesRemaining = 0;
                        }
                    }
                }

                // Move to the next hex, tell it we're occupying it, and add hex to our recent path
                outcome.activeUnit.Position = outcome.position;

                foreach (AttackResult attackResult in outcome.combat)
                {
                    //Debug.Log("Execute attack on enemy at " + outcome.activeUnit.CurrentHex);
                    attackResult.source.ExecuteAttack();
                    attackResult.target.HP = attackResult.healthRemaining;
                    if (attackResult.healthRemaining <= 0)
                    {
                        attackResult.target.Position = null;
                        selectionManager.UnitsByPlayer[attackResult.target.PlayerOwner].Remove(attackResult.target);
                    }
                    if (attackResult.pushMoves != null)
                    {
                        ExecuteMoves(attackResult.pushMoves); // When executing forced movement, don't deduct ZoC or move points
                    }
                }

                if (outcome.activeUnit.Position != null && outcome.activeUnit.Position.Terrain == Terrain.Pit)
                {
                    outcome.activeUnit.Position = null;
                    selectionManager.UnitsByPlayer[outcome.activeUnit.PlayerOwner].Remove(outcome.activeUnit);
                }
            }
        }
예제 #4
0
        private static bool MeetsTerrainCostRequirement(List <HexEntry> path, IUnitController controller, int movesRemaining)
        {
            int          sum      = 0;
            UnitBaseType unitType = controller.UnitType;

            // Note: skip the origin of the path
            foreach (HexEntry hex in path.Skip(1))
            {
                if (UnitBaseStats.TerrainCost(unitType, hex.Terrain) <= 0)
                {
                    return(false);
                }
                if (hex.Occupant != null)
                {
                    return(false);
                }
                sum += UnitBaseStats.TerrainCost(unitType, hex.Terrain);
            }
            return(sum <= movesRemaining);
        }
예제 #5
0
        public void Initialize(IMover mover, OutcomeAnimator outcomeAnimator, UnitSpriteManager unitSpriteManager,
                               HexEntry startPosition)
        {
            this._mover             = mover;
            this._outcomeAnimator   = outcomeAnimator;
            this._unitSpriteManager = unitSpriteManager;

            RecentPath = new List <HexEntry>();
            Position   = startPosition;
            unitSpriteManager.VisiblePosition = Position;

            HP = UnitBaseStats.HP(UnitType);
            SpriteManager.MaxHealthDisplay     = HP; // Instantiate the health bar sizing for the unit, maxHP must be first
            SpriteManager.CurrentHealthDisplay = HP;

            TurnEndUpkeep();
            TurnStartUpkeep();

            UnitType    = _unitType; // Gives spritemanager unit-type data
            WeaponType  = _weaponType;
            PlayerOwner = _playerOwner;
        }
예제 #6
0
        // Lower is better
        private int HexSpacingWeight(UnitBaseType unitType, WeaponType weaponType, HexEntry hex)
        {
            int result = 0;

            // Per-weapon spacing weights
            if (weaponType == WeaponType.Spear)
            {
                if (hex.AIDistanceToEnemy == 1)
                {
                    result = +2;
                }
                if (hex.AIDistanceToEnemy == UnitBaseStats.MoveSpeed(unitType) + 1)
                {
                    result = -2;
                }
            }
            if (weaponType == WeaponType.Sword)
            {
                if (hex.AIDistanceToEnemy == 1)
                {
                    result = -1;
                }
                if (hex.AIDistanceToEnemy == 2)
                {
                    result = +1;
                }
                if (hex.AIDistanceToEnemy == UnitBaseStats.MoveSpeed(unitType) + 1)
                {
                    result = +2;
                }
            }
            if (weaponType == WeaponType.Flail)
            {
                result = -1 * hex.aiAdjacentEnemies;
            }
            if (weaponType == WeaponType.Longbow)
            {
                if (hex.AIDistanceToEnemy == 2)
                {
                    result = -4;
                }
                if (hex.AIDistanceToEnemy == 3)
                {
                    result = -8;
                }
            }
            if (weaponType == WeaponType.Dagger)
            {
                result = -2 * hex.aiAdjacentEnemies;
            }
            if (weaponType == WeaponType.Shield)
            {
                if (hex.AIDistanceToEnemy == 1)
                {
                    result = +3;
                }
            }

            //Generally encourage movement toward the enemy if out of range
            if (hex.AIDistanceToEnemy > UnitBaseStats.MoveSpeed(unitType) + 1)
            {
                result += hex.AIDistanceToEnemy - UnitBaseStats.MoveSpeed(unitType) - 1;
            }

            return(result);
        }
예제 #7
0
        IEnumerator QueueAnimator()
        {
            if (cameraFollow)
            {
                if (selectionManager.playbackAnimation == activeAnimation)   // If this is a newly created animation, and is of the playback type, changes the turn button display color
                {
                    uiHandler.TurnButtonDisplay(outcomeQueue[0].activeUnit.PlayerOwner);
                }
                yield return(new WaitForSeconds(Config.unitStepSpeed));
            }

            while (outcomeQueue.Count > 0)
            {
                Outcome currentOutcome = outcomeQueue[0];
                outcomeQueue.RemoveAt(0);

                currentOutcome.activeUnit.SpriteManager.VisiblePosition = currentOutcome.position; // Move one step on the grid
                if (cameraFollow)
                {
                    uiHandler.SlideCameraToHex(currentOutcome.position);
                }
                if (currentOutcome.spendingMoves && !cameraFollow)   // The camerafollow becomes active immediately even if it's a later part of the queue, so I know if an enemy move is about to play

                {
                    currentOutcome.activeUnit.SpriteManager.ShowExtraInfo(UnitSpriteManager.UnitInfoDisplaySource.Movement, true);

                    currentOutcome.activeUnit.SpriteManager.VisualMovesRemaining -=
                        UnitBaseStats.TerrainCost(currentOutcome.activeUnit.UnitType, currentOutcome.position.Terrain); // Deduct move points visually

                    if (outcomeQueue.Count > 0)
                    {
                        if (outcomeQueue[0].activeUnit != currentOutcome.activeUnit)
                        {
                            if (currentOutcome.activeUnit.ZoCRemaining == 0)
                            {
                                currentOutcome.activeUnit.SpriteManager.VisualMovesRemaining = 0;
                            }
                        }
                    }
                    else
                    {
                        if (currentOutcome.activeUnit.ZoCRemaining == 0)
                        {
                            currentOutcome.activeUnit.SpriteManager.VisualMovesRemaining = 0;
                        }
                    }
                }

                foreach (AttackResult attackResult in currentOutcome.combat)  // Show hp on all units fighting this step
                {
                    attackResult.target.SpriteManager.ShowExtraInfo(UnitSpriteManager.UnitInfoDisplaySource.CombatAnimation, true);
                    attackResult.source.SpriteManager.ShowExtraInfo(UnitSpriteManager.UnitInfoDisplaySource.CombatAnimation, true);
                }

                foreach (AttackResult attackResult in currentOutcome.combat)  // Animate combat
                {
                    if (attackResult.source.WeaponType == WeaponType.Longbow || attackResult.source.WeaponType == WeaponType.Crossbow)
                    {
                        attackResult.source.SpriteManager.ShootArrow(attackResult.target.SpriteManager);

                        yield return(new WaitForSeconds(Config.shotTimer));
                    }
                    else
                    {
                        attackResult.source.SpriteManager.Bump(attackResult.target.SpriteManager);

                        yield return(new WaitForSeconds(Config.bumpTimer));
                    }

                    attackResult.target.SpriteManager.SetBorderColor(Config.Palette.attack);
                    attackResult.target.SpriteManager.Shake(4.0f);
                    attackResult.target.SpriteManager.CurrentHealthDisplay = attackResult.healthRemaining;

                    if (attackResult.pushMoves != null)
                    {
                        //outcomeQueue = new Queue<Outcome>(outcomeQueue.Concat(attackResult.pushMoves)); // Not used so multiple units' animations can have simultaneity
                        yield return(attackResult.target.OutcomeAnimator.Interpret(attackResult.pushMoves)); // Animate push and any moves and attacks that go with it
                    }
                    else
                    {
                        yield return(new WaitForSeconds(Config.attackStepSpeed));
                    }

                    attackResult.target.SpriteManager.SetBorderColor(Config.Palette.border);
                    if (attackResult.healthRemaining <= 0 || attackResult.targetHex.Terrain == Terrain.Pit)   //Unit death animation
                    {
                        attackResult.target.OutcomeAnimator.AnimateDeath(attackResult.target.SpriteManager);
                    }
                }

                yield return(new WaitForSeconds(Config.unitStepSpeed));

                currentOutcome.activeUnit.SpriteManager.ShowExtraInfo(UnitSpriteManager.UnitInfoDisplaySource.Movement, false);

                foreach (AttackResult attackResult in currentOutcome.combat)  // Hide hp on all units that fought on this step
                {
                    attackResult.target.SpriteManager.ShowExtraInfo(UnitSpriteManager.UnitInfoDisplaySource.CombatAnimation, false);
                    attackResult.source.SpriteManager.ShowExtraInfo(UnitSpriteManager.UnitInfoDisplaySource.CombatAnimation, false);
                }
            }

            selectionManager.AnimationComplete(activeAnimation);
            activeAnimation = null;
        }