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; }
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); }
// 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); } } }
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); }
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; }
// 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); }
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; }