/// <summary> /// Select a unit stack from a list of existing ones and make an illusory clone of it /// </summary> /// <param name="existing">The list of existing unit stacks</param> public override UnitStack Create(List <UnitStack> existing) { if (existing.Count > 0) { UnitStack toClone = existing[0]; int qty = toClone.GetTotalQty(); int candidateQty; for (int i = 1; i < existing.Count; i++) { candidateQty = existing[i].GetTotalQty(); if (candidateQty > qty) { toClone = existing[i]; qty = candidateQty; } } UnitType illusion = new UnitType(toClone.GetUnitType()); illusion.SetShield(0); illusion.SetArmor(0); illusion.SetHitPoints(1); illusion.AddAttackQuality(AttackData.Quality.ILLUSORY); Unit mirrorImage = new Unit(illusion, toClone.GetTotalQty()); UnitStack stack = new UnitStack(mirrorImage, toClone.GetProvinceToRetreat()); stack.AffectBySpell(this); return(stack); } return(null); }
/// <summary> /// Handles defender selection and related animations. /// </summary> private void ProcessPhaseWithAttacks() { FileLogger.Trace("COMBAT VIEW", "ProcessPhaseWithAttacks"); // unit stacks could be created or destroyed - update the stack views UpdateUnitStackViews(); if (!_model.AreThereUnresolvedAttacks()) { _skipPhase = false; ProcessCombatTurn(); } else { // show all attacks UpdateAttackViews(); AttackRollResultsCollection currentAttackBatch = _model.SelectAttackRollResultsCollection(); if (currentAttackBatch != null) { FileLogger.Trace("COMBAT", "Selected attacks by " + currentAttackBatch.GetUnitStack().GetUnitType().GetName()); if (currentAttackBatch.GetUnitStack() != _currentAttacker) { SetNewStackForCurrentAttackView(currentAttackBatch.GetUnitStack()); // a new defender will be selected against a new attack _currentDefender = null; _skipStack = false; FileLogger.Trace("COMBAT VIEW", "ProcessPhaseWithAttacks: Setting skip stack to false"); } if (!_model.IsPlayerTurn()) { SelectAnNPCStackAsTarget(); } else { // if it's the player's turn // and he already selected a defending stack, resolve the attack if (_currentDefender != null && _currentDefender.GetTotalQty() > 0) { FileLogger.Trace("COMBAT", "Resolving an attack against " + _currentDefender.GetUnitType().GetName()); _model.ResolveCurrentAttack(false); } // else wait until the player will click on a stack view } } // else panic - there should be no case when there are unresolved attacks // but the model can't return an attack collection } }
/// <summary> /// Select a target for the spell from a list of candidates and cast the spell on it /// </summary> /// <param name="potentialTargets">The list of potential targets</param> public override void CastOn(List <UnitStack> potentialTargets) { if (potentialTargets.Count > 0) { // note: the spell doesn't work on holy units UnitStack toTarget = potentialTargets[0]; int qty = toTarget.GetTotalQty(); int candidateQty; for (int i = 1; i < potentialTargets.Count; i++) { candidateQty = potentialTargets[i].GetTotalQty(); if (toTarget.IsAffectedBy(this) || toTarget.GetUnitType().IsHoly() || (candidateQty > qty && !potentialTargets[i].IsAffectedBy(this) && !potentialTargets[i].GetUnitType().IsHoly())) { toTarget = potentialTargets[i]; qty = candidateQty; } } if (!toTarget.IsAffectedBy(this) && !toTarget.GetUnitType().IsHoly()) { toTarget.AffectBySpell(this); } } }
public void UpdateView() { _quantityField.text = _model.GetTotalQty().ToString(); _healthField.text = _model.GetTotalHealth().ToString(); _mirrorImageField.gameObject.SetActive(_model.IsAffectedBy("Mirror Image")); _confusionField.gameObject.SetActive(_model.IsAffectedBy("Confusion")); _magicShieldField.gameObject.SetActive(_model.IsAffectedBy("Magic Shield")); _stoneSkinField.gameObject.SetActive(_model.IsAffectedBy("Stone Skin")); }
/// <summary> /// Select a target for the spell from a list of candidates and cast the spell on it /// </summary> /// <param name="potentialTargets">The list of potential targets</param> public override void CastOn(List <UnitStack> potentialTargets) { if (potentialTargets.Count > 0) { UnitStack toTarget = potentialTargets[0]; int qty = toTarget.GetTotalQty(); int candidateQty; for (int i = 1; i < potentialTargets.Count; i++) { candidateQty = potentialTargets[i].GetTotalQty(); if (toTarget.IsAffectedBy(this) || (candidateQty > qty && !potentialTargets[i].IsAffectedBy(this))) { toTarget = potentialTargets[i]; qty = candidateQty; } } toTarget.AffectBySpell(this); } }
/// <summary> /// Resolve current attack /// </summary> /// <param name="useEstimates">Whether estimated results will be used or honest rolls will be made</param> public void ResolveCurrentAttack(bool useEstimates) { bool ok = false; if (_currentTarget != null && _currentAttacks != null && _currentAttacks.Count > 0) { ok = ResolveAnAttackAgainstTarget(_currentTarget, _currentAttacks.GetAt(_currentAttacks.Count - 1), useEstimates); } if (!ok || _currentAttacks == null || _currentAttacks.Count == 0 || _currentTarget == null || _currentTarget.GetTotalQty() == 0) { _currentTarget = null; _currentAttacks = null; FileLogger.Trace("COMBAT", "ResolveCurrentAttack: reset current target."); } else { FileLogger.Trace("COMBAT", "ResolveCurrentAttack: " + _currentAttacks.Count + " attacks and " + _currentTarget.GetTotalQty() + " targets left."); } }
/// <summary> /// Is the unit stack a valid target for the attack? /// </summary> /// <param name="target">Unit stack which is a potential target for the attack</param> /// <param name="attackRollResult">Attack roll result representing the attack</param> /// <returns>Whether the unit stack is a valid target for the attack</returns> private bool IsValidAttackTarget(UnitStack target, AttackRollResult attackRollResult) { if (_attackers.Contains(target) && _attackers.Contains(attackRollResult.UnitStack)) { FileLogger.Trace("COMBAT", "Both " + attackRollResult.UnitStack.GetUnitType().GetName() + " and " + target.GetUnitType().GetName() + " belong to the attacker"); return(false); } if (_defenders.Contains(target) && _defenders.Contains(attackRollResult.UnitStack)) { FileLogger.Trace("COMBAT", "Both " + attackRollResult.UnitStack.GetUnitType().GetName() + " and " + target.GetUnitType().GetName() + " belong to the defender"); return(false); } if (target.GetTotalQty() == 0) { FileLogger.Trace("COMBAT", "No defenders left in this stack"); return(false); } return(true); }