private void DetermineTurnOrder() { _turnOrder.Clear(); IEnumerable <PBEPokemon> pkmnSwitchingOut = ActiveBattlers.Where(p => p.TurnAction.Decision == PBETurnDecision.SwitchOut); IEnumerable <PBEPokemon> pkmnFighting = ActiveBattlers.Where(p => p.TurnAction.Decision == PBETurnDecision.Fight); // Switching happens first: _turnOrder.AddRange(GetActingOrder(pkmnSwitchingOut, true)); // Moves: sbyte GetPrio(PBEPokemon p) { PBEMoveData mData = PBEMoveData.Data[p.TurnAction.FightMove]; return((sbyte)PBEUtils.Clamp(mData.Priority + (p.Ability == PBEAbility.Prankster && mData.Category == PBEMoveCategory.Status ? 1 : 0), sbyte.MinValue, sbyte.MaxValue)); } foreach (sbyte priority in pkmnFighting.Select(p => GetPrio(p)).Distinct().OrderByDescending(p => p)) { PBEPokemon[] pkmnWithThisPriority = pkmnFighting.Where(p => GetPrio(p) == priority).ToArray(); if (pkmnWithThisPriority.Length > 0) { Debug.WriteLine("Priority {0} bracket...", priority); _turnOrder.AddRange(GetActingOrder(pkmnWithThisPriority, false)); } } }
private void RunActionsInOrder() { foreach (PBEPokemon pkmn in _turnOrder.ToArray()) // Copy the list so a faint or ejection does not cause a collection modified exception { if (Winner != null) // Do not broadcast winner by calling WinCheck() in here; do it in TurnEnded() { return; } else if (ActiveBattlers.Contains(pkmn)) { switch (pkmn.TurnAction.Decision) { case PBETurnDecision.Fight: { UseMove(pkmn, pkmn.TurnAction.FightMove, pkmn.TurnAction.FightTargets); break; } case PBETurnDecision.SwitchOut: { SwitchTwoPokemon(pkmn, TryGetPokemon(pkmn.TurnAction.SwitchPokemonId), false); break; } default: throw new ArgumentOutOfRangeException(nameof(pkmn.TurnAction.Decision)); } } } }
void RunActionsInOrder() { foreach (PBEPokemon pkmn in turnOrder.ToArray()) // Copy the list so a faint or ejection does not cause a collection modified exception { if (ActiveBattlers.Contains(pkmn)) { switch (pkmn.SelectedAction.Decision) { case PBEDecision.Fight: { UseMove(pkmn); break; } case PBEDecision.SwitchOut: { SwitchTwoPokemon(pkmn, TryGetPokemon(pkmn.SelectedAction.SwitchPokemonId), false); break; } default: throw new ArgumentOutOfRangeException(nameof(pkmn.SelectedAction.Decision)); } } } }
/// <summary>Gets a specific active <see cref="PBEPokemon"/> by its <see cref="PBEPokemon.FieldPosition"/>.</summary> /// <param name="pos">The <see cref="PBEFieldPosition"/> of the <see cref="PBEPokemon"/>.</param> public PBEPokemon TryGetPokemon(PBEFieldPosition pos) { if (IsDisposed) { throw new ObjectDisposedException(null); } return(ActiveBattlers.SingleOrDefault(p => p.FieldPosition == pos)); }
void DetermineTurnOrder() { turnOrder.Clear(); IEnumerable <PBEPokemon> pkmnSwitchingOut = ActiveBattlers.Where(p => p.SelectedAction.Decision == PBEDecision.SwitchOut); IEnumerable <PBEPokemon> pkmnFighting = ActiveBattlers.Where(p => p.SelectedAction.Decision == PBEDecision.Fight); // Switching happens first: turnOrder.AddRange(GetActingOrder(pkmnSwitchingOut, true)); // Moves: foreach (sbyte priority in pkmnFighting.Select(p => PBEMoveData.Data[p.SelectedAction.FightMove].Priority).Distinct().OrderByDescending(p => p)) { IEnumerable <PBEPokemon> pkmnWithThisPriority = pkmnFighting.Where(p => PBEMoveData.Data[p.SelectedAction.FightMove].Priority == priority); if (pkmnWithThisPriority.Count() > 0) { Debug.WriteLine("Priority {0} bracket...", priority); turnOrder.AddRange(GetActingOrder(pkmnWithThisPriority, false)); } } }
/// <summary>Gets a specific active <see cref="PBEBattlePokemon"/> by its <see cref="PBEBattlePokemon.FieldPosition"/>.</summary> /// <param name="pos">The <see cref="PBEFieldPosition"/> of the <see cref="PBEBattlePokemon"/>.</param> public PBEBattlePokemon TryGetPokemon(PBEFieldPosition pos) { return(ActiveBattlers.SingleOrDefault(p => p.FieldPosition == pos)); }
private void SwitchesOrActions() { BattleState = PBEBattleState.Processing; OnStateChanged?.Invoke(this); PBETeam[] teamsWithSwitchIns = Teams.Where(t => t.SwitchInQueue.Count > 0).ToArray(); if (teamsWithSwitchIns.Length > 0) { foreach (PBETeam team in teamsWithSwitchIns) { ActiveBattlers.AddRange(team.SwitchInQueue); BroadcastPkmnSwitchIn(team, team.SwitchInQueue.Select(p => CreateSwitchInInfo(p)).ToArray(), false); } DoSwitchInEffects(teamsWithSwitchIns.SelectMany(t => t.SwitchInQueue)); } foreach (PBETeam team in Teams) { int available = team.NumPkmnAlive - team.NumPkmnOnField; team.SwitchInsRequired = 0; team.SwitchInQueue.Clear(); switch (BattleFormat) { case PBEBattleFormat.Single: { if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Center) == null) { team.SwitchInsRequired = 1; } break; } case PBEBattleFormat.Double: { if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Left) == null) { available--; team.SwitchInsRequired++; } if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Right) == null) { team.SwitchInsRequired++; } break; } case PBEBattleFormat.Rotation: case PBEBattleFormat.Triple: { if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Left) == null) { available--; team.SwitchInsRequired++; } if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Center) == null) { available--; team.SwitchInsRequired++; } if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Right) == null) { team.SwitchInsRequired++; } break; } default: throw new ArgumentOutOfRangeException(nameof(BattleFormat)); } } teamsWithSwitchIns = Teams.Where(t => t.SwitchInsRequired > 0).ToArray(); if (teamsWithSwitchIns.Length > 0) { BattleState = PBEBattleState.WaitingForSwitchIns; OnStateChanged?.Invoke(this); foreach (PBETeam team in teamsWithSwitchIns) { BroadcastSwitchInRequest(team); } } else { if (WinCheck()) { return; } foreach (PBEPokemon pkmn in ActiveBattlers) { pkmn.SpeedBoost_AbleToSpeedBoostThisTurn = pkmn.Ability == PBEAbility.SpeedBoost; if (pkmn.Status2.HasFlag(PBEStatus2.Flinching)) { pkmn.Status2 &= ~PBEStatus2.Flinching; BroadcastStatus2(pkmn, pkmn, PBEStatus2.Flinching, PBEStatusAction.Ended); } if (pkmn.Status2.HasFlag(PBEStatus2.HelpingHand)) { pkmn.Status2 &= ~PBEStatus2.HelpingHand; BroadcastStatus2(pkmn, pkmn, PBEStatus2.HelpingHand, PBEStatusAction.Ended); } if (pkmn.Status2.HasFlag(PBEStatus2.Protected)) { pkmn.Status2 &= ~PBEStatus2.Protected; BroadcastStatus2(pkmn, pkmn, PBEStatus2.Protected, PBEStatusAction.Ended); } } foreach (PBETeam team in Teams) { if (team.TeamStatus.HasFlag(PBETeamStatus.WideGuard)) { team.TeamStatus &= ~PBETeamStatus.WideGuard; BroadcastTeamStatus(team, PBETeamStatus.WideGuard, PBETeamStatusAction.Ended); } } foreach (PBETeam team in Teams) { team.ActionsRequired.Clear(); team.ActionsRequired.AddRange(team.ActiveBattlers); } if (BattleFormat == PBEBattleFormat.Triple && Teams.All(t => t.NumPkmnAlive == 1)) { PBEPokemon pkmn1 = ActiveBattlers[0], pkmn2 = ActiveBattlers[1]; if ((pkmn1.FieldPosition == PBEFieldPosition.Left && pkmn2.FieldPosition == PBEFieldPosition.Right) || (pkmn1.FieldPosition == PBEFieldPosition.Right && pkmn2.FieldPosition == PBEFieldPosition.Left)) { PBEFieldPosition pkmn1OldPos = pkmn1.FieldPosition, pkmn2OldPos = pkmn2.FieldPosition; pkmn2.FieldPosition = pkmn1.FieldPosition = PBEFieldPosition.Center; BroadcastAutoCenter(pkmn1.Id, pkmn1OldPos, pkmn1.Team, pkmn2.Id, pkmn2OldPos, pkmn2.Team); } } TurnNumber++; BroadcastTurnBegan(); foreach (PBETeam team in Teams) { bool old = team.MonFaintedThisTurn; // Fire events in a specific order team.MonFaintedThisTurn = false; team.MonFaintedLastTurn = old; } BattleState = PBEBattleState.WaitingForActions; OnStateChanged?.Invoke(this); foreach (PBETeam team in Teams) { BroadcastActionsRequest(team); } } }
/// <summary> /// Gets a specific active Pokémon by its position. /// </summary> /// <param name="pos">The position of the Pokémon you want to get.</param> /// <returns>null if no Pokémon was found was found at <paramref name="pos"/>; otherwise the <see cref="PBEPokemon"/>.</returns> public PBEPokemon TryGetPokemon(PBEFieldPosition pos) => ActiveBattlers.SingleOrDefault(p => p.FieldPosition == pos);
private void SwitchesOrActions() { BattleState = PBEBattleState.Processing; OnStateChanged?.Invoke(this); // Checking SwitchInQueue count since SwitchInsRequired is set to 0 after submitting switches PBETrainer[] trainersWithSwitchIns = Trainers.Where(t => t.SwitchInQueue.Count > 0).ToArray(); if (trainersWithSwitchIns.Length > 0) { var list = new List <PBEBattlePokemon>(6); foreach (PBETrainer trainer in trainersWithSwitchIns) { int count = trainer.SwitchInQueue.Count; var switches = new PBEPkmnSwitchInPacket.PBESwitchInInfo[count]; for (int i = 0; i < count; i++) { (PBEBattlePokemon pkmn, PBEFieldPosition pos) = trainer.SwitchInQueue[i]; pkmn.FieldPosition = pos; switches[i] = CreateSwitchInInfo(pkmn); PBETrainer.SwitchTwoPokemon(pkmn, pos); ActiveBattlers.Add(pkmn); // Add before broadcast list.Add(pkmn); } BroadcastPkmnSwitchIn(trainer, switches); } DoSwitchInEffects(list); } foreach (PBETrainer trainer in Trainers) { int available = trainer.NumConsciousPkmn - trainer.NumPkmnOnField; trainer.SwitchInsRequired = 0; trainer.SwitchInQueue.Clear(); if (available > 0) { switch (BattleFormat) { case PBEBattleFormat.Single: { if (trainer.TryGetPokemon(PBEFieldPosition.Center) == null) { trainer.SwitchInsRequired = 1; } break; } case PBEBattleFormat.Double: { if (trainer.OwnsSpot(PBEFieldPosition.Left) && trainer.TryGetPokemon(PBEFieldPosition.Left) == null) { available--; trainer.SwitchInsRequired++; } if (available > 0 && trainer.OwnsSpot(PBEFieldPosition.Right) && trainer.TryGetPokemon(PBEFieldPosition.Right) == null) { trainer.SwitchInsRequired++; } break; } case PBEBattleFormat.Rotation: case PBEBattleFormat.Triple: { if (trainer.OwnsSpot(PBEFieldPosition.Left) && trainer.TryGetPokemon(PBEFieldPosition.Left) == null) { available--; trainer.SwitchInsRequired++; } if (available > 0 && trainer.OwnsSpot(PBEFieldPosition.Center) && trainer.TryGetPokemon(PBEFieldPosition.Center) == null) { available--; trainer.SwitchInsRequired++; } if (available > 0 && trainer.OwnsSpot(PBEFieldPosition.Right) && trainer.TryGetPokemon(PBEFieldPosition.Right) == null) { trainer.SwitchInsRequired++; } break; } default: throw new ArgumentOutOfRangeException(nameof(BattleFormat)); } } } trainersWithSwitchIns = Trainers.Where(t => t.SwitchInsRequired > 0).ToArray(); if (trainersWithSwitchIns.Length > 0) { BattleState = PBEBattleState.WaitingForSwitchIns; OnStateChanged?.Invoke(this); foreach (PBETrainer trainer in trainersWithSwitchIns) { BroadcastSwitchInRequest(trainer); } } else { if (WinCheck()) { return; } foreach (PBEBattlePokemon pkmn in ActiveBattlers) { pkmn.HasUsedMoveThisTurn = false; pkmn.TurnAction = null; pkmn.SpeedBoost_AbleToSpeedBoostThisTurn = pkmn.Ability == PBEAbility.SpeedBoost; if (pkmn.Status2.HasFlag(PBEStatus2.Flinching)) { BroadcastStatus2(pkmn, pkmn, PBEStatus2.Flinching, PBEStatusAction.Ended); } if (pkmn.Status2.HasFlag(PBEStatus2.HelpingHand)) { BroadcastStatus2(pkmn, pkmn, PBEStatus2.HelpingHand, PBEStatusAction.Ended); } if (pkmn.Status2.HasFlag(PBEStatus2.LockOn)) { if (--pkmn.LockOnTurns == 0) { pkmn.LockOnPokemon = null; BroadcastStatus2(pkmn, pkmn, PBEStatus2.LockOn, PBEStatusAction.Ended); } } if (pkmn.Protection_Used) { pkmn.Protection_Counter++; pkmn.Protection_Used = false; if (pkmn.Status2.HasFlag(PBEStatus2.Protected)) { BroadcastStatus2(pkmn, pkmn, PBEStatus2.Protected, PBEStatusAction.Ended); } } else { pkmn.Protection_Counter = 0; } if (pkmn.Status2.HasFlag(PBEStatus2.Roost)) { pkmn.EndRoost(); BroadcastStatus2(pkmn, pkmn, PBEStatus2.Roost, PBEStatusAction.Ended); } } foreach (PBETeam team in Teams) { if (team.TeamStatus.HasFlag(PBETeamStatus.QuickGuard)) { BroadcastTeamStatus(team, PBETeamStatus.QuickGuard, PBETeamStatusAction.Ended); } if (team.TeamStatus.HasFlag(PBETeamStatus.WideGuard)) { BroadcastTeamStatus(team, PBETeamStatus.WideGuard, PBETeamStatusAction.Ended); } } foreach (PBETrainer trainer in Trainers) { trainer.ActionsRequired.Clear(); trainer.ActionsRequired.AddRange(trainer.ActiveBattlers); } if (BattleFormat == PBEBattleFormat.Triple && Teams.All(t => t.NumConsciousPkmn == 1)) { PBEBattlePokemon pkmn0 = ActiveBattlers[0], pkmn1 = ActiveBattlers[1]; if ((pkmn0.FieldPosition == PBEFieldPosition.Left && pkmn1.FieldPosition == PBEFieldPosition.Left) || (pkmn0.FieldPosition == PBEFieldPosition.Right && pkmn1.FieldPosition == PBEFieldPosition.Right)) { PBEFieldPosition pkmn0OldPos = pkmn0.FieldPosition, pkmn1OldPos = pkmn1.FieldPosition; pkmn0.FieldPosition = PBEFieldPosition.Center; pkmn1.FieldPosition = PBEFieldPosition.Center; BroadcastAutoCenter(pkmn0, pkmn0OldPos, pkmn1, pkmn1OldPos); } } TurnNumber++; BroadcastTurnBegan(); foreach (PBETeam team in Teams) { bool old = team.MonFaintedThisTurn; // Fire events in a specific order team.MonFaintedThisTurn = false; team.MonFaintedLastTurn = old; } BattleState = PBEBattleState.WaitingForActions; OnStateChanged?.Invoke(this); foreach (PBETrainer trainer in Trainers.Where(t => t.NumConsciousPkmn > 0)) { BroadcastActionsRequest(trainer); } } }
// Sets BattleState to PBEBattleState.Processing/PBEBattleState.WaitingForActions/PBEBattleState.WaitingForSwitches/PBEBattleState.Ended void SwitchesOrActions() { BattleState = PBEBattleState.Processing; OnStateChanged?.Invoke(this); IEnumerable <PBETeam> teamsWithSwitchIns = Teams.Where(t => t.SwitchInQueue.Count > 0); if (teamsWithSwitchIns.Count() > 0) { foreach (PBETeam team in teamsWithSwitchIns) { ActiveBattlers.AddRange(team.SwitchInQueue); BroadcastPkmnSwitchIn(team, team.SwitchInQueue.Select(p => CreateSwitchInInfo(p)), false); } DoSwitchInEffects(teamsWithSwitchIns.SelectMany(t => t.SwitchInQueue)); } foreach (PBETeam team in Teams) { int available = team.NumPkmnAlive - team.NumPkmnOnField; team.SwitchInsRequired = 0; team.SwitchInQueue.Clear(); switch (BattleFormat) { case PBEBattleFormat.Single: { if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Center) == null) { team.SwitchInsRequired = 1; } break; } case PBEBattleFormat.Double: { if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Left) == null) { available--; team.SwitchInsRequired++; } if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Right) == null) { team.SwitchInsRequired++; } break; } case PBEBattleFormat.Rotation: case PBEBattleFormat.Triple: { if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Left) == null) { available--; team.SwitchInsRequired++; } if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Center) == null) { available--; team.SwitchInsRequired++; } if (available > 0 && team.TryGetPokemon(PBEFieldPosition.Right) == null) { team.SwitchInsRequired++; } break; } default: throw new ArgumentOutOfRangeException(nameof(BattleFormat)); } } teamsWithSwitchIns = Teams.Where(t => t.SwitchInsRequired > 0); if (teamsWithSwitchIns.Count() > 0) { BattleState = PBEBattleState.WaitingForSwitchIns; OnStateChanged?.Invoke(this); foreach (PBETeam team in teamsWithSwitchIns) { BroadcastSwitchInRequest(team); } } else { if (WinCheck()) { return; } foreach (PBEPokemon pkmn in ActiveBattlers) { pkmn.Status2 &= ~PBEStatus2.Flinching; pkmn.Status2 &= ~PBEStatus2.Protected; } foreach (PBETeam team in Teams) { team.ActionsRequired.Clear(); team.ActionsRequired.AddRange(team.ActiveBattlers); } TurnNumber++; BroadcastTurnBegan(); BattleState = PBEBattleState.WaitingForActions; OnStateChanged?.Invoke(this); foreach (PBETeam team in Teams) { BroadcastActionsRequest(team); } } }