Full Code of Kermalis/PokemonBattleEngine for AI

master e733883abb04 cached
242 files
1.7 MB
562.6k tokens
1787 symbols
1 requests
Download .txt
Showing preview only (1,838K chars total). Download the full file or copy to clipboard to get everything.
Repository: Kermalis/PokemonBattleEngine
Branch: master
Commit: e733883abb04
Files: 242
Total size: 1.7 MB

Directory structure:
gitextract_erdgdp2y/

├── .gitattributes
├── .gitignore
├── LICENSE.md
├── PokemonBattleEngine/
│   ├── Battle/
│   │   ├── Battle.cs
│   │   ├── BattleActions.cs
│   │   ├── BattleDamage.cs
│   │   ├── BattleEffects.cs
│   │   ├── BattleEffects_HitLogic.cs
│   │   ├── BattleEnums.cs
│   │   ├── BattleEvents.cs
│   │   ├── BattleInventory.cs
│   │   ├── BattleMoveset.cs
│   │   ├── BattlePokemon.cs
│   │   ├── BattleReplay.cs
│   │   ├── BattleTargets.cs
│   │   ├── BattleTeam.cs
│   │   ├── BattleTrainer.cs
│   │   ├── BattleUtils.cs
│   │   ├── TrainerInfo.cs
│   │   └── TypeEffectiveness.cs
│   ├── Data/
│   │   ├── DataEnums.cs
│   │   ├── DataProvider.cs
│   │   ├── Interfaces/
│   │   │   ├── ItemData.cs
│   │   │   ├── LocalizedString.cs
│   │   │   ├── MoveData.cs
│   │   │   ├── MovesetInterfaces.cs
│   │   │   ├── PokemonData.cs
│   │   │   ├── PokemonInterfaces.cs
│   │   │   └── StatInterfaces.cs
│   │   ├── Legality/
│   │   │   ├── LegalEffortValues.cs
│   │   │   ├── LegalIndividualValues.cs
│   │   │   ├── LegalMoveset.cs
│   │   │   ├── LegalPokemon.cs
│   │   │   └── LegalPokemonCollection.cs
│   │   ├── PBEAlphabeticalList.cs
│   │   ├── PBEList.cs
│   │   ├── ReadOnlyLocalizedString.cs
│   │   ├── ReadOnlyMoveset.cs
│   │   ├── ReadOnlyPokemon.cs
│   │   ├── ReadOnlyPokemonCollection.cs
│   │   ├── Settings.cs
│   │   ├── StatCollection.cs
│   │   └── Utils/
│   │       ├── DataUtils_Effects.cs
│   │       ├── DataUtils_Forms.cs
│   │       ├── DataUtils_Items.cs
│   │       ├── DataUtils_Moves.cs
│   │       ├── DataUtils_Stats.cs
│   │       └── DataUtils_Validate.cs
│   ├── Network/
│   │   ├── Client.cs
│   │   ├── Encryption.cs
│   │   ├── NetworkUtils.cs
│   │   ├── Server.cs
│   │   └── ServerClient.cs
│   ├── Packets/
│   │   ├── ActionsRequestPacket.cs
│   │   ├── ActionsResponsePacket.cs
│   │   ├── AutoCenterPacket.cs
│   │   ├── BattlePacket.cs
│   │   ├── BattleResultPacket.cs
│   │   ├── FleeResponsePacket.cs
│   │   ├── HazePacket.cs
│   │   ├── MatchCancelledPacket.cs
│   │   ├── PartyRequestPacket.cs
│   │   ├── PartyResponsePacket.cs
│   │   ├── PlayerJoinedPacket.cs
│   │   ├── ResponsePacket.cs
│   │   ├── SwitchInRequestPacket.cs
│   │   ├── SwitchInResponsePacket.cs
│   │   ├── TurnBeganPacket.cs
│   │   ├── _AbilityPacket.cs
│   │   ├── _AbilityReplacedPacket.cs
│   │   ├── _BattleStatusPacket.cs
│   │   ├── _CapturePacket.cs
│   │   ├── _FleeFailedPacket.cs
│   │   ├── _IllusionPacket.cs
│   │   ├── _ItemPacket.cs
│   │   ├── _ItemTurnPacket.cs
│   │   ├── _MoveCritPacket.cs
│   │   ├── _MoveLockPacket.cs
│   │   ├── _MovePPChangedPacket.cs
│   │   ├── _MoveResultPacket.cs
│   │   ├── _MoveUsedPacket.cs
│   │   ├── _PkmnEXPChangedPacket.cs
│   │   ├── _PkmnEXPEarnedPacket.cs
│   │   ├── _PkmnFaintedPacket.cs
│   │   ├── _PkmnFormChangedPacket.cs
│   │   ├── _PkmnHPChangedPacket.cs
│   │   ├── _PkmnLevelChangedPacket.cs
│   │   ├── _PkmnStatChangedPacket.cs
│   │   ├── _PkmnSwitchInPacket.cs
│   │   ├── _PkmnSwitchOutPacket.cs
│   │   ├── _PsychUpPacket.cs
│   │   ├── _ReflectTypePacket.cs
│   │   ├── _SpecialMessagePacket.cs
│   │   ├── _Status1Packet.cs
│   │   ├── _Status2Packet.cs
│   │   ├── _TeamStatusDamagePacket.cs
│   │   ├── _TeamStatusPacket.cs
│   │   ├── _TransformPacket.cs
│   │   ├── _TypeChangedPacket.cs
│   │   ├── _WeatherDamagePacket.cs
│   │   ├── _WeatherPacket.cs
│   │   ├── _WildPkmnAppearedPacket.cs
│   │   ├── __Packet.cs
│   │   └── __PacketProcessor.cs
│   ├── PokemonBattleEngine.csproj
│   └── Utils/
│       ├── EmptyCollections.cs
│       ├── Random.cs
│       └── Utils.cs
├── PokemonBattleEngine.DefaultData/
│   ├── AI/
│   │   ├── AI.cs
│   │   ├── AIDecisions.cs
│   │   └── WildAI.cs
│   ├── Data/
│   │   ├── BerryData.cs
│   │   ├── BerryData_Data.cs
│   │   ├── EXPTables.cs
│   │   ├── EventPokemon.cs
│   │   ├── EventPokemon_Data.cs
│   │   ├── ItemData.cs
│   │   ├── ItemData_Data.cs
│   │   ├── LegalityChecker.cs
│   │   ├── MoveData.cs
│   │   ├── MoveData_Data.cs
│   │   └── PokemonData.cs
│   ├── DefaultDataProvider.cs
│   ├── Enums.cs
│   ├── IPokemonDataExtended.cs
│   ├── LocalizedString.cs
│   ├── PokemonBattleEngine.DefaultData.csproj
│   └── RandomTeamGenerator.cs
├── PokemonBattleEngine.sln
├── PokemonBattleEngineClient/
│   ├── App.xaml
│   ├── App.xaml.cs
│   ├── Clients/
│   │   ├── ActionsBuilder.cs
│   │   ├── BattleClient.cs
│   │   ├── NetworkClient.cs
│   │   ├── NonLocalClient.cs
│   │   ├── ReplayClient.cs
│   │   ├── SinglePlayerClient.cs
│   │   └── SwitchesBuilder.cs
│   ├── Infrastructure/
│   │   ├── BetterWrapPanel.cs
│   │   ├── Converters.cs
│   │   ├── StringRenderer.cs
│   │   ├── Utils.cs
│   │   └── WriteableBitmapSurface.cs
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── Models/
│   │   ├── MoveInfo.cs
│   │   ├── PokemonInfo.cs
│   │   ├── SwitchInfo.cs
│   │   ├── TargetInfo.cs
│   │   └── TeamInfo.cs
│   ├── PokemonBattleEngineClient.csproj
│   └── Views/
│       ├── ActionsView.xaml
│       ├── ActionsView.xaml.cs
│       ├── BattleView.xaml
│       ├── BattleView.xaml.cs
│       ├── FieldView.xaml
│       ├── FieldView.xaml.cs
│       ├── HPBarView.xaml
│       ├── HPBarView.xaml.cs
│       ├── MainView.xaml
│       ├── MainView.xaml.cs
│       ├── MessageView.xaml
│       ├── MessageView.xaml.cs
│       ├── PokemonView.xaml
│       ├── PokemonView.xaml.cs
│       ├── TeamBuilderView.xaml
│       └── TeamBuilderView.xaml.cs
├── PokemonBattleEngineClient.Android/
│   ├── Assets/
│   │   └── AboutAssets.txt
│   ├── MainActivity.cs
│   ├── PokemonBattleEngineClient.Android.csproj
│   ├── Properties/
│   │   ├── AndroidManifest.xml
│   │   └── AssemblyInfo.cs
│   └── Resources/
│       ├── AboutResources.txt
│       ├── Resource.Designer.cs
│       ├── layout/
│       │   └── Main.axml
│       └── values/
│           └── Strings.xml
├── PokemonBattleEngineClient.Desktop/
│   ├── PokemonBattleEngineClient.Desktop.csproj
│   └── Program.cs
├── PokemonBattleEngineClient.iOS/
│   ├── AppDelegate.cs
│   ├── Entitlements.plist
│   ├── Info.plist
│   ├── Main.cs
│   ├── PokemonBattleEngineClient.iOS.csproj
│   ├── Properties/
│   │   └── AssemblyInfo.cs
│   └── Resources/
│       └── LaunchScreen.xib
├── PokemonBattleEngineDiscord/
│   ├── BattleContext.cs
│   ├── BattleContext_Constants.cs
│   ├── BotCommands.cs
│   ├── ChannelHandler.cs
│   ├── Matchmaking.cs
│   ├── PokemonBattleEngineDiscord.csproj
│   ├── Program.cs
│   ├── ReactionHandler.cs
│   ├── ReplaySaver.cs
│   └── Utils.cs
├── PokemonBattleEngineExtras/
│   ├── AIBattleDemo.cs
│   ├── LocalizationDumper.cs
│   ├── NARCTextDumper.cs
│   ├── PokemonBattleEngineExtras.csproj
│   ├── PokemonDataDumper.cs
│   ├── PokemonDataDumper_Data.cs
│   ├── PokemonDataDumper_DreamWorld.cs
│   ├── Program.cs
│   └── Utils.cs
├── PokemonBattleEngineServer/
│   ├── BattleServer.cs
│   ├── Player.cs
│   ├── PokemonBattleEngineServer.csproj
│   └── Properties/
│       └── launchSettings.json
├── PokemonBattleEngineTests/
│   ├── Abilities/
│   │   ├── AntiStatusAbilityTests.cs
│   │   ├── IllusionTests.cs
│   │   ├── IntimidateTests.cs
│   │   ├── NaturalCureTests.cs
│   │   └── PoisonHealTests.cs
│   ├── ActionsTests.cs
│   ├── AutoCenterTests.cs
│   ├── BattleResultTests.cs
│   ├── BehaviorTests.cs
│   ├── Forms/
│   │   ├── CastformCherrimTests.cs
│   │   └── ShayminTests.cs
│   ├── Items/
│   │   └── GemTests.cs
│   ├── Moves/
│   │   ├── BellyDrumTests.cs
│   │   ├── CamouflageTests.cs
│   │   ├── HelpingHandTests.cs
│   │   ├── MultiStrikeTests.cs
│   │   ├── ProtectionTests.cs
│   │   ├── RoostTests.cs
│   │   ├── SecretPowerTests.cs
│   │   ├── TeleportTests.cs
│   │   └── WhirlwindTests.cs
│   ├── PokemonBattleEngineTests.csproj
│   ├── Statuses/
│   │   ├── ConfusionTests.cs
│   │   ├── PowerTrickTests.cs
│   │   └── SubstituteTests.cs
│   ├── TestUtils.cs
│   └── ThrowTests.cs
├── README.md
├── Shared Assets/
│   └── PKMN/
│       ├── FemaleMinispriteLookup.txt
│       └── FemaleSpriteLookup.txt
├── To Do Abilities.txt
├── To Do Items.txt
├── To Do Moves.txt
└── nuget.config

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text eol=lf

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

PokemonBattleEngineExtras/DumpedData

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) 2022 Kermalis

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: PokemonBattleEngine/Battle/Battle.cs
================================================
using Kermalis.PokemonBattleEngine.Data;
using Kermalis.PokemonBattleEngine.Packets;
using Kermalis.PokemonBattleEngine.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Kermalis.PokemonBattleEngine.Battle;

/// <summary>Represents a specific Pokémon battle.</summary>
public sealed partial class PBEBattle
{
	public delegate void BattleStateChangedEvent(PBEBattle battle);
	public event BattleStateChangedEvent? OnStateChanged;
	private PBEBattleState _battleState;
	public PBEBattleState BattleState
	{
		get => _battleState;
		private set
		{
			if (value != _battleState)
			{
				_battleState = value;
				OnStateChanged?.Invoke(this);
			}
		}
	}
	public ushort TurnNumber { get; set; }
	public PBEBattleResult? BattleResult { get; set; }

	private readonly PBERandom _rand;
	public bool IsLocallyHosted { get; }
	public PBEBattleType BattleType { get; }
	public PBEBattleTerrain BattleTerrain { get; }
	public PBEBattleFormat BattleFormat { get; }
	public PBESettings Settings { get; }
	public PBETeams Teams { get; }
	public PBETrainers Trainers { get; }
	public List<PBEBattlePokemon> ActiveBattlers { get; } = new(6);
	private readonly List<PBEBattlePokemon> _turnOrder;

	public PBEWeather Weather { get; set; }
	public byte WeatherCounter { get; set; }
	public PBEBattleStatus BattleStatus { get; set; }
	public byte TrickRoomCount { get; set; }

	public List<IPBEPacket> Events { get; } = new();

	// Trainer battle
	private PBEBattle(PBEBattleFormat battleFormat, PBESettings settings, IReadOnlyList<PBETrainerInfo> ti0, IReadOnlyList<PBETrainerInfo> ti1,
		PBEBattleTerrain battleTerrain, PBEWeather weather, int? randomSeed)
	{
		if (battleFormat >= PBEBattleFormat.MAX)
		{
			throw new ArgumentOutOfRangeException(nameof(battleFormat));
		}
		if (battleTerrain >= PBEBattleTerrain.MAX)
		{
			throw new ArgumentOutOfRangeException(nameof(battleTerrain));
		}
		if (weather >= PBEWeather.MAX)
		{
			throw new ArgumentOutOfRangeException(nameof(weather));
		}

		settings.ShouldBeReadOnly(nameof(settings));
		_rand = new PBERandom(randomSeed ?? PBEDataProvider.GlobalRandom.RandomInt());
		IsLocallyHosted = true;
		BattleType = PBEBattleType.Trainer;
		BattleTerrain = battleTerrain;
		BattleFormat = battleFormat;
		Settings = settings;
		Weather = weather;
		Teams = new PBETeams(this, ti0, ti1, out PBETrainers trainers);
		Trainers = trainers;
		_turnOrder = new List<PBEBattlePokemon>(6);
		QueueUpPokemon();
	}
	// Wild battle
	private PBEBattle(PBEBattleFormat battleFormat, PBESettings settings, IReadOnlyList<PBETrainerInfo> ti, PBEWildInfo wi,
		PBEBattleTerrain battleTerrain, PBEWeather weather, int? randomSeed)
	{
		if (battleFormat >= PBEBattleFormat.MAX)
		{
			throw new ArgumentOutOfRangeException(nameof(battleFormat));
		}
		if (battleTerrain >= PBEBattleTerrain.MAX)
		{
			throw new ArgumentOutOfRangeException(nameof(battleTerrain));
		}
		if (weather >= PBEWeather.MAX)
		{
			throw new ArgumentOutOfRangeException(nameof(weather));
		}
		settings.ShouldBeReadOnly(nameof(settings));
		_rand = new PBERandom(randomSeed ?? PBEDataProvider.GlobalRandom.RandomInt());
		IsLocallyHosted = true;
		BattleType = PBEBattleType.Wild;
		BattleTerrain = battleTerrain;
		BattleFormat = battleFormat;
		Settings = settings;
		Weather = weather;
		Teams = new PBETeams(this, ti, wi, out PBETrainers trainers);
		Trainers = trainers;
		_turnOrder = new List<PBEBattlePokemon>(6);
		QueueUpPokemon();
	}
	// Remote battle
	private PBEBattle(PBEBattlePacket packet)
	{
		IsLocallyHosted = false;
		BattleType = packet.BattleType;
		BattleFormat = packet.BattleFormat;
		BattleTerrain = packet.BattleTerrain;
		Weather = packet.Weather;
		Settings = packet.Settings;
		Teams = new PBETeams(this, packet, out PBETrainers trainers);
		Trainers = trainers;
		// These two will never be used in a non-local battle
		_rand = null!;
		_turnOrder = null!;
	}

	public static PBEBattle CreateTrainerBattle(PBEBattleFormat battleFormat, PBESettings settings, PBETrainerInfo ti0, PBETrainerInfo ti1,
		PBEBattleTerrain battleTerrain = PBEBattleTerrain.Plain, PBEWeather weather = PBEWeather.None, int? randomSeed = null)
	{
		return new PBEBattle(battleFormat, settings, new[] { ti0 }, new[] { ti1 }, battleTerrain, weather, randomSeed);
	}
	public static PBEBattle CreateTrainerBattle(PBEBattleFormat battleFormat, PBESettings settings, IReadOnlyList<PBETrainerInfo> ti0, IReadOnlyList<PBETrainerInfo> ti1,
		PBEBattleTerrain battleTerrain = PBEBattleTerrain.Plain, PBEWeather weather = PBEWeather.None, int? randomSeed = null)
	{
		return new PBEBattle(battleFormat, settings, ti0, ti1, battleTerrain, weather, randomSeed);
	}
	public static PBEBattle CreateWildBattle(PBEBattleFormat battleFormat, PBESettings settings, PBETrainerInfo ti0, PBEWildInfo wi,
		PBEBattleTerrain battleTerrain = PBEBattleTerrain.Plain, PBEWeather weather = PBEWeather.None, int? randomSeed = null)
	{
		return new PBEBattle(battleFormat, settings, new[] { ti0 }, wi, battleTerrain, weather, randomSeed);
	}
	public static PBEBattle CreateWildBattle(PBEBattleFormat battleFormat, PBESettings settings, IReadOnlyList<PBETrainerInfo> ti0, PBEWildInfo wi,
		PBEBattleTerrain battleTerrain = PBEBattleTerrain.Plain, PBEWeather weather = PBEWeather.None, int? randomSeed = null)
	{
		return new PBEBattle(battleFormat, settings, ti0, wi, battleTerrain, weather, randomSeed);
	}
	public static PBEBattle CreateRemoteBattle(PBEBattlePacket packet)
	{
		return new PBEBattle(packet);
	}

	private void QueueUp(PBETeam team, PBEFieldPosition pos, ref PBETrainer? tr, ref int i)
	{
		// See which trainer owns this spot
		PBETrainer t = team.GetTrainer(pos);
		// If it's not the previous trainer, we start at their first PKMN
		if (tr != t)
		{
			i = 0;
			tr = t;
		}
		PBEList<PBEBattlePokemon> party = t.Party;
	// If the check index is valid, try to send out a non-fainted non-ignore PKMN
	tryget:
		if (i < party.Count)
		{
			PBEBattlePokemon p = party[i];
			// If we should ignore this PKMN, try to get the one in the next index
			if (!p.CanBattle)
			{
				i++;
				goto tryget;
			}
			// Valid PKMN, send it out
			p.Trainer.SwitchInQueue.Add((p, pos));
			// Wild PKMN should be out already
			if (team.IsWild)
			{
				p.FieldPosition = pos;
				ActiveBattlers.Add(p);
			}
			// Next slot to check
			i++;
		}
	}
	internal void QueueUpPokemon()
	{
		switch (BattleFormat)
		{
			case PBEBattleFormat.Single:
			{
				foreach (PBETeam team in Teams)
				{
					PBETrainer? t = null;
					int i = 0;
					QueueUp(team, PBEFieldPosition.Center, ref t, ref i);
				}
				break;
			}
			case PBEBattleFormat.Double:
			{
				foreach (PBETeam team in Teams)
				{
					PBETrainer? t = null;
					int i = 0;
					QueueUp(team, PBEFieldPosition.Left, ref t, ref i);
					QueueUp(team, PBEFieldPosition.Right, ref t, ref i);
				}
				break;
			}
			case PBEBattleFormat.Triple:
			{
				foreach (PBETeam team in Teams)
				{
					PBETrainer? t = null;
					int i = 0;
					QueueUp(team, PBEFieldPosition.Left, ref t, ref i);
					QueueUp(team, PBEFieldPosition.Center, ref t, ref i);
					QueueUp(team, PBEFieldPosition.Right, ref t, ref i);
				}
				break;
			}
			case PBEBattleFormat.Rotation:
			{
				foreach (PBETeam team in Teams)
				{
					PBETrainer? t = null;
					int i = 0;
					QueueUp(team, PBEFieldPosition.Center, ref t, ref i);
					QueueUp(team, PBEFieldPosition.Left, ref t, ref i);
					QueueUp(team, PBEFieldPosition.Right, ref t, ref i);
				}
				break;
			}
			default: throw new ArgumentOutOfRangeException(nameof(BattleFormat));
		}

		BattleState = PBEBattleState.ReadyToBegin;
	}
	private void CheckLocal()
	{
		if (!IsLocallyHosted)
		{
			throw new InvalidOperationException("This battle is not locally hosted");
		}
	}
	/// <summary>Begins the battle.</summary>
	/// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.ReadyToBegin"/>.</exception>
	public void Begin()
	{
		CheckLocal();
		if (_battleState != PBEBattleState.ReadyToBegin)
		{
			throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.ReadyToBegin} to begin the battle.");
		}
		BattleState = PBEBattleState.Processing;
		BroadcastBattle(); // The first packet sent is PBEBattlePacket which replays rely on
						   // Wild Pokémon appearing
		if (BattleType == PBEBattleType.Wild)
		{
			PBETeam team = Teams[1];
			PBETrainer trainer = team.Trainers[0];
			int count = trainer.SwitchInQueue.Count;
			var appearances = new PBEPkmnAppearedInfo[count];
			for (int i = 0; i < count; i++)
			{
				appearances[i] = new PBEPkmnAppearedInfo(trainer.SwitchInQueue[i].Pkmn);
			}
			trainer.SwitchInQueue.Clear();
			BroadcastWildPkmnAppeared(appearances);
		}
		SwitchesOrActions();
	}
	/// <summary>Runs a turn.</summary>
	/// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.ReadyToRunTurn"/>.</exception>
	public void RunTurn()
	{
		CheckLocal();
		if (_battleState != PBEBattleState.ReadyToRunTurn)
		{
			throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.ReadyToRunTurn} to run a turn.");
		}
		BattleState = PBEBattleState.Processing;
		FleeCheck();
		if (EndCheck())
		{
			return;
		}
		DetermineTurnOrder();
		RunActionsInOrder();
		TurnEnded();
	}
	public void RunSwitches()
	{
		CheckLocal();
		if (_battleState != PBEBattleState.ReadyToRunSwitches)
		{
			throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.ReadyToRunSwitches} to run switches.");
		}
		BattleState = PBEBattleState.Processing;
		FleeCheck();
		if (EndCheck())
		{
			return;
		}
		SwitchesOrActions();
	}

	/// <summary>Sets <see cref="BattleState"/> to <see cref="PBEBattleState.Ended"/> and clears <see cref="OnNewEvent"/> and <see cref="OnStateChanged"/>. Does not touch <see cref="BattleResult"/>.</summary>
	public void SetEnded()
	{
		if (_battleState != PBEBattleState.Ended)
		{
			BattleState = PBEBattleState.Ended;
			OnNewEvent = null;
			OnStateChanged = null;
		}
	}
	private bool EndCheck()
	{
		if (BattleResult is not null)
		{
			BroadcastBattleResult(BattleResult.Value);
			foreach (PBEBattlePokemon pkmn in ActiveBattlers)
			{
				pkmn.ApplyNaturalCure(); // Natural Cure happens at the end of the battle. Pokémon should be copied when BattleState is set to "Ended", not upon battle result.
			}
			SetEnded();
			return true;
		}
		return false;
	}
	private void SwitchesOrActions()
	{
		// 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 PBEPkmnAppearedInfo[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); // Swap after Illusion
					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.IsSpotOccupied(PBEFieldPosition.Center))
						{
							trainer.SwitchInsRequired = 1;
						}
						break;
					}
					case PBEBattleFormat.Double:
					{
						if (trainer.OwnsSpot(PBEFieldPosition.Left) && !trainer.IsSpotOccupied(PBEFieldPosition.Left))
						{
							available--;
							trainer.SwitchInsRequired++;
						}
						if (available > 0 && trainer.OwnsSpot(PBEFieldPosition.Right) && !trainer.IsSpotOccupied(PBEFieldPosition.Right))
						{
							trainer.SwitchInsRequired++;
						}
						break;
					}
					case PBEBattleFormat.Rotation:
					case PBEBattleFormat.Triple:
					{
						if (trainer.OwnsSpot(PBEFieldPosition.Left) && !trainer.IsSpotOccupied(PBEFieldPosition.Left))
						{
							available--;
							trainer.SwitchInsRequired++;
						}
						if (available > 0 && trainer.OwnsSpot(PBEFieldPosition.Center) && !trainer.IsSpotOccupied(PBEFieldPosition.Center))
						{
							available--;
							trainer.SwitchInsRequired++;
						}
						if (available > 0 && trainer.OwnsSpot(PBEFieldPosition.Right) && !trainer.IsSpotOccupied(PBEFieldPosition.Right))
						{
							trainer.SwitchInsRequired++;
						}
						break;
					}
					default: throw new ArgumentOutOfRangeException(nameof(BattleFormat));
				}
			}
		}
		trainersWithSwitchIns = Trainers.Where(t => t.SwitchInsRequired > 0).ToArray();
		if (trainersWithSwitchIns.Length > 0)
		{
			BattleState = PBEBattleState.WaitingForSwitchIns;
			foreach (PBETrainer trainer in trainersWithSwitchIns)
			{
				BroadcastSwitchInRequest(trainer);
			}
		}
		else
		{
			if (EndCheck())
			{
				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.ActiveBattlersOrdered);
			}

			// #318 - We check pkmn on the field instead of conscious pkmn because of multi-battles
			// It still works if there's only one trainer on the team since we check for available switch-ins above
			if (BattleFormat == PBEBattleFormat.Triple && Teams.All(t => t.NumPkmnOnField == 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;
			foreach (PBETrainer trainer in Trainers.Where(t => t.NumConsciousPkmn > 0))
			{
				BroadcastActionsRequest(trainer);
			}
		}
	}
	private IEnumerable<PBEBattlePokemon> GetActingOrder(IEnumerable<PBEBattlePokemon> pokemon, bool ignoreItemsThatActivate)
	{
		var evaluated = new List<(PBEBattlePokemon Pokemon, float Speed)>(); // TODO: Full Incense, Lagging Tail, Stall, Quick Claw
		foreach (PBEBattlePokemon pkmn in pokemon)
		{
			float speed = pkmn.Speed * GetStatChangeModifier(pkmn.SpeedChange, false);

			switch (pkmn.Item)
			{
				case PBEItem.ChoiceScarf:
				{
					speed *= 1.5f;
					break;
				}
				case PBEItem.MachoBrace:
				case PBEItem.PowerAnklet:
				case PBEItem.PowerBand:
				case PBEItem.PowerBelt:
				case PBEItem.PowerBracer:
				case PBEItem.PowerLens:
				case PBEItem.PowerWeight:
				{
					speed *= 0.5f;
					break;
				}
				case PBEItem.QuickPowder:
				{
					if (pkmn.OriginalSpecies == PBESpecies.Ditto && !pkmn.Status2.HasFlag(PBEStatus2.Transformed))
					{
						speed *= 2.0f;
					}
					break;
				}
			}
			if (ShouldDoWeatherEffects())
			{
				if (Weather == PBEWeather.HarshSunlight && pkmn.Ability == PBEAbility.Chlorophyll)
				{
					speed *= 2.0f;
				}
				else if (Weather == PBEWeather.Rain && pkmn.Ability == PBEAbility.SwiftSwim)
				{
					speed *= 2.0f;
				}
				else if (Weather == PBEWeather.Sandstorm && pkmn.Ability == PBEAbility.SandRush)
				{
					speed *= 2.0f;
				}
			}
			switch (pkmn.Ability)
			{
				case PBEAbility.QuickFeet:
				{
					if (pkmn.Status1 != PBEStatus1.None)
					{
						speed *= 1.5f;
					}
					break;
				}
				case PBEAbility.SlowStart:
				{
					if (pkmn.SlowStart_HinderTurnsLeft > 0)
					{
						speed *= 0.5f;
					}
					break;
				}
			}
			if (pkmn.Ability != PBEAbility.QuickFeet && pkmn.Status1 == PBEStatus1.Paralyzed)
			{
				speed *= 0.25f;
			}
			if (pkmn.Team.TeamStatus.HasFlag(PBETeamStatus.Tailwind))
			{
				speed *= 2.0f;
			}

			(PBEBattlePokemon Pokemon, float Speed) tup = (pkmn, speed);
			if (evaluated.Count == 0)
			{
				evaluated.Add(tup);
			}
			else
			{
				int pkmnTiedWith = evaluated.FindIndex(t => t.Speed == speed);
				if (pkmnTiedWith != -1) // Speed tie - randomly go before or after the Pokémon it tied with
				{
					if (_rand.RandomBool())
					{
						if (pkmnTiedWith == evaluated.Count - 1)
						{
							evaluated.Add(tup);
						}
						else
						{
							evaluated.Insert(pkmnTiedWith + 1, tup);
						}
					}
					else
					{
						evaluated.Insert(pkmnTiedWith, tup);
					}
				}
				else
				{
					int pkmnToGoBefore = evaluated.FindIndex(t => BattleStatus.HasFlag(PBEBattleStatus.TrickRoom) ? t.Speed > speed : t.Speed < speed);
					if (pkmnToGoBefore == -1)
					{
						evaluated.Add(tup);
					}
					else
					{
						evaluated.Insert(pkmnToGoBefore, tup);
					}
				}
			}
		}
		return evaluated.Select(t => t.Pokemon);
	}
	private void DetermineTurnOrder()
	{
		static int GetMovePrio(PBEBattlePokemon p)
		{
			IPBEMoveData mData = PBEDataProvider.Instance.GetMoveData(p.TurnAction!.FightMove);
			int priority = mData.Priority;
			if (p.Ability == PBEAbility.Prankster && mData.Category == PBEMoveCategory.Status)
			{
				priority++;
			}
			return priority;
		}

		_turnOrder.Clear();
		//const int PursuitPriority = +7;
		const int SwitchRotatePriority = +6;
		const int WildFleePriority = -7;
		List<PBEBattlePokemon> pkmnUsingItem = ActiveBattlers.FindAll(p => p.TurnAction?.Decision == PBETurnDecision.Item);
		List<PBEBattlePokemon> pkmnSwitchingOut = ActiveBattlers.FindAll(p => p.TurnAction?.Decision == PBETurnDecision.SwitchOut);
		List<PBEBattlePokemon> pkmnFighting = ActiveBattlers.FindAll(p => p.TurnAction?.Decision == PBETurnDecision.Fight);
		List<PBEBattlePokemon> wildFleeing = ActiveBattlers.FindAll(p => p.TurnAction?.Decision == PBETurnDecision.WildFlee);
		// Item use happens first:
		_turnOrder.AddRange(GetActingOrder(pkmnUsingItem, true));
		// Get move/switch/rotate/wildflee priority sorted
		IOrderedEnumerable<IGrouping<int, PBEBattlePokemon>> prios =
				pkmnSwitchingOut.Select(p => (p, SwitchRotatePriority))
				.Concat(pkmnFighting.Select(p => (p, GetMovePrio(p)))) // Get move priority
                .Concat(wildFleeing.Select(p => (p, WildFleePriority)))
				.GroupBy(t => t.Item2, t => t.p)
				.OrderByDescending(t => t.Key);
		foreach (IGrouping<int, PBEBattlePokemon> bracket in prios)
		{
			bool ignoreItemsThatActivate = bracket.Key == SwitchRotatePriority || bracket.Key == WildFleePriority;
			_turnOrder.AddRange(GetActingOrder(bracket, ignoreItemsThatActivate));
		}
	}
	private void RunActionsInOrder()
	{
		foreach (PBEBattlePokemon pkmn in _turnOrder.ToArray()) // Copy the list so a faint or ejection does not cause a collection modified exception
		{
			if (BattleResult is not null) // Do not broadcast battle result by calling EndCheck() 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.Item:
					{
						UseItem(pkmn, pkmn.TurnAction.UseItem);
						break;
					}
					case PBETurnDecision.SwitchOut:
					{
						SwitchTwoPokemon(pkmn, pkmn.Trainer.GetPokemon(pkmn.TurnAction.SwitchPokemonId));
						break;
					}
					case PBETurnDecision.WildFlee:
					{
						WildFleeCheck(pkmn);
						break;
					}
					default: throw new ArgumentOutOfRangeException(nameof(pkmn.TurnAction.Decision));
				}
			}
		}
	}
	private void TurnEnded()
	{
		if (EndCheck())
		{
			return;
		}

		// Verified: Effects before LightScreen/LuckyChant/Reflect/Safeguard/TrickRoom
		DoTurnEndedEffects();

		if (EndCheck())
		{
			return;
		}

		// Verified: LightScreen/LuckyChant/Reflect/Safeguard/TrickRoom are removed in the order they were added
		foreach (PBETeam team in Teams)
		{
			if (team.TeamStatus.HasFlag(PBETeamStatus.LightScreen))
			{
				team.LightScreenCount--;
				if (team.LightScreenCount == 0)
				{
					BroadcastTeamStatus(team, PBETeamStatus.LightScreen, PBETeamStatusAction.Ended);
				}
			}
			if (team.TeamStatus.HasFlag(PBETeamStatus.LuckyChant))
			{
				team.LuckyChantCount--;
				if (team.LuckyChantCount == 0)
				{
					BroadcastTeamStatus(team, PBETeamStatus.LuckyChant, PBETeamStatusAction.Ended);
				}
			}
			if (team.TeamStatus.HasFlag(PBETeamStatus.Reflect))
			{
				team.ReflectCount--;
				if (team.ReflectCount == 0)
				{
					BroadcastTeamStatus(team, PBETeamStatus.Reflect, PBETeamStatusAction.Ended);
				}
			}
			if (team.TeamStatus.HasFlag(PBETeamStatus.Safeguard))
			{
				team.SafeguardCount--;
				if (team.SafeguardCount == 0)
				{
					BroadcastTeamStatus(team, PBETeamStatus.Safeguard, PBETeamStatusAction.Ended);
				}
			}
			if (team.TeamStatus.HasFlag(PBETeamStatus.Tailwind))
			{
				team.TailwindCount--;
				if (team.TailwindCount == 0)
				{
					BroadcastTeamStatus(team, PBETeamStatus.Tailwind, PBETeamStatusAction.Ended);
				}
			}
		}
		// Trick Room
		if (BattleStatus.HasFlag(PBEBattleStatus.TrickRoom))
		{
			TrickRoomCount--;
			if (TrickRoomCount == 0)
			{
				BroadcastBattleStatus(PBEBattleStatus.TrickRoom, PBEBattleStatusAction.Ended);
			}
		}

		SwitchesOrActions();
	}
}


================================================
FILE: PokemonBattleEngine/Battle/BattleActions.cs
================================================
using Kermalis.EndianBinaryIO;
using Kermalis.PokemonBattleEngine.Data;
using Kermalis.PokemonBattleEngine.Data.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;

namespace Kermalis.PokemonBattleEngine.Battle;

public sealed class PBETurnAction
{
	public byte PokemonId { get; }
	public PBETurnDecision Decision { get; }
	public PBEMove FightMove { get; }
	public PBETurnTarget FightTargets { get; internal set; } // Internal set because of PBEMoveTarget.RandomFoeSurrounding (TODO: Shouldn't this happen at runtime?)
	public PBEItem UseItem { get; }
	public byte SwitchPokemonId { get; }

	internal PBETurnAction(EndianBinaryReader r)
	{
		PokemonId = r.ReadByte();
		Decision = r.ReadEnum<PBETurnDecision>();
		switch (Decision)
		{
			case PBETurnDecision.Fight:
			{
				FightMove = r.ReadEnum<PBEMove>();
				FightTargets = r.ReadEnum<PBETurnTarget>();
				break;
			}
			case PBETurnDecision.Item:
			{
				UseItem = r.ReadEnum<PBEItem>();
				break;
			}
			case PBETurnDecision.SwitchOut:
			{
				SwitchPokemonId = r.ReadByte();
				break;
			}
			case PBETurnDecision.WildFlee: break;
			default: throw new InvalidDataException(nameof(Decision));
		}
	}
	// Fight
	public PBETurnAction(PBEBattlePokemon pokemon, PBEMove fightMove, PBETurnTarget fightTargets)
		: this(pokemon.Id, fightMove, fightTargets) { }
	public PBETurnAction(byte pokemonId, PBEMove fightMove, PBETurnTarget fightTargets)
	{
		PokemonId = pokemonId;
		Decision = PBETurnDecision.Fight;
		FightMove = fightMove;
		FightTargets = fightTargets;
	}
	// Item
	public PBETurnAction(PBEBattlePokemon pokemon, PBEItem item)
		: this(pokemon.Id, item) { }
	public PBETurnAction(byte pokemonId, PBEItem item)
	{
		PokemonId = pokemonId;
		Decision = PBETurnDecision.Item;
		UseItem = item;
	}
	// Switch
	public PBETurnAction(PBEBattlePokemon pokemon, PBEBattlePokemon switchPokemon)
		: this(pokemon.Id, switchPokemon.Id) { }
	public PBETurnAction(byte pokemonId, byte switchPokemonId)
	{
		PokemonId = pokemonId;
		Decision = PBETurnDecision.SwitchOut;
		SwitchPokemonId = switchPokemonId;
	}
	// Internal wild flee
	internal PBETurnAction(PBEBattlePokemon pokemon)
		: this(pokemon.Id) { }
	internal PBETurnAction(byte pokemonId)
	{
		PokemonId = pokemonId;
		Decision = PBETurnDecision.WildFlee;
	}

	internal void ToBytes(EndianBinaryWriter w)
	{
		w.WriteByte(PokemonId);
		w.WriteEnum(Decision);
		switch (Decision)
		{
			case PBETurnDecision.Fight:
			{
				w.WriteEnum(FightMove);
				w.WriteEnum(FightTargets);
				break;
			}
			case PBETurnDecision.Item:
			{
				w.WriteEnum(UseItem);
				break;
			}
			case PBETurnDecision.SwitchOut:
			{
				w.WriteByte(SwitchPokemonId);
				break;
			}
			case PBETurnDecision.WildFlee: break;
			default: throw new InvalidDataException(nameof(Decision));
		}
	}
}
public sealed class PBESwitchIn
{
	public byte PokemonId { get; }
	public PBEFieldPosition Position { get; }

	internal PBESwitchIn(EndianBinaryReader r)
	{
		PokemonId = r.ReadByte();
		Position = r.ReadEnum<PBEFieldPosition>();
	}
	public PBESwitchIn(PBEBattlePokemon pokemon, PBEFieldPosition position)
		: this(pokemon.Id, position) { }
	public PBESwitchIn(byte pokemonId, PBEFieldPosition position)
	{
		PokemonId = pokemonId;
		Position = position;
	}

	internal void ToBytes(EndianBinaryWriter w)
	{
		w.WriteByte(PokemonId);
		w.WriteEnum(Position);
	}
}
public sealed partial class PBEBattle
{
	internal static bool AreActionsValid(PBETrainer trainer, IReadOnlyCollection<PBETurnAction> actions, [NotNullWhen(false)] out string? invalidReason)
	{
		if (trainer.Battle._battleState != PBEBattleState.WaitingForActions)
		{
			throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to validate actions.");
		}
		if (trainer.ActionsRequired.Count == 0)
		{
			invalidReason = "Actions were already submitted";
			return false;
		}
		if (actions.Count != trainer.ActionsRequired.Count)
		{
			invalidReason = $"Invalid amount of actions submitted; required amount is {trainer.ActionsRequired.Count}";
			return false;
		}

		var verified = new List<PBEBattlePokemon>(trainer.ActionsRequired.Count);
		var standBy = new List<PBEBattlePokemon>(trainer.ActionsRequired.Count);
		var items = new Dictionary<PBEItem, int>(trainer.ActionsRequired.Count);
		foreach (PBETurnAction action in actions)
		{
			if (!trainer.TryGetPokemon(action.PokemonId, out PBEBattlePokemon? pkmn))
			{
				invalidReason = $"Invalid Pokémon ID ({action.PokemonId})";
				return false;
			}
			if (!trainer.ActionsRequired.Contains(pkmn))
			{
				invalidReason = $"Pokémon {action.PokemonId} not looking for actions";
				return false;
			}
			if (verified.Contains(pkmn))
			{
				invalidReason = $"Pokémon {action.PokemonId} was multiple actions";
				return false;
			}
			switch (action.Decision)
			{
				case PBETurnDecision.Fight:
				{
					if (Array.IndexOf(pkmn.GetUsableMoves(), action.FightMove) == -1)
					{
						invalidReason = $"{action.FightMove} is not usable by Pokémon {action.PokemonId}";
						return false;
					}
					if (action.FightMove == pkmn.TempLockedMove && action.FightTargets != pkmn.TempLockedTargets)
					{
						invalidReason = $"Pokémon {action.PokemonId} must target {pkmn.TempLockedTargets}";
						return false;
					}
					if (!AreTargetsValid(pkmn, action.FightMove, action.FightTargets))
					{
						invalidReason = $"Invalid move targets for Pokémon {action.PokemonId}'s {action.FightMove}";
						return false;
					}
					break;
				}
				case PBETurnDecision.Item:
				{
					if (pkmn.TempLockedMove != PBEMove.None)
					{
						invalidReason = $"Pokémon {action.PokemonId} must use {pkmn.TempLockedMove}";
						return false;
					}
					if (!trainer.Inventory.TryGetValue(action.UseItem, out PBEBattleInventory.PBEBattleInventorySlot? slot))
					{
						invalidReason = $"Trainer \"{trainer.Name}\" does not have any {action.UseItem}"; // Handles wild Pokémon
						return false;
					}
					bool used = items.TryGetValue(action.UseItem, out int amtUsed);
					if (!used)
					{
						amtUsed = 0;
					}
					long newAmt = slot.Quantity - amtUsed;
					if (newAmt <= 0)
					{
						invalidReason = $"Tried to use too many {action.UseItem}";
						return false;
					}
					if (trainer.Battle.BattleType == PBEBattleType.Wild && trainer.Team.OpposingTeam.ActiveBattlers.Count > 1
						&& PBEDataUtils.AllBalls.Contains(action.UseItem))
					{
						invalidReason = $"Cannot throw a ball at multiple wild Pokémon";
						return false;
					}
					amtUsed++;
					if (used)
					{
						items[action.UseItem] = amtUsed;
					}
					else
					{
						items.Add(action.UseItem, amtUsed);
					}
					break;
				}
				case PBETurnDecision.SwitchOut:
				{
					if (!pkmn.CanSwitchOut())
					{
						invalidReason = $"Pokémon {action.PokemonId} cannot switch out";
						return false;
					}
					if (!trainer.TryGetPokemon(action.SwitchPokemonId, out PBEBattlePokemon? switchPkmn))
					{
						invalidReason = $"Invalid switch Pokémon ID ({action.PokemonId})";
						return false;
					}
					if (switchPkmn.HP == 0)
					{
						invalidReason = $"Switch Pokémon {action.PokemonId} is fainted";
						return false;
					}
					if (switchPkmn.PBEIgnore)
					{
						invalidReason = $"Switch Pokémon {action.PokemonId} cannot battle";
						return false;
					}
					if (switchPkmn.FieldPosition != PBEFieldPosition.None)
					{
						invalidReason = $"Switch Pokémon {action.PokemonId} is already on the field";
						return false;
					}
					if (standBy.Contains(switchPkmn))
					{
						invalidReason = $"Switch Pokémon {action.PokemonId} was asked to be switched in multiple times";
						return false;
					}
					standBy.Add(switchPkmn);
					break;
				}
				default:
				{
					invalidReason = $"Invalid turn decision ({action.Decision})";
					return false;
				}
			}
			verified.Add(pkmn);
		}
		invalidReason = null;
		return true;
	}
	internal static bool SelectActionsIfValid(PBETrainer trainer, IReadOnlyCollection<PBETurnAction> actions, [NotNullWhen(false)] out string? invalidReason)
	{
		if (!AreActionsValid(trainer, actions, out invalidReason))
		{
			return false;
		}

		trainer.ActionsRequired.Clear();
		foreach (PBETurnAction action in actions)
		{
			PBEBattlePokemon pkmn = trainer.GetPokemon(action.PokemonId);
			if (action.Decision == PBETurnDecision.Fight && pkmn.GetMoveTargets(action.FightMove) == PBEMoveTarget.RandomFoeSurrounding)
			{
				switch (trainer.Battle.BattleFormat)
				{
					case PBEBattleFormat.Single:
					case PBEBattleFormat.Rotation:
					{
						action.FightTargets = PBETurnTarget.FoeCenter;
						break;
					}
					case PBEBattleFormat.Double:
					{
						action.FightTargets = trainer.Battle._rand.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeRight;
						break;
					}
					case PBEBattleFormat.Triple:
					{
						if (pkmn.FieldPosition == PBEFieldPosition.Left)
						{
							action.FightTargets = trainer.Battle._rand.RandomBool() ? PBETurnTarget.FoeCenter : PBETurnTarget.FoeRight;
						}
						else if (pkmn.FieldPosition == PBEFieldPosition.Center)
						{
							PBETeam oppTeam = trainer.Team.OpposingTeam;
							int r; // Keep randomly picking until a non-fainted foe is selected
						roll:
							r = trainer.Battle._rand.RandomInt(0, 2);
							if (r == 0)
							{
								if (oppTeam.IsSpotOccupied(PBEFieldPosition.Left))
								{
									action.FightTargets = PBETurnTarget.FoeLeft;
								}
								else
								{
									goto roll;
								}
							}
							else if (r == 1)
							{
								if (oppTeam.IsSpotOccupied(PBEFieldPosition.Center))
								{
									action.FightTargets = PBETurnTarget.FoeCenter;
								}
								else
								{
									goto roll;
								}
							}
							else
							{
								if (oppTeam.IsSpotOccupied(PBEFieldPosition.Right))
								{
									action.FightTargets = PBETurnTarget.FoeRight;
								}
								else
								{
									goto roll;
								}
							}
						}
						else
						{
							action.FightTargets = trainer.Battle._rand.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeCenter;
						}
						break;
					}
					default: throw new InvalidDataException(nameof(trainer.Battle.BattleFormat));
				}
			}
			pkmn.TurnAction = action;
		}
		if (trainer.Battle.Trainers.All(t => t.ActionsRequired.Count == 0))
		{
			trainer.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
		}
		return true;
	}

	internal static bool AreSwitchesValid(PBETrainer trainer, IReadOnlyCollection<PBESwitchIn> switches, [NotNullWhen(false)] out string? invalidReason)
	{
		if (trainer.Battle._battleState != PBEBattleState.WaitingForSwitchIns)
		{
			throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to validate switches.");
		}
		if (trainer.SwitchInsRequired == 0)
		{
			invalidReason = "Switches were already submitted";
			return false;
		}
		if (switches.Count != trainer.SwitchInsRequired)
		{
			invalidReason = $"Invalid amount of switches submitted; required amount is {trainer.SwitchInsRequired}";
			return false;
		}
		var verified = new List<PBEBattlePokemon>(trainer.SwitchInsRequired);
		foreach (PBESwitchIn s in switches)
		{
			if (s.Position == PBEFieldPosition.None || s.Position >= PBEFieldPosition.MAX || !trainer.OwnsSpot(s.Position))
			{
				invalidReason = $"Invalid position ({s.PokemonId})";
				return false;
			}
			if (!trainer.TryGetPokemon(s.PokemonId, out PBEBattlePokemon? pkmn))
			{
				invalidReason = $"Invalid Pokémon ID ({s.PokemonId})";
				return false;
			}
			if (pkmn.HP == 0)
			{
				invalidReason = $"Pokémon {s.PokemonId} is fainted";
				return false;
			}
			if (pkmn.PBEIgnore)
			{
				invalidReason = $"Pokémon {s.PokemonId} cannot battle";
				return false;
			}
			if (pkmn.FieldPosition != PBEFieldPosition.None)
			{
				invalidReason = $"Pokémon {s.PokemonId} is already on the field";
				return false;
			}
			if (verified.Contains(pkmn))
			{
				invalidReason = $"Pokémon {s.PokemonId} was asked to be switched in multiple times";
				return false;
			}
			verified.Add(pkmn);
		}
		invalidReason = null;
		return true;
	}
	internal static bool SelectSwitchesIfValid(PBETrainer trainer, IReadOnlyCollection<PBESwitchIn> switches, [NotNullWhen(false)] out string? invalidReason)
	{
		if (!AreSwitchesValid(trainer, switches, out invalidReason))
		{
			return false;
		}
		trainer.SwitchInsRequired = 0;
		foreach (PBESwitchIn s in switches)
		{
			trainer.SwitchInQueue.Add((trainer.GetPokemon(s.PokemonId), s.Position));
		}
		if (trainer.Battle.Trainers.All(t => t.SwitchInsRequired == 0))
		{
			trainer.Battle.BattleState = PBEBattleState.ReadyToRunSwitches;
		}
		return true;
	}

	internal static bool IsFleeValid(PBETrainer trainer, [NotNullWhen(false)] out string? invalidReason)
	{
		if (trainer.Battle.BattleType != PBEBattleType.Wild)
		{
			throw new InvalidOperationException($"{nameof(BattleType)} must be {PBEBattleType.Wild} to flee.");
		}
		switch (trainer.Battle._battleState)
		{
			case PBEBattleState.WaitingForActions:
			{
				if (trainer.ActionsRequired.Count == 0)
				{
					invalidReason = "Actions were already submitted";
					return false;
				}
				PBEBattlePokemon pkmn = trainer.ActiveBattlersOrdered.First();
				if (pkmn.TempLockedMove != PBEMove.None)
				{
					invalidReason = $"Pokémon {pkmn.Id} must use {pkmn.TempLockedMove}";
					return false;
				}
				break;
			}
			case PBEBattleState.WaitingForSwitchIns:
			{
				if (trainer.SwitchInsRequired == 0)
				{
					invalidReason = "Switches were already submitted";
					return false;
				}
				break;
			}
			default: throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} or {PBEBattleState.WaitingForSwitchIns} to flee.");
		}
		invalidReason = null;
		return true;
	}
	internal static bool SelectFleeIfValid(PBETrainer trainer, [NotNullWhen(false)] out string? invalidReason)
	{
		if (!IsFleeValid(trainer, out invalidReason))
		{
			return false;
		}
		trainer.RequestedFlee = true;
		if (trainer.Battle._battleState == PBEBattleState.WaitingForActions)
		{
			trainer.ActionsRequired.Clear();
			if (trainer.Battle.Trainers.All(t => t.ActionsRequired.Count == 0))
			{
				trainer.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
			}
		}
		else // WaitingForSwitches
		{
			trainer.SwitchInsRequired = 0;
			if (trainer.Battle.Trainers.All(t => t.SwitchInsRequired == 0))
			{
				trainer.Battle.BattleState = PBEBattleState.ReadyToRunSwitches;
			}
		}
		return true;
	}
}
public sealed partial class PBETrainer
{
	public bool AreActionsValid([NotNullWhen(false)] out string? invalidReason, params PBETurnAction[] actions)
	{
		return PBEBattle.AreActionsValid(this, actions, out invalidReason);
	}
	public bool AreActionsValid(IReadOnlyCollection<PBETurnAction> actions, [NotNullWhen(false)] out string? invalidReason)
	{
		return PBEBattle.AreActionsValid(this, actions, out invalidReason);
	}
	public bool SelectActionsIfValid([NotNullWhen(false)] out string? invalidReason, params PBETurnAction[] actions)
	{
		return PBEBattle.SelectActionsIfValid(this, actions, out invalidReason);
	}
	public bool SelectActionsIfValid(IReadOnlyCollection<PBETurnAction> actions, [NotNullWhen(false)] out string? invalidReason)
	{
		return PBEBattle.SelectActionsIfValid(this, actions, out invalidReason);
	}

	public bool AreSwitchesValid([NotNullWhen(false)] out string? invalidReason, params PBESwitchIn[] switches)
	{
		return PBEBattle.AreSwitchesValid(this, switches, out invalidReason);
	}
	public bool AreSwitchesValid(IReadOnlyCollection<PBESwitchIn> switches, [NotNullWhen(false)] out string? invalidReason)
	{
		return PBEBattle.AreSwitchesValid(this, switches, out invalidReason);
	}
	public bool SelectSwitchesIfValid([NotNullWhen(false)] out string? invalidReason, params PBESwitchIn[] switches)
	{
		return PBEBattle.SelectSwitchesIfValid(this, switches, out invalidReason);
	}
	public bool SelectSwitchesIfValid(IReadOnlyCollection<PBESwitchIn> switches, [NotNullWhen(false)] out string? invalidReason)
	{
		return PBEBattle.SelectSwitchesIfValid(this, switches, out invalidReason);
	}

	public bool IsFleeValid([NotNullWhen(false)] out string? invalidReason)
	{
		return PBEBattle.IsFleeValid(this, out invalidReason);
	}
	public bool SelectFleeIfValid([NotNullWhen(false)] out string? invalidReason)
	{
		return PBEBattle.SelectFleeIfValid(this, out invalidReason);
	}
}


================================================
FILE: PokemonBattleEngine/Battle/BattleDamage.cs
================================================
using Kermalis.PokemonBattleEngine.Data;
using System;
using System.Linq;

namespace Kermalis.PokemonBattleEngine.Battle;

public sealed partial class PBEBattle
{
	/// <summary>Gets the influence a stat change has on a stat.</summary>
	/// <param name="change">The stat change.</param>
	/// <param name="forMissing">True if the stat is <see cref="PBEStat.Accuracy"/> or <see cref="PBEStat.Evasion"/>.</param>
	public static float GetStatChangeModifier(sbyte change, bool forMissing)
	{
		float baseVal = forMissing ? 3 : 2;
		float numerator = Math.Max(baseVal, baseVal + change);
		float denominator = Math.Max(baseVal, baseVal - change);
		return numerator / denominator;
	}

	// Verified: Sturdy and Substitute only activate on damaging attacks (so draining HP or liquid ooze etc can bypass sturdy)
	private ushort DealDamage(PBEBattlePokemon culprit, PBEBattlePokemon victim, int hp, bool ignoreSubstitute = true, bool ignoreSturdy = true)
	{
		if (hp < 1)
		{
			hp = 1;
		}
		if (!ignoreSubstitute && victim.Status2.HasFlag(PBEStatus2.Substitute))
		{
			ushort oldSubHP = victim.SubstituteHP;
			victim.SubstituteHP = (ushort)Math.Max(0, victim.SubstituteHP - hp);
			ushort damageAmt = (ushort)(oldSubHP - victim.SubstituteHP);
			BroadcastStatus2(victim, culprit, PBEStatus2.Substitute, PBEStatusAction.Damage);
			return damageAmt;
		}
		ushort oldHP = victim.HP;
		float oldPercentage = victim.HPPercentage;
		victim.HP = (ushort)Math.Max(0, victim.HP - hp);
		bool sturdyHappened = false, focusBandHappened = false, focusSashHappened = false;
		if (!ignoreSturdy && victim.HP == 0)
		{
			// TODO: Endure
			if (oldHP == victim.MaxHP && victim.Ability == PBEAbility.Sturdy && !culprit.HasCancellingAbility())
			{
				sturdyHappened = true;
				victim.HP = 1;
			}
			else if (victim.Item == PBEItem.FocusBand && _rand.RandomBool(10, 100))
			{
				focusBandHappened = true;
				victim.HP = 1;
			}
			else if (oldHP == victim.MaxHP && victim.Item == PBEItem.FocusSash)
			{
				focusSashHappened = true;
				victim.HP = 1;
			}
		}
		victim.UpdateHPPercentage();
		BroadcastPkmnHPChanged(victim, oldHP, oldPercentage);
		if (sturdyHappened)
		{
			BroadcastAbility(victim, culprit, PBEAbility.Sturdy, PBEAbilityAction.Damage);
			BroadcastEndure(victim);
		}
		else if (focusBandHappened)
		{
			BroadcastItem(victim, culprit, PBEItem.FocusBand, PBEItemAction.Damage);
		}
		else if (focusSashHappened)
		{
			BroadcastItem(victim, culprit, PBEItem.FocusSash, PBEItemAction.Consumed);
		}
		return (ushort)(oldHP - victim.HP);
	}
	/// <summary>Restores HP to <paramref name="pkmn"/> and broadcasts the HP changing if it changes.</summary>
	/// <param name="pkmn">The Pokémon receiving the HP.</param>
	/// <param name="hp">The amount of HP <paramref name="pkmn"/> will try to gain.</param>
	/// <returns>The amount of HP restored.</returns>
	private ushort HealDamage(PBEBattlePokemon pkmn, int hp)
	{
		if (hp < 1)
		{
			hp = 1;
		}
		ushort oldHP = pkmn.HP;
		float oldPercentage = pkmn.HPPercentage;
		pkmn.HP = (ushort)Math.Min(pkmn.MaxHP, pkmn.HP + hp); // Always try to heal at least 1 HP
		ushort healAmt = (ushort)(pkmn.HP - oldHP);
		if (healAmt > 0)
		{
			pkmn.UpdateHPPercentage();
			BroadcastPkmnHPChanged(pkmn, oldHP, oldPercentage);
		}
		return healAmt;
	}

	private float CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targets, IPBEMoveData mData, PBEType moveType)
	{
		float basePower;

		#region Get move's base power
		switch (mData.Effect)
		{
			case PBEMoveEffect.CrushGrip:
			{
				basePower = Math.Max(1, targets.Select(t => (float)mData.Power * t.HP / t.MaxHP).Average());
				break;
			}
			case PBEMoveEffect.Eruption:
			{
				basePower = Math.Max(1, mData.Power * user.HP / user.MaxHP);
				break;
			}
			case PBEMoveEffect.Flail:
			{
				int val = 48 * user.HP / user.MaxHP;
				if (val < 2)
				{
					basePower = 200;
				}
				else if (val < 4)
				{
					basePower = 150;
				}
				else if (val < 8)
				{
					basePower = 100;
				}
				else if (val < 16)
				{
					basePower = 80;
				}
				else if (val < 32)
				{
					basePower = 40;
				}
				else
				{
					basePower = 20;
				}
				break;
			}
			case PBEMoveEffect.Frustration:
			{
				basePower = Math.Max(1, (byte.MaxValue - user.Friendship) / 2.5f);
				break;
			}
			case PBEMoveEffect.GrassKnot:
			{
				basePower = targets.Select(t =>
				{
					if (t.Weight >= 200.0f)
					{
						return 120f;
					}
					else if (t.Weight >= 100.0f)
					{
						return 100f;
					}
					else if (t.Weight >= 50.0f)
					{
						return 80f;
					}
					else if (t.Weight >= 25.0f)
					{
						return 60f;
					}
					else if (t.Weight >= 10.0f)
					{
						return 40f;
					}
					return 20f;
				}).Average();
				break;
			}
			case PBEMoveEffect.HeatCrash:
			{
				basePower = targets.Select(t =>
				{
					float relative = user.Weight / t.Weight;
					if (relative < 2)
					{
						return 40f;
					}
					else if (relative < 3)
					{
						return 60f;
					}
					else if (relative < 4)
					{
						return 80f;
					}
					else if (relative < 5)
					{
						return 100f;
					}
					return 120f;
				}).Average();
				break;
			}
			case PBEMoveEffect.HiddenPower:
			{
				basePower = user.IndividualValues!.GetHiddenPowerBasePower(Settings);
				break;
			}
			case PBEMoveEffect.Magnitude:
			{
				int val = _rand.RandomInt(0, 99);
				byte magnitude;
				if (val < 5) // Magnitude 4 - 5%
				{
					magnitude = 4;
					basePower = 10;
				}
				else if (val < 15) // Magnitude 5 - 10%
				{
					magnitude = 5;
					basePower = 30;
				}
				else if (val < 35) // Magnitude 6 - 20%
				{
					magnitude = 6;
					basePower = 50;
				}
				else if (val < 65) // Magnitude 7 - 30%
				{
					magnitude = 7;
					basePower = 70;
				}
				else if (val < 85) // Magnitude 8 - 20%
				{
					magnitude = 8;
					basePower = 90;
				}
				else if (val < 95) // Magnitude 9 - 10%
				{
					magnitude = 9;
					basePower = 110;
				}
				else // Magnitude 10 - 5%
				{
					magnitude = 10;
					basePower = 150;
				}
				BroadcastMagnitude(magnitude);
				break;
			}
			case PBEMoveEffect.Punishment:
			{
				basePower = Math.Max(1, Math.Min(200, targets.Select(t => mData.Power + (20f * t.GetPositiveStatTotal())).Average()));
				break;
			}
			case PBEMoveEffect.Return:
			{
				basePower = Math.Max(1, user.Friendship / 2.5f);
				break;
			}
			case PBEMoveEffect.StoredPower:
			{
				basePower = mData.Power + (20 * user.GetPositiveStatTotal());
				break;
			}
			default:
			{
				basePower = Math.Max(1, (int)mData.Power);
				break;
			}
		}
		#endregion

		// Technician goes before any other power boosts
		if (user.Ability == PBEAbility.Technician && basePower <= 60)
		{
			basePower *= 1.5f;
		}

		#region Item-specific power boosts
		switch (moveType)
		{
			case PBEType.Bug:
			{
				switch (user.Item)
				{
					case PBEItem.InsectPlate:
					case PBEItem.SilverPowder:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.BugGem:
					{
						BroadcastItem(user, user, PBEItem.BugGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Dark:
			{
				switch (user.Item)
				{
					case PBEItem.BlackGlasses:
					case PBEItem.DreadPlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.DarkGem:
					{
						BroadcastItem(user, user, PBEItem.DarkGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Dragon:
			{
				switch (user.Item)
				{
					case PBEItem.AdamantOrb:
					{
						if (user.OriginalSpecies == PBESpecies.Dialga)
						{
							basePower *= 1.2f;
						}
						break;
					}
					case PBEItem.DracoPlate:
					case PBEItem.DragonFang:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.GriseousOrb:
					{
						if (user.OriginalSpecies == PBESpecies.Giratina && user.RevertForm == PBEForm.Giratina_Origin)
						{
							basePower *= 1.2f;
						}
						break;
					}
					case PBEItem.LustrousOrb:
					{
						if (user.OriginalSpecies == PBESpecies.Palkia)
						{
							basePower *= 1.2f;
						}
						break;
					}
					case PBEItem.DragonGem:
					{
						BroadcastItem(user, user, PBEItem.DragonGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Electric:
			{
				switch (user.Item)
				{
					case PBEItem.Magnet:
					case PBEItem.ZapPlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.ElectricGem:
					{
						BroadcastItem(user, user, PBEItem.ElectricGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Fighting:
			{
				switch (user.Item)
				{
					case PBEItem.BlackBelt:
					case PBEItem.FistPlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.FightingGem:
					{
						BroadcastItem(user, user, PBEItem.FightingGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Fire:
			{
				switch (user.Item)
				{
					case PBEItem.Charcoal:
					case PBEItem.FlamePlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.FireGem:
					{
						BroadcastItem(user, user, PBEItem.FireGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Flying:
			{
				switch (user.Item)
				{
					case PBEItem.SharpBeak:
					case PBEItem.SkyPlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.FlyingGem:
					{
						BroadcastItem(user, user, PBEItem.FlyingGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Ghost:
			{
				switch (user.Item)
				{
					case PBEItem.GriseousOrb:
					{
						if (user.OriginalSpecies == PBESpecies.Giratina && user.RevertForm == PBEForm.Giratina_Origin)
						{
							basePower *= 1.2f;
						}
						break;
					}
					case PBEItem.SpellTag:
					case PBEItem.SpookyPlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.GhostGem:
					{
						BroadcastItem(user, user, PBEItem.GhostGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Grass:
			{
				switch (user.Item)
				{
					case PBEItem.MeadowPlate:
					case PBEItem.MiracleSeed:
					case PBEItem.RoseIncense:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.GrassGem:
					{
						BroadcastItem(user, user, PBEItem.GrassGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Ground:
			{
				switch (user.Item)
				{
					case PBEItem.EarthPlate:
					case PBEItem.SoftSand:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.GroundGem:
					{
						BroadcastItem(user, user, PBEItem.GroundGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Ice:
			{
				switch (user.Item)
				{
					case PBEItem.IciclePlate:
					case PBEItem.NeverMeltIce:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.IceGem:
					{
						BroadcastItem(user, user, PBEItem.IceGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.None:
			{
				break;
			}
			case PBEType.Normal:
			{
				switch (user.Item)
				{
					case PBEItem.SilkScarf:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.NormalGem:
					{
						BroadcastItem(user, user, PBEItem.NormalGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Poison:
			{
				switch (user.Item)
				{
					case PBEItem.PoisonBarb:
					case PBEItem.ToxicPlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.PoisonGem:
					{
						BroadcastItem(user, user, PBEItem.PoisonGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Psychic:
			{
				switch (user.Item)
				{
					case PBEItem.MindPlate:
					case PBEItem.OddIncense:
					case PBEItem.TwistedSpoon:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.PsychicGem:
					{
						BroadcastItem(user, user, PBEItem.PsychicGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Rock:
			{
				switch (user.Item)
				{
					case PBEItem.HardStone:
					case PBEItem.RockIncense:
					case PBEItem.StonePlate:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.RockGem:
					{
						BroadcastItem(user, user, PBEItem.RockGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Steel:
			{
				switch (user.Item)
				{
					case PBEItem.AdamantOrb:
					{
						if (user.OriginalSpecies == PBESpecies.Dialga)
						{
							basePower *= 1.2f;
						}
						break;
					}
					case PBEItem.IronPlate:
					case PBEItem.MetalCoat:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.SteelGem:
					{
						BroadcastItem(user, user, PBEItem.SteelGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			case PBEType.Water:
			{
				switch (user.Item)
				{
					case PBEItem.LustrousOrb:
					{
						if (user.OriginalSpecies == PBESpecies.Palkia)
						{
							basePower *= 1.2f;
						}
						break;
					}
					case PBEItem.MysticWater:
					case PBEItem.SeaIncense:
					case PBEItem.SplashPlate:
					case PBEItem.WaveIncense:
					{
						basePower *= 1.2f;
						break;
					}
					case PBEItem.WaterGem:
					{
						BroadcastItem(user, user, PBEItem.WaterGem, PBEItemAction.Consumed);
						basePower *= 1.5f;
						break;
					}
				}
				break;
			}
			default: throw new ArgumentOutOfRangeException(nameof(moveType));
		}
		#endregion

		#region Move-specific power boosts
		switch (mData.Effect)
		{
			case PBEMoveEffect.Acrobatics:
			{
				if (user.Item == PBEItem.None)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.Brine:
			{
				if (Array.FindIndex(targets, t => t.HP <= t.HP / 2) != -1)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.Facade:
			{
				if (user.Status1 == PBEStatus1.Burned || user.Status1 == PBEStatus1.Paralyzed || user.Status1 == PBEStatus1.Poisoned || user.Status1 == PBEStatus1.BadlyPoisoned)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.Hex:
			{
				if (Array.FindIndex(targets, t => t.Status1 != PBEStatus1.None) != -1)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.Payback:
			{
				if (Array.FindIndex(targets, t => t.HasUsedMoveThisTurn) != -1)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.Retaliate:
			{
				if (user.Team.MonFaintedLastTurn)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.SmellingSalt:
			{
				if (Array.FindIndex(targets, t => t.Status1 == PBEStatus1.Paralyzed) != -1)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.Venoshock:
			{
				if (Array.FindIndex(targets, t => t.Status1 == PBEStatus1.Poisoned || t.Status1 == PBEStatus1.BadlyPoisoned) != -1)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.WakeUpSlap:
			{
				if (Array.FindIndex(targets, t => t.Status1 == PBEStatus1.Asleep) != -1)
				{
					basePower *= 2.0f;
				}
				break;
			}
			case PBEMoveEffect.WeatherBall:
			{
				if (ShouldDoWeatherEffects() && Weather != PBEWeather.None)
				{
					basePower *= 2.0f;
				}
				break;
			}
		}
		#endregion

		#region Weather-specific power boosts
		if (ShouldDoWeatherEffects())
		{
			switch (Weather)
			{
				case PBEWeather.HarshSunlight:
				{
					if (moveType == PBEType.Fire)
					{
						basePower *= 1.5f;
					}
					else if (moveType == PBEType.Water)
					{
						basePower *= 0.5f;
					}
					break;
				}
				case PBEWeather.Rain:
				{
					if (moveType == PBEType.Water)
					{
						basePower *= 1.5f;
					}
					else if (moveType == PBEType.Fire)
					{
						basePower *= 0.5f;
					}
					break;
				}
				case PBEWeather.Sandstorm:
				{
					if (user.Ability == PBEAbility.SandForce && (moveType == PBEType.Rock || moveType == PBEType.Ground || moveType == PBEType.Steel))
					{
						basePower *= 1.3f;
					}
					break;
				}
			}
		}
		#endregion

		#region Other power boosts
		if (user.Status2.HasFlag(PBEStatus2.HelpingHand))
		{
			basePower *= 1.5f;
		}
		if (user.Ability == PBEAbility.FlareBoost && mData.Category == PBEMoveCategory.Special && user.Status1 == PBEStatus1.Burned)
		{
			basePower *= 1.5f;
		}
		if (user.Ability == PBEAbility.ToxicBoost && mData.Category == PBEMoveCategory.Physical && (user.Status1 == PBEStatus1.Poisoned || user.Status1 == PBEStatus1.BadlyPoisoned))
		{
			basePower *= 1.5f;
		}
		if (user.Item == PBEItem.LifeOrb)
		{
			basePower *= 1.3f;
		}
		if (user.Ability == PBEAbility.IronFist && mData.Flags.HasFlag(PBEMoveFlag.AffectedByIronFist))
		{
			basePower *= 1.2f;
		}
		if (user.Ability == PBEAbility.Reckless && mData.Flags.HasFlag(PBEMoveFlag.AffectedByReckless))
		{
			basePower *= 1.2f;
		}
		if (user.Item == PBEItem.MuscleBand && mData.Category == PBEMoveCategory.Physical)
		{
			basePower *= 1.1f;
		}
		if (user.Item == PBEItem.WiseGlasses && mData.Category == PBEMoveCategory.Special)
		{
			basePower *= 1.1f;
		}
		#endregion

		return basePower;
	}
	private float CalculateDamageMultiplier(PBEBattlePokemon user, PBEBattlePokemon target, IPBEMoveData mData, PBEType moveType, PBEResult moveResult, bool criticalHit)
	{
		float damageMultiplier = 1;
		if (target.Status2.HasFlag(PBEStatus2.Airborne) && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageAirborne))
		{
			damageMultiplier *= 2.0f;
		}
		if (target.Minimize_Used && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageMinimized))
		{
			damageMultiplier *= 2.0f;
		}
		if (target.Status2.HasFlag(PBEStatus2.Underground) && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderground))
		{
			damageMultiplier *= 2.0f;
		}
		if (target.Status2.HasFlag(PBEStatus2.Underwater) && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderwater))
		{
			damageMultiplier *= 2.0f;
		}

		if (criticalHit)
		{
			damageMultiplier *= Settings.CritMultiplier;
			if (user.Ability == PBEAbility.Sniper)
			{
				damageMultiplier *= 1.5f;
			}
		}
		else if (user.Ability != PBEAbility.Infiltrator)
		{
			if ((target.Team.TeamStatus.HasFlag(PBETeamStatus.Reflect) && mData.Category == PBEMoveCategory.Physical)
				|| (target.Team.TeamStatus.HasFlag(PBETeamStatus.LightScreen) && mData.Category == PBEMoveCategory.Special))
			{
				if (target.Team.NumPkmnOnField == 1)
				{
					damageMultiplier *= 0.5f;
				}
				else
				{
					damageMultiplier *= 0.66f;
				}
			}
		}

		switch (moveResult)
		{
			case PBEResult.NotVeryEffective_Type:
			{
				if (user.Ability == PBEAbility.TintedLens)
				{
					damageMultiplier *= 2.0f;
				}
				break;
			}
			case PBEResult.SuperEffective_Type:
			{
				if ((target.Ability == PBEAbility.Filter || target.Ability == PBEAbility.SolidRock) && !user.HasCancellingAbility())
				{
					damageMultiplier *= 0.75f;
				}
				if (user.Item == PBEItem.ExpertBelt)
				{
					damageMultiplier *= 1.2f;
				}
				break;
			}
		}
		if (user.ReceivesSTAB(moveType))
		{
			if (user.Ability == PBEAbility.Adaptability)
			{
				damageMultiplier *= 2.0f;
			}
			else
			{
				damageMultiplier *= 1.5f;
			}
		}
		if (mData.Category == PBEMoveCategory.Physical && user.Status1 == PBEStatus1.Burned && user.Ability != PBEAbility.Guts)
		{
			damageMultiplier *= 0.5f;
		}
		if (moveType == PBEType.Fire && target.Ability == PBEAbility.Heatproof && !user.HasCancellingAbility())
		{
			damageMultiplier *= 0.5f;
		}

		return damageMultiplier;
	}

	private float CalculateAttack(PBEBattlePokemon user, PBEBattlePokemon target, PBEType moveType, float initialAttack)
	{
		float attack = initialAttack;

		if (user.Ability == PBEAbility.HugePower || user.Ability == PBEAbility.PurePower)
		{
			attack *= 2.0f;
		}
		if (user.Item == PBEItem.ThickClub && (user.OriginalSpecies == PBESpecies.Cubone || user.OriginalSpecies == PBESpecies.Marowak))
		{
			attack *= 2.0f;
		}
		if (user.Item == PBEItem.LightBall && user.OriginalSpecies == PBESpecies.Pikachu)
		{
			attack *= 2.0f;
		}
		if (moveType == PBEType.Bug && user.Ability == PBEAbility.Swarm && user.HP <= user.MaxHP / 3)
		{
			attack *= 1.5f;
		}
		if (moveType == PBEType.Fire && user.Ability == PBEAbility.Blaze && user.HP <= user.MaxHP / 3)
		{
			attack *= 1.5f;
		}
		if (moveType == PBEType.Grass && user.Ability == PBEAbility.Overgrow && user.HP <= user.MaxHP / 3)
		{
			attack *= 1.5f;
		}
		if (moveType == PBEType.Water && user.Ability == PBEAbility.Torrent && user.HP <= user.MaxHP / 3)
		{
			attack *= 1.5f;
		}
		if (user.Ability == PBEAbility.Hustle)
		{
			attack *= 1.5f;
		}
		if (user.Ability == PBEAbility.Guts && user.Status1 != PBEStatus1.None)
		{
			attack *= 1.5f;
		}
		if (user.Item == PBEItem.ChoiceBand)
		{
			attack *= 1.5f;
		}
		if (!user.HasCancellingAbility() && ShouldDoWeatherEffects() && Weather == PBEWeather.HarshSunlight && user.Team.ActiveBattlers.FindIndex(p => p.Ability == PBEAbility.FlowerGift) != -1)
		{
			attack *= 1.5f;
		}
		if ((moveType == PBEType.Fire || moveType == PBEType.Ice) && target.Ability == PBEAbility.ThickFat && !user.HasCancellingAbility())
		{
			attack *= 0.5f;
		}
		if (user.Ability == PBEAbility.Defeatist && user.HP <= user.MaxHP / 2)
		{
			attack *= 0.5f;
		}
		if (user.Ability == PBEAbility.SlowStart && user.SlowStart_HinderTurnsLeft > 0)
		{
			attack *= 0.5f;
		}

		return attack;
	}
	private static float CalculateDefense(PBEBattlePokemon user, PBEBattlePokemon target, float initialDefense)
	{
		float defense = initialDefense;

		if (target.Item == PBEItem.MetalPowder && target.OriginalSpecies == PBESpecies.Ditto && !target.Status2.HasFlag(PBEStatus2.Transformed))
		{
			defense *= 2.0f;
		}
		if (target.Ability == PBEAbility.MarvelScale && target.Status1 != PBEStatus1.None && !user.HasCancellingAbility())
		{
			defense *= 1.5f;
		}
		if (target.Item == PBEItem.Eviolite && PBEDataProvider.Instance.HasEvolutions(target.OriginalSpecies, target.RevertForm))
		{
			defense *= 1.5f;
		}

		return defense;
	}
	private float CalculateSpAttack(PBEBattlePokemon user, PBEBattlePokemon target, PBEType moveType, float initialSpAttack)
	{
		float spAttack = initialSpAttack;

		if (user.Item == PBEItem.DeepSeaTooth && user.OriginalSpecies == PBESpecies.Clamperl)
		{
			spAttack *= 2.0f;
		}
		if (user.Item == PBEItem.LightBall && user.OriginalSpecies == PBESpecies.Pikachu)
		{
			spAttack *= 2.0f;
		}
		if (moveType == PBEType.Bug && user.Ability == PBEAbility.Swarm && user.HP <= user.MaxHP / 3)
		{
			spAttack *= 1.5f;
		}
		if (moveType == PBEType.Fire && user.Ability == PBEAbility.Blaze && user.HP <= user.MaxHP / 3)
		{
			spAttack *= 1.5f;
		}
		if (moveType == PBEType.Grass && user.Ability == PBEAbility.Overgrow && user.HP <= user.MaxHP / 3)
		{
			spAttack *= 1.5f;
		}
		if (moveType == PBEType.Water && user.Ability == PBEAbility.Torrent && user.HP <= user.MaxHP / 3)
		{
			spAttack *= 1.5f;
		}
		if (ShouldDoWeatherEffects() && Weather == PBEWeather.HarshSunlight && user.Ability == PBEAbility.SolarPower)
		{
			spAttack *= 1.5f;
		}
		if (user.Item == PBEItem.SoulDew && (user.OriginalSpecies == PBESpecies.Latias || user.OriginalSpecies == PBESpecies.Latios))
		{
			spAttack *= 1.5f;
		}
		if (user.Item == PBEItem.ChoiceSpecs)
		{
			spAttack *= 1.5f;
		}
		if ((user.Ability == PBEAbility.Minus || user.Ability == PBEAbility.Plus) && user.Team.ActiveBattlers.FindIndex(p => p != user && (p.Ability == PBEAbility.Minus || p.Ability == PBEAbility.Plus)) != -1)
		{
			spAttack *= 1.5f;
		}
		if ((moveType == PBEType.Fire || moveType == PBEType.Ice) && target.Ability == PBEAbility.ThickFat && !user.HasCancellingAbility())
		{
			spAttack *= 0.5f;
		}
		if (user.Ability == PBEAbility.Defeatist && user.HP <= user.MaxHP / 2)
		{
			spAttack *= 0.5f;
		}

		return spAttack;
	}
	private float CalculateSpDefense(PBEBattlePokemon user, PBEBattlePokemon target, float initialSpDefense)
	{
		float spDefense = initialSpDefense;

		if (target.Item == PBEItem.DeepSeaScale && target.OriginalSpecies == PBESpecies.Clamperl)
		{
			spDefense *= 2.0f;
		}
		if (target.Item == PBEItem.SoulDew && (target.OriginalSpecies == PBESpecies.Latias || target.OriginalSpecies == PBESpecies.Latios))
		{
			spDefense *= 1.5f;
		}
		if (target.Item == PBEItem.Eviolite && PBEDataProvider.Instance.HasEvolutions(target.OriginalSpecies, target.RevertForm))
		{
			spDefense *= 1.5f;
		}
		if (ShouldDoWeatherEffects())
		{
			if (Weather == PBEWeather.Sandstorm && target.HasType(PBEType.Rock))
			{
				spDefense *= 1.5f;
			}
			if (!user.HasCancellingAbility() && Weather == PBEWeather.HarshSunlight && target.Team.ActiveBattlers.FindIndex(p => p.Ability == PBEAbility.FlowerGift) != -1)
			{
				spDefense *= 1.5f;
			}
		}

		return spDefense;
	}

	private int CalculateDamage(PBEBattlePokemon user, float a, float d, float basePower)
	{
		float damage;
		damage = (2 * user.Level / 5) + 2;
		damage = damage * a * basePower / d;
		damage /= 50;
		damage += 2;
		return (int)(damage * ((100f - _rand.RandomInt(0, 15)) / 100));
	}
	private int CalculateConfusionDamage(PBEBattlePokemon pkmn)
	{
		// Verified: Unaware has no effect on confusion damage
		float m = GetStatChangeModifier(pkmn.AttackChange, false);
		float a = CalculateAttack(pkmn, pkmn, PBEType.None, pkmn.Attack * m);
		m = GetStatChangeModifier(pkmn.DefenseChange, false);
		float d = CalculateDefense(pkmn, pkmn, pkmn.Defense * m);
		return CalculateDamage(pkmn, a, d, 40);
	}
	private int CalculateDamage(PBEBattlePokemon user, PBEBattlePokemon target, IPBEMoveData mData, PBEType moveType, float basePower, bool criticalHit)
	{
		PBEBattlePokemon aPkmn;
		PBEMoveCategory aCat = mData.Category, dCat;
		switch (mData.Effect)
		{
			case PBEMoveEffect.FoulPlay:
			{
				aPkmn = target;
				dCat = aCat;
				break;
			}
			case PBEMoveEffect.Psyshock:
			{
				aPkmn = user;
				dCat = PBEMoveCategory.Physical;
				break;
			}
			default:
			{
				aPkmn = user;
				dCat = aCat;
				break;
			}
		}

		bool ignoreA = user != target && target.Ability == PBEAbility.Unaware && !user.HasCancellingAbility();
		bool ignoreD = user != target && (mData.Effect == PBEMoveEffect.ChipAway || user.Ability == PBEAbility.Unaware);
		float a, d;
		if (aCat == PBEMoveCategory.Physical)
		{
			float m = ignoreA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, aPkmn.AttackChange) : aPkmn.AttackChange, false);
			a = CalculateAttack(user, target, moveType, aPkmn.Attack * m);
		}
		else
		{
			float m = ignoreA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, aPkmn.SpAttackChange) : aPkmn.SpAttackChange, false);
			a = CalculateSpAttack(user, target, moveType, aPkmn.SpAttack * m);
		}
		if (dCat == PBEMoveCategory.Physical)
		{
			float m = ignoreD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false);
			d = CalculateDefense(user, target, target.Defense * m);
		}
		else
		{
			float m = ignoreD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.SpDefenseChange) : target.SpDefenseChange, false);
			d = CalculateSpDefense(user, target, target.SpDefense * m);
		}

		return CalculateDamage(user, a, d, basePower);
	}
}


================================================
FILE: PokemonBattleEngine/Battle/BattleEffects.cs
================================================
using Kermalis.PokemonBattleEngine.Data;
using Kermalis.PokemonBattleEngine.Data.Utils;
using Kermalis.PokemonBattleEngine.Packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Kermalis.PokemonBattleEngine.Battle;

public sealed partial class PBEBattle
{
	private bool _calledFromOtherMove = false;

	private void DoSwitchInEffects(IEnumerable<PBEBattlePokemon> battlers, PBEBattlePokemon? forcedInBy = null)
	{
		// Set EXP Seens first
		foreach (PBEBattlePokemon pkmn in battlers)
		{
			PBETeam opTeam = pkmn.Team.OpposingTeam;
			foreach (PBEBattlePokemon op in opTeam.ActiveBattlers)
			{
				op.AddEXPPokemon(pkmn);
				pkmn.AddEXPPokemon(op);
			}
		}

		IEnumerable<PBEBattlePokemon> order = GetActingOrder(battlers, true);

		foreach (PBEBattlePokemon pkmn in order)
		{
			bool grounded = pkmn.IsGrounded(forcedInBy) == PBEResult.Success;
			// Verified: (Spikes/StealthRock/ToxicSpikes in the order they were applied) before ability
			if (grounded && pkmn.Team.TeamStatus.HasFlag(PBETeamStatus.Spikes))
			{
				BroadcastTeamStatusDamage(pkmn.Team, PBETeamStatus.Spikes, pkmn);
				DealDamage(pkmn, pkmn, (int)(pkmn.MaxHP / (10.0 - (2 * pkmn.Team.SpikeCount))));
				if (FaintCheck(pkmn))
				{
					continue;
				}
				LowHPBerryCheck(pkmn, forcedToEatBy: forcedInBy);
			}
			if (pkmn.Team.TeamStatus.HasFlag(PBETeamStatus.StealthRock))
			{
				BroadcastTeamStatusDamage(pkmn.Team, PBETeamStatus.StealthRock, pkmn);
				DealDamage(pkmn, pkmn, (int)(pkmn.MaxHP * PBETypeEffectiveness.GetStealthRockMultiplier(pkmn.Type1, pkmn.Type2)));
				if (FaintCheck(pkmn))
				{
					continue;
				}
				LowHPBerryCheck(pkmn, forcedToEatBy: forcedInBy);
			}
			if (grounded && pkmn.Team.TeamStatus.HasFlag(PBETeamStatus.ToxicSpikes))
			{
				if (pkmn.HasType(PBEType.Poison))
				{
					pkmn.Team.ToxicSpikeCount = 0;
					BroadcastTeamStatus(pkmn.Team, PBETeamStatus.ToxicSpikes, PBETeamStatusAction.Cleared);
				}
				else if (pkmn.IsPoisonPossible(forcedInBy, ignoreSubstitute: true) == PBEResult.Success)
				{
					if (pkmn.Team.ToxicSpikeCount == 1)
					{
						pkmn.Status1 = PBEStatus1.Poisoned;
					}
					else
					{
						pkmn.Status1 = PBEStatus1.BadlyPoisoned;
						pkmn.Status1Counter = 1;
					}
					BroadcastStatus1(pkmn, pkmn, pkmn.Status1, PBEStatusAction.Added);
					// Immunity activates in ActivateAbility() below
				}
			}

			ActivateAbility(pkmn, true);
		}

		// Verified: Castform/Cherrim transformation goes last. Even if multiple weather abilities activate, they will not change until every ability has been activated
		CastformCherrimCheck(order);
	}
	private void DoPostHitEffects(PBEBattlePokemon user, PBEBattlePokemon victim, IPBEMoveData mData, PBEType moveType)
	{
		IllusionBreak(victim, user); // Verified: Illusion before Rocky Helmet
		if (victim.HP > 0 && victim.Ability == PBEAbility.Justified && moveType == PBEType.Dark) // Verified: Justified before Rocky Helmet
		{
			BroadcastAbility(victim, user, PBEAbility.Justified, PBEAbilityAction.Damage);
			ApplyStatChangeIfPossible(victim, victim, PBEStat.Attack, +1);
		}
		if (victim.HP > 0 && victim.Ability == PBEAbility.Rattled && (moveType == PBEType.Bug || moveType == PBEType.Dark || moveType == PBEType.Ghost)) // Verified: Rattled before Rocky Helmet
		{
			BroadcastAbility(victim, user, PBEAbility.Rattled, PBEAbilityAction.Damage);
			ApplyStatChangeIfPossible(victim, victim, PBEStat.Speed, +1);
		}
		if (victim.HP > 0 && victim.Ability == PBEAbility.WeakArmor && mData.Category == PBEMoveCategory.Physical) // Verified: Weak Armor before Rocky Helmet
		{
			BroadcastAbility(victim, user, PBEAbility.WeakArmor, PBEAbilityAction.Damage);
			ApplyStatChangeIfPossible(victim, victim, PBEStat.Defense, -1);
			ApplyStatChangeIfPossible(victim, victim, PBEStat.Speed, +1);
		}

		if (mData.Flags.HasFlag(PBEMoveFlag.MakesContact))
		{
			if (user.HP > 0 && victim.Ability == PBEAbility.Mummy && user.Ability != PBEAbility.Multitype && user.Ability != PBEAbility.Mummy && user.Ability != PBEAbility.ZenMode)
			{
				BroadcastAbility(victim, user, PBEAbility.Mummy, PBEAbilityAction.Damage);
				SetAbility(victim, user, PBEAbility.Mummy);
			}
			if (user.HP > 0 && (victim.Ability == PBEAbility.IronBarbs || victim.Ability == PBEAbility.RoughSkin))
			{
				BroadcastAbility(victim, user, victim.Ability, PBEAbilityAction.Damage);
				DealDamage(victim, user, user.MaxHP / 8);
				if (!FaintCheck(user))
				{
					LowHPBerryCheck(user);
				}
			}
			// Verified: Cute Charm can activate when victim is about to faint
			if (user.HP > 0 && victim.Ability == PBEAbility.CuteCharm && user.IsAttractionPossible(victim) == PBEResult.Success && GetManipulableChance(victim, 30))
			{
				BroadcastAbility(victim, user, PBEAbility.CuteCharm, PBEAbilityAction.ChangedStatus);
				CauseInfatuation(user, victim);
			}
			if (user.HP > 0 && victim.Ability == PBEAbility.EffectSpore && user.Status1 == PBEStatus1.None)
			{
				// Commented in case the Rainbow affects Effect Spore
				//int randomNum = PBERandom.RandomInt(0, 99);
				if (GetManipulableChance(victim, 30))
				{
					// Spaghetti code taken from the assembly in generation 5 games
					PBEStatus1 status = PBEStatus1.None;
					int randomNum = _rand.RandomInt(0, 29);
					if (randomNum <= 20)
					{
						if (randomNum > 10) // 11-20 (10%)
						{
							// TODO: Can it really not paralyze electric? I thought that's gen 6+
							if (!user.HasType(PBEType.Electric) && user.IsParalysisPossible(victim) == PBEResult.Success)
							{
								status = PBEStatus1.Paralyzed;
							}
						}
						else // 0-10 (11%)
						{
							if (user.IsSleepPossible(victim) == PBEResult.Success)
							{
								status = PBEStatus1.Asleep;
							}
						}
					}
					else // 21-29 (9%)
					{
						if (user.IsPoisonPossible(victim) == PBEResult.Success)
						{
							status = PBEStatus1.Poisoned;
						}
					}
					if (status != PBEStatus1.None)
					{
						BroadcastAbility(victim, user, PBEAbility.EffectSpore, PBEAbilityAction.ChangedStatus);
						user.Status1 = status;
						if (status == PBEStatus1.Asleep)
						{
							SetSleepTurns(user, Settings.SleepMinTurns, Settings.SleepMaxTurns);
						}
						user.Status1Counter = 0;
						BroadcastStatus1(user, victim, status, PBEStatusAction.Added);
						AntiStatusAbilityCheck(user);
					}
				}
			}
			if (user.HP > 0 && victim.Ability == PBEAbility.FlameBody && user.IsBurnPossible(victim) == PBEResult.Success && GetManipulableChance(victim, 30))
			{
				BroadcastAbility(victim, user, PBEAbility.FlameBody, PBEAbilityAction.ChangedStatus);
				user.Status1 = PBEStatus1.Burned;
				BroadcastStatus1(user, victim, PBEStatus1.Burned, PBEStatusAction.Added);
				AntiStatusAbilityCheck(user);
			}
			if (user.HP > 0 && victim.Ability == PBEAbility.PoisonPoint && user.IsPoisonPossible(victim) == PBEResult.Success && GetManipulableChance(victim, 30))
			{
				BroadcastAbility(victim, user, PBEAbility.PoisonPoint, PBEAbilityAction.ChangedStatus);
				user.Status1 = PBEStatus1.Poisoned;
				BroadcastStatus1(user, victim, PBEStatus1.Poisoned, PBEStatusAction.Added);
				AntiStatusAbilityCheck(user);
			}
			if (user.HP > 0 && victim.Ability == PBEAbility.Static && user.IsParalysisPossible(victim) == PBEResult.Success && GetManipulableChance(victim, 30))
			{
				BroadcastAbility(victim, user, PBEAbility.Static, PBEAbilityAction.ChangedStatus);
				user.Status1 = PBEStatus1.Paralyzed;
				BroadcastStatus1(user, victim, PBEStatus1.Paralyzed, PBEStatusAction.Added);
				AntiStatusAbilityCheck(user);
			}
			// Verified: Above abilities before Rocky Helmet
			if (user.HP > 0 && victim.Item == PBEItem.RockyHelmet)
			{
				BroadcastItem(victim, user, PBEItem.RockyHelmet, PBEItemAction.Damage);
				DealDamage(victim, user, user.MaxHP / 6);
				if (!FaintCheck(user))
				{
					LowHPBerryCheck(user);
				}
			}
		}
	}
	private void DoPostAttackedEffects(PBEBattlePokemon user, List<PBEAttackVictim> allies, List<PBEAttackVictim> foes, bool doLifeOrb,
		int? recoilDamage = null,
		PBEType colorChangeType = PBEType.None)
	{
		#region User
		if (user.HP > 0)
		{
			// Verified: Recoil before LifeOrb
			// Verified: Recoil calls berry check directly, and both can faint here
			if (recoilDamage is not null)
			{
				BroadcastRecoil(user);
				DealDamage(user, user, recoilDamage.Value);
				if (!FaintCheck(user))
				{
					LowHPBerryCheck(user);
				}
			}
			if (user.HP > 0 && doLifeOrb && user.Item == PBEItem.LifeOrb)
			{
				BroadcastItem(user, user, PBEItem.LifeOrb, PBEItemAction.Damage);
				DealDamage(user, user, user.MaxHP / 10);
				FaintCheck(user); // No berry check because we are holding Life Orb
			}
		}
		#endregion

		#region Victims
		void DoColorChange(IEnumerable<PBEBattlePokemon> order)
		{
			foreach (PBEBattlePokemon pkmn in order)
			{
				if (pkmn.Ability == PBEAbility.ColorChange && !pkmn.HasType(colorChangeType))
				{
					BroadcastAbility(pkmn, pkmn, PBEAbility.ColorChange, PBEAbilityAction.ChangedAppearance);
					BroadcastTypeChanged(pkmn, colorChangeType, PBEType.None);
				}
			}
		}

		IEnumerable<PBEBattlePokemon> a = allies.Select(v => v.Pkmn).Where(p => p.HP > 0);
		IEnumerable<PBEBattlePokemon> f = foes.Select(v => v.Pkmn).Where(p => p.HP > 0);
		// Verified: ColorChange (foes, allies) before Berry
		if (colorChangeType != PBEType.None)
		{
			DoColorChange(f);
			DoColorChange(a);
		}
		// Verified: Berry (allies, foes) before AntiStatusAbility
		LowHPBerryCheck(a, forcedToEatBy: user);
		LowHPBerryCheck(f, forcedToEatBy: user);
		// Verified: AntiStatusAbility (allies, foes)
		AntiStatusAbilityCheck(a); // Heal a status that was given with the user's Mold Breaker
		AntiStatusAbilityCheck(f);
		#endregion
	}
	private void DoTurnEndedEffects()
	{
		IEnumerable<PBEBattlePokemon> order = GetActingOrder(ActiveBattlers, true);
		// Verified: Weather stops before doing damage
		if (Weather != PBEWeather.None && WeatherCounter > 0)
		{
			WeatherCounter--;
			if (WeatherCounter == 0)
			{
				PBEWeather w = Weather;
				Weather = PBEWeather.None;
				BroadcastWeather(w, PBEWeatherAction.Ended);
				CastformCherrimCheck(order);
			}
		}
		// Verified: Hailstorm/Sandstorm/IceBody/RainDish/SolarPower before all
		if (Weather != PBEWeather.None && ShouldDoWeatherEffects())
		{
			foreach (PBEBattlePokemon pkmn in order)
			{
				if (pkmn.HP == 0)
				{
					continue;
				}
				switch (Weather)
				{
					case PBEWeather.Hailstorm:
					{
						if (pkmn.Ability == PBEAbility.IceBody)
						{
							if (pkmn.HP < pkmn.MaxHP)
							{
								BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.RestoredHP);
								HealDamage(pkmn, pkmn.MaxHP / Settings.IceBodyHealDenominator);
							}
						}
						else if (!pkmn.HasType(PBEType.Ice)
							&& pkmn.Ability != PBEAbility.Overcoat
							&& pkmn.Ability != PBEAbility.SnowCloak)
						{
							BroadcastWeatherDamage(PBEWeather.Hailstorm, pkmn);
							DealDamage(pkmn, pkmn, pkmn.MaxHP / Settings.HailDamageDenominator);
							if (!FaintCheck(pkmn))
							{
								LowHPBerryCheck(pkmn);
							}
						}
						break;
					}
					case PBEWeather.HarshSunlight:
					{
						if (pkmn.Ability == PBEAbility.SolarPower)
						{
							BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Damage);
							DealDamage(pkmn, pkmn, pkmn.MaxHP / 8);
							if (!FaintCheck(pkmn))
							{
								LowHPBerryCheck(pkmn);
							}
						}
						break;
					}
					case PBEWeather.Rain:
					{
						if (pkmn.Ability == PBEAbility.RainDish && pkmn.HP < pkmn.MaxHP)
						{
							BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.RestoredHP);
							HealDamage(pkmn, pkmn.MaxHP / 16);
						}
						break;
					}
					case PBEWeather.Sandstorm:
					{
						if (!pkmn.HasType(PBEType.Rock)
							&& !pkmn.HasType(PBEType.Ground)
							&& !pkmn.HasType(PBEType.Steel)
							&& pkmn.Ability != PBEAbility.Overcoat
							&& pkmn.Ability != PBEAbility.SandForce
							&& pkmn.Ability != PBEAbility.SandRush
							&& pkmn.Ability != PBEAbility.SandVeil
							&& !pkmn.Status2.HasFlag(PBEStatus2.Underground)
							&& !pkmn.Status2.HasFlag(PBEStatus2.Underwater))
						{
							BroadcastWeatherDamage(PBEWeather.Sandstorm, pkmn);
							DealDamage(pkmn, pkmn, pkmn.MaxHP / Settings.SandstormDamageDenominator);
							if (!FaintCheck(pkmn))
							{
								LowHPBerryCheck(pkmn);
							}
						}
						break;
					}
				}
			}
		}

		// Verified: Healer/ShedSkin/BlackSludge/Leftovers before LeechSeed
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0)
			{
				continue;
			}
			switch (pkmn.Ability)
			{
				case PBEAbility.Healer:
				{
					foreach (PBEBattlePokemon ally in GetRuntimeSurrounding(pkmn, true, false))
					{
						// TODO: #265
						if (ally.Status1 != PBEStatus1.None && GetManipulableChance(pkmn, 30))
						{
							BroadcastAbility(pkmn, ally, pkmn.Ability, PBEAbilityAction.ChangedStatus);
							PBEStatus1 status1 = ally.Status1;
							ally.Status1 = PBEStatus1.None;
							ally.Status1Counter = 0;
							ally.SleepTurns = 0;
							BroadcastStatus1(ally, pkmn, status1, PBEStatusAction.Cleared);
							if (status1 == PBEStatus1.Asleep)
							{
								CureNightmare(ally, pkmn);
							}
						}
					}
					break;
				}
				case PBEAbility.ShedSkin:
				{
					if (pkmn.Status1 != PBEStatus1.None && GetManipulableChance(pkmn, 30))
					{
						BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
						PBEStatus1 status1 = pkmn.Status1;
						pkmn.Status1 = PBEStatus1.None;
						pkmn.Status1Counter = 0;
						pkmn.SleepTurns = 0;
						BroadcastStatus1(pkmn, pkmn, status1, PBEStatusAction.Cleared);
						if (status1 == PBEStatus1.Asleep)
						{
							CureNightmare(pkmn, pkmn);
						}
					}
					break;
				}
			}
			switch (pkmn.Item)
			{
				case PBEItem.BlackSludge:
				{
					if (!pkmn.HasType(PBEType.Poison))
					{
						BroadcastItem(pkmn, pkmn, pkmn.Item, PBEItemAction.Damage);
						DealDamage(pkmn, pkmn, pkmn.MaxHP / Settings.BlackSludgeDamageDenominator);
						FaintCheck(pkmn); // No need to call HealingBerryCheck() because if you are holding BlackSludge you are not holding a healing berry
					}
					else if (pkmn.HP < pkmn.MaxHP)
					{
						BroadcastItem(pkmn, pkmn, pkmn.Item, PBEItemAction.RestoredHP);
						HealDamage(pkmn, pkmn.MaxHP / Settings.BlackSludgeHealDenominator);
					}
					break;
				}
				case PBEItem.Leftovers:
				{
					if (pkmn.HP < pkmn.MaxHP)
					{
						BroadcastItem(pkmn, pkmn, pkmn.Item, PBEItemAction.RestoredHP);
						HealDamage(pkmn, pkmn.MaxHP / Settings.LeftoversHealDenominator);
					}
					break;
				}
			}
		}

		// Verified: LeechSeed before Status1/PoisonHeal
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0 || !pkmn.Status2.HasFlag(PBEStatus2.LeechSeed))
			{
				continue;
			}
			if (!pkmn.SeededTeam!.TryGetPokemon(pkmn.SeededPosition, out PBEBattlePokemon? sucker))
			{
				continue;
			}
			BroadcastStatus2(pkmn, sucker, PBEStatus2.LeechSeed, PBEStatusAction.Damage);
			int restoreAmt = DealDamage(sucker, pkmn, pkmn.MaxHP / Settings.LeechSeedDenominator);

			// In the games, the pkmn faints after taking damage (before liquid ooze/heal)
			// We cannot have it faint and then still broadcast ability like the games, similar to why we can't faint before Explosion
			// The faint order should be maintained, though, so the correct winner can be chosen
			ApplyBigRoot(pkmn, ref restoreAmt);
			if (pkmn.Ability == PBEAbility.LiquidOoze)
			{
				BroadcastAbility(pkmn, sucker, PBEAbility.LiquidOoze, PBEAbilityAction.Damage);
				DealDamage(pkmn, sucker, restoreAmt);
				if (!FaintCheck(pkmn))
				{
					LowHPBerryCheck(pkmn);
				}
				if (!FaintCheck(sucker))
				{
					LowHPBerryCheck(sucker);
				}
			}
			else
			{
				if (!FaintCheck(pkmn))
				{
					LowHPBerryCheck(pkmn);
				}
				HealDamage(sucker, restoreAmt);
			}
		}

		// Verified: Status1/PoisonHeal before Curse
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0)
			{
				continue;
			}
			switch (pkmn.Status1)
			{
				case PBEStatus1.BadlyPoisoned:
				case PBEStatus1.Poisoned:
				{
					if (pkmn.Ability != PBEAbility.PoisonHeal)
					{
						BroadcastStatus1(pkmn, pkmn, pkmn.Status1, PBEStatusAction.Damage);
						int damage = pkmn.Status1 == PBEStatus1.BadlyPoisoned
									? pkmn.MaxHP * pkmn.Status1Counter / Settings.ToxicDamageDenominator
									: pkmn.MaxHP / Settings.PoisonDamageDenominator;
						DealDamage(pkmn, pkmn, damage);
						if (!FaintCheck(pkmn))
						{
							LowHPBerryCheck(pkmn);
						}
					}
					else if (pkmn.HP < pkmn.MaxHP)
					{
						BroadcastAbility(pkmn, pkmn, PBEAbility.PoisonHeal, PBEAbilityAction.RestoredHP);
						HealDamage(pkmn, pkmn.MaxHP / 8);
					}
					if (pkmn.Status1 == PBEStatus1.BadlyPoisoned)
					{
						pkmn.Status1Counter++; // Counter still increments if PoisonHeal exists
					}
					break;
				}
				case PBEStatus1.Burned:
				{
					BroadcastStatus1(pkmn, pkmn, pkmn.Status1, PBEStatusAction.Damage);
					int damage = pkmn.MaxHP / Settings.BurnDamageDenominator;
					if (pkmn.Ability == PBEAbility.Heatproof)
					{
						damage /= 2;
					}
					DealDamage(pkmn, pkmn, damage);
					if (!FaintCheck(pkmn))
					{
						LowHPBerryCheck(pkmn);
					}
					break;
				}
			}
		}

		// Verified: Nightmare before Curse, not same loop
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0 || !pkmn.Status2.HasFlag(PBEStatus2.Nightmare))
			{
				continue;
			}
			BroadcastStatus2(pkmn, pkmn, PBEStatus2.Nightmare, PBEStatusAction.Damage);
			DealDamage(pkmn, pkmn, pkmn.MaxHP / 4);
			if (!FaintCheck(pkmn))
			{
				LowHPBerryCheck(pkmn);
			}
		}

		// Verified: Curse before MagnetRise
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0 || !pkmn.Status2.HasFlag(PBEStatus2.Cursed))
			{
				continue;
			}
			BroadcastStatus2(pkmn, pkmn, PBEStatus2.Cursed, PBEStatusAction.Damage);
			DealDamage(pkmn, pkmn, pkmn.MaxHP / Settings.CurseDenominator);
			if (!FaintCheck(pkmn))
			{
				LowHPBerryCheck(pkmn);
			}
		}

		// Verified: MagnetRise before Abilities/Orbs
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0 || !pkmn.Status2.HasFlag(PBEStatus2.MagnetRise) || pkmn.MagnetRiseTurns == 0)
			{
				continue;
			}
			pkmn.MagnetRiseTurns--;
			if (pkmn.MagnetRiseTurns == 0)
			{
				BroadcastStatus2(pkmn, pkmn, PBEStatus2.MagnetRise, PBEStatusAction.Ended);
			}
		}

		// Verified: BadDreams/Moody/SlowStart/SpeedBoost before Orbs, but activate together
		foreach (PBEBattlePokemon pkmn in order)
		{
			if (pkmn.HP == 0)
			{
				continue;
			}
			// Ability before Orb
			switch (pkmn.Ability)
			{
				case PBEAbility.BadDreams:
				{
					foreach (PBEBattlePokemon victim in GetRuntimeSurrounding(pkmn, false, true).Where(p => p.Status1 == PBEStatus1.Asleep))
					{
						BroadcastAbility(pkmn, victim, PBEAbility.BadDreams, PBEAbilityAction.Damage);
						DealDamage(pkmn, victim, pkmn.MaxHP / 8);
						if (!FaintCheck(victim))
						{
							LowHPBerryCheck(victim);
						}
					}
					break;
				}
				case PBEAbility.Moody:
				{
					List<PBEStat> statsThatCanGoUp = PBEDataUtils.MoodyStats.FindAll(s => pkmn.GetStatChange(s) < Settings.MaxStatChange);
					PBEStat? upStat = statsThatCanGoUp.Count == 0 ? null : _rand.RandomElement(statsThatCanGoUp);
					List<PBEStat> statsThatCanGoDown = PBEDataUtils.MoodyStats.FindAll(s => pkmn.GetStatChange(s) > -Settings.MaxStatChange);
					if (upStat is not null)
					{
						statsThatCanGoDown.Remove(upStat.Value);
					}
					PBEStat? downStat = statsThatCanGoDown.Count == 0 ? null : _rand.RandomElement(statsThatCanGoDown);
					if (upStat is not null || downStat is not null)
					{
						BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Stats);
						if (upStat is not null)
						{
							ApplyStatChangeIfPossible(pkmn, pkmn, upStat.Value, +2);
						}
						if (downStat is not null)
						{
							ApplyStatChangeIfPossible(pkmn, pkmn, downStat.Value, -1);
						}
					}
					break;
				}
				case PBEAbility.SlowStart:
				{
					if (pkmn.SlowStart_HinderTurnsLeft > 0)
					{
						pkmn.SlowStart_HinderTurnsLeft--;
						if (pkmn.SlowStart_HinderTurnsLeft == 0)
						{
							BroadcastAbility(pkmn, pkmn, PBEAbility.SlowStart, PBEAbilityAction.SlowStart_Ended);
						}
					}
					break;
				}
				case PBEAbility.SpeedBoost:
				{
					if (pkmn.SpeedBoost_AbleToSpeedBoostThisTurn && pkmn.SpeedChange < Settings.MaxStatChange)
					{
						BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Stats);
						ApplyStatChangeIfPossible(pkmn, pkmn, PBEStat.Speed, +1);
					}
					break;
				}
			}
			// Orb
			switch (pkmn.Item)
			{
				case PBEItem.FlameOrb:
				{
					if (pkmn.IsBurnPossible(null, ignoreSubstitute: true, ignoreSafeguard: true) == PBEResult.Success)
					{
						pkmn.Status1 = PBEStatus1.Burned;
						BroadcastItem(pkmn, pkmn, pkmn.Item, PBEItemAction.Announced);
						BroadcastStatus1(pkmn, pkmn, PBEStatus1.Burned, PBEStatusAction.Added);
					}
					break;
				}
				case PBEItem.ToxicOrb:
				{
					if (pkmn.IsPoisonPossible(null, ignoreSubstitute: true, ignoreSafeguard: true) == PBEResult.Success)
					{
						pkmn.Status1 = PBEStatus1.BadlyPoisoned;
						pkmn.Status1Counter = 1;
						BroadcastItem(pkmn, pkmn, pkmn.Item, PBEItemAction.Announced);
						BroadcastStatus1(pkmn, pkmn, PBEStatus1.BadlyPoisoned, PBEStatusAction.Added);
					}
					break;
				}
			}
		}
	}

	public bool ShouldDoWeatherEffects()
	{
		// If HP is needed to be above 0, use HPPercentage so clients can continue to use this
		// However, I see no instance of this getting called where an ActiveBattler has 0 hp
		return ActiveBattlers.FindIndex(p => p.Ability == PBEAbility.AirLock || p.Ability == PBEAbility.CloudNine) == -1;
	}
	public bool WillLeafGuardActivate()
	{
		return ShouldDoWeatherEffects() && Weather == PBEWeather.HarshSunlight;
	}

	private void FleeCheck()
	{
		foreach (PBETrainer trainer in Trainers)
		{
			if (!trainer.RequestedFlee)
			{
				continue;
			}
			if (trainer.IsWild)
			{
				PBEBattlePokemon wildPkmn = trainer.ActiveBattlersOrdered.First();
				wildPkmn.TurnAction = new PBETurnAction(wildPkmn); // Convert into a WildFlee turn action for the first Pokémon
				trainer.RequestedFlee = false;
				continue;
			}
			PBEBattlePokemon? pkmn = trainer.ActiveBattlersOrdered.FirstOrDefault();
			if (pkmn is not null)
			{
				// Verified: RunAway before SmokeBall
				if (pkmn.Ability == PBEAbility.RunAway)
				{
					BroadcastAbility(pkmn, pkmn, PBEAbility.RunAway, PBEAbilityAction.Announced);
					SetEscaped(pkmn);
					return;
				}
				if (pkmn.Item == PBEItem.SmokeBall)
				{
					BroadcastItem(pkmn, pkmn, PBEItem.SmokeBall, PBEItemAction.Announced);
					SetEscaped(pkmn);
					return;
				}
			}
			else
			{
				pkmn = trainer.Party[0]; // Use the first fainted Pokémon's speed if there's no active battler
			}
			// TODO: I'm using the gen 3/4 formula below.
			// TODO: Figure out the gen 5 formula, as well as what to use in a double wild battle
			int a = pkmn.Speed;
			int b = (int)trainer.Team.OpposingTeam.ActiveBattlers.Average(p => p.Speed);
			int c = ++trainer.Team.NumTimesTriedToFlee; // Increment even if guaranteed
			bool success;
			if (a > b)
			{
				success = true;
			}
			else
			{
				int f = ((a * 128 / b) + (30 * c)) % 256;
				success = _rand.RandomInt(0, 255) < f;
			}
			if (success)
			{
				SetEscaped(pkmn);
				return;
			}
			else
			{
				BroadcastFleeFailed(pkmn);
			}
			trainer.RequestedFlee = false;
		}
	}
	private void WildFleeCheck(PBEBattlePokemon pkmn)
	{
		// TODO: Trapping effects
		SetEscaped(pkmn);
	}

	private void CalcEXP(PBEBattlePokemon loser)
	{
		IPBEPokemonData loserPData = PBEDataProvider.Instance.GetPokemonData(loser);
		float modTrainer = loser.IsWild ? 1 : 1.5f;
		int expYield = loserPData.BaseEXPYield;
		int levelLoser = loser.Level;
		float modPassPower = PBEDataProvider.Instance.GetEXPModifier(this);
		int amtParticipated = loser.EXPPokemon.Count(pk => pk.Trainer.GainsEXP && pk.HP > 0);
		int amtEXPShare = loser.EXPPokemon.Count(pk => pk.Trainer.GainsEXP && pk.Item == PBEItem.ExpShare);
		foreach (PBEBattlePokemon victor in loser.EXPPokemon)
		{
			if (!victor.Trainer.GainsEXP || victor.HP == 0 || victor.Level >= Settings.MaxLevel)
			{
				continue;
			}

			int levelVictor = victor.Level;
			float modParticipators;
			if (amtEXPShare == 0)
			{
				modParticipators = amtParticipated;
			}
			else if (victor.Item == PBEItem.ExpShare)
			{
				modParticipators = 2 * amtEXPShare;
			}
			else
			{
				modParticipators = 2 * amtParticipated;
			}
			float modTraded = PBEDataProvider.Instance.GetEXPTradeModifier(victor);
			float modLuckyEgg = victor.Item == PBEItem.LuckyEgg ? 1.5f : 1;

			float result1H = modTrainer * expYield * levelLoser;
			float result1L = 5 * modParticipators;
			float result1 = result1H / result1L;
			float result2H = MathF.Pow(2 * levelLoser + 10, 2.5f);
			float result2L = MathF.Pow(levelLoser + levelVictor + 10, 2.5f);
			float result2 = result2H / result2L;
			float combined = result1 * result2 + 1;
			float final = combined * modTraded * modLuckyEgg * modPassPower;
			GiveEXP(victor, (uint)final);
		}
	}
	private void GiveEXP(PBEBattlePokemon victor, uint amount)
	{
		// TODO: Should we allow remote battles with learning moves? No packets right now
		BroadcastPkmnEXPEarned(victor, amount);
		PBEGrowthRate growthRate = PBEDataProvider.Instance.GetPokemonData(victor).GrowthRate;
	top:
		uint oldEXP = victor.EXP;
		uint nextLevelAmt = PBEDataProvider.Instance.GetEXPRequired(growthRate, (byte)(victor.Level + 1));
		if (oldEXP + amount >= nextLevelAmt)
		{
			victor.EXP = nextLevelAmt;
			BroadcastPkmnEXPChanged(victor, oldEXP);
			victor.Level++;
			victor.SetStats(true, false);
			BroadcastPkmnLevelChanged(victor);
			// BUG: PBEStatus2.PowerTrick is not cleared when leveling up, even though the stats are replaced (meaning it can still be baton passed)
			if (Settings.BugFix && victor.Status2.HasFlag(PBEStatus2.PowerTrick))
			{
				BroadcastStatus2(victor, victor, PBEStatus2.PowerTrick, PBEStatusAction.Ended);
			}
			if (victor.Level == Settings.MaxLevel)
			{
				return;
			}
			uint grewBy = nextLevelAmt - oldEXP;
			amount -= grewBy;
			if (amount > 0)
			{
				goto top; // Keep gaining and leveling
			}
		}
		else
		{
			victor.EXP = oldEXP + amount;
			BroadcastPkmnEXPChanged(victor, oldEXP);
		}
	}

	private static float PokedexCountTable(int count, float g600, float g450, float g300, float g150, float g30, float ge0)
	{
		if (count > 600)
		{
			return g600;
		}
		if (count > 450)
		{
			return g450;
		}
		if (count > 300)
		{
			return g300;
		}
		if (count > 150)
		{
			return g150;
		}
		if (count > 30)
		{
			return g30;
		}
		return ge0;
	}
	private void GenerateCapture(PBEBattlePokemon user, PBEBattlePokemon wildPkmn, PBEItem ball, out byte shakes, out bool success, out bool isCriticalCapture)
	{
		if (PBEDataProvider.Instance.IsGuaranteedCapture(this, wildPkmn.OriginalSpecies, wildPkmn.RevertForm))
		{
			shakes = 3;
			success = true;
			isCriticalCapture = false;
			return;
		}
		IPBEPokemonData pData = PBEDataProvider.Instance.GetPokemonData(wildPkmn.OriginalSpecies, wildPkmn.RevertForm);
		float rate = pData.CatchRate * PBEDataProvider.Instance.GetCatchRateModifier(this);
		float bonusBall = 1;
		switch (ball)
		{
			case PBEItem.GreatBall:
			case PBEItem.SafariBall:
			case PBEItem.SportBall: bonusBall = 1.5f; break;
			case PBEItem.UltraBall: bonusBall = 2; break;
			case PBEItem.MasterBall:
			case PBEItem.ParkBall: bonusBall = 255; break;
			case PBEItem.FastBall:
			{
				if (wildPkmn.Speed >= 100)
				{
					rate *= 4;
				}
				break;
			}
			case PBEItem.LevelBall:
			{
				int wl = wildPkmn.Level;
				int ul = user.Level;
				if (ul > wl * 4)
				{
					rate *= 8;
				}
				else if (ul > wl * 2)
				{
					rate *= 4;
				}
				else if (ul > wl)
				{
					rate *= 2;
				}
				break;
			}
			case PBEItem.LureBall:
			{
				if (PBEDataProvider.Instance.IsFishing(this))
				{
					rate *= 3;
				}
				break;
			}
			case PBEItem.HeavyBall:
			{
				float weight = pData.Weight;
				if (weight >= 409.6f)
				{
					rate += 40;
				}
				else if (weight >= 307.2f)
				{
					rate += 30;
				}
				else if (weight >= 204.8f)
				{
					rate += 20;
				}
				else
				{
					rate -= 20;
				}
				break;
			}
			case PBEItem.LoveBall:
			{
				if (user.Species == wildPkmn.Species && user.Gender.IsOppositeGender(wildPkmn.Gender))
				{
					rate *= 8;
				}
				break;
			}
			case PBEItem.MoonBall:
			{
				if (PBEDataProvider.Instance.IsMoonBallFamily(wildPkmn.OriginalSpecies, wildPkmn.RevertForm))
				{
					rate *= 4;
				}
				break;
			}
			case PBEItem.NetBall:
			{
				if (wildPkmn.HasType(PBEType.Bug) || wildPkmn.HasType(PBEType.Water))
				{
					bonusBall = 3;
				}
				break;
			}
			case PBEItem.NestBall:
			{
				bonusBall = Math.Max(1, (41 - wildPkmn.Level) / 10);
				break;
			}
			case PBEItem.RepeatBall:
			{
				if (PBEDataProvider.Instance.IsRepeatBallSpecies(wildPkmn.OriginalSpecies))
				{
					bonusBall = 3;
				}
				break;
			}
			case PBEItem.TimerBall:
			{
				bonusBall = Math.Min(4, 1 + (TurnNumber * 0.3f));
				break;
			}
			case PBEItem.DiveBall:
			{
				if (PBEDataProvider.Instance.IsFishing(this) || PBEDataProvider.Instance.IsSurfing(this) || PBEDataProvider.Instance.IsUnderwater(this))
				{
					bonusBall = 3.5f;
				}
				break;
			}
			case PBEItem.DuskBall:
			{
				if (PBEDataProvider.Instance.IsDuskBallSetting(this))
				{
					bonusBall = 3.5f;
				}
				break;
			}
			case PBEItem.QuickBall:
			{
				if (TurnNumber == 1)
				{
					bonusBall = 5;
				}
				break;
			}
		}
		rate = Math.Clamp(rate, 1, 255);
		float bonusStatus;
		switch (wildPkmn.Status1)
		{
			case PBEStatus1.Asleep:
			case PBEStatus1.Frozen: bonusStatus = 2.5f; break;
			case PBEStatus1.None: bonusStatus = 1; break;
			default: bonusStatus = 1.5f; break;
		}
		float pkmnFactor = (3 * wildPkmn.MaxHP) - (2 * wildPkmn.HP);
		int pkmnCaught = PBEDataProvider.Instance.GetSpeciesCaught();
		if (PBEDataProvider.Instance.IsDarkGrass(this))
		{
			pkmnFactor *= PokedexCountTable(pkmnCaught, 1, 0.9f, 0.8f, 0.7f, 0.5f, 0.3f);
		}
		float a = pkmnFactor * rate * bonusBall / (3 * wildPkmn.MaxHP) * bonusStatus;
		float c = a * PokedexCountTable(pkmnCaught, 2.5f, 2, 1.5f, 1, 0.5f, 0); // Critical capture modifier
		isCriticalCapture = _rand.RandomInt(0, 0xFF) < c / 6;
		byte numShakes = isCriticalCapture ? (byte)1 : (byte)3;
		if (a >= 0xFF)
		{
			shakes = numShakes; // Skip shake checks
			success = true;
			return;
		}
		float b = 0x10000 / MathF.Sqrt(MathF.Sqrt(0xFF / a));
		for (shakes = 0; shakes < numShakes; shakes++)
		{
			if (_rand.RandomInt(0, 0xFFFF) >= b)
			{
				break; // Shake check fails
			}
		}
		success = shakes == numShakes;
		if (shakes == 2)
		{
			shakes = 3; // If there are only 2 shakes and a failure, shake three times and still fail
		}
	}
	private void UseItem(PBEBattlePokemon user, PBEItem item)
	{
		BroadcastItemTurn(user, item, PBEItemTurnAction.Attempt);
		if (PBEDataUtils.AllBalls.Contains(item))
		{
			user.Trainer.Inventory.Remove(item);
			if (BattleType != PBEBattleType.Wild)
			{
				goto fail;
			}
			PBEBattlePokemon wildPkmn = user.Team.OpposingTeam.ActiveBattlers.Single();
			GenerateCapture(user, wildPkmn, item, out byte numShakes, out bool success, out bool critical);
			BroadcastCapture(wildPkmn, item, numShakes, success, critical);
			if (success)
			{
				wildPkmn.CaughtBall = wildPkmn.KnownCaughtBall = item;
				BattleResult = PBEBattleResult.WildCapture;
			}
			return;
		}
		else
		{
			switch (item)
			{
				case PBEItem.FluffyTail:
				case PBEItem.PokeDoll:
				case PBEItem.PokeToy:
				{
					user.Trainer.Inventory.Remove(item);
					if (BattleType == PBEBattleType.Wild)
					{
						SetEscaped(user);
						return;
					}
					goto fail;
				}
			}
		}
	fail:
		BroadcastItemTurn(user, item, PBEItemTurnAction.NoEffect);
	}

	private void UseMove(PBEBattlePokemon user, PBEMove move, PBETurnTarget requestedTargets)
	{
		// Cancel the semi-invulnerable move if the user is affected by its status1
		if (!_calledFromOtherMove && PreMoveStatusCheck(user, move))
		{
			if (user.Status2.HasFlag(PBEStatus2.Airborne))
			{
				BroadcastMoveLock_Temporary(user, PBEMove.None, PBETurnTarget.None);
				BroadcastStatus2(user, user, PBEStatus2.Airborne, PBEStatusAction.Ended);
			}
			if (user.Status2.HasFlag(PBEStatus2.ShadowForce))
			{
				BroadcastMoveLock_Temporary(user, PBEMove.None, PBETurnTarget.None);
				BroadcastStatus2(user, user, PBEStatus2.ShadowForce, PBEStatusAction.Ended);
			}
			if (user.Status2.HasFlag(PBEStatus2.Underground))
			{
				BroadcastMoveLock_Temporary(user, PBEMove.None, PBETurnTarget.None);
				BroadcastStatus2(user, user, PBEStatus2.Underground, PBEStatusAction.Ended);
			}
			if (user.Status2.HasFlag(PBEStatus2.Underwater))
			{
				BroadcastMoveLock_Temporary(user, PBEMove.None, PBETurnTarget.None);
				BroadcastStatus2(user, user, PBEStatus2.Underwater, PBEStatusAction.Ended);
			}
			return;
		}
		IPBEMoveData mData = PBEDataProvider.Instance.GetMoveData(move);
		PBEBattlePokemon[] targets = GetRuntimeTargets(user, requestedTargets, user.GetMoveTargets(mData) == PBEMoveTarget.SingleNotSelf, _rand);
		switch (mData.Effect)
		{
			case PBEMoveEffect.Acrobatics:
			case PBEMoveEffect.Brine:
			case PBEMoveEffect.ChipAway:
			case PBEMoveEffect.CrushGrip:
			case PBEMoveEffect.Eruption:
			case PBEMoveEffect.Facade:
			case PBEMoveEffect.Flail:
			case PBEMoveEffect.FoulPlay:
			case PBEMoveEffect.Frustration:
			case PBEMoveEffect.GrassKnot:
			case PBEMoveEffect.HeatCrash:
			case PBEMoveEffect.Hex:
			case PBEMoveEffect.HiddenPower:
			case PBEMoveEffect.Hit:
			case PBEMoveEffect.Judgment:
			case PBEMoveEffect.Magnitude:
			case PBEMoveEffect.Payback:
			case PBEMoveEffect.Psyshock:
			case PBEMoveEffect.Punishment:
			case PBEMoveEffect.Retaliate:
			case PBEMoveEffect.Return:
			case PBEMoveEffect.StoredPower:
			case PBEMoveEffect.TechnoBlast:
			case PBEMoveEffect.Venoshock:
			case PBEMoveEffect.WeatherBall: Ef_Hit(user, targets, move, mData); break;
			case PBEMoveEffect.Attract: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Infatuated); break;
			case PBEMoveEffect.BellyDrum: Ef_BellyDrum(user, targets, move, mData); break;
			case PBEMoveEffect.Bounce: Ef_Bounce(user, targets, move, mData, requestedTargets); break;
			case PBEMoveEffect.BrickBreak: Ef_BrickBreak(user, targets, move, mData); break;
			case PBEMoveEffect.Burn: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Burned); break;
			case PBEMoveEffect.Camouflage: Ef_Camouflage(user, targets, move, mData); break;
			case PBEMoveEffect.ChangeTarget_ACC: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Accuracy, mData.EffectParam) }); break;
			case PBEMoveEffect.ChangeTarget_ATK: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, mData.EffectParam) }); break;
			case PBEMoveEffect.ChangeTarget_DEF: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, mData.EffectParam) }); break;
			case PBEMoveEffect.ChangeTarget_EVA:
			case PBEMoveEffect.Minimize: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Evasion, mData.EffectParam) }); break;
			case PBEMoveEffect.ChangeTarget_SPATK: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, mData.EffectParam) }); break;
			case PBEMoveEffect.ChangeTarget_SPATK__IfAttractionPossible: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, mData.EffectParam) }, requireAttraction: true); break;
			case PBEMoveEffect.ChangeTarget_SPDEF: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpDefense, mData.EffectParam) }); break;
			case PBEMoveEffect.ChangeTarget_SPE: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Speed, mData.EffectParam) }); break;
			case PBEMoveEffect.Confuse: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Confused); break;
			case PBEMoveEffect.Conversion: Ef_Conversion(user, targets, move, mData); break;
			case PBEMoveEffect.Curse: Ef_Curse(user, targets, move, mData); break;
			case PBEMoveEffect.Dig: SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Underground); break;
			case PBEMoveEffect.Dive: SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Underwater); break;
			case PBEMoveEffect.Endeavor: Ef_Endeavor(user, targets, move, mData); break;
			case PBEMoveEffect.Entrainment: Ef_Entrainment(user, targets, move, mData); break;
			case PBEMoveEffect.Feint: Ef_Feint(user, targets, move, mData); break;
			case PBEMoveEffect.FinalGambit: Ef_FinalGambit(user, targets, move, mData); break;
			case PBEMoveEffect.Flatter: Ef_Flatter(user, targets, move, mData); break;
			case PBEMoveEffect.Fly: SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Airborne); break;
			case PBEMoveEffect.FocusEnergy: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Pumped); break;
			case PBEMoveEffect.Foresight: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Identified); break;
			case PBEMoveEffect.GastroAcid: Ef_SetOtherAbility(user, targets, move, mData, PBEAbility.None, false); break;
			case PBEMoveEffect.Growth: Ef_Growth(user, targets, move, mData); break;
			case PBEMoveEffect.Hail: Ef_TryForceWeather(user, move, mData, PBEWeather.Hailstorm); break;
			case PBEMoveEffect.Haze: Ef_Haze(user, targets, move, mData); break;
			case PBEMoveEffect.HelpingHand: Ef_HelpingHand(user, targets, move, mData); break;
			case PBEMoveEffect.Hit__2Times: Ef_MultiHit(user, targets, move, mData, 2); break;
			case PBEMoveEffect.Hit__2Times__MaybePoison: Ef_MultiHit(user, targets, move, mData, 2, status1: PBEStatus1.Poisoned, chanceToInflictStatus1: mData.EffectParam); break;
			case PBEMoveEffect.Hit__2To5Times: Ef_MultiHit_2To5(user, targets, move, mData); break;
			case PBEMoveEffect.Hit__MaybeBurn: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Burned, chanceToInflictStatus1: mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeBurn__10PercentFlinch: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Burned, chanceToInflictStatus1: mData.EffectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); break;
			case PBEMoveEffect.Hit__MaybeBurnFreezeParalyze: Ef_Hit__MaybeBurnFreezeParalyze(user, targets, move, mData); break;
			case PBEMoveEffect.Hit__MaybeConfuse: Ef_Hit(user, targets, move, mData, status2: PBEStatus2.Confused, chanceToInflictStatus2: mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeFlinch: Ef_Hit(user, targets, move, mData, status2: PBEStatus2.Flinching, chanceToInflictStatus2: mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeFreeze: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Frozen, chanceToInflictStatus1: mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeFreeze__10PercentFlinch: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Frozen, chanceToInflictStatus1: mData.EffectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Accuracy, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpDefense, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpDefense, -2) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Speed, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeParalyze: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeParalyze__10PercentFlinch: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: mData.EffectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); break;
			case PBEMoveEffect.Hit__MaybePoison: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Poisoned, chanceToInflictStatus1: mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Attack, -1), (PBEStat.Defense, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Defense, -1), (PBEStat.SpDefense, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, -2) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Speed, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Speed, -1), (PBEStat.Defense, -1), (PBEStat.SpDefense, -1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Defense, +1), (PBEStat.SpAttack, +1), (PBEStat.SpDefense, +1), (PBEStat.Speed, +1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Defense, +1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, +1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Speed, +1) }, mData.EffectParam); break;
			case PBEMoveEffect.Hit__MaybeToxic: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.BadlyPoisoned, chanceToInflictStatus1: mData.EffectParam); break;
			case PBEMoveEffect.HPDrain: Ef_HPDrain(user, targets, move, mData); break;
			case PBEMoveEffect.HPDrain__RequireSleep: Ef_HPDrain(user, targets, move, mData, requireSleep: true); break;
			case PBEMoveEffect.LeechSeed: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.LeechSeed); break;
			case PBEMoveEffect.LightScreen: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.LightScreen); break;
			case PBEMoveEffect.LockOn: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.LockOn); break;
			case PBEMoveEffect.LowerTarget_ATK_DEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, -1), (PBEStat.Defense, -1) }); break;
			case PBEMoveEffect.LowerTarget_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, -1), (PBEStat.SpDefense, -1), (PBEStat.Attack, +2), (PBEStat.SpAttack, +2), (PBEStat.Speed, +2) }); break;
			case PBEMoveEffect.LuckyChant: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.LuckyChant); break;
			case PBEMoveEffect.MagnetRise: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.MagnetRise); break;
			case PBEMoveEffect.Metronome: Ef_Metronome(user, move, mData); break;
			case PBEMoveEffect.MiracleEye: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.MiracleEye); break;
			case PBEMoveEffect.Moonlight: Ef_Moonlight(user, targets, move, mData); break;
			case PBEMoveEffect.Nightmare: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Nightmare); break;
			case PBEMoveEffect.Nothing: Ef_Nothing(user, move, mData); break;
			case PBEMoveEffect.OneHitKnockout: Ef_OneHitKnockout(user, targets, move, mData); break;
			case PBEMoveEffect.PainSplit: Ef_PainSplit(user, targets, move, mData); break;
			case PBEMoveEffect.Paralyze: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Paralyzed); break;
			case PBEMoveEffect.PayDay: Ef_PayDay(user, targets, move, mData); break;
			case PBEMoveEffect.Poison: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Poisoned); break;
			case PBEMoveEffect.PowerTrick: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.PowerTrick); break;
			case PBEMoveEffect.Protect: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Protected); break;
			case PBEMoveEffect.PsychUp: Ef_PsychUp(user, targets, move, mData); break;
			case PBEMoveEffect.Psywave: Ef_Psywave(user, targets, move, mData); break;
			case PBEMoveEffect.QuickGuard: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.QuickGuard); break;
			case PBEMoveEffect.RainDance: Ef_TryForceWeather(user, move, mData, PBEWeather.Rain); break;
			case PBEMoveEffect.RaiseTarget_ATK_ACC_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Accuracy, +1) }); break;
			case PBEMoveEffect.RaiseTarget_ATK_DEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Defense, +1) }); break;
			case PBEMoveEffect.RaiseTarget_ATK_DEF_ACC_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Defense, +1), (PBEStat.Accuracy, +1) }); break;
			case PBEMoveEffect.RaiseTarget_ATK_SPATK_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.SpAttack, +1) }); break;
			case PBEMoveEffect.RaiseTarget_ATK_SPE_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Speed, +1) }); break;
			case PBEMoveEffect.RaiseTarget_DEF_SPDEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, +1), (PBEStat.SpDefense, +1) }); break;
			case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, +1), (PBEStat.SpDefense, +1) }); break;
			case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_SPE_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, +1), (PBEStat.SpDefense, +1), (PBEStat.Speed, +1) }); break;
			case PBEMoveEffect.RaiseTarget_SPE_By2_ATK_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Speed, +2), (PBEStat.Attack, +1) }); break;
			case PBEMoveEffect.Recoil: Ef_Recoil(user, targets, move, mData); break;
			case PBEMoveEffect.Recoil__10PercentBurn: Ef_Recoil(user, targets, move, mData, status1: PBEStatus1.Burned, chanceToInflictStatus1: 10); break;
			case PBEMoveEffect.Recoil__10PercentParalyze: Ef_Recoil(user, targets, move, mData, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: 10); break;
			case PBEMoveEffect.Reflect: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Reflect); break;
			case PBEMoveEffect.ReflectType: Ef_ReflectType(user, targets, move, mData); break;
			case PBEMoveEffect.Refresh: Ef_Refresh(user, targets, move, mData); break;
			case PBEMoveEffect.Rest: Ef_Rest(user, move, mData); break;
			case PBEMoveEffect.RestoreTargetHP: Ef_RestoreTargetHP(user, targets, move, mData); break;
			case PBEMoveEffect.RolePlay: Ef_RolePlay(user, targets, move, mData); break;
			case PBEMoveEffect.Roost: Ef_Roost(user, targets, move, mData); break;
			case PBEMoveEffect.Safeguard: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Safeguard); break;
			case PBEMoveEffect.Sandstorm: Ef_TryForceWeather(user, move, mData, PBEWeather.Sandstorm); break;
			case PBEMoveEffect.SecretPower: Ef_SecretPower(user, targets, move, mData); break;
			case PBEMoveEffect.SeismicToss: Ef_SeismicToss(user, targets, move, mData); break;
			case PBEMoveEffect.Selfdestruct: Ef_Selfdestruct(user, targets, move, mData); break;
			case PBEMoveEffect.SetDamage: Ef_SetDamage(user, targets, move, mData); break;
			case PBEMoveEffect.ShadowForce: Ef_ShadowForce(user, targets, move, mData, requestedTargets); break;
			case PBEMoveEffect.SimpleBeam: Ef_SetOtherAbility(user, targets, move, mData, PBEAbility.Simple, true); break;
			case PBEMoveEffect.Sleep: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Asleep); break;
			case PBEMoveEffect.SmellingSalt: Ef_SmellingSalt(user, targets, move, mData); break;
			case PBEMoveEffect.Snore: Ef_Snore(user, targets, move, mData); break;
			case PBEMoveEffect.Soak: Ef_Soak(user, targets, move, mData); break;
			case PBEMoveEffect.Spikes: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Spikes); break;
			case PBEMoveEffect.StealthRock: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.StealthRock); break;
			case PBEMoveEffect.Struggle: Ef_Struggle(user, targets, move, mData); break;
			case PBEMoveEffect.Substitute: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Substitute); break;
			case PBEMoveEffect.SuckerPunch: Ef_SuckerPunch(user, targets, move, mData); break;
			case PBEMoveEffect.SunnyDay: Ef_TryForceWeather(user, move, mData, PBEWeather.HarshSunlight); break;
			case PBEMoveEffect.SuperFang: Ef_SuperFang(user, targets, move, mData); break;
			case PBEMoveEffect.Swagger: Ef_Swagger(user, targets, move, mData); break;
			case PBEMoveEffect.Tailwind: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Tailwind); break;
			case PBEMoveEffect.Teleport: Ef_Teleport(user, move, mData); break;
			case PBEMoveEffect.ThunderWave: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Paralyzed, thunderWave: true); break;
			case PBEMoveEffect.Toxic: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.BadlyPoisoned); break;
			case PBEMoveEffect.ToxicSpikes: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.ToxicSpikes); break;
			case PBEMoveEffect.Transform: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Transformed); break;
			case PBEMoveEffect.TrickRoom: Ef_TryForceBattleStatus(user, move, mData, PBEBattleStatus.TrickRoom); break;
			case PBEMoveEffect.WakeUpSlap: Ef_WakeUpSlap(user, targets, move, mData); break;
			case PBEMoveEffect.Whirlwind: Ef_Whirlwind(user, targets, move, mData); break;
			case PBEMoveEffect.WideGuard: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.WideGuard); break;
			case PBEMoveEffect.WorrySeed: Ef_SetOtherAbility(user, targets, move, mData, PBEAbility.Insomnia, true); break;
			default: throw new InvalidDataException(nameof(mData.Effect));
		}
	}

	private bool PreMoveStatusCheck(PBEBattlePokemon user, PBEMove move)
	{
		IPBEMoveData mData = PBEDataProvider.Instance.GetMoveData(move);

		// Verified: Sleep and Freeze don't interact with Flinch unless they come out of the status
		// Sleep causes Confusion, Flinch, and Infatuation to activate if the user is trying to use Snore
		if (user.Status1 == PBEStatus1.Asleep)
		{
			user.Status1Counter++;
			if (user.Status1Counter > user.SleepTurns)
			{
				user.Status1 = PBEStatus1.None;
				user.Status1Counter = 0;
				user.SleepTurns = 0;
				BroadcastStatus1(user, user, PBEStatus1.Asleep, PBEStatusAction.Ended);
				CureNightmare(user, user);
			}
			else if (mData.Effect != PBEMoveEffect.Snore)
			{
				BroadcastStatus1(user, user, PBEStatus1.Asleep, PBEStatusAction.CausedImmobility);
				return true;
			}
		}
		else if (user.Status1 == PBEStatus1.Frozen)
		{
			if (mData.Flags.HasFlag(PBEMoveFlag.DefrostsUser) || _rand.RandomBool(20, 100))
			{
				user.Status1 = PBEStatus1.None;
				BroadcastStatus1(user, user, PBEStatus1.Frozen, PBEStatusAction.Ended);
			}
			else
			{
				BroadcastStatus1(user, user, PBEStatus1.Frozen, PBEStatusAction.CausedImmobility);
				return true;
			}
		}
		// Verified: Flinch before Confusion, Infatuation, and Paralysis can do anything
		if (user.Status2.HasFlag(PBEStatus2.Flinching))
		{
			BroadcastStatus2(user, user, PBEStatus2.Flinching, PBEStatusAction.CausedImmobility);
			if (user.Ability == PBEAbility.Steadfast && user.SpeedChange < Settings.MaxStatChange)
			{
				BroadcastAbility(user, user, PBEAbility.Steadfast, PBEAbilityAction.Stats);
				ApplyStatChangeIfPossible(user, user, PBEStat.Speed, +1);
			}
			return true;
		}
		// Verified: Confusion before Infatuation and Paralysis
		if (user.Status2.HasFlag(PBEStatus2.Confused))
		{
			user.ConfusionCounter++;
			if (user.ConfusionCounter > user.ConfusionTurns)
			{
				user.ConfusionCounter = 0;
				user.ConfusionTurns = 0;
				BroadcastStatus2(user, user, PBEStatus2.Confused, PBEStatusAction.Ended);
			}
			else
			{
				BroadcastStatus2(user, user, PBEStatus2.Confused, PBEStatusAction.Announced);
				if (_rand.RandomBool(50, 100))
				{
					int damage = CalculateConfusionDamage(user);
					DealDamage(user, user, damage, ignoreSturdy: false);
					BroadcastStatus2(user, user, PBEStatus2.Confused, PBEStatusAction.Damage);
					// BUG: Confusion damage does not activate these items
					if (!FaintCheck(user) && Settings.BugFix)
					{
						LowHPBerryCheck(user);
					}
					return true;
				}
			}
		}
		// Verified: Paralysis before Infatuation
		if (user.Status1 == PBEStatus1.Paralyzed && _rand.RandomBool(25, 100))
		{
			BroadcastStatus1(user, user, PBEStatus1.Paralyzed, PBEStatusAction.CausedImmobility);
			return true;
		}
		// Infatuation
		if (user.Status2.HasFlag(PBEStatus2.Infatuated))
		{
			BroadcastStatus2(user, user.InfatuatedWithPokemon!, PBEStatus2.Infatuated, PBEStatusAction.Announced);
			if (_rand.RandomBool(50, 100))
			{
				BroadcastStatus2(user, user.InfatuatedWithPokemon!, PBEStatus2.Infatuated, PBEStatusAction.CausedImmobility);
				return true;
			}
		}
		return false;
	}
	private bool MissCheck(PBEBattlePokemon user, PBEBattlePokemon target, IPBEMoveData mData)
	{
		if (user == target)
		{
			return false;
		}
		// Verified: WideGuard happens before Protect
		if (target.Team.TeamStatus.HasFlag(PBETeamStatus.WideGuard) && mData.Category != PBEMoveCategory.Status && PBEDataUtils.IsSpreadMove(user.GetMoveTargets(mData)))
		{
			BroadcastTeamStatusDamage(target.Team, PBETeamStatus.WideGuard, target);
			return true;
		}
		// Feint ignores Quick Guard unless the target is an ally
		if (target.Team.TeamStatus.HasFlag(PBETeamStatus.QuickGuard) && mData.Priority > 0 && (mData.Effect != PBEMoveEffect.Feint || user.Team == target.Team))
		{
			BroadcastTeamStatusDamage(target.Team, PBETeamStatus.QuickGuard, target);
			return true;
		}
		if (target.Status2.HasFlag(PBEStatus2.Protected) && mData.Flags.HasFlag(PBEMoveFlag.AffectedByProtect))
		{
			BroadcastStatus2(target, user, PBEStatus2.Protected, PBEStatusAction.Damage);
			return true;
		}
		if (user.Status2.HasFlag(PBEStatus2.LockOn) && user.LockOnPokemon == target)
		{
			return false;
		}
		if (user.Ability == PBEAbility.NoGuard || target.Ability == PBEAbility.NoGuard)
		{
			return false;
		}
		if (target.Status2.HasFlag(PBEStatus2.Airborne) && !(mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageAirborne) || mData.Flags.HasFlag(PBEMoveFlag.HitsAirborne)))
		{
			goto miss;
		}
		if (target.Status2.HasFlag(PBEStatus2.ShadowForce))
		{
			goto miss;
		}
		if (target.Status2.HasFlag(PBEStatus2.Underground) && !(mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderground) || mData.Flags.HasFlag(PBEMoveFlag.HitsUnderground)))
		{
			goto miss;
		}
		if (target.Status2.HasFlag(PBEStatus2.Underwater) && !(mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderwater) || mData.Flags.HasFlag(PBEMoveFlag.HitsUnderwater)))
		{
			goto miss;
		}
		// These go after semi-invulnerable
		float chance = mData.Accuracy;
		if (chance == 0) // Moves that don't miss
		{
			return false;
		}
		if (ShouldDoWeatherEffects())
		{
			if (Weather == PBEWeather.Hailstorm && mData.Flags.HasFlag(PBEMoveFlag.NeverMissHail))
			{
				return false;
			}
			if (mData.Flags.HasFlag(PBEMoveFlag.NeverMissRain))
			{
				if (Weather == PBEWeather.Rain)
				{
					return false;
				}
				if (Weather == PBEWeather.HarshSunlight)
				{
					chance = Math.Min(50, chance);
				}
			}
		}
		if (mData.Effect == PBEMoveEffect.OneHitKnockout)
		{
			chance = user.Level - target.Level + chance;
			if (chance < 1)
			{
				goto miss;
			}
			else
			{
				goto roll; // Skip all modifiers
			}
		}
		if (target.Ability == PBEAbility.WonderSkin && mData.Category == PBEMoveCategory.Status && !user.HasCancellingAbility())
		{
			chance = Math.Min(50, chance);
		}
		bool ignoreA = mData.Category != PBEMoveCategory.Status && target.Ability == PBEAbility.Unaware && !user.HasCancellingAbility();
		bool ignoreE = mData.Effect == PBEMoveEffect.ChipAway || (mData.Category != PBEMoveCategory.Status && user.Ability == PBEAbility.Unaware);
		float accuracy = ignoreA ? 1 : GetStatChangeModifier(user.AccuracyChange, true);
		float evasion;
		if (ignoreE)
		{
			evasion = 1;
		}
		else
		{
			bool ignorePositive = target.Status2.HasFlag(PBEStatus2.Identified) || target.Status2.HasFlag(PBEStatus2.MiracleEye);
			evasion = GetStatChangeModifier(ignorePositive ? Math.Min((sbyte)0, target.EvasionChange) : target.EvasionChange, true);
		}
		chance *= accuracy / evasion;
		if (user.Ability == PBEAbility.Compoundeyes)
		{
			chance *= 1.3f;
		}
		if (user.Team.ActiveBattlers.FindIndex(p => p.Ability == PBEAbility.VictoryStar) != -1)
		{
			chance *= 1.1f;
		}
		if (user.Ability == PBEAbility.Hustle && mData.Category == PBEMoveCategory.Physical)
		{
			chance *= 0.8f;
		}
		if (!user.HasCancellingAbility() && ShouldDoWeatherEffects())
		{
			if (Weather == PBEWeather.Sandstorm && target.Ability == PBEAbility.SandVeil)
			{
				chance *= 0.8f;
			}
			if (Weather == PBEWeather.Hailstorm && target.Ability == PBEAbility.SnowCloak)
			{
				chance *= 0.8f;
			}
		}
		if (target.Item == PBEItem.BrightPowder)
		{
			chance *= 0.9f;
		}
		if (target.Item == PBEItem.LaxIncense)
		{
			chance *= 0.9f;
		}
		if (user.Item == PBEItem.WideLens)
		{
			chance *= 1.1f;
		}
		if (target.Ability == PBEAbility.TangledFeet && target.Status2.HasFlag(PBEStatus2.Confused) && !user.HasCancellingAbility())
		{
			chance *= 0.5f;
		}
	roll:
		if (_rand.RandomBool((int)chance, 100))
		{
			return false;
		}
	miss:
		BroadcastMoveResult(user, target, PBEResult.Missed);
		return true;
	}
	private bool AttackTypeCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEType moveType, out PBEResult result, out float damageMultiplier)
	{
		result = PBETypeEffectiveness.IsAffectedByAttack(user, target, moveType, out damageMultiplier);
		if (result == PBEResult.Ineffective_Ability)
		{
			BroadcastAbility(target, user, target.Ability, PBEAbilityAction.Damage);
		}
		if (result != PBEResult.NotVeryEffective_Type && result != PBEResult.Success && result != PBEResult.SuperEffective_Type)
		{
			BroadcastMoveResult(user, target, result);
			return false;
		}
		return true;
	}
	private bool CritCheck(PBEBattlePokemon user, PBEBattlePokemon target, IPBEMoveData mData)
	{
		if (((target.Ability == PBEAbility.BattleArmor || target.Ability == PBEAbility.ShellArmor) && !user.HasCancellingAbility())
			|| target.Team.TeamStatus.HasFlag(PBETeamStatus.LuckyChant))
		{
			return false;
		}
		if (mData.Flags.HasFlag(PBEMoveFlag.AlwaysCrit))
		{
			return true;
		}
		byte stage = 0;
		if (user.Status2.HasFlag(PBEStatus2.Pumped))
		{
			stage += 2;
		}
		if (user.OriginalSpecies == PBESpecies.Chansey && user.Item == PBEItem.LuckyPunch)
		{
			stage += 2;
		}
		if (user.OriginalSpecies == PBESpecies.Farfetchd && user.Item == PBEItem.Stick)
		{
			stage += 2;
		}
		if (mData.Flags.HasFlag(PBEMoveFlag.HighCritChance))
		{
			stage += 1;
		}
		if (user.Ability == PBEAbility.SuperLuck)
		{
			stage += 1;
		}
		if (user.Item == PBEItem.RazorClaw || user.Item == PBEItem.ScopeLens)
		{
			stage += 1;
		}
		float chance;
		switch (stage)
		{
			case 0: chance = 6.25f; break;
			case 1: chance = 12.5f; break;
			case 2: chance = 25; break;
			case 3: chance = 33.3f; break;
			default: chance = 50; break;
		}
		return _rand.RandomBool((int)(chance * 100), 100 * 100);
	}
	private void TrySetLoser(PBEBattlePokemon pkmn)
	{
		if (BattleResult is null && pkmn.Team.NumConsciousPkmn == 0)
		{
			BattleResult = pkmn.Team.Id == 0 ? PBEBattleResult.Team1Win : PBEBattleResult.Team0Win;
		}
	}
	private void SetEscaped(PBEBattlePokemon pkmn)
	{
		BattleResult = pkmn.IsWild ? PBEBattleResult.WildFlee : PBEBattleResult.WildEscape;
	}
	private bool FaintCheck(PBEBattlePokemon pkmn)
	{
		if (pkmn.HP == 0)
		{
			_turnOrder.Remove(pkmn);
			ActiveBattlers.Remove(pkmn);
			PBEFieldPosition oldPos = pkmn.FieldPosition;
			pkmn.ClearForFaint();
			BroadcastPkmnFainted(pkmn, oldPos);
			RemoveInfatuationsAndLockOns(pkmn);
			CalcEXP(pkmn);
			pkmn.EXPPokemon.Clear();
			pkmn.Team.MonFaintedThisTurn = true;
			TrySetLoser(pkmn);
			CastformCherrimCheckAll();
			return true;
		}
		return false;
	}
	private bool GetManipulableChance(PBEBattlePokemon pkmn, int chance)
	{
		// TODO: Does the Rainbow affect abilities activating, such as CuteCharm/Static, Healer/ShedSkin, etc, and which side of the field would they activate from? Victim?
		// TODO: If it does affect abilities, does it affect Effect Spore? It uses its own weird rng
		if (pkmn.Ability == PBEAbility.SereneGrace)
		{
			chance *= 2;
		}
		return _rand.RandomBool(chance, 100);
	}

	private void ActivateAbility(PBEBattlePokemon pkmn, bool switchIn)
	{
		if (!switchIn)
		{
			CastformCherrimCheck(pkmn); // Switch-Ins check this after all Pokémon are sent out
		}
		AntiStatusAbilityCheck(pkmn);
		switch (pkmn.Ability)
		{
			case PBEAbility.AirLock:
			case PBEAbility.CloudNine:
			{
				if (switchIn)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Weather);
				}
				else
				{
					CastformCherrimCheckAll();
				}
				break;
			}
			case PBEAbility.Anticipation:
			{
				foreach (PBEBattlePokemon opponent in pkmn.Team.OpposingTeam.ActiveBattlers)
				{
					foreach (PBEBattleMoveset.PBEBattleMovesetSlot moveSlot in opponent.Moves)
					{
						PBEMove move = moveSlot.Move;
						if (move != PBEMove.None)
						{
							IPBEMoveData mData = PBEDataProvider.Instance.GetMoveData(move);
							if (mData.Category != PBEMoveCategory.Status)
							{
								float d = PBETypeEffectiveness.GetEffectiveness(mData.Type, pkmn);
								if (d > 1)
								{
									BroadcastAbility(pkmn, pkmn, PBEAbility.Anticipation, PBEAbilityAction.Announced);
									goto bottomAnticipation;
								}
							}
						}
					}
				}
			bottomAnticipation:
				break;
			}
			case PBEAbility.Download:
			{
				List<PBEBattlePokemon> oppActive = pkmn.Team.OpposingTeam.ActiveBattlers;
				if (oppActive.Count != 0)
				{
					PBEStat stat = oppActive.Average(p => p.Defense * GetStatChangeModifier(p.DefenseChange, false))
								< oppActive.Average(p => p.SpDefense * GetStatChangeModifier(p.SpDefenseChange, false))
								? PBEStat.Attack : PBEStat.SpAttack;
					if (pkmn.GetStatChange(stat) < Settings.MaxStatChange)
					{
						BroadcastAbility(pkmn, pkmn, PBEAbility.Download, PBEAbilityAction.Stats);
						ApplyStatChangeIfPossible(pkmn, pkmn, stat, +1);
					}
				}
				break;
			}
			case PBEAbility.Drizzle:
			{
				if (Weather != PBEWeather.Rain || WeatherCounter != 0)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Weather);
					SetWeather(PBEWeather.Rain, 0, switchIn);
				}
				break;
			}
			case PBEAbility.Drought:
			{
				if (Weather != PBEWeather.HarshSunlight || WeatherCounter != 0)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Weather);
					SetWeather(PBEWeather.HarshSunlight, 0, switchIn);
				}
				break;
			}
			case PBEAbility.Imposter:
			{
				PBEFieldPosition targetPos = GetPositionAcross(BattleFormat, pkmn.FieldPosition);
				if (pkmn.Team.OpposingTeam.TryGetPokemon(targetPos, out PBEBattlePokemon? target)
					&& target.IsTransformPossible(pkmn) == PBEResult.Success)
				{
					BroadcastAbility(pkmn, target, pkmn.Ability, PBEAbilityAction.ChangedAppearance);
					DoTransform(pkmn, target);
				}
				break;
			}
			case PBEAbility.Intimidate:
			{
				// Verified: Do not announce if the positions are empty
				IReadOnlyList<PBEBattlePokemon> targets = GetRuntimeSurrounding(pkmn, false, true);
				if (targets.Count > 0)
				{
					// Verified: Announce even if nobody is lowered (due to Substitute, Minimized Attack, or Ability)
					BroadcastAbility(pkmn, pkmn, PBEAbility.Intimidate, PBEAbilityAction.Stats);
					foreach (PBEBattlePokemon target in GetActingOrder(targets, true))
					{
						ApplyStatChangeIfPossible(pkmn, target, PBEStat.Attack, -1); // Verified: Substitute, Minimized Attack, and Ability are announced
					}
				}
				break;
			}
			case PBEAbility.MoldBreaker:
			case PBEAbility.Teravolt:
			case PBEAbility.Turboblaze:
			{
				BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Announced);
				break;
			}
			case PBEAbility.SandStream:
			{
				if (Weather != PBEWeather.Sandstorm || WeatherCounter != 0)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Weather);
					SetWeather(PBEWeather.Sandstorm, 0, switchIn);
				}
				break;
			}
			case PBEAbility.SlowStart:
			{
				pkmn.SlowStart_HinderTurnsLeft = 5;
				BroadcastAbility(pkmn, pkmn, PBEAbility.SlowStart, PBEAbilityAction.Announced);
				break;
			}
			case PBEAbility.SnowWarning:
			{
				if (Weather != PBEWeather.Hailstorm || WeatherCounter != 0)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.Weather);
					SetWeather(PBEWeather.Hailstorm, 0, switchIn);
				}
				break;
			}
		}
	}
	private void CastformCherrimCheckAll()
	{
		CastformCherrimCheck(GetActingOrder(ActiveBattlers, true));
	}
	private void CastformCherrimCheck(IEnumerable<PBEBattlePokemon> order)
	{
		foreach (PBEBattlePokemon pkmn in order)
		{
			CastformCherrimCheck(pkmn);
		}
	}
	private void CastformCherrimCheck(PBEBattlePokemon pkmn)
	{
		if (pkmn.HP == 0)
		{
			return; // #344 - Castform/Cherrim can change form while fainting from Explosion, if they kill someone with a weather-blocking ability
		}
		if (pkmn.Species == PBESpecies.Castform && pkmn.OriginalSpecies == PBESpecies.Castform)
		{
			PBEForm newForm = PBEForm.Castform;
			if (pkmn.Ability == PBEAbility.Forecast && ShouldDoWeatherEffects())
			{
				switch (Weather)
				{
					case PBEWeather.Hailstorm: newForm = PBEForm.Castform_Snowy; break;
					case PBEWeather.HarshSunlight: newForm = PBEForm.Castform_Sunny; break;
					case PBEWeather.Rain: newForm = PBEForm.Castform_Rainy; break;
				}
				if (newForm != pkmn.Form)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedAppearance);
				}
			}
			if (newForm != pkmn.Form)
			{
				BroadcastPkmnFormChanged(pkmn, newForm, pkmn.Ability, pkmn.KnownAbility, false);
			}
		}
		else if (pkmn.Species == PBESpecies.Cherrim && pkmn.OriginalSpecies == PBESpecies.Cherrim)
		{
			PBEForm newForm = PBEForm.Cherrim;
			if (pkmn.Ability == PBEAbility.FlowerGift && ShouldDoWeatherEffects())
			{
				if (Weather == PBEWeather.HarshSunlight)
				{
					newForm = PBEForm.Cherrim_Sunshine;
				}
				if (newForm != pkmn.Form)
				{
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedAppearance);
				}
			}
			if (newForm != pkmn.Form)
			{
				BroadcastPkmnFormChanged(pkmn, newForm, pkmn.Ability, pkmn.KnownAbility, false);
			}
		}
	}
	private void ShayminCheck(PBEBattlePokemon pkmn)
	{
		// If a Shaymin_Sky is given MagmaArmor and then Frozen, it will change to Shaymin and obtain Shaymin's ability, therefore losing MagmaArmor and as a result will not be cured of its Frozen status.
		if (pkmn.Species == PBESpecies.Shaymin && pkmn.OriginalSpecies == PBESpecies.Shaymin && pkmn.Form == PBEForm.Shaymin_Sky && pkmn.Status1 == PBEStatus1.Frozen)
		{
			const PBEForm newForm = PBEForm.Shaymin;
			PBEAbility newAbility = PBEDataProvider.Instance.GetPokemonData(PBESpecies.Shaymin, newForm).Abilities[0];
			BroadcastPkmnFormChanged(pkmn, newForm, newAbility, PBEAbility.MAX, true);
			ActivateAbility(pkmn, false);
		}
	}
	private void IllusionBreak(PBEBattlePokemon pkmn, PBEBattlePokemon breaker)
	{
		if (pkmn.Status2.HasFlag(PBEStatus2.Disguised))
		{
			pkmn.KnownGender = pkmn.Gender;
			pkmn.KnownCaughtBall = pkmn.CaughtBall;
			pkmn.KnownNickname = pkmn.Nickname;
			pkmn.KnownShiny = pkmn.Shiny;
			pkmn.KnownSpecies = pkmn.Species;
			pkmn.KnownType1 = pkmn.Type1;
			pkmn.KnownType2 = pkmn.Type2;
			BroadcastIllusion(pkmn);
			BroadcastAbility(pkmn, breaker, PBEAbility.Illusion, PBEAbilityAction.ChangedAppearance);
			BroadcastStatus2(pkmn, breaker, PBEStatus2.Disguised, PBEStatusAction.Ended);
		}
	}
	private void AntiStatusAbilityCheck(IEnumerable<PBEBattlePokemon> order)
	{
		foreach (PBEBattlePokemon pkmn in order)
		{
			AntiStatusAbilityCheck(pkmn);
		}
	}
	private void AntiStatusAbilityCheck(PBEBattlePokemon pkmn)
	{
		switch (pkmn.Ability)
		{
			case PBEAbility.Immunity:
			{
				if (pkmn.Status1 == PBEStatus1.BadlyPoisoned || pkmn.Status1 == PBEStatus1.Poisoned)
				{
					PBEStatus1 oldStatus1 = pkmn.Status1;
					pkmn.Status1 = PBEStatus1.None;
					pkmn.Status1Counter = 0;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus1(pkmn, pkmn, oldStatus1, PBEStatusAction.Cleared);
				}
				break;
			}
			case PBEAbility.Insomnia:
			case PBEAbility.VitalSpirit:
			{
				if (pkmn.Status1 == PBEStatus1.Asleep)
				{
					pkmn.Status1 = PBEStatus1.None;
					pkmn.Status1Counter = 0;
					pkmn.SleepTurns = 0;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus1(pkmn, pkmn, PBEStatus1.Asleep, PBEStatusAction.Cleared);
					CureNightmare(pkmn, pkmn);
				}
				break;
			}
			case PBEAbility.Limber:
			{
				if (pkmn.Status1 == PBEStatus1.Paralyzed)
				{
					pkmn.Status1 = PBEStatus1.None;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus1(pkmn, pkmn, PBEStatus1.Paralyzed, PBEStatusAction.Cleared);
				}
				break;
			}
			case PBEAbility.MagmaArmor:
			{
				if (pkmn.Status1 == PBEStatus1.Frozen)
				{
					pkmn.Status1 = PBEStatus1.None;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus1(pkmn, pkmn, PBEStatus1.Frozen, PBEStatusAction.Cleared);
				}
				break;
			}
			case PBEAbility.Oblivious:
			{
				if (pkmn.Status2.HasFlag(PBEStatus2.Infatuated))
				{
					pkmn.InfatuatedWithPokemon = null;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus2(pkmn, pkmn, PBEStatus2.Infatuated, PBEStatusAction.Cleared);
				}
				break;
			}
			case PBEAbility.OwnTempo:
			{
				if (pkmn.Status2.HasFlag(PBEStatus2.Confused))
				{
					pkmn.ConfusionCounter = 0;
					pkmn.ConfusionTurns = 0;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus2(pkmn, pkmn, PBEStatus2.Confused, PBEStatusAction.Cleared);
				}
				break;
			}
			case PBEAbility.WaterVeil:
			{
				if (pkmn.Status1 == PBEStatus1.Burned)
				{
					pkmn.Status1 = PBEStatus1.None;
					BroadcastAbility(pkmn, pkmn, pkmn.Ability, PBEAbilityAction.ChangedStatus);
					BroadcastStatus1(pkmn, pkmn, PBEStatus1.Burned, PBEStatusAction.Cleared);
				}
				break;
			}
		}
	}
	private void CauseConfusion(PBEBattlePokemon target, PBEBattlePokemon other)
	{
		target.ConfusionCounter = 0;
		target.ConfusionTurns = (byte)_rand.RandomInt(Settings.ConfusionMinTurns, Settings.ConfusionMaxTurns);
		BroadcastStatus2(target, other, PBEStatus2.Confused, PBEStatusAction.Added);
		AntiStatusAbilityCheck(target);
	}
	private void CauseInfatuation(PBEBattlePokemon target, PBEBattlePokemon other)
	{
		target.InfatuatedWithPokemon = other;
		BroadcastStatus2(target, other, PBEStatus2.Infatuated, PBEStatusAction.Added);
		if (target.Item == PBEItem.DestinyKnot && other.IsAttractionPossible(target) == PBEResult.Success)
		{
			BroadcastItem(target, other, PBEItem.DestinyKnot, PBEItemAction.Announced);
			other.InfatuatedWithPokemon = target;
			BroadcastStatus2(other, target, PBEStatus2.Infatuated, PBEStatusAction.Added);
		}
		AntiStatusAbilityCheck(target);
	}
	// TODO: Use & add packet handlers
	private void WhiteHerbCheck(PBEBattlePokemon pkmn)
	{
		if (pkmn.Item == PBEItem.WhiteHerb)
		{
			PBEStat[] negStats = pkmn.GetStatsLessThan(0);
			if (negStats.Length > 0)
			{
				foreach (PBEStat s in negStats)
				{
					pkmn.SetStatChange(s, 0);
				}
				BroadcastItem(pkmn, pkmn, PBEItem.WhiteHerb, PBEItemAction.Consumed);
			}
		}
	}
	private bool PowerHerbCheck(PBEBattlePokemon pkmn)
	{
		if (pkmn.Item == PBEItem.PowerHerb)
		{
			BroadcastItem(pkmn, pkmn, PBEItem.PowerHerb, PBEItemAction.Consumed);
			return true;
		}
		return false;
	}
	private void LowHPBerryCheck(IEnumerable<PBEBattlePokemon> order, PBEBattlePokemon? forcedToEatBy = null)
	{
		foreach (PBEBattlePokemon pkmn in order)
		{
			LowHPBerryCheck(pkmn, forcedToEatBy: forcedToEatBy);
		}
	}
	private void LowHPBerryCheck(PBEBattlePokemon pkmn, PBEBattlePokemon? forcedToEatBy = null)
	{
		forcedToEatBy ??= pkmn;
		void DoConfuseBerry(PBEFlavor flavor)
		{
			BroadcastItem(pkmn, forcedToEatBy, pkmn.Item, PBEItemAction.Consumed);
			HealDamage(pkmn, pkmn.MaxHP / 8);
			// Verified: Ignores Safeguard & Substitute, but not Own Tempo
			// Mold Breaker etc actually affect whether Own Tempo is ignored, which is what forcedToEatBy is for
			// I verified each of the times the Pokémon eats to check if Mold Breaker affected the outcome
			if (pkmn.Nature.GetRelationshipToFlavor(flavor) < 0 && pkmn.IsConfusionPossible(forcedToEatBy, ignoreSubstitute: true, ignoreSafeguard: true) == PBEResult.Success)
			{
				CauseConfusion(pkmn, forcedToEatBy);
			}
		}
		void DoHealItem(int hp)
		{
			BroadcastItem(pkmn, forcedToEatBy, pkmn.Item, PBEItemAction.Consumed);
			HealDamage(pkmn, hp);
		}
		void DoStatItem(PBEStat stat, int change)
		{
			// Verified: Mold Breaker affects Contrary/Simple here, unlike with Belly Drum
			if (pkmn.IsStatChangePossible(stat, forcedToEatBy, change, out sbyte oldValue, out sbyte newValue, ignoreSubstitute: true) == PBEResult.Success)
			{
				BroadcastItem(pkmn, forcedToEatBy, pkmn.Item, PBEItemAction.Consumed);
				SetStatAndBroadcast(pkmn, stat, oldValue, newValue);
			}
		}

		if (pkmn.HP <= pkmn.MaxHP / 4)
		{
			switch (pkmn.Item)
			{
				case PBEItem.ApicotBerry: DoStatItem(PBEStat.SpDefense, +1); break;
				case PBEItem.GanlonBerry: DoStatItem(PBEStat.Defense, +1); break;
				case PBEItem.LiechiBerry: DoStatItem(PBEStat.Attack, +1); break;
				case PBEItem.PetayaBerry: DoStatItem(PBEStat.SpAttack, +1); break;
				case PBEItem.SalacBerry: DoStatItem(PBEStat.Speed, +1); break;
				case PBEItem.StarfBerry:
				{
					// Verified: Starf Berry does not activate for Accuracy or Evasion, or if all other stats are maximized
					List<PBEStat> statsThatCanGoUp = PBEDataUtils.StarfBerryStats.FindAll(s => pkmn.GetStatChange(s) < Settings.MaxStatChange);
					if (statsThatCanGoUp.Count > 0)
					{
						DoStatItem(_rand.RandomElement(statsThatCanGoUp), +2);
					}
					break;
				}
			}
		}
		if (pkmn.HP <= pkmn.MaxHP / 2)
		{
			switch (pkmn.Item)
			{
				case PBEItem.AguavBerry: DoConfuseBerry(PBEFlavor.Bitter); break;
				case PBEItem.BerryJuice: DoHealItem(20); break;
				case PBEItem.FigyBerry: DoConfuseBerry(PBEFlavor.Spicy); break;
				case PBEItem.IapapaBerry: DoConfuseBerry(PBEFlavor.Sour); break;
				case PBEItem.MagoBerry: DoConfuseBerry(PBEFlavor.Sweet); break;
				case PBEItem.OranBerry: DoHealItem(10); break;
				case PBEItem.SitrusBerry: DoHealItem(pkmn.MaxHP / 4); break;
				case PBEItem.WikiBerry: DoConfuseBerry(PBEFlavor.Dry); break;
			}
		}
	}
	private void SetAbility(PBEBattlePokemon user, PBEBattlePokemon target, PBEAbility ability)
	{
		// This func assumes new ability is different from current
		PBEAbility oldAbility = target.Ability;
		BroadcastAbilityReplaced(target, ability);

		switch (oldAbility)
		{
			case PBEAbility.Illusion:
			{
				IllusionBreak(target, user);
				break;
			}
			case PBEAbility.SlowStart:
			{
				target.SlowStart_HinderTurnsLeft = 0;
				break;
			}
			case PBEAbility.SpeedBoost:
			{
				target.SpeedBoost_AbleToSpeedBoostThisTurn = false;
				break;
			}
		}

		ActivateAbility(target, false);
	}
	private void SetWeather(PBEWeather weather, byte weatherCounter, bool switchIn)
	{
		Weather = weather;
		WeatherCounter = weatherCounter;
		BroadcastWeather(Weather, PBEWeatherAction.Added);
		if (!switchIn)
		{
			CastformCherrimCheckAll(); // Switch-Ins check this after all Pokémon are sent out
		}
	}

	private void RecordExecutedMove(PBEBattlePokemon user, PBEMove move, IPBEMoveData mData)
	{
		user.HasUsedMoveThisTurn = true;
		// Doesn't care if there is a Choice Locked move already. As long as the user knows it, it will become locked. (Metronome calling a move the user knows, Ditto transforming into someone else with transform)
		if ((user.Item == PBEItem.ChoiceBand || user.Item == PBEItem.ChoiceScarf || user.Item == PBEItem.ChoiceSpecs) && user.Moves.Contains(move))
		{
			BroadcastMoveLock_ChoiceItem(user, move);
		}
		if (mData.Effect == PBEMoveEffect.Minimize)
		{
			user.Minimize_Used = true;
		}
	}
	private void PPReduce(PBEBattlePokemon pkmn, PBEMove move)
	{
		if (!_calledFromOtherMove)
		{
			const int amountToReduce = 1;
			// TODO: If target is not self and has pressure
			PBEBattleMoveset.PBEBattleMovesetSlot slot = pkmn.Moves[move]!;
			int oldPP = slot.PP;
			int newPP = Math.Max(0, oldPP - amountToReduce);
			int amountReduced = oldPP - newPP;
			slot.PP = newPP;
			pkmn.UpdateKnownPP(move, amountReduced);
			BroadcastMovePPChanged(pkmn, move, amountReduced);
		}
	}

	private static void ApplyBigRoot(PBEBattlePokemon pkmn, ref int restoreAmt)
	{
		if (pkmn.Item == PBEItem.BigRoot)
		{
			restoreAmt += (int)(restoreAmt * 0.3);
		}
	}
	private void CureNightmare(PBEBattlePokemon wakingUp, PBEBattlePokemon pokemon2)
	{
		if (wakingUp.Status2.HasFlag(PBEStatus2.Nightmare))
		{
			BroadcastStatus2(wakingUp, pokemon2, PBEStatus2.Nightmare, PBEStatusAction.Ended);
		}
	}
	private void SetSleepTurns(PBEBattlePokemon pkmn, int minTurns, int maxTurns)
	{
		pkmn.SleepTurns = (byte)(_rand.RandomInt(minTurns, maxTurns) / (pkmn.Ability == PBEAbility.EarlyBird ? 2 : 1));
	}
	private void DoTransform(PBEBattlePokemon user, PBEBattlePokemon target)
	{
		user.Transform(target);
		BroadcastTransform(user, target);
		BroadcastStatus2(user, target, PBEStatus2.Transformed, PBEStatusAction.Added);
		// Remove power trick (so it cannot be baton passed)
		if (user.Status2.HasFlag(PBEStatus2.PowerTrick))
		{
			BroadcastStatus2(user, user, PBEStatus2.PowerTrick, PBEStatusAction.Ended);
		}
		if (!user.Moves.Contains(user.ChoiceLockedMove))
		{
			BroadcastMoveLock_ChoiceItem(user, PBEMove.None);
		}
	}
	private PBEResult ApplyStatus1IfPossible(PBEBattlePokemon user, PBEBattlePokemon target, PBEStatus1 status, bool broadcastUnsuccessful)
	{
		PBEResult result;
		switch (status)
		{
			case PBEStatus1.Asleep: result = target.IsSleepPossible(user); break;
			case PBEStatus1.BadlyPoisoned:
			case PBEStatus1.Poisoned: result = target.IsPoisonPossible(user); break;
			case PBEStatus1.Burned: result = target.IsBurnPossible(user); break;
			case PBEStatus1.Frozen: result = target.IsFreezePossible(user); break;
			case PBEStatus1.Paralyzed: result = target.IsParalysisPossible(user); break;
			default: throw new ArgumentOutOfRangeException(nameof(status));
		}
		if (result == PBEResult.Success)
		{
			target.Status1 = status;
			if (status == PBEStatus1.BadlyPoisoned)
			{
				target.Status1Counter = 1;
			}
			else if (status == PBEStatus1.Asleep)
			{
				SetSleepTurns(target, Settings.SleepMinTurns, Settings.SleepMaxTurns);
				target.Status1Counter = 0;
			}
			BroadcastStatus1(target, user, status, PBEStatusAction.Added);
			ShayminCheck(target);
		}
		else if (broadcastUnsuccessful)
		{
			if (result == PBEResult.Ineffective_Ability)
			{
				BroadcastAbility(target, user, target.Ability, PBEAbilityAction.PreventedStatus);
			}
			BroadcastMoveResult(user, target, result);
		}
		return result;
	}
	private PBEResult ApplyStatus2IfPossible(PBEBattlePokemon user, PBEBattlePokemon target, PBEStatus2 status, bool broadcastUnsuccessful)
	{
		PBEResult result;
		switch (status)
		{
			case PBEStatus2.Confused:
			{
				result = target.IsConfusionPossible(user);
				if (result == PBEResult.Success)
				{
					CauseConfusion(target, user);
				}
				break;
			}
			case PBEStatus2.Cursed:
			{
				if (!target.Status2.HasFlag(PBEStatus2.Cursed))
				{
					BroadcastStatus2(target, user, PBEStatus2.Cursed, PBEStatusAction.Added);
					DealDamage(user, user, user.MaxHP / 2);
					if (!FaintCheck(user))
					{
						LowHPBerryCheck(user);
					}
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBEStatus2.Flinching:
			{
				result = target.IsFlinchPossible(user);
				if (result == PBEResult.Success)
				{
					target.Status2 |= PBEStatus2.Flinching; // No broadcast, not known
				}
				break;
			}
			case PBEStatus2.HelpingHand:
			{
				if (!target.HasUsedMoveThisTurn)
				{
					BroadcastStatus2(target, user, PBEStatus2.HelpingHand, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.InvalidConditions;
				}
				break;
			}
			case PBEStatus2.Identified:
			{
				if (!target.Status2.HasFlag(PBEStatus2.Identified))
				{
					BroadcastStatus2(target, user, PBEStatus2.Identified, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBEStatus2.Infatuated:
			{
				result = target.IsAttractionPossible(user);
				if (result == PBEResult.Success)
				{
					CauseInfatuation(target, user);
				}
				break;
			}
			case PBEStatus2.LeechSeed:
			{
				result = target.IsLeechSeedPossible();
				if (result == PBEResult.Success)
				{
					target.SeededPosition = user.FieldPosition;
					target.SeededTeam = user.Team;
					BroadcastStatus2(target, user, PBEStatus2.LeechSeed, PBEStatusAction.Added);
				}
				break;
			}
			case PBEStatus2.LockOn:
			{
				if (!user.Status2.HasFlag(PBEStatus2.LockOn))
				{
					user.LockOnPokemon = target;
					user.LockOnTurns = 2;
					BroadcastStatus2(user, target, PBEStatus2.LockOn, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBEStatus2.MagnetRise:
			{
				result = target.IsMagnetRisePossible();
				if (result == PBEResult.Success)
				{
					target.MagnetRiseTurns = 5;
					BroadcastStatus2(target, user, PBEStatus2.MagnetRise, PBEStatusAction.Added);
				}
				break;
			}
			case PBEStatus2.MiracleEye:
			{
				if (!target.Status2.HasFlag(PBEStatus2.MiracleEye))
				{
					BroadcastStatus2(target, user, PBEStatus2.MiracleEye, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBEStatus2.Nightmare:
			{
				if (target.Status1 == PBEStatus1.Asleep && !target.Status2.HasFlag(PBEStatus2.Nightmare))
				{
					BroadcastStatus2(target, user, PBEStatus2.Nightmare, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBEStatus2.PowerTrick:
			{
				target.ApplyPowerTrickChange();
				BroadcastStatus2(target, user, PBEStatus2.PowerTrick, PBEStatusAction.Added);
				result = PBEResult.Success;
				break;
			}
			case PBEStatus2.Protected:
			{
				// TODO: If the user goes last, fail
				if (_rand.RandomBool(user.GetProtectionChance(), ushort.MaxValue))
				{
					user.Protection_Used = true;
					BroadcastStatus2(user, user, PBEStatus2.Protected, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.InvalidConditions;
				}
				break;
			}
			case PBEStatus2.Pumped:
			{
				if (!target.Status2.HasFlag(PBEStatus2.Pumped))
				{
					BroadcastStatus2(target, user, PBEStatus2.Pumped, PBEStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBEStatus2.Substitute:
			{
				result = target.IsSubstitutePossible();
				if (result == PBEResult.Success)
				{
					int hpRequired = target.MaxHP / 4;
					DealDamage(user, target, hpRequired);
					LowHPBerryCheck(target); // Verified: Berry is eaten between damage and substitute
					target.SubstituteHP = (ushort)hpRequired;
					BroadcastStatus2(target, user, PBEStatus2.Substitute, PBEStatusAction.Added);
				}
				break;
			}
			case PBEStatus2.Transformed:
			{
				result = target.IsTransformPossible(user);
				if (result == PBEResult.Success)
				{
					DoTransform(user, target);
				}
				break;
			}
			default: throw new ArgumentOutOfRangeException(nameof(status));
		}
		if (broadcastUnsuccessful && result != PBEResult.Success)
		{
			if (result == PBEResult.Ineffective_Ability)
			{
				BroadcastAbility(target, user, target.Ability, PBEAbilityAction.PreventedStatus);
			}
			BroadcastMoveResult(user, target, result);
		}
		return result;
	}
	private void ApplyStatChangeIfPossible(PBEBattlePokemon user, PBEBattlePokemon target, PBEStat stat, int change, bool isSecondaryEffect = false)
	{
		PBEResult result = target.IsStatChangePossible(stat, user, change, out sbyte oldValue, out sbyte newValue);
		bool broadcast;
		if (result == PBEResult.Success)
		{
			target.SetStatChange(stat, newValue);
			broadcast = true;
		}
		else
		{
			if (result == PBEResult.Ineffective_Ability)
			{
				if (!isSecondaryEffect)
				{
					BroadcastAbility(target, user, target.Ability, PBEAbilityAction.Stats);
				}
				return;
			}
			if (result == PBEResult.Ineffective_Substitute)
			{
				if (!isSecondaryEffect)
				{
					BroadcastMoveResult(user, target, PBEResult.Ineffective_Substitute);
				}
				return;
			}
			// Do not broadcast "could not be lowered!" for Mud-Slap, etc
			broadcast = !isSecondaryEffect;
		}
		if (broadcast)
		{
			BroadcastPkmnStatChanged(target, stat, oldValue, newValue);
		}
	}
	private void SetStatAndBroadcast(PBEBattlePokemon pkmn, PBEStat stat, sbyte oldValue, sbyte newValue)
	{
		pkmn.SetStatChange(stat, newValue);
		BroadcastPkmnStatChanged(pkmn, stat, oldValue, newValue);
	}

	private static PBEPkmnAppearedInfo CreateSwitchInInfo(PBEBattlePokemon pkmn)
	{
		if (pkmn.Ability == PBEAbility.Illusion)
		{
			PBEBattlePokemon? p = pkmn.GetPkmnWouldDisguiseAs();
			if (p is not null)
			{
				pkmn.Status2 |= PBEStatus2.Disguised; // No broadcast, not known
				pkmn.KnownGender = p.Gender;
				pkmn.KnownCaughtBall = p.CaughtBall;
				pkmn.KnownNickname = p.Nickname;
				pkmn.KnownShiny = p.Shiny;
				pkmn.KnownSpecies = p.OriginalSpecies;
				pkmn.KnownForm = p.Form;
				IPBEPokemonData pData = PBEDataProvider.Instance.GetPokemonData(pkmn.KnownSpecies, pkmn.KnownForm);
				pkmn.KnownType1 = pData.Type1;
				pkmn.KnownType2 = pData.Type2;
			}
		}
		return new PBEPkmnAppearedInfo(pkmn);
	}
	private void SwitchTwoPokemon(PBEBattlePokemon pkmnLeaving, PBEBattlePokemon pkmnComing, PBEBattlePokemon? forcedByPkmn = null)
	{
		_turnOrder.Remove(pkmnLeaving);
		ActiveBattlers.Remove(pkmnLeaving);
		PBEFieldPosition pos = pkmnLeaving.FieldPosition;
		pkmnLeaving.ClearForSwitch();
		BroadcastPkmnSwitchOut(pkmnLeaving, pos, forcedByPkmn);
		RemoveInfatuationsAndLockOns(pkmnLeaving);
		pkmnComing.FieldPosition = pos;
		var switches = new PBEPkmnAppearedInfo[] { CreateSwitchInInfo(pkmnComing) };
		PBETrainer.SwitchTwoPokemon(pkmnLeaving, pkmnComing); // Swap after Illusion
		ActiveBattlers.Add(pkmnComing); // Add to active before broadcast
		BroadcastPkmnSwitchIn(pkmnComing.Trainer, switches, forcedByPkmn);
		if (forcedByPkmn is not null)
		{
			BroadcastDraggedOut(pkmnComing);
		}
		DoSwitchInEffects(new[] { pkmnComing }, forcedByPkmn);
		CastformCherrimCheckAll();
	}
	private void RemoveInfatuationsAndLockOns(PBEBattlePokemon pkmnLeaving)
	{
		foreach (PBEBattlePokemon pkmn in ActiveBattlers)
		{
			if (pkmn.Status2.HasFlag(PBEStatus2.Infatuated) && pkmn.InfatuatedWithPokemon == pkmnLeaving)
			{
				pkmn.InfatuatedWithPokemon = null;
				BroadcastStatus2(pkmn, pkmn, PBEStatus2.Infatuated, PBEStatusAction.Ended);
			}
			if (pkmn.Status2.HasFlag(PBEStatus2.LockOn) && pkmn.LockOnPokemon == pkmnLeaving)
			{
				pkmn.LockOnPokemon = null;
				pkmn.LockOnTurns = 0;
				BroadcastStatus2(pkmn, pkmn, PBEStatus2.LockOn, PBEStatusAction.Ended);
			}
		}
	}

	private void SemiInvulnerableChargeMove(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBETurnTarget requestedTargets, PBEStatus2 status2,
		Action<PBEBattlePokemon, ushort>? beforePostHit = null,
		Action<PBEBattlePokemon>? afterPostHit = null)
	{
		BroadcastMoveUsed(user, move);
	top:
		if (user.Status2.HasFlag(status2))
		{
			BroadcastMoveLock_Temporary(user, PBEMove.None, PBETurnTarget.None);
			BroadcastStatus2(user, user, status2, PBEStatusAction.Ended);
			if (targets.Length == 0)
			{
				BroadcastMoveResult(user, user, PBEResult.NoTarget);
			}
			else
			{
				BasicHit(user, targets, mData, beforePostHit: beforePostHit, afterPostHit: afterPostHit);
			}
			RecordExecutedMove(user, move, mData); // Should only count as the last used move if it finishes charging
		}
		else
		{
			PPReduce(user, move);
			BroadcastMoveLock_Temporary(user, move, requestedTargets);
			BroadcastStatus2(user, user, status2, PBEStatusAction.Added);
			if (PowerHerbCheck(user))
			{
				goto top;
			}
		}
	}

	private void Ef_TryForceStatus1(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBEStatus1 status, bool thunderWave = false)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			foreach (PBEBattlePokemon target in targets)
			{
				if (!MissCheck(user, target, mData))
				{
					if (thunderWave)
					{
						PBEResult result = PBETypeEffectiveness.ThunderWaveTypeCheck(user, target, move);
						if (result != PBEResult.Success)
						{
							BroadcastMoveResult(user, target, result);
							continue;
						}
					}
					ApplyStatus1IfPossible(user, target, status, true);
					AntiStatusAbilityCheck(target);
				}
			}
		}
		RecordExecutedMove(user, move, mData);
		return;
	}
	private void Ef_TryForceStatus2(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBEStatus2 status)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			foreach (PBEBattlePokemon target in targets)
			{
				if (!MissCheck(user, target, mData))
				{
					ApplyStatus2IfPossible(user, target, status, true);
					AntiStatusAbilityCheck(target);
				}
			}
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_TryForceBattleStatus(PBEBattlePokemon user, PBEMove move, IPBEMoveData mData, PBEBattleStatus status)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		switch (status)
		{
			case PBEBattleStatus.TrickRoom:
			{
				if (!BattleStatus.HasFlag(PBEBattleStatus.TrickRoom))
				{
					TrickRoomCount = 5;
					BroadcastBattleStatus(PBEBattleStatus.TrickRoom, PBEBattleStatusAction.Added);
				}
				else
				{
					TrickRoomCount = 0;
					BroadcastBattleStatus(PBEBattleStatus.TrickRoom, PBEBattleStatusAction.Cleared);
				}
				break;
			}
			default: throw new ArgumentOutOfRangeException(nameof(status));
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_TryForceTeamStatus(PBEBattlePokemon user, PBEMove move, IPBEMoveData mData, PBETeamStatus status)
	{
		PBEResult result;
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		switch (status)
		{
			case PBETeamStatus.LightScreen:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.LightScreen))
				{
					user.Team.LightScreenCount = (byte)(Settings.LightScreenTurns + (user.Item == PBEItem.LightClay ? Settings.LightClayTurnExtension : 0));
					BroadcastTeamStatus(user.Team, PBETeamStatus.LightScreen, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.LuckyChant:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.LuckyChant))
				{
					user.Team.LuckyChantCount = 5;
					BroadcastTeamStatus(user.Team, PBETeamStatus.LuckyChant, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.QuickGuard:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.QuickGuard) && _rand.RandomBool(user.GetProtectionChance(), ushort.MaxValue))
				{
					user.Protection_Used = true;
					BroadcastTeamStatus(user.Team, PBETeamStatus.QuickGuard, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.Reflect:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.Reflect))
				{
					user.Team.ReflectCount = (byte)(Settings.ReflectTurns + (user.Item == PBEItem.LightClay ? Settings.LightClayTurnExtension : 0));
					BroadcastTeamStatus(user.Team, PBETeamStatus.Reflect, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.Safeguard:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.Safeguard))
				{
					user.Team.SafeguardCount = 5;
					BroadcastTeamStatus(user.Team, PBETeamStatus.Safeguard, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.Spikes:
			{
				if (user.Team.OpposingTeam.SpikeCount < 3)
				{
					user.Team.OpposingTeam.SpikeCount++;
					BroadcastTeamStatus(user.Team.OpposingTeam, PBETeamStatus.Spikes, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.StealthRock:
			{
				if (!user.Team.OpposingTeam.TeamStatus.HasFlag(PBETeamStatus.StealthRock))
				{
					BroadcastTeamStatus(user.Team.OpposingTeam, PBETeamStatus.StealthRock, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.Tailwind:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.Tailwind))
				{
					user.Team.TailwindCount = 4;
					BroadcastTeamStatus(user.Team, PBETeamStatus.Tailwind, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.ToxicSpikes:
			{
				if (user.Team.OpposingTeam.ToxicSpikeCount < 2)
				{
					user.Team.OpposingTeam.ToxicSpikeCount++;
					BroadcastTeamStatus(user.Team.OpposingTeam, PBETeamStatus.ToxicSpikes, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			case PBETeamStatus.WideGuard:
			{
				if (!user.Team.TeamStatus.HasFlag(PBETeamStatus.WideGuard) && _rand.RandomBool(user.GetProtectionChance(), ushort.MaxValue))
				{
					user.Protection_Used = true;
					BroadcastTeamStatus(user.Team, PBETeamStatus.WideGuard, PBETeamStatusAction.Added);
					result = PBEResult.Success;
				}
				else
				{
					result = PBEResult.Ineffective_Status;
				}
				break;
			}
			default: throw new ArgumentOutOfRangeException(nameof(status));
		}
		if (result != PBEResult.Success)
		{
			BroadcastMoveResult(user, user, result);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_TryForceWeather(PBEBattlePokemon user, PBEMove move, IPBEMoveData mData, PBEWeather weather)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (Weather == weather)
		{
			BroadcastMoveResult(user, user, PBEResult.Ineffective_Status);
		}
		else
		{
			byte turns;
			PBEItem extensionItem;
			byte itemTurnExtension;
			switch (weather)
			{
				case PBEWeather.Hailstorm:
				{
					turns = Settings.HailTurns;
					extensionItem = PBEItem.IcyRock;
					itemTurnExtension = Settings.IcyRockTurnExtension;
					break;
				}
				case PBEWeather.HarshSunlight:
				{
					turns = Settings.SunTurns;
					extensionItem = PBEItem.HeatRock;
					itemTurnExtension = Settings.HeatRockTurnExtension;
					break;
				}
				case PBEWeather.Rain:
				{
					turns = Settings.RainTurns;
					extensionItem = PBEItem.DampRock;
					itemTurnExtension = Settings.DampRockTurnExtension;
					break;
				}
				case PBEWeather.Sandstorm:
				{
					turns = Settings.SandstormTurns;
					extensionItem = PBEItem.SmoothRock;
					itemTurnExtension = Settings.SmoothRockTurnExtension;
					break;
				}
				default: throw new ArgumentOutOfRangeException(nameof(weather));
			}
			SetWeather(weather, (byte)(turns + (user.Item == extensionItem ? itemTurnExtension : 0)), false);
		}
		RecordExecutedMove(user, move, mData);
	}

	private void Ef_Growth(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		int change = WillLeafGuardActivate() ? +2 : +1;
		Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, change), (PBEStat.SpAttack, change) });
	}
	private void Ef_ChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, (PBEStat, int)[] statChanges, bool requireAttraction = false)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			foreach (PBEBattlePokemon target in targets)
			{
				if (!MissCheck(user, target, mData))
				{
					PBEResult result = requireAttraction ? target.IsAttractionPossible(user, ignoreCurrentStatus: true) : PBEResult.Success;
					if (result != PBEResult.Success)
					{
						BroadcastMoveResult(user, target, result);
					}
					else if (user != target && target.Status2.HasFlag(PBEStatus2.Substitute))
					{
						BroadcastMoveResult(user, target, PBEResult.Ineffective_Substitute);
					}
					else
					{
						for (int i = 0; i < statChanges.Length; i++)
						{
							(PBEStat stat, int change) = statChanges[i];
							ApplyStatChangeIfPossible(user, target, stat, change);
						}
					}
				}
			}
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Hit__MaybeChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, (PBEStat, int)[] statChanges, int chanceToChangeStats)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (target.HP == 0 || !GetManipulableChance(user, chanceToChangeStats))
				{
					return;
				}
				for (int i = 0; i < statChanges.Length; i++)
				{
					(PBEStat stat, int change) = statChanges[i];
					ApplyStatChangeIfPossible(user, target, stat, change, isSecondaryEffect: true);
				}
			}
			BasicHit(user, targets, mData, beforePostHit: BeforePostHit);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Hit__MaybeChangeUserStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, (PBEStat, int)[] statChanges, int chanceToChangeStats)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (user.HP > 0 && GetManipulableChance(user, chanceToChangeStats))
				{
					for (int i = 0; i < statChanges.Length; i++)
					{
						(PBEStat stat, int change) = statChanges[i];
						ApplyStatChangeIfPossible(user, user, stat, change, isSecondaryEffect: true);
					}
				}
			}
			BasicHit(user, targets, mData, beforePostHit: BeforePostHit);
		}
		RecordExecutedMove(user, move, mData);
	}

	private void Ef_Entrainment(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		var blockedUserAbilities = new PBEAbility[] { PBEAbility.FlowerGift, PBEAbility.Forecast, PBEAbility.Illusion,
				PBEAbility.Imposter, PBEAbility.Trace };

		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			foreach (PBEBattlePokemon target in targets)
			{
				if (!MissCheck(user, target, mData))
				{
					if (target.Ability == user.Ability || blockedUserAbilities.Contains(user.Ability))
					{
						BroadcastMoveResult(user, target, PBEResult.InvalidConditions);
					}
					else if (target.Ability == PBEAbility.Multitype || target.Ability == PBEAbility.Truant)
					{
						BroadcastMoveResult(user, target, PBEResult.Ineffective_Ability);
					}
					else
					{
						SetAbility(user, target, user.Ability);
						// TODO: #234 - Reveal other Pokémon's Ability
					}
				}
			}
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_RolePlay(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		var blockedUserAbilities = new PBEAbility[] { PBEAbility.Imposter, PBEAbility.Multitype, PBEAbility.ZenMode };
		var blockedTargetAbilities = new PBEAbility[] { PBEAbility.FlowerGift, PBEAbility.Forecast, PBEAbility.Illusion,
				PBEAbility.Imposter, PBEAbility.Multitype, PBEAbility.Trace, PBEAbility.WonderGuard, PBEAbility.ZenMode };

		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			foreach (PBEBattlePokemon target in targets)
			{
				if (!MissCheck(user, target, mData))
				{
					if (target.Ability == user.Ability || blockedUserAbilities.Contains(user.Ability) || blockedTargetAbilities.Contains(target.Ability))
					{
						BroadcastMoveResult(user, target, PBEResult.InvalidConditions);
					}
					else
					{
						SetAbility(user, user, target.Ability);
						// TODO: #234 - Reveal other Pokémon's Ability
					}
				}
			}
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SetOtherAbility(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBEAbility ability, bool blockedByTruant)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			foreach (PBEBattlePokemon target in targets)
			{
				if (!MissCheck(user, target, mData))
				{
					if (target.Ability == ability)
					{
						BroadcastMoveResult(user, target, PBEResult.InvalidConditions);
					}
					else if (target.Ability == PBEAbility.Multitype || (blockedByTruant && target.Ability == PBEAbility.Truant))
					{
						BroadcastMoveResult(user, target, PBEResult.Ineffective_Ability);
					}
					else
					{
						SetAbility(user, target, ability);
					}
				}
			}
		}
		RecordExecutedMove(user, move, mData);
	}

	private void Ef_Bounce(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBETurnTarget requestedTargets)
	{
		void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
		{
			if (target.HP > 0 && GetManipulableChance(user, mData.EffectParam))
			{
				ApplyStatus1IfPossible(user, target, PBEStatus1.Paralyzed, false);
			}
		}
		SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Airborne, beforePostHit: BeforePostHit);
	}
	private void Ef_ShadowForce(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBETurnTarget requestedTargets)
	{
		void AfterPostHit(PBEBattlePokemon target)
		{
			if (target.HP > 0 && target.Status2.HasFlag(PBEStatus2.Protected))
			{
				BroadcastStatus2(target, user, PBEStatus2.Protected, PBEStatusAction.Cleared);
			}
			if (target.Team.TeamStatus.HasFlag(PBETeamStatus.QuickGuard))
			{
				BroadcastTeamStatus(target.Team, PBETeamStatus.QuickGuard, PBETeamStatusAction.Cleared);
			}
			if (target.Team.TeamStatus.HasFlag(PBETeamStatus.WideGuard))
			{
				BroadcastTeamStatus(target.Team, PBETeamStatus.WideGuard, PBETeamStatusAction.Cleared);
			}
		}
		SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.ShadowForce, afterPostHit: AfterPostHit);
	}

	private void Ef_BrickBreak(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforeDoingDamage(PBEBattlePokemon target)
			{
				// Verified: Reflect then Light Screen
				if (target.Team.TeamStatus.HasFlag(PBETeamStatus.Reflect))
				{
					target.Team.ReflectCount = 0;
					BroadcastTeamStatus(target.Team, PBETeamStatus.Reflect, PBETeamStatusAction.Cleared);
				}
				if (target.Team.TeamStatus.HasFlag(PBETeamStatus.LightScreen))
				{
					target.Team.LightScreenCount = 0;
					BroadcastTeamStatus(target.Team, PBETeamStatus.LightScreen, PBETeamStatusAction.Cleared);
				}
			}
			BasicHit(user, targets, mData, beforeDoingDamage: BeforeDoingDamage);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Feint(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforeDoingDamage(PBEBattlePokemon target)
			{
				if (target.HP > 0 && target.Status2.HasFlag(PBEStatus2.Protected))
				{
					BroadcastStatus2(target, user, PBEStatus2.Protected, PBEStatusAction.Cleared);
				}
				if (target.Team == user.Team.OpposingTeam)
				{
					if (target.Team.TeamStatus.HasFlag(PBETeamStatus.QuickGuard))
					{
						BroadcastTeamStatus(target.Team, PBETeamStatus.QuickGuard, PBETeamStatusAction.Cleared);
					}
					if (target.Team.TeamStatus.HasFlag(PBETeamStatus.WideGuard))
					{
						BroadcastTeamStatus(target.Team, PBETeamStatus.WideGuard, PBETeamStatusAction.Cleared);
					}
				}
			}
			BasicHit(user, targets, mData, beforeDoingDamage: BeforeDoingDamage);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Hit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0, PBEStatus2 status2 = PBEStatus2.None, int chanceToInflictStatus2 = 0)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (target.HP == 0)
				{
					return;
				}
				if (status1 != PBEStatus1.None && GetManipulableChance(user, chanceToInflictStatus1))
				{
					ApplyStatus1IfPossible(user, target, status1, false);
				}
				if (status2 != PBEStatus2.None && GetManipulableChance(user, chanceToInflictStatus2))
				{
					ApplyStatus2IfPossible(user, target, status2, false);
				}
			}
			BasicHit(user, targets, mData, beforePostHit: status1 != PBEStatus1.None || status2 != PBEStatus2.None ? BeforePostHit : null);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Hit__MaybeBurnFreezeParalyze(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (target.HP == 0 || !GetManipulableChance(user, mData.EffectParam))
				{
					return;
				}
				PBEStatus1 status1;
				int val = _rand.RandomInt(0, 2);
				if (val == 0)
				{
					status1 = PBEStatus1.Burned;
				}
				else if (val == 1)
				{
					status1 = PBEStatus1.Frozen;
				}
				else
				{
					status1 = PBEStatus1.Paralyzed;
				}
				ApplyStatus1IfPossible(user, target, status1, false);
			}
			BasicHit(user, targets, mData, beforePostHit: BeforePostHit);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, byte numHits, bool subsequentMissChecks = false, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target)
			{
				if (target.HP > 0 && GetManipulableChance(user, chanceToInflictStatus1))
				{
					ApplyStatus1IfPossible(user, target, status1, false);
				}
			}
			MultiHit(user, targets, mData, numHits, subsequentMissChecks: subsequentMissChecks, beforePostHit: status1 != PBEStatus1.None ? BeforePostHit : null); // Doesn't need to be its own func but neater
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_MultiHit_2To5(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		byte numHits;
		if (user.Ability == PBEAbility.SkillLink)
		{
			numHits = 5;
		}
		else
		{
			int val = _rand.RandomInt(0, 5);
			if (val < 2)
			{
				numHits = 2;
			}
			else if (val < 4)
			{
				numHits = 3;
			}
			else if (val < 5)
			{
				numHits = 4;
			}
			else
			{
				numHits = 5;
			}
		}
		Ef_MultiHit(user, targets, move, mData, numHits);
	}
	private void Ef_PayDay(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforeDoingDamage(PBEBattlePokemon target)
			{
				BroadcastPayDay();
			}
			BasicHit(user, targets, mData, beforeDoingDamage: BeforeDoingDamage);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Recoil(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0, PBEStatus2 status2 = PBEStatus2.None, int chanceToInflictStatus2 = 0)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int? RecoilFunc(int totalDamageDealt)
			{
				return user.Ability == PBEAbility.RockHead || totalDamageDealt == 0 ? null : totalDamageDealt / mData.EffectParam;
			}
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (target.HP == 0)
				{
					return;
				}
				if (status1 != PBEStatus1.None && GetManipulableChance(user, chanceToInflictStatus1))
				{
					ApplyStatus1IfPossible(user, target, status1, false);
				}
				if (status2 != PBEStatus2.None && GetManipulableChance(user, chanceToInflictStatus2))
				{
					ApplyStatus2IfPossible(user, target, status2, false);
				}
			}
			BasicHit(user, targets, mData, recoilFunc: RecoilFunc, beforePostHit: status1 != PBEStatus1.None || status2 != PBEStatus2.None ? BeforePostHit : null);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SecretPower(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				// BUG: SecretPower is unaffected by SereneGrace and the Rainbow
				if (target.HP > 0
					&& (Settings.BugFix
					? GetManipulableChance(user, mData.EffectParam)
					: _rand.RandomBool(mData.EffectParam, 100))
					)
				{
					switch (BattleTerrain)
					{
						case PBEBattleTerrain.Cave: ApplyStatus2IfPossible(user, target, PBEStatus2.Flinching, false); break;
						case PBEBattleTerrain.Grass: ApplyStatus1IfPossible(user, target, PBEStatus1.Asleep, false); break;
						case PBEBattleTerrain.Plain: ApplyStatus1IfPossible(user, target, PBEStatus1.Paralyzed, false); break;
						case PBEBattleTerrain.Puddle: ApplyStatChangeIfPossible(user, target, PBEStat.Speed, -1, isSecondaryEffect: true); break;
						case PBEBattleTerrain.Sand: ApplyStatChangeIfPossible(user, target, PBEStat.Accuracy, -1, isSecondaryEffect: true); break;
						case PBEBattleTerrain.Snow: ApplyStatus1IfPossible(user, target, PBEStatus1.Frozen, false); break;
						case PBEBattleTerrain.Water: ApplyStatChangeIfPossible(user, target, PBEStat.Attack, -1, isSecondaryEffect: true); break;
						default: throw new InvalidDataException(nameof(BattleTerrain));
					}
				}
			}
			BasicHit(user, targets, mData, beforePostHit: BeforePostHit);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Selfdestruct(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		// TODO: Damp
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		// In gen 5, the user faints first (and loses if possible)
		// Due to technical limitations, we cannot faint first, but we should still make the user lose so it is the same behavior
		DealDamage(user, user, user.MaxHP);
		TrySetLoser(user);
		if (targets.Length == 0) // You still faint if there are no targets
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			BasicHit(user, targets, mData);
		}
		FaintCheck(user); // No berry check because we are always fainted
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SmellingSalt(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void AfterPostHit(PBEBattlePokemon target)
			{
				if (target.HP > 0 && target.Status1 == PBEStatus1.Paralyzed)
				{
					target.Status1 = PBEStatus1.None;
					BroadcastStatus1(target, user, PBEStatus1.Paralyzed, PBEStatusAction.Cleared);
				}
			}
			BasicHit(user, targets, mData, afterPostHit: AfterPostHit);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Snore(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		// TODO: Snore etc fail in BasicHit?
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else if (user.Status1 != PBEStatus1.Asleep)
		{
			BroadcastMoveResult(user, user, PBEResult.Ineffective_Status);
		}
		else
		{
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (target.HP > 0 && GetManipulableChance(user, mData.EffectParam))
				{
					ApplyStatus2IfPossible(user, target, PBEStatus2.Flinching, false);
				}
			}
			BasicHit(user, targets, mData, beforePostHit: BeforePostHit);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Struggle(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastStruggle(user);
		BroadcastMoveUsed(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int? RecoilFunc(int totalDamageDealt)
			{
				return user.MaxHP / mData.EffectParam;
			}
			BasicHit(user, targets, mData, recoilFunc: RecoilFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SuckerPunch(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			PBEResult FailFunc(PBEBattlePokemon target)
			{
				if (target.TurnAction is null // Just switched in, used item, etc
					|| target.HasUsedMoveThisTurn
					|| target.TurnAction.Decision != PBETurnDecision.Fight
					|| PBEDataProvider.Instance.GetMoveData(target.TurnAction.FightMove).Category == PBEMoveCategory.Status)
				{
					const PBEResult result = PBEResult.InvalidConditions;
					BroadcastMoveResult(user, target, result);
					return result;
				}
				return PBEResult.Success;
			}
			BasicHit(user, targets, mData, failFunc: FailFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_WakeUpSlap(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			void AfterPostHit(PBEBattlePokemon target)
			{
				if (target.HP > 0 && target.Status1 == PBEStatus1.Asleep)
				{
					target.Status1 = PBEStatus1.None;
					target.Status1Counter = 0;
					target.SleepTurns = 0;
					BroadcastStatus1(target, user, PBEStatus1.Asleep, PBEStatusAction.Cleared);
					CureNightmare(target, user);
				}
			}
			BasicHit(user, targets, mData, afterPostHit: AfterPostHit);
		}
		RecordExecutedMove(user, move, mData);
	}

	private void Ef_Endeavor(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int DamageFunc(PBEBattlePokemon target)
			{
				return target.HP - user.HP;
			}
			PBEResult FailFunc(PBEBattlePokemon target)
			{
				if (target.HP <= user.HP)
				{
					const PBEResult result = PBEResult.InvalidConditions;
					BroadcastMoveResult(user, target, result);
					return result;
				}
				return PBEResult.Success;
			}
			FixedDamageHit(user, targets, mData, DamageFunc, failFunc: FailFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_FinalGambit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int oldHP = user.HP;
			int DamageFunc(PBEBattlePokemon target)
			{
				// Only faint/deal damage first time
				if (user.HP > 0)
				{
					DealDamage(user, user, oldHP);
					FaintCheck(user); // No berry check because we are always fainted
				}
				return oldHP;
			}
			FixedDamageHit(user, targets, mData, DamageFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_OneHitKnockout(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int DamageFunc(PBEBattlePokemon target)
			{
				return target.HP;
			}
			PBEResult FailFunc(PBEBattlePokemon target)
			{
				if (target.Level > user.Level)
				{
					const PBEResult result = PBEResult.Ineffective_Level;
					BroadcastMoveResult(user, target, result);
					return result;
				}
				else
				{
					return PBEResult.Success;
				}
			}
			void BeforePostHit()
			{
				// This Any is for Sturdy survivors
				if (Array.FindIndex(targets, p => p.HP == 0) != -1)
				{
					BroadcastOneHitKnockout();
				}
			}
			FixedDamageHit(user, targets, mData, DamageFunc, failFunc: FailFunc, beforePostHit: BeforePostHit);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_Psywave(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int DamageFunc(PBEBattlePokemon target)
			{
				return user.Level * (_rand.RandomInt(0, 100) + 50) / 100;
			}
			FixedDamageHit(user, targets, mData, DamageFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SeismicToss(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int DamageFunc(PBEBattlePokemon target)
			{
				return user.Level;
			}
			FixedDamageHit(user, targets, mData, DamageFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SetDamage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			int DamageFunc(PBEBattlePokemon target)
			{
				return mData.EffectParam;
			}
			FixedDamageHit(user, targets, mData, DamageFunc);
		}
		RecordExecutedMove(user, move, mData);
	}
	private void Ef_SuperFang(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			static int DamageFunc(PBEBattlePokemon target)
			{
				return target.HP / 2;
			}
			FixedDamageHit(user, targets, mData, DamageFunc);
		}
		RecordExecutedMove(user, move, mData);
	}

	private void Ef_HPDrain(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, IPBEMoveData mData, bool requireSleep = false)
	{
		BroadcastMoveUsed(user, move);
		PPReduce(user, move);
		if (targets.Length == 0)
		{
			BroadcastMoveResult(user, user, PBEResult.NoTarget);
		}
		else
		{
			PBEResult FailFunc(PBEBattlePokemon target)
			{
				if (target.Status1 != PBEStatus1.Asleep)
				{
					const PBEResult result = PBEResult.Ineffective_Status;
					BroadcastMoveResult(user, target, result);
					return result;
				}
				return PBEResult.Success;
			}
			void BeforePostHit(PBEBattlePokemon target, ushort damageDealt)
			{
				if (user.HP == 0)
				{
					return;
				}
				int resto
Download .txt
gitextract_erdgdp2y/

├── .gitattributes
├── .gitignore
├── LICENSE.md
├── PokemonBattleEngine/
│   ├── Battle/
│   │   ├── Battle.cs
│   │   ├── BattleActions.cs
│   │   ├── BattleDamage.cs
│   │   ├── BattleEffects.cs
│   │   ├── BattleEffects_HitLogic.cs
│   │   ├── BattleEnums.cs
│   │   ├── BattleEvents.cs
│   │   ├── BattleInventory.cs
│   │   ├── BattleMoveset.cs
│   │   ├── BattlePokemon.cs
│   │   ├── BattleReplay.cs
│   │   ├── BattleTargets.cs
│   │   ├── BattleTeam.cs
│   │   ├── BattleTrainer.cs
│   │   ├── BattleUtils.cs
│   │   ├── TrainerInfo.cs
│   │   └── TypeEffectiveness.cs
│   ├── Data/
│   │   ├── DataEnums.cs
│   │   ├── DataProvider.cs
│   │   ├── Interfaces/
│   │   │   ├── ItemData.cs
│   │   │   ├── LocalizedString.cs
│   │   │   ├── MoveData.cs
│   │   │   ├── MovesetInterfaces.cs
│   │   │   ├── PokemonData.cs
│   │   │   ├── PokemonInterfaces.cs
│   │   │   └── StatInterfaces.cs
│   │   ├── Legality/
│   │   │   ├── LegalEffortValues.cs
│   │   │   ├── LegalIndividualValues.cs
│   │   │   ├── LegalMoveset.cs
│   │   │   ├── LegalPokemon.cs
│   │   │   └── LegalPokemonCollection.cs
│   │   ├── PBEAlphabeticalList.cs
│   │   ├── PBEList.cs
│   │   ├── ReadOnlyLocalizedString.cs
│   │   ├── ReadOnlyMoveset.cs
│   │   ├── ReadOnlyPokemon.cs
│   │   ├── ReadOnlyPokemonCollection.cs
│   │   ├── Settings.cs
│   │   ├── StatCollection.cs
│   │   └── Utils/
│   │       ├── DataUtils_Effects.cs
│   │       ├── DataUtils_Forms.cs
│   │       ├── DataUtils_Items.cs
│   │       ├── DataUtils_Moves.cs
│   │       ├── DataUtils_Stats.cs
│   │       └── DataUtils_Validate.cs
│   ├── Network/
│   │   ├── Client.cs
│   │   ├── Encryption.cs
│   │   ├── NetworkUtils.cs
│   │   ├── Server.cs
│   │   └── ServerClient.cs
│   ├── Packets/
│   │   ├── ActionsRequestPacket.cs
│   │   ├── ActionsResponsePacket.cs
│   │   ├── AutoCenterPacket.cs
│   │   ├── BattlePacket.cs
│   │   ├── BattleResultPacket.cs
│   │   ├── FleeResponsePacket.cs
│   │   ├── HazePacket.cs
│   │   ├── MatchCancelledPacket.cs
│   │   ├── PartyRequestPacket.cs
│   │   ├── PartyResponsePacket.cs
│   │   ├── PlayerJoinedPacket.cs
│   │   ├── ResponsePacket.cs
│   │   ├── SwitchInRequestPacket.cs
│   │   ├── SwitchInResponsePacket.cs
│   │   ├── TurnBeganPacket.cs
│   │   ├── _AbilityPacket.cs
│   │   ├── _AbilityReplacedPacket.cs
│   │   ├── _BattleStatusPacket.cs
│   │   ├── _CapturePacket.cs
│   │   ├── _FleeFailedPacket.cs
│   │   ├── _IllusionPacket.cs
│   │   ├── _ItemPacket.cs
│   │   ├── _ItemTurnPacket.cs
│   │   ├── _MoveCritPacket.cs
│   │   ├── _MoveLockPacket.cs
│   │   ├── _MovePPChangedPacket.cs
│   │   ├── _MoveResultPacket.cs
│   │   ├── _MoveUsedPacket.cs
│   │   ├── _PkmnEXPChangedPacket.cs
│   │   ├── _PkmnEXPEarnedPacket.cs
│   │   ├── _PkmnFaintedPacket.cs
│   │   ├── _PkmnFormChangedPacket.cs
│   │   ├── _PkmnHPChangedPacket.cs
│   │   ├── _PkmnLevelChangedPacket.cs
│   │   ├── _PkmnStatChangedPacket.cs
│   │   ├── _PkmnSwitchInPacket.cs
│   │   ├── _PkmnSwitchOutPacket.cs
│   │   ├── _PsychUpPacket.cs
│   │   ├── _ReflectTypePacket.cs
│   │   ├── _SpecialMessagePacket.cs
│   │   ├── _Status1Packet.cs
│   │   ├── _Status2Packet.cs
│   │   ├── _TeamStatusDamagePacket.cs
│   │   ├── _TeamStatusPacket.cs
│   │   ├── _TransformPacket.cs
│   │   ├── _TypeChangedPacket.cs
│   │   ├── _WeatherDamagePacket.cs
│   │   ├── _WeatherPacket.cs
│   │   ├── _WildPkmnAppearedPacket.cs
│   │   ├── __Packet.cs
│   │   └── __PacketProcessor.cs
│   ├── PokemonBattleEngine.csproj
│   └── Utils/
│       ├── EmptyCollections.cs
│       ├── Random.cs
│       └── Utils.cs
├── PokemonBattleEngine.DefaultData/
│   ├── AI/
│   │   ├── AI.cs
│   │   ├── AIDecisions.cs
│   │   └── WildAI.cs
│   ├── Data/
│   │   ├── BerryData.cs
│   │   ├── BerryData_Data.cs
│   │   ├── EXPTables.cs
│   │   ├── EventPokemon.cs
│   │   ├── EventPokemon_Data.cs
│   │   ├── ItemData.cs
│   │   ├── ItemData_Data.cs
│   │   ├── LegalityChecker.cs
│   │   ├── MoveData.cs
│   │   ├── MoveData_Data.cs
│   │   └── PokemonData.cs
│   ├── DefaultDataProvider.cs
│   ├── Enums.cs
│   ├── IPokemonDataExtended.cs
│   ├── LocalizedString.cs
│   ├── PokemonBattleEngine.DefaultData.csproj
│   └── RandomTeamGenerator.cs
├── PokemonBattleEngine.sln
├── PokemonBattleEngineClient/
│   ├── App.xaml
│   ├── App.xaml.cs
│   ├── Clients/
│   │   ├── ActionsBuilder.cs
│   │   ├── BattleClient.cs
│   │   ├── NetworkClient.cs
│   │   ├── NonLocalClient.cs
│   │   ├── ReplayClient.cs
│   │   ├── SinglePlayerClient.cs
│   │   └── SwitchesBuilder.cs
│   ├── Infrastructure/
│   │   ├── BetterWrapPanel.cs
│   │   ├── Converters.cs
│   │   ├── StringRenderer.cs
│   │   ├── Utils.cs
│   │   └── WriteableBitmapSurface.cs
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── Models/
│   │   ├── MoveInfo.cs
│   │   ├── PokemonInfo.cs
│   │   ├── SwitchInfo.cs
│   │   ├── TargetInfo.cs
│   │   └── TeamInfo.cs
│   ├── PokemonBattleEngineClient.csproj
│   └── Views/
│       ├── ActionsView.xaml
│       ├── ActionsView.xaml.cs
│       ├── BattleView.xaml
│       ├── BattleView.xaml.cs
│       ├── FieldView.xaml
│       ├── FieldView.xaml.cs
│       ├── HPBarView.xaml
│       ├── HPBarView.xaml.cs
│       ├── MainView.xaml
│       ├── MainView.xaml.cs
│       ├── MessageView.xaml
│       ├── MessageView.xaml.cs
│       ├── PokemonView.xaml
│       ├── PokemonView.xaml.cs
│       ├── TeamBuilderView.xaml
│       └── TeamBuilderView.xaml.cs
├── PokemonBattleEngineClient.Android/
│   ├── Assets/
│   │   └── AboutAssets.txt
│   ├── MainActivity.cs
│   ├── PokemonBattleEngineClient.Android.csproj
│   ├── Properties/
│   │   ├── AndroidManifest.xml
│   │   └── AssemblyInfo.cs
│   └── Resources/
│       ├── AboutResources.txt
│       ├── Resource.Designer.cs
│       ├── layout/
│       │   └── Main.axml
│       └── values/
│           └── Strings.xml
├── PokemonBattleEngineClient.Desktop/
│   ├── PokemonBattleEngineClient.Desktop.csproj
│   └── Program.cs
├── PokemonBattleEngineClient.iOS/
│   ├── AppDelegate.cs
│   ├── Entitlements.plist
│   ├── Info.plist
│   ├── Main.cs
│   ├── PokemonBattleEngineClient.iOS.csproj
│   ├── Properties/
│   │   └── AssemblyInfo.cs
│   └── Resources/
│       └── LaunchScreen.xib
├── PokemonBattleEngineDiscord/
│   ├── BattleContext.cs
│   ├── BattleContext_Constants.cs
│   ├── BotCommands.cs
│   ├── ChannelHandler.cs
│   ├── Matchmaking.cs
│   ├── PokemonBattleEngineDiscord.csproj
│   ├── Program.cs
│   ├── ReactionHandler.cs
│   ├── ReplaySaver.cs
│   └── Utils.cs
├── PokemonBattleEngineExtras/
│   ├── AIBattleDemo.cs
│   ├── LocalizationDumper.cs
│   ├── NARCTextDumper.cs
│   ├── PokemonBattleEngineExtras.csproj
│   ├── PokemonDataDumper.cs
│   ├── PokemonDataDumper_Data.cs
│   ├── PokemonDataDumper_DreamWorld.cs
│   ├── Program.cs
│   └── Utils.cs
├── PokemonBattleEngineServer/
│   ├── BattleServer.cs
│   ├── Player.cs
│   ├── PokemonBattleEngineServer.csproj
│   └── Properties/
│       └── launchSettings.json
├── PokemonBattleEngineTests/
│   ├── Abilities/
│   │   ├── AntiStatusAbilityTests.cs
│   │   ├── IllusionTests.cs
│   │   ├── IntimidateTests.cs
│   │   ├── NaturalCureTests.cs
│   │   └── PoisonHealTests.cs
│   ├── ActionsTests.cs
│   ├── AutoCenterTests.cs
│   ├── BattleResultTests.cs
│   ├── BehaviorTests.cs
│   ├── Forms/
│   │   ├── CastformCherrimTests.cs
│   │   └── ShayminTests.cs
│   ├── Items/
│   │   └── GemTests.cs
│   ├── Moves/
│   │   ├── BellyDrumTests.cs
│   │   ├── CamouflageTests.cs
│   │   ├── HelpingHandTests.cs
│   │   ├── MultiStrikeTests.cs
│   │   ├── ProtectionTests.cs
│   │   ├── RoostTests.cs
│   │   ├── SecretPowerTests.cs
│   │   ├── TeleportTests.cs
│   │   └── WhirlwindTests.cs
│   ├── PokemonBattleEngineTests.csproj
│   ├── Statuses/
│   │   ├── ConfusionTests.cs
│   │   ├── PowerTrickTests.cs
│   │   └── SubstituteTests.cs
│   ├── TestUtils.cs
│   └── ThrowTests.cs
├── README.md
├── Shared Assets/
│   └── PKMN/
│       ├── FemaleMinispriteLookup.txt
│       └── FemaleSpriteLookup.txt
├── To Do Abilities.txt
├── To Do Items.txt
├── To Do Moves.txt
└── nuget.config
Download .txt
SYMBOL INDEX (1787 symbols across 200 files)

FILE: PokemonBattleEngine.DefaultData/AI/AI.cs
  class PBEDDAI (line 9) | public partial class PBEDDAI
    method PBEDDAI (line 14) | public PBEDDAI(PBETrainer trainer)
    method CreateActions (line 26) | public void CreateActions()
    method CreateSwitches (line 68) | public void CreateSwitches()

FILE: PokemonBattleEngine.DefaultData/AI/AIDecisions.cs
  class PBEDDAI (line 12) | public partial class PBEDDAI
    method DecideAction (line 14) | private PBETurnAction DecideAction(PBEBattlePokemon user, List<PBETurn...
    method Debug_LogGeneratedActions (line 79) | private void Debug_LogGeneratedActions(PBEBattlePokemon user, IOrdered...
    method ScoreMove (line 97) | private float ScoreMove(List<PBEBattlePokemon> targets, PBEBattlePokem...
    method ScoreStatChange (line 626) | private static void ScoreStatChange(PBEBattlePokemon user, PBEBattlePo...
    method IsTeammateUsingEffect (line 638) | private static bool IsTeammateUsingEffect(List<PBETurnAction> actions,...
    method HPAware (line 642) | private static float HPAware(float hpPercentage, float zeroPercentScor...

FILE: PokemonBattleEngine.DefaultData/AI/WildAI.cs
  class PBEDDWildAI (line 9) | public sealed class PBEDDWildAI
    method PBEDDWildAI (line 13) | public PBEDDWildAI(PBETrainer trainer)
    method CreateActions (line 18) | public void CreateActions(bool allowFlee)

FILE: PokemonBattleEngine.DefaultData/Data/BerryData.cs
  class PBEDDBerryData (line 5) | public sealed partial class PBEDDBerryData : IPBEBerryData
    method PBEDDBerryData (line 15) | private PBEDDBerryData(byte naturalGiftPower, PBEType naturalGiftType,

FILE: PokemonBattleEngine.DefaultData/Data/BerryData_Data.cs
  class PBEDDBerryData (line 7) | public sealed partial class PBEDDBerryData

FILE: PokemonBattleEngine.DefaultData/Data/EXPTables.cs
  class PBEDDEXPTables (line 6) | public static class PBEDDEXPTables
    method GetEXPRequired (line 636) | public static uint GetEXPRequired(PBEGrowthRate type, byte level)
    method GetEXPLevel (line 650) | public static byte GetEXPLevel(PBEGrowthRate type, uint exp)
    method GetTable (line 675) | private static ReadOnlySpan<uint> GetTable(PBEGrowthRate type)

FILE: PokemonBattleEngine.DefaultData/Data/EventPokemon.cs
  class PBEDDEventPokemon (line 7) | public sealed partial class PBEDDEventPokemon
    method PBEDDEventPokemon (line 21) | private PBEDDEventPokemon(IList<byte> generations, PBESpecies species,...
    method PBEDDEventPokemon (line 33) | private PBEDDEventPokemon(IList<byte> generations, PBESpecies species,...
    method PBEDDEventPokemon (line 38) | private PBEDDEventPokemon(IList<byte> generations, PBESpecies species,...

FILE: PokemonBattleEngine.DefaultData/Data/EventPokemon_Data.cs
  class PBEDDEventPokemon (line 8) | public sealed partial class PBEDDEventPokemon

FILE: PokemonBattleEngine.DefaultData/Data/ItemData.cs
  class PBEDDItemData (line 5) | public sealed partial class PBEDDItemData : IPBEItemData
    method PBEDDItemData (line 9) | private PBEDDItemData(byte flingPower = 0)

FILE: PokemonBattleEngine.DefaultData/Data/ItemData_Data.cs
  class PBEDDItemData (line 7) | public sealed partial class PBEDDItemData

FILE: PokemonBattleEngine.DefaultData/Data/LegalityChecker.cs
  class PBEDDLegalityChecker (line 9) | public static class PBEDDLegalityChecker
    method GetSpecies (line 11) | private static List<(PBESpecies, PBEForm)> GetSpecies(PBESpecies speci...
    method GetLegalMoves (line 43) | public static IReadOnlyCollection<PBEMove> GetLegalMoves(PBESpecies sp...

FILE: PokemonBattleEngine.DefaultData/Data/MoveData.cs
  class PBEDDMoveData (line 7) | public sealed partial class PBEDDMoveData : IPBEMoveData
    method PBEDDMoveData (line 20) | private PBEDDMoveData(PBEType type, PBEMoveCategory category, sbyte pr...
    method ToString (line 29) | public override string ToString()

FILE: PokemonBattleEngine.DefaultData/Data/MoveData_Data.cs
  class PBEDDMoveData (line 7) | public sealed partial class PBEDDMoveData

FILE: PokemonBattleEngine.DefaultData/Data/PokemonData.cs
  class PBEDDPokemonData (line 10) | public sealed class PBEDDPokemonData : IPBEDDPokemonDataExtended
    method PBEDDPokemonData (line 36) | private PBEDDPokemonData(SearchResult result)
    class SearchResult (line 99) | private class SearchResult : IPBEStatCollection
    method GetData (line 126) | public static PBEDDPokemonData GetData(PBESpecies species, PBEForm for...

FILE: PokemonBattleEngine.DefaultData/DefaultDataProvider.cs
  class PBEDefaultDataProvider (line 16) | public class PBEDefaultDataProvider : PBEDataProvider
    method PBEDefaultDataProvider (line 23) | protected PBEDefaultDataProvider(string databasePath, PBELanguage lang...
    method InitEngine (line 31) | public static void InitEngine(string databasePath, int? randomSeed = n...
    method InitEngine (line 40) | public static void InitEngine(string databasePath, PBELanguage languag...
    method StrCmp (line 49) | private static bool StrCmp(object arg0, object arg1)
    method QueryDatabase (line 59) | internal List<T> QueryDatabase<T>(string commandText) where T : new()
    method IsBerry (line 88) | public override bool IsBerry(PBEItem item)
    method GetBerryData (line 92) | public override IPBEBerryData GetBerryData(PBEItem item, bool cache = ...
    method TryGetBerryData (line 96) | public override bool TryGetBerryData(PBEItem item, [NotNullWhen(true)]...
    method GetItemData (line 106) | public override IPBEItemData GetItemData(PBEItem item, bool cache = true)
    method GetMoveData (line 110) | public override IPBEMoveData GetMoveData(PBEMove move, bool cache = true)
    method HasEvolutions (line 114) | public override bool HasEvolutions(PBESpecies species, PBEForm form, b...
    method GetPokemonData (line 118) | public override IPBEPokemonData GetPokemonData(PBESpecies species, PBE...
    method GetPokemonDataExtended (line 122) | public virtual IPBEDDPokemonDataExtended GetPokemonDataExtended(PBESpe...
    method GetSpeciesCaught (line 127) | public override int GetSpeciesCaught()
    method GetLegalMoves (line 132) | public override IReadOnlyCollection<PBEMove> GetLegalMoves(PBESpecies ...
    method GetPokemonDataExtended (line 137) | public virtual IPBEDDPokemonDataExtended GetPokemonDataExtended(IPBESp...
    method GetEXPRequired (line 146) | public override uint GetEXPRequired(PBEGrowthRate type, byte level)
    method GetEXPLevel (line 150) | public override byte GetEXPLevel(PBEGrowthRate type, uint exp)
    method GetEXPModifier (line 154) | public override float GetEXPModifier(PBEBattle battle)
    method GetEXPTradeModifier (line 158) | public override float GetEXPTradeModifier(PBEBattlePokemon pkmn)
    method IsDarkGrass (line 167) | public override bool IsDarkGrass(PBEBattle battle)
    method IsDuskBallSetting (line 171) | public override bool IsDuskBallSetting(PBEBattle battle)
    method IsFishing (line 175) | public override bool IsFishing(PBEBattle battle)
    method IsGuaranteedCapture (line 179) | public override bool IsGuaranteedCapture(PBEBattle battle, IPBESpecies...
    method IsGuaranteedCapture (line 183) | public override bool IsGuaranteedCapture(PBEBattle battle, PBESpecies ...
    method IsMoonBallFamily (line 187) | public override bool IsMoonBallFamily(IPBESpeciesForm pkmn)
    method IsMoonBallFamily (line 191) | public override bool IsMoonBallFamily(PBESpecies species, PBEForm form)
    method IsRepeatBallSpecies (line 195) | public override bool IsRepeatBallSpecies(PBESpecies species)
    method IsSurfing (line 199) | public override bool IsSurfing(PBEBattle battle)
    method IsUnderwater (line 203) | public override bool IsUnderwater(PBEBattle battle)
    method GetCatchRateModifier (line 207) | public override float GetCatchRateModifier(PBEBattle battle)
    method GetAbilityByName (line 216) | public override bool GetAbilityByName(string abilityName, [NotNullWhen...
    method GetAbilityDescription (line 220) | public virtual IPBEReadOnlyLocalizedString GetAbilityDescription(PBEAb...
    method GetAbilityName (line 224) | public override IPBEReadOnlyLocalizedString GetAbilityName(PBEAbility ...
    method GetFormByName (line 228) | public override bool GetFormByName(PBESpecies species, string formName...
    method GetFormName (line 232) | public override IPBEReadOnlyLocalizedString GetFormName(PBESpecies spe...
    method GetGenderByName (line 236) | public override bool GetGenderByName(string genderName, [NotNullWhen(t...
    method GetGenderName (line 240) | public override IPBEReadOnlyLocalizedString GetGenderName(PBEGender ge...
    method GetItemByName (line 244) | public override bool GetItemByName(string itemName, [NotNullWhen(true)...
    method GetItemDescription (line 248) | public virtual IPBEReadOnlyLocalizedString GetItemDescription(PBEItem ...
    method GetItemName (line 252) | public override IPBEReadOnlyLocalizedString GetItemName(PBEItem item)
    method GetMoveByName (line 256) | public override bool GetMoveByName(string moveName, [NotNullWhen(true)...
    method GetMoveDescription (line 260) | public virtual IPBEReadOnlyLocalizedString GetMoveDescription(PBEMove ...
    method GetMoveName (line 264) | public override IPBEReadOnlyLocalizedString GetMoveName(PBEMove move)
    method GetNatureByName (line 268) | public override bool GetNatureByName(string natureName, [NotNullWhen(t...
    method GetNatureName (line 272) | public override IPBEReadOnlyLocalizedString GetNatureName(PBENature na...
    method GetSpeciesByName (line 276) | public override bool GetSpeciesByName(string speciesName, [NotNullWhen...
    method GetSpeciesCategory (line 280) | public virtual IPBEReadOnlyLocalizedString GetSpeciesCategory(PBESpeci...
    method GetSpeciesEntry (line 284) | public virtual IPBEReadOnlyLocalizedString GetSpeciesEntry(PBESpecies ...
    method GetSpeciesName (line 288) | public override IPBEReadOnlyLocalizedString GetSpeciesName(PBESpecies ...
    method GetStatByName (line 292) | public override bool GetStatByName(string statName, [NotNullWhen(true)...
    method GetStatName (line 296) | public override IPBEReadOnlyLocalizedString GetStatName(PBEStat stat)
    method GetTypeByName (line 300) | public override bool GetTypeByName(string typeName, [NotNullWhen(true)...
    method GetTypeName (line 304) | public override IPBEReadOnlyLocalizedString GetTypeName(PBEType type)

FILE: PokemonBattleEngine.DefaultData/Enums.cs
  type PBEDDMoveObtainMethod (line 5) | [Flags]

FILE: PokemonBattleEngine.DefaultData/IPokemonDataExtended.cs
  type IPBEDDPokemonDataExtended (line 6) | public interface IPBEDDPokemonDataExtended : IPBEPokemonData
  class PBEDDPokemonDataExtensions (line 14) | public static class PBEDDPokemonDataExtensions
    method HasEvolutions (line 16) | public static bool HasEvolutions(this IPBEDDPokemonDataExtended pData)

FILE: PokemonBattleEngine.DefaultData/LocalizedString.cs
  class PBEDDLocalizedString (line 10) | public static class PBEDDLocalizedString
    class SearchResult (line 13) | private sealed class SearchResult : IPBELocalizedString
    class FormNameSearchResult (line 25) | private sealed class FormNameSearchResult : IPBELocalizedString
    method GetEnumValue (line 44) | private static bool GetEnumValue<TEnum>(string value, [NotNullWhen(tru...
    method GetAbilityByName (line 58) | public static bool GetAbilityByName(string abilityName, [NotNullWhen(t...
    method GetAbilityDescription (line 72) | public static PBEReadOnlyLocalizedString GetAbilityDescription(PBEAbil...
    method GetAbilityName (line 85) | public static PBEReadOnlyLocalizedString GetAbilityName(PBEAbility abi...
    method GetFormByName (line 98) | public static bool GetFormByName(PBESpecies species, string formName, ...
    method GetFormName (line 112) | public static PBEReadOnlyLocalizedString GetFormName(PBESpecies specie...
    method GetGenderByName (line 122) | public static bool GetGenderByName(string genderName, [NotNullWhen(tru...
    method GetGenderName (line 136) | public static PBEReadOnlyLocalizedString GetGenderName(PBEGender gender)
    method GetItemByName (line 149) | public static bool GetItemByName(string itemName, [NotNullWhen(true)] ...
    method GetItemDescription (line 163) | public static PBEReadOnlyLocalizedString GetItemDescription(PBEItem item)
    method GetItemName (line 176) | public static PBEReadOnlyLocalizedString GetItemName(PBEItem item)
    method GetMoveByName (line 189) | public static bool GetMoveByName(string moveName, [NotNullWhen(true)] ...
    method GetMoveDescription (line 203) | public static PBEReadOnlyLocalizedString GetMoveDescription(PBEMove move)
    method GetMoveName (line 216) | public static PBEReadOnlyLocalizedString GetMoveName(PBEMove move)
    method GetNatureByName (line 229) | public static bool GetNatureByName(string natureName, [NotNullWhen(tru...
    method GetNatureName (line 243) | public static PBEReadOnlyLocalizedString GetNatureName(PBENature nature)
    method GetSpeciesByName (line 256) | public static bool GetSpeciesByName(string speciesName, [NotNullWhen(t...
    method GetSpeciesCategory (line 270) | public static PBEReadOnlyLocalizedString GetSpeciesCategory(PBESpecies...
    method GetSpeciesEntry (line 283) | public static PBEReadOnlyLocalizedString GetSpeciesEntry(PBESpecies sp...
    method GetSpeciesName (line 296) | public static PBEReadOnlyLocalizedString GetSpeciesName(PBESpecies spe...
    method GetStatByName (line 309) | public static bool GetStatByName(string statName, [NotNullWhen(true)] ...
    method GetStatName (line 323) | public static PBEReadOnlyLocalizedString GetStatName(PBEStat stat)
    method GetTypeByName (line 336) | public static bool GetTypeByName(string typeName, [NotNullWhen(true)] ...
    method GetTypeName (line 350) | public static PBEReadOnlyLocalizedString GetTypeName(PBEType type)

FILE: PokemonBattleEngine.DefaultData/RandomTeamGenerator.cs
  class PBEDDRandomTeamGenerator (line 13) | public static class PBEDDRandomTeamGenerator
    class TeamDetails (line 15) | private sealed class TeamDetails
    class Counter (line 26) | private sealed class Counter
      method Counter (line 49) | public Counter()
    method GetAbility (line 95) | private static PBEAbility GetAbility(PBESpecies species, List<PBEMove>...
    method GetItem (line 186) | private static PBEItem GetItem(PBESpecies species, PBEForm form, PBEAb...
    method GetMoves (line 384) | private static List<PBEMove> GetMoves(PBESpecies species, PBEForm form...
    method QueryMoves (line 1086) | private static Counter QueryMoves(IPBEDDPokemonDataExtended pData, Lis...
    method GetRandomSet (line 1272) | private static void GetRandomSet(PBESpecies species, PBEForm form, IPB...
    method CreateRandomTeam (line 1322) | public static PBELegalPokemonCollection CreateRandomTeam(int numPkmn)
    method CreateRandomTeam (line 1335) | public static PBELegalPokemonCollection CreateRandomTeam(int numPkmn, ...
    method AddTypeToDict (line 1423) | private static void AddTypeToDict(Dictionary<PBEType, int> dict, PBETy...
    method ShouldDenyType (line 1437) | private static bool ShouldDenyType(Dictionary<PBEType, int> dict, PBET...

FILE: PokemonBattleEngine/Battle/Battle.cs
  class PBEBattle (line 11) | public sealed partial class PBEBattle
    method PBEBattle (line 50) | private PBEBattle(PBEBattleFormat battleFormat, PBESettings settings, ...
    method PBEBattle (line 80) | private PBEBattle(PBEBattleFormat battleFormat, PBESettings settings, ...
    method PBEBattle (line 109) | private PBEBattle(PBEBattlePacket packet)
    method CreateTrainerBattle (line 124) | public static PBEBattle CreateTrainerBattle(PBEBattleFormat battleForm...
    method CreateTrainerBattle (line 129) | public static PBEBattle CreateTrainerBattle(PBEBattleFormat battleForm...
    method CreateWildBattle (line 134) | public static PBEBattle CreateWildBattle(PBEBattleFormat battleFormat,...
    method CreateWildBattle (line 139) | public static PBEBattle CreateWildBattle(PBEBattleFormat battleFormat,...
    method CreateRemoteBattle (line 144) | public static PBEBattle CreateRemoteBattle(PBEBattlePacket packet)
    method QueueUp (line 149) | private void QueueUp(PBETeam team, PBEFieldPosition pos, ref PBETraine...
    method QueueUpPokemon (line 183) | internal void QueueUpPokemon()
    method CheckLocal (line 237) | private void CheckLocal()
    method Begin (line 246) | public void Begin()
    method RunTurn (line 273) | public void RunTurn()
    method RunSwitches (line 290) | public void RunSwitches()
    method SetEnded (line 307) | public void SetEnded()
    method EndCheck (line 316) | private bool EndCheck()
    method SwitchesOrActions (line 330) | private void SwitchesOrActions()
    method GetActingOrder (line 513) | private IEnumerable<PBEBattlePokemon> GetActingOrder(IEnumerable<PBEBa...
    method DetermineTurnOrder (line 632) | private void DetermineTurnOrder()
    method RunActionsInOrder (line 668) | private void RunActionsInOrder()
    method TurnEnded (line 705) | private void TurnEnded()

FILE: PokemonBattleEngine/Battle/BattleActions.cs
  class PBETurnAction (line 12) | public sealed class PBETurnAction
    method PBETurnAction (line 21) | internal PBETurnAction(EndianBinaryReader r)
    method PBETurnAction (line 48) | public PBETurnAction(PBEBattlePokemon pokemon, PBEMove fightMove, PBET...
    method PBETurnAction (line 50) | public PBETurnAction(byte pokemonId, PBEMove fightMove, PBETurnTarget ...
    method PBETurnAction (line 58) | public PBETurnAction(PBEBattlePokemon pokemon, PBEItem item)
    method PBETurnAction (line 60) | public PBETurnAction(byte pokemonId, PBEItem item)
    method PBETurnAction (line 67) | public PBETurnAction(PBEBattlePokemon pokemon, PBEBattlePokemon switch...
    method PBETurnAction (line 69) | public PBETurnAction(byte pokemonId, byte switchPokemonId)
    method PBETurnAction (line 76) | internal PBETurnAction(PBEBattlePokemon pokemon)
    method PBETurnAction (line 78) | internal PBETurnAction(byte pokemonId)
    method ToBytes (line 84) | internal void ToBytes(EndianBinaryWriter w)
  class PBESwitchIn (line 111) | public sealed class PBESwitchIn
    method PBESwitchIn (line 116) | internal PBESwitchIn(EndianBinaryReader r)
    method PBESwitchIn (line 121) | public PBESwitchIn(PBEBattlePokemon pokemon, PBEFieldPosition position)
    method PBESwitchIn (line 123) | public PBESwitchIn(byte pokemonId, PBEFieldPosition position)
    method ToBytes (line 129) | internal void ToBytes(EndianBinaryWriter w)
  class PBEBattle (line 135) | public sealed partial class PBEBattle
    method AreActionsValid (line 137) | internal static bool AreActionsValid(PBETrainer trainer, IReadOnlyColl...
    method SelectActionsIfValid (line 281) | internal static bool SelectActionsIfValid(PBETrainer trainer, IReadOnl...
    method AreSwitchesValid (line 371) | internal static bool AreSwitchesValid(PBETrainer trainer, IReadOnlyCol...
    method SelectSwitchesIfValid (line 425) | internal static bool SelectSwitchesIfValid(PBETrainer trainer, IReadOn...
    method IsFleeValid (line 443) | internal static bool IsFleeValid(PBETrainer trainer, [NotNullWhen(fals...
    method SelectFleeIfValid (line 480) | internal static bool SelectFleeIfValid(PBETrainer trainer, [NotNullWhe...
  class PBETrainer (line 506) | public sealed partial class PBETrainer
    method AreActionsValid (line 508) | public bool AreActionsValid([NotNullWhen(false)] out string? invalidRe...
    method AreActionsValid (line 512) | public bool AreActionsValid(IReadOnlyCollection<PBETurnAction> actions...
    method SelectActionsIfValid (line 516) | public bool SelectActionsIfValid([NotNullWhen(false)] out string? inva...
    method SelectActionsIfValid (line 520) | public bool SelectActionsIfValid(IReadOnlyCollection<PBETurnAction> ac...
    method AreSwitchesValid (line 525) | public bool AreSwitchesValid([NotNullWhen(false)] out string? invalidR...
    method AreSwitchesValid (line 529) | public bool AreSwitchesValid(IReadOnlyCollection<PBESwitchIn> switches...
    method SelectSwitchesIfValid (line 533) | public bool SelectSwitchesIfValid([NotNullWhen(false)] out string? inv...
    method SelectSwitchesIfValid (line 537) | public bool SelectSwitchesIfValid(IReadOnlyCollection<PBESwitchIn> swi...
    method IsFleeValid (line 542) | public bool IsFleeValid([NotNullWhen(false)] out string? invalidReason)
    method SelectFleeIfValid (line 546) | public bool SelectFleeIfValid([NotNullWhen(false)] out string? invalid...

FILE: PokemonBattleEngine/Battle/BattleDamage.cs
  class PBEBattle (line 7) | public sealed partial class PBEBattle
    method GetStatChangeModifier (line 12) | public static float GetStatChangeModifier(sbyte change, bool forMissing)
    method DealDamage (line 21) | private ushort DealDamage(PBEBattlePokemon culprit, PBEBattlePokemon v...
    method HealDamage (line 79) | private ushort HealDamage(PBEBattlePokemon pkmn, int hp)
    method CalculateBasePower (line 97) | private float CalculateBasePower(PBEBattlePokemon user, PBEBattlePokem...
    method CalculateDamageMultiplier (line 827) | private float CalculateDamageMultiplier(PBEBattlePokemon user, PBEBatt...
    method CalculateAttack (line 917) | private float CalculateAttack(PBEBattlePokemon user, PBEBattlePokemon ...
    method CalculateDefense (line 980) | private static float CalculateDefense(PBEBattlePokemon user, PBEBattle...
    method CalculateSpAttack (line 999) | private float CalculateSpAttack(PBEBattlePokemon user, PBEBattlePokemo...
    method CalculateSpDefense (line 1054) | private float CalculateSpDefense(PBEBattlePokemon user, PBEBattlePokem...
    method CalculateDamage (line 1085) | private int CalculateDamage(PBEBattlePokemon user, float a, float d, f...
    method CalculateConfusionDamage (line 1094) | private int CalculateConfusionDamage(PBEBattlePokemon pkmn)
    method CalculateDamage (line 1103) | private int CalculateDamage(PBEBattlePokemon user, PBEBattlePokemon ta...

FILE: PokemonBattleEngine/Battle/BattleEffects.cs
  class PBEBattle (line 11) | public sealed partial class PBEBattle
    method DoSwitchInEffects (line 15) | private void DoSwitchInEffects(IEnumerable<PBEBattlePokemon> battlers,...
    method DoPostHitEffects (line 83) | private void DoPostHitEffects(PBEBattlePokemon user, PBEBattlePokemon ...
    method DoPostAttackedEffects (line 206) | private void DoPostAttackedEffects(PBEBattlePokemon user, List<PBEAtta...
    method DoTurnEndedEffects (line 262) | private void DoTurnEndedEffects()
    method ShouldDoWeatherEffects (line 670) | public bool ShouldDoWeatherEffects()
    method WillLeafGuardActivate (line 676) | public bool WillLeafGuardActivate()
    method FleeCheck (line 681) | private void FleeCheck()
    method WildFleeCheck (line 744) | private void WildFleeCheck(PBEBattlePokemon pkmn)
    method CalcEXP (line 750) | private void CalcEXP(PBEBattlePokemon loser)
    method GiveEXP (line 794) | private void GiveEXP(PBEBattlePokemon victor, uint amount)
    method PokedexCountTable (line 832) | private static float PokedexCountTable(int count, float g600, float g4...
    method GenerateCapture (line 856) | private void GenerateCapture(PBEBattlePokemon user, PBEBattlePokemon w...
    method UseItem (line 1037) | private void UseItem(PBEBattlePokemon user, PBEItem item)
    method UseMove (line 1079) | private void UseMove(PBEBattlePokemon user, PBEMove move, PBETurnTarge...
    method PreMoveStatusCheck (line 1278) | private bool PreMoveStatusCheck(PBEBattlePokemon user, PBEMove move)
    method MissCheck (line 1370) | private bool MissCheck(PBEBattlePokemon user, PBEBattlePokemon target,...
    method AttackTypeCheck (line 1519) | private bool AttackTypeCheck(PBEBattlePokemon user, PBEBattlePokemon t...
    method CritCheck (line 1533) | private bool CritCheck(PBEBattlePokemon user, PBEBattlePokemon target,...
    method TrySetLoser (line 1580) | private void TrySetLoser(PBEBattlePokemon pkmn)
    method SetEscaped (line 1587) | private void SetEscaped(PBEBattlePokemon pkmn)
    method FaintCheck (line 1591) | private bool FaintCheck(PBEBattlePokemon pkmn)
    method GetManipulableChance (line 1610) | private bool GetManipulableChance(PBEBattlePokemon pkmn, int chance)
    method ActivateAbility (line 1621) | private void ActivateAbility(PBEBattlePokemon pkmn, bool switchIn)
    method CastformCherrimCheckAll (line 1761) | private void CastformCherrimCheckAll()
    method CastformCherrimCheck (line 1765) | private void CastformCherrimCheck(IEnumerable<PBEBattlePokemon> order)
    method CastformCherrimCheck (line 1772) | private void CastformCherrimCheck(PBEBattlePokemon pkmn)
    method ShayminCheck (line 1819) | private void ShayminCheck(PBEBattlePokemon pkmn)
    method IllusionBreak (line 1830) | private void IllusionBreak(PBEBattlePokemon pkmn, PBEBattlePokemon bre...
    method AntiStatusAbilityCheck (line 1846) | private void AntiStatusAbilityCheck(IEnumerable<PBEBattlePokemon> order)
    method AntiStatusAbilityCheck (line 1853) | private void AntiStatusAbilityCheck(PBEBattlePokemon pkmn)
    method CauseConfusion (line 1936) | private void CauseConfusion(PBEBattlePokemon target, PBEBattlePokemon ...
    method CauseInfatuation (line 1943) | private void CauseInfatuation(PBEBattlePokemon target, PBEBattlePokemo...
    method WhiteHerbCheck (line 1956) | private void WhiteHerbCheck(PBEBattlePokemon pkmn)
    method PowerHerbCheck (line 1971) | private bool PowerHerbCheck(PBEBattlePokemon pkmn)
    method LowHPBerryCheck (line 1980) | private void LowHPBerryCheck(IEnumerable<PBEBattlePokemon> order, PBEB...
    method LowHPBerryCheck (line 1987) | private void LowHPBerryCheck(PBEBattlePokemon pkmn, PBEBattlePokemon? ...
    method SetAbility (line 2053) | private void SetAbility(PBEBattlePokemon user, PBEBattlePokemon target...
    method SetWeather (line 2080) | private void SetWeather(PBEWeather weather, byte weatherCounter, bool ...
    method RecordExecutedMove (line 2091) | private void RecordExecutedMove(PBEBattlePokemon user, PBEMove move, I...
    method PPReduce (line 2104) | private void PPReduce(PBEBattlePokemon pkmn, PBEMove move)
    method ApplyBigRoot (line 2120) | private static void ApplyBigRoot(PBEBattlePokemon pkmn, ref int restor...
    method CureNightmare (line 2127) | private void CureNightmare(PBEBattlePokemon wakingUp, PBEBattlePokemon...
    method SetSleepTurns (line 2134) | private void SetSleepTurns(PBEBattlePokemon pkmn, int minTurns, int ma...
    method DoTransform (line 2138) | private void DoTransform(PBEBattlePokemon user, PBEBattlePokemon target)
    method ApplyStatus1IfPossible (line 2153) | private PBEResult ApplyStatus1IfPossible(PBEBattlePokemon user, PBEBat...
    method ApplyStatus2IfPossible (line 2191) | private PBEResult ApplyStatus2IfPossible(PBEBattlePokemon user, PBEBat...
    method ApplyStatChangeIfPossible (line 2398) | private void ApplyStatChangeIfPossible(PBEBattlePokemon user, PBEBattl...
    method SetStatAndBroadcast (line 2433) | private void SetStatAndBroadcast(PBEBattlePokemon pkmn, PBEStat stat, ...
    method CreateSwitchInInfo (line 2439) | private static PBEPkmnAppearedInfo CreateSwitchInInfo(PBEBattlePokemon...
    method SwitchTwoPokemon (line 2460) | private void SwitchTwoPokemon(PBEBattlePokemon pkmnLeaving, PBEBattleP...
    method RemoveInfatuationsAndLockOns (line 2480) | private void RemoveInfatuationsAndLockOns(PBEBattlePokemon pkmnLeaving)
    method SemiInvulnerableChargeMove (line 2498) | private void SemiInvulnerableChargeMove(PBEBattlePokemon user, PBEBatt...
    method Ef_TryForceStatus1 (line 2530) | private void Ef_TryForceStatus1(PBEBattlePokemon user, PBEBattlePokemo...
    method Ef_TryForceStatus2 (line 2561) | private void Ef_TryForceStatus2(PBEBattlePokemon user, PBEBattlePokemo...
    method Ef_TryForceBattleStatus (line 2582) | private void Ef_TryForceBattleStatus(PBEBattlePokemon user, PBEMove mo...
    method Ef_TryForceTeamStatus (line 2606) | private void Ef_TryForceTeamStatus(PBEBattlePokemon user, PBEMove move...
    method Ef_TryForceWeather (line 2760) | private void Ef_TryForceWeather(PBEBattlePokemon user, PBEMove move, I...
    method Ef_Growth (line 2810) | private void Ef_Growth(PBEBattlePokemon user, PBEBattlePokemon[] targe...
    method Ef_ChangeTargetStats (line 2815) | private void Ef_ChangeTargetStats(PBEBattlePokemon user, PBEBattlePoke...
    method Ef_Hit__MaybeChangeTargetStats (line 2851) | private void Ef_Hit__MaybeChangeTargetStats(PBEBattlePokemon user, PBE...
    method Ef_Hit__MaybeChangeUserStats (line 2877) | private void Ef_Hit__MaybeChangeUserStats(PBEBattlePokemon user, PBEBa...
    method Ef_Entrainment (line 2903) | private void Ef_Entrainment(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_RolePlay (line 2938) | private void Ef_RolePlay(PBEBattlePokemon user, PBEBattlePokemon[] tar...
    method Ef_SetOtherAbility (line 2970) | private void Ef_SetOtherAbility(PBEBattlePokemon user, PBEBattlePokemo...
    method Ef_Bounce (line 3002) | private void Ef_Bounce(PBEBattlePokemon user, PBEBattlePokemon[] targe...
    method Ef_ShadowForce (line 3013) | private void Ef_ShadowForce(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_BrickBreak (line 3033) | private void Ef_BrickBreak(PBEBattlePokemon user, PBEBattlePokemon[] t...
    method Ef_Feint (line 3061) | private void Ef_Feint(PBEBattlePokemon user, PBEBattlePokemon[] target...
    method Ef_Hit (line 3093) | private void Ef_Hit(PBEBattlePokemon user, PBEBattlePokemon[] targets,...
    method Ef_Hit__MaybeBurnFreezeParalyze (line 3122) | private void Ef_Hit__MaybeBurnFreezeParalyze(PBEBattlePokemon user, PB...
    method Ef_MultiHit (line 3158) | private void Ef_MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] tar...
    method Ef_MultiHit_2To5 (line 3179) | private void Ef_MultiHit_2To5(PBEBattlePokemon user, PBEBattlePokemon[...
    method Ef_PayDay (line 3208) | private void Ef_PayDay(PBEBattlePokemon user, PBEBattlePokemon[] targe...
    method Ef_Recoil (line 3226) | private void Ef_Recoil(PBEBattlePokemon user, PBEBattlePokemon[] targe...
    method Ef_SecretPower (line 3259) | private void Ef_SecretPower(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_Selfdestruct (line 3295) | private void Ef_Selfdestruct(PBEBattlePokemon user, PBEBattlePokemon[]...
    method Ef_SmellingSalt (line 3315) | private void Ef_SmellingSalt(PBEBattlePokemon user, PBEBattlePokemon[]...
    method Ef_Snore (line 3337) | private void Ef_Snore(PBEBattlePokemon user, PBEBattlePokemon[] target...
    method Ef_Struggle (line 3363) | private void Ef_Struggle(PBEBattlePokemon user, PBEBattlePokemon[] tar...
    method Ef_SuckerPunch (line 3381) | private void Ef_SuckerPunch(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_WakeUpSlap (line 3408) | private void Ef_WakeUpSlap(PBEBattlePokemon user, PBEBattlePokemon[] t...
    method Ef_Endeavor (line 3434) | private void Ef_Endeavor(PBEBattlePokemon user, PBEBattlePokemon[] tar...
    method Ef_FinalGambit (line 3462) | private void Ef_FinalGambit(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_OneHitKnockout (line 3487) | private void Ef_OneHitKnockout(PBEBattlePokemon user, PBEBattlePokemon...
    method Ef_Psywave (line 3526) | private void Ef_Psywave(PBEBattlePokemon user, PBEBattlePokemon[] targ...
    method Ef_SeismicToss (line 3544) | private void Ef_SeismicToss(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_SetDamage (line 3562) | private void Ef_SetDamage(PBEBattlePokemon user, PBEBattlePokemon[] ta...
    method Ef_SuperFang (line 3580) | private void Ef_SuperFang(PBEBattlePokemon user, PBEBattlePokemon[] ta...
    method Ef_HPDrain (line 3599) | private void Ef_HPDrain(PBEBattlePokemon user, PBEBattlePokemon[] targ...
    method Ef_Moonlight (line 3646) | private void Ef_Moonlight(PBEBattlePokemon user, PBEBattlePokemon[] ta...
    method Ef_PainSplit (line 3683) | private void Ef_PainSplit(PBEBattlePokemon user, PBEBattlePokemon[] ta...
    method Ef_Rest (line 3726) | private void Ef_Rest(PBEBattlePokemon user, PBEMove move, IPBEMoveData...
    method Ef_RestoreTargetHP (line 3760) | private void Ef_RestoreTargetHP(PBEBattlePokemon user, PBEBattlePokemo...
    method Ef_Roost (line 3790) | private void Ef_Roost(PBEBattlePokemon user, PBEBattlePokemon[] target...
    method Ef_BellyDrum (line 3826) | private void Ef_BellyDrum(PBEBattlePokemon user, PBEBattlePokemon[] ta...
    method Ef_Camouflage (line 3868) | private void Ef_Camouflage(PBEBattlePokemon user, PBEBattlePokemon[] t...
    method Ef_Conversion (line 3908) | private void Ef_Conversion(PBEBattlePokemon user, PBEBattlePokemon[] t...
    method Ef_Curse (line 3950) | private void Ef_Curse(PBEBattlePokemon user, PBEBattlePokemon[] target...
    method Ef_Flatter (line 4004) | private void Ef_Flatter(PBEBattlePokemon user, PBEBattlePokemon[] targ...
    method Ef_Haze (line 4032) | private void Ef_Haze(PBEBattlePokemon user, PBEBattlePokemon[] targets...
    method Ef_HelpingHand (line 4043) | private void Ef_HelpingHand(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_Metronome (line 4069) | private void Ef_Metronome(PBEBattlePokemon user, PBEMove move, IPBEMov...
    method Ef_Nothing (line 4081) | private void Ef_Nothing(PBEBattlePokemon user, PBEMove move, IPBEMoveD...
    method Ef_PsychUp (line 4088) | private void Ef_PsychUp(PBEBattlePokemon user, PBEBattlePokemon[] targ...
    method Ef_ReflectType (line 4108) | private void Ef_ReflectType(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Ef_Refresh (line 4136) | private void Ef_Refresh(PBEBattlePokemon user, PBEBattlePokemon[] targ...
    method Ef_Soak (line 4166) | private void Ef_Soak(PBEBattlePokemon user, PBEBattlePokemon[] targets...
    method Ef_Swagger (line 4186) | private void Ef_Swagger(PBEBattlePokemon user, PBEBattlePokemon[] targ...
    method Ef_Teleport (line 4214) | private void Ef_Teleport(PBEBattlePokemon user, PBEMove move, IPBEMove...
    method Ef_Whirlwind (line 4230) | private void Ef_Whirlwind(PBEBattlePokemon user, PBEBattlePokemon[] ta...

FILE: PokemonBattleEngine/Battle/BattleEffects_HitLogic.cs
  class PBEBattle (line 9) | public sealed partial class PBEBattle
    class PBEAttackVictim (line 11) | private class PBEAttackVictim
      method PBEAttackVictim (line 19) | public PBEAttackVictim(PBEBattlePokemon pkmn, PBEResult result, floa...
    method Hit_GetVictims (line 26) | private void Hit_GetVictims(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method Hit_HitTargets (line 51) | private static void Hit_HitTargets(PBETeam user, Action<List<PBEAttack...
    method Hit_DoCrit (line 79) | private void Hit_DoCrit(List<PBEAttackVictim> victims)
    method Hit_DoMoveResult (line 89) | private void Hit_DoMoveResult(PBEBattlePokemon user, List<PBEAttackVic...
    method Hit_FaintCheck (line 100) | private void Hit_FaintCheck(List<PBEAttackVictim> victims)
    method BasicHit (line 108) | private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] target...
    method FixedDamageHit (line 198) | private void FixedDamageHit(PBEBattlePokemon user, PBEBattlePokemon[] ...
    method MultiHit (line 253) | private void MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] target...

FILE: PokemonBattleEngine/Battle/BattleEnums.cs
  type PBEBattleTerrain (line 7) | public enum PBEBattleTerrain : byte
  type PBEBattleFormat (line 20) | public enum PBEBattleFormat : byte
  type PBEBattleType (line 34) | public enum PBEBattleType : byte
  type PBEBattleState (line 40) | public enum PBEBattleState : byte
  type PBEBattleResult (line 60) | public enum PBEBattleResult : byte
  type PBEWeather (line 78) | public enum PBEWeather : byte
  type PBEFieldPosition (line 93) | public enum PBEFieldPosition : byte
  type PBETurnTarget (line 106) | [Flags]
  type PBETurnDecision (line 125) | public enum PBETurnDecision : byte
  type PBEStatus1 (line 139) | public enum PBEStatus1 : byte
  type PBEStatus2 (line 158) | [Flags]
  type PBERoostTypes (line 202) | [Flags]
  type PBEBattleStatus (line 212) | [Flags]
  type PBETeamStatus (line 221) | [Flags]
  type PBEAbilityAction (line 246) | public enum PBEAbilityAction : byte
  type PBEItemAction (line 268) | public enum PBEItemAction : byte
  type PBEItemTurnAction (line 279) | public enum PBEItemTurnAction : byte
  type PBEStatusAction (line 286) | public enum PBEStatusAction : byte
  type PBEBattleStatusAction (line 307) | public enum PBEBattleStatusAction : byte
  type PBETeamStatusAction (line 314) | public enum PBETeamStatusAction : byte
  type PBEResult (line 327) | public enum PBEResult : byte
  type PBEWeatherAction (line 361) | public enum PBEWeatherAction : byte
  type PBESpecialMessage (line 368) | public enum PBESpecialMessage : byte
  type PBEMoveLockType (line 382) | public enum PBEMoveLockType : byte

FILE: PokemonBattleEngine/Battle/BattleEvents.cs
  class PBEBattle (line 11) | public sealed partial class PBEBattle
    method Broadcast (line 16) | private void Broadcast(IPBEPacket packet)
    method BroadcastAbility (line 22) | private void BroadcastAbility(PBEBattlePokemon abilityOwner, PBEBattle...
    method BroadcastAbilityReplaced (line 28) | private void BroadcastAbilityReplaced(PBEBattlePokemon abilityOwner, P...
    method BroadcastBattleStatus (line 35) | private void BroadcastBattleStatus(PBEBattleStatus battleStatus, PBEBa...
    method BroadcastCapture (line 46) | private void BroadcastCapture(PBEBattlePokemon pokemon, PBEItem ball, ...
    method BroadcastFleeFailed (line 50) | private void BroadcastFleeFailed(PBEBattlePokemon pokemon)
    method BroadcastHaze (line 54) | private void BroadcastHaze()
    method BroadcastIllusion (line 58) | private void BroadcastIllusion(PBEBattlePokemon pokemon)
    method BroadcastItem (line 62) | private void BroadcastItem(PBEBattlePokemon itemHolder, PBEBattlePokem...
    method BroadcastItemTurn (line 81) | private void BroadcastItemTurn(PBEBattlePokemon itemUser, PBEItem item...
    method BroadcastMoveCrit (line 85) | private void BroadcastMoveCrit(PBEBattlePokemon victim)
    method BroadcastMoveLock_ChoiceItem (line 89) | private void BroadcastMoveLock_ChoiceItem(PBEBattlePokemon moveUser, P...
    method BroadcastMoveLock_Temporary (line 94) | private void BroadcastMoveLock_Temporary(PBEBattlePokemon moveUser, PB...
    method BroadcastMovePPChanged (line 100) | private void BroadcastMovePPChanged(PBEBattlePokemon moveUser, PBEMove...
    method BroadcastMoveResult (line 104) | private void BroadcastMoveResult(PBEBattlePokemon moveUser, PBEBattleP...
    method BroadcastMoveUsed (line 108) | private void BroadcastMoveUsed(PBEBattlePokemon moveUser, PBEMove move)
    method BroadcastPkmnEXPChanged (line 126) | private void BroadcastPkmnEXPChanged(PBEBattlePokemon pokemon, uint ol...
    method BroadcastPkmnEXPEarned (line 130) | private void BroadcastPkmnEXPEarned(PBEBattlePokemon pokemon, uint ear...
    method BroadcastPkmnFainted (line 134) | private void BroadcastPkmnFainted(PBEBattlePokemon pokemon, PBEFieldPo...
    method BroadcastPkmnFormChanged (line 138) | private void BroadcastPkmnFormChanged(PBEBattlePokemon pokemon, PBEFor...
    method BroadcastPkmnHPChanged (line 169) | private void BroadcastPkmnHPChanged(PBEBattlePokemon pokemon, ushort o...
    method BroadcastPkmnLevelChanged (line 173) | private void BroadcastPkmnLevelChanged(PBEBattlePokemon pokemon)
    method BroadcastPkmnStatChanged (line 177) | private void BroadcastPkmnStatChanged(PBEBattlePokemon pokemon, PBESta...
    method BroadcastPkmnSwitchIn (line 181) | private void BroadcastPkmnSwitchIn(PBETrainer trainer, PBEPkmnAppeared...
    method BroadcastPkmnSwitchOut (line 185) | private void BroadcastPkmnSwitchOut(PBEBattlePokemon pokemon, PBEField...
    method BroadcastPsychUp (line 189) | private void BroadcastPsychUp(PBEBattlePokemon user, PBEBattlePokemon ...
    method BroadcastReflectType (line 200) | private void BroadcastReflectType(PBEBattlePokemon user, PBEBattlePoke...
    method BroadcastDraggedOut (line 207) | private void BroadcastDraggedOut(PBEBattlePokemon pokemon)
    method BroadcastEndure (line 211) | private void BroadcastEndure(PBEBattlePokemon pokemon)
    method BroadcastHPDrained (line 215) | private void BroadcastHPDrained(PBEBattlePokemon pokemon)
    method BroadcastMagnitude (line 219) | private void BroadcastMagnitude(byte magnitude)
    method BroadcastMultiHit (line 223) | private void BroadcastMultiHit(byte numHits)
    method BroadcastNothingHappened (line 227) | private void BroadcastNothingHappened()
    method BroadcastOneHitKnockout (line 231) | private void BroadcastOneHitKnockout()
    method BroadcastPainSplit (line 235) | private void BroadcastPainSplit(PBEBattlePokemon user, PBEBattlePokemo...
    method BroadcastPayDay (line 239) | private void BroadcastPayDay()
    method BroadcastRecoil (line 243) | private void BroadcastRecoil(PBEBattlePokemon pokemon)
    method BroadcastStruggle (line 247) | private void BroadcastStruggle(PBEBattlePokemon pokemon)
    method BroadcastStatus1 (line 252) | private void BroadcastStatus1(PBEBattlePokemon status1Receiver, PBEBat...
    method BroadcastStatus2 (line 256) | private void BroadcastStatus2(PBEBattlePokemon status2Receiver, PBEBat...
    method BroadcastTeamStatus (line 270) | private void BroadcastTeamStatus(PBETeam team, PBETeamStatus teamStatu...
    method BroadcastTeamStatusDamage (line 281) | private void BroadcastTeamStatusDamage(PBETeam team, PBETeamStatus tea...
    method BroadcastTransform (line 286) | private void BroadcastTransform(PBEBattlePokemon user, PBEBattlePokemo...
    method BroadcastTypeChanged (line 290) | private void BroadcastTypeChanged(PBEBattlePokemon pokemon, PBEType ty...
    method BroadcastWeather (line 298) | private void BroadcastWeather(PBEWeather weather, PBEWeatherAction wea...
    method BroadcastWeatherDamage (line 302) | private void BroadcastWeatherDamage(PBEWeather weather, PBEBattlePokem...
    method BroadcastWildPkmnAppeared (line 306) | private void BroadcastWildPkmnAppeared(PBEPkmnAppearedInfo[] appearances)
    method BroadcastActionsRequest (line 310) | private void BroadcastActionsRequest(PBETrainer trainer)
    method BroadcastAutoCenter (line 314) | private void BroadcastAutoCenter(PBEBattlePokemon pokemon0, PBEFieldPo...
    method BroadcastBattle (line 318) | private void BroadcastBattle()
    method BroadcastBattleResult (line 322) | private void BroadcastBattleResult(PBEBattleResult r)
    method BroadcastSwitchInRequest (line 326) | private void BroadcastSwitchInRequest(PBETrainer trainer)
    method BroadcastTurnBegan (line 330) | private void BroadcastTurnBegan()
    method GetDefaultMessage (line 335) | public static string? GetDefaultMessage(PBEBattle battle, IPBEPacket p...
    method ConsoleBattleEventHandler (line 1682) | public static void ConsoleBattleEventHandler(PBEBattle battle, IPBEPac...

FILE: PokemonBattleEngine/Battle/BattleInventory.cs
  class PBEBattleInventory (line 10) | public sealed class PBEBattleInventory : IReadOnlyDictionary<PBEItem, PB...
    class PBEBattleInventorySlot (line 12) | public sealed class PBEBattleInventorySlot
      method PBEBattleInventorySlot (line 17) | internal PBEBattleInventorySlot(PBEItem item, uint quantity)
    method PBEBattleInventory (line 31) | internal PBEBattleInventory(IReadOnlyList<(PBEItem item, uint quantity...
    method PBEBattleInventory (line 51) | internal PBEBattleInventory(IReadOnlyList<PBEBattlePacket.PBETeamInfo....
    method ContainsKey (line 60) | public bool ContainsKey(PBEItem key)
    method TryGetValue (line 64) | public bool TryGetValue(PBEItem key, [NotNullWhen(true)] out PBEBattle...
    method GetEnumerator (line 68) | public IEnumerator<KeyValuePair<PBEItem, PBEBattleInventorySlot>> GetE...
    method GetEnumerator (line 72) | IEnumerator IEnumerable.GetEnumerator()
    method Empty (line 78) | internal static PBEBattleInventory Empty()
    method Remove (line 83) | internal void Remove(PBEItem item)

FILE: PokemonBattleEngine/Battle/BattleMoveset.cs
  class PBEBattleMoveset (line 11) | public sealed class PBEBattleMoveset : IReadOnlyList<PBEBattleMoveset.PB...
    class PBEBattleMovesetSlot (line 13) | public sealed class PBEBattleMovesetSlot : INotifyPropertyChanged
      method OnPropertyChanged (line 15) | private void OnPropertyChanged(string property)
      method PBEBattleMovesetSlot (line 61) | internal PBEBattleMovesetSlot()
      method PBEBattleMovesetSlot (line 65) | internal PBEBattleMovesetSlot(PBEMove move, int pp, int maxPP)
    method PBEBattleMoveset (line 102) | internal PBEBattleMoveset(PBESettings settings)
    method PBEBattleMoveset (line 111) | internal PBEBattleMoveset(PBESettings settings, PBEReadOnlyPartyMovese...
    method PBEBattleMoveset (line 127) | internal PBEBattleMoveset(PBEBattleMoveset other)
    method GetTransformPP (line 138) | public static int GetTransformPP(PBESettings settings, PBEMove move)
    method GetNonTransformPP (line 156) | public static int GetNonTransformPP(PBESettings settings, PBEMove move...
    method DoTransform (line 176) | internal static void DoTransform(PBEBattlePokemon user, PBEBattlePokem...
    method ForTransformPacket (line 232) | internal ReadOnlyCollection<PBEMove> ForTransformPacket()
    method Organize (line 242) | internal void Organize()
    method Reset (line 260) | internal void Reset(PBEBattleMoveset other)
    method SetUnknown (line 271) | internal void SetUnknown()
    method Contains (line 282) | public bool Contains(PBEMove move)
    method Contains (line 286) | public bool Contains(PBEMoveEffect effect)
    method CountMoves (line 300) | public int CountMoves()
    method GetEnumerator (line 313) | public IEnumerator<PBEBattleMovesetSlot> GetEnumerator()
    method GetEnumerator (line 320) | IEnumerator IEnumerable.GetEnumerator()

FILE: PokemonBattleEngine/Battle/BattlePokemon.cs
  class PBEBattlePokemon (line 13) | public sealed class PBEBattlePokemon : IPBEPokemonKnownTypes, IPBEPokemo...
    method PBEBattlePokemon (line 191) | private PBEBattlePokemon(PBETrainer trainer, byte id,
    method PBEBattlePokemon (line 229) | private PBEBattlePokemon(PBETrainer trainer, byte id, IPBEPokemon pkmn...
    method PBEBattlePokemon (line 237) | internal PBEBattlePokemon(PBETrainer trainer, byte id, IPBEPokemon pkmn)
    method PBEBattlePokemon (line 242) | internal PBEBattlePokemon(PBETrainer trainer, byte id, IPBEPartyPokemo...
    method PBEBattlePokemon (line 270) | internal PBEBattlePokemon(PBETrainer trainer, PBEBattlePacket.PBETeamI...
    method PBEBattlePokemon (line 282) | private PBEBattlePokemon(PBETrainer trainer, IPBEPkmnAppearedInfo_Hidd...
    method PBEBattlePokemon (line 312) | private PBEBattlePokemon(PBETrainer trainer, IPBEPkmnSwitchInInfo_Hidd...
    method PBEBattlePokemon (line 317) | public PBEBattlePokemon(PBETrainer trainer, PBEPkmnSwitchInPacket_Hidd...
    method PBEBattlePokemon (line 319) | public PBEBattlePokemon(PBEBattle battle, PBEWildPkmnAppearedPacket_Hi...
    method AddEXPPokemon (line 324) | public void AddEXPPokemon(PBEBattlePokemon pkmn)
    method LearnMove (line 332) | public void LearnMove(PBEMove move, int index)
    method ApplyPowerTrickChange (line 356) | public void ApplyPowerTrickChange()
    method ApplyNaturalCure (line 363) | public void ApplyNaturalCure()
    method ResetSpecies (line 372) | private void ResetSpecies()
    method ResetVolatileStuff (line 387) | private void ResetVolatileStuff()
    method ClearForSwitch (line 418) | public void ClearForSwitch()
    method ClearForFaint (line 442) | public void ClearForFaint()
    method SetStats (line 453) | public void SetStats(bool calculateHP, bool setMaxHPIfCalcHP)
    method Transform (line 484) | public void Transform(PBEBattlePokemon target)
    method UpdateKnownPP (line 523) | public void UpdateKnownPP(PBEMove move, int amountReduced)
    method UpdateHPPercentage (line 544) | public void UpdateHPPercentage()
    method StartRoost (line 548) | public void StartRoost()
    method EndRoost (line 591) | public void EndRoost()
    method HasCancellingAbility (line 612) | public bool HasCancellingAbility(bool useKnownInfo = false)
    method GetChangedStats (line 617) | public PBEStat[] GetChangedStats()
    method GetStatsLessThan (line 650) | public PBEStat[] GetStatsLessThan(int i)
    method GetStatsGreaterThan (line 683) | public PBEStat[] GetStatsGreaterThan(int i)
    method GetStatChange (line 716) | public sbyte GetStatChange(PBEStat stat)
    method SetStatChange (line 730) | public sbyte SetStatChange(PBEStat stat, int value)
    method IsStatChangePossible (line 747) | public PBEResult IsStatChangePossible(PBEStat stat, PBEBattlePokemon c...
    method ClearStatChanges (line 822) | public void ClearStatChanges()
    method GetPositiveStatTotal (line 833) | public int GetPositiveStatTotal()
    method GetMoveType (line 837) | public PBEType GetMoveType(IPBEMoveData mData, bool useKnownInfo = false)
    method GetMoveType (line 912) | public PBEType GetMoveType(PBEMove move, bool useKnownInfo = false)
    method GetMoveTargets (line 920) | public PBEMoveTarget GetMoveTargets(IPBEMoveData mData)
    method GetMoveTargets (line 939) | public PBEMoveTarget GetMoveTargets(PBEMove move)
    method IsForcedToStruggle (line 948) | public bool IsForcedToStruggle()
    method CanSwitchOut (line 966) | public bool CanSwitchOut()
    method CanHitThroughSafeguard (line 970) | public bool CanHitThroughSafeguard()
    method IsAttractionPossible (line 974) | public PBEResult IsAttractionPossible(PBEBattlePokemon causer, bool us...
    method IsBurnPossible (line 997) | public PBEResult IsBurnPossible(PBEBattlePokemon? other, bool useKnown...
    method IsConfusionPossible (line 1023) | public PBEResult IsConfusionPossible(PBEBattlePokemon? other, bool use...
    method IsFreezePossible (line 1045) | public PBEResult IsFreezePossible(PBEBattlePokemon? other, bool useKno...
    method IsFlinchPossible (line 1071) | public PBEResult IsFlinchPossible(PBEBattlePokemon? other, bool useKno...
    method IsGrounded (line 1089) | public PBEResult IsGrounded(PBEBattlePokemon? other, bool useKnownInfo...
    method IsLeechSeedPossible (line 1107) | public PBEResult IsLeechSeedPossible(bool useKnownInfo = false)
    method IsMagnetRisePossible (line 1124) | public PBEResult IsMagnetRisePossible(bool useKnownInfo = false)
    method IsParalysisPossible (line 1133) | public PBEResult IsParalysisPossible(PBEBattlePokemon? other, bool use...
    method IsPoisonPossible (line 1155) | public PBEResult IsPoisonPossible(PBEBattlePokemon? other, bool useKno...
    method IsSleepPossible (line 1181) | public PBEResult IsSleepPossible(PBEBattlePokemon? other, bool useKnow...
    method IsSubstitutePossible (line 1203) | public PBEResult IsSubstitutePossible(bool useKnownInfo = false, bool ...
    method IsTransformPossible (line 1217) | public PBEResult IsTransformPossible(PBEBattlePokemon user, bool useKn...
    method GetUsableMoves (line 1235) | public PBEMove[] GetUsableMoves()
    method GetProtectionChance (line 1265) | public ushort GetProtectionChance()
    method GetPkmnWouldDisguiseAs (line 1270) | public PBEBattlePokemon? GetPkmnWouldDisguiseAs()
    method ToString (line 1292) | public override string ToString()

FILE: PokemonBattleEngine/Battle/BattleReplay.cs
  class PBEBattle (line 12) | public sealed partial class PBEBattle
    method GetDefaultReplayFileName (line 16) | public string GetDefaultReplayFileName()
    method CheckCanSaveReplay (line 21) | private void CheckCanSaveReplay()
    method SaveReplay (line 33) | public void SaveReplay()
    method SaveReplayToFolder (line 38) | public void SaveReplayToFolder(string path)
    method SaveReplay (line 43) | public void SaveReplay(string path)
    method LoadReplay (line 69) | public static PBEBattle LoadReplay(string path, PBEPacketProcessor pac...

FILE: PokemonBattleEngine/Battle/BattleTargets.cs
  class PBEBattle (line 11) | public sealed partial class PBEBattle
    method GetPositionAcross (line 17) | public static PBEFieldPosition GetPositionAcross(PBEBattleFormat battl...
    method GetRuntimeSurrounding (line 76) | public static IReadOnlyList<PBEBattlePokemon> GetRuntimeSurrounding(PB...
    method FindFoeLeftTarget (line 235) | private static void FindFoeLeftTarget(PBEBattlePokemon user, bool canH...
    method FindFoeCenterTarget (line 275) | private static void FindFoeCenterTarget(PBEBattlePokemon user, bool ca...
    method FindFoeRightTarget (line 357) | private static void FindFoeRightTarget(PBEBattlePokemon user, bool can...
    method GetRuntimeTargets (line 402) | private static PBEBattlePokemon[] GetRuntimeTargets(PBEBattlePokemon u...
    method AreTargetsValid (line 439) | public static bool AreTargetsValid(PBEBattlePokemon pkmn, PBEMove move...
    method AreTargetsValid (line 452) | public static bool AreTargetsValid(PBEBattlePokemon pkmn, IPBEMoveData...
    method GetRandomTargetForMetronome (line 878) | public static PBETurnTarget GetRandomTargetForMetronome(PBEBattlePokem...

FILE: PokemonBattleEngine/Battle/BattleTeam.cs
  class PBETeams (line 14) | public sealed class PBETeams : IReadOnlyList<PBETeam>
    method PBETeams (line 34) | internal PBETeams(PBEBattle battle, IReadOnlyList<PBETrainerInfo> ti0,...
    method PBETeams (line 44) | internal PBETeams(PBEBattle battle, IReadOnlyList<PBETrainerInfo> ti, ...
    method PBETeams (line 54) | internal PBETeams(PBEBattle battle, PBEBattlePacket packet, out PBETra...
    method All (line 64) | public bool All(Predicate<PBETeam> match)
    method GetEnumerator (line 69) | public IEnumerator<PBETeam> GetEnumerator()
    method GetEnumerator (line 74) | IEnumerator IEnumerable.GetEnumerator()
  class PBETeam (line 81) | public sealed class PBETeam
    method PBETeam (line 109) | internal PBETeam(PBEBattle battle, byte id, IReadOnlyList<PBETrainerIn...
    method PBETeam (line 135) | internal PBETeam(PBEBattle battle, byte id, PBEWildInfo wi, List<PBETr...
    method PBETeam (line 153) | internal PBETeam(PBEBattle battle, PBEBattlePacket.PBETeamInfo info, L...
    method VerifyWildCount (line 172) | private static bool VerifyWildCount(PBEBattleFormat format, int count)
    method VerifyTrainerCount (line 183) | private static bool VerifyTrainerCount(PBEBattleFormat format, int count)
    method GetCombinedName (line 194) | private string GetCombinedName()
    method IsSpotOccupied (line 204) | public bool IsSpotOccupied(PBEFieldPosition pos)
    method TryGetPokemon (line 215) | public bool TryGetPokemon(PBEFieldPosition pos, [NotNullWhen(true)] ou...
    method TryAddPokemonToCollection (line 228) | public void TryAddPokemonToCollection(PBEFieldPosition pos, ICollectio...
    method ToString (line 236) | public override string ToString()

FILE: PokemonBattleEngine/Battle/BattleTrainer.cs
  class PBETrainers (line 12) | public sealed class PBETrainers : IReadOnlyList<PBETrainer>
    method PBETrainers (line 19) | internal PBETrainers(List<PBETrainer> trainers)
    method GetEnumerator (line 24) | public IEnumerator<PBETrainer> GetEnumerator()
    method GetEnumerator (line 28) | IEnumerator IEnumerable.GetEnumerator()
  class PBETrainer (line 33) | public sealed partial class PBETrainer
    method PBETrainer (line 55) | private PBETrainer(PBETeam team, PBETrainerInfoBase ti, string name, R...
    method PBETrainer (line 86) | internal PBETrainer(PBETeam team, PBETrainerInfo ti, List<PBETrainer> ...
    method PBETrainer (line 92) | internal PBETrainer(PBETeam team, PBEWildInfo wi, List<PBETrainer> tra...
    method PBETrainer (line 95) | internal PBETrainer(PBETeam team, PBEBattlePacket.PBETeamInfo.PBETrain...
    method Remove (line 106) | public static void Remove(PBEBattlePokemon pokemon)
    method SwitchTwoPokemon (line 110) | public static void SwitchTwoPokemon(PBEBattlePokemon a, PBEFieldPositi...
    method SwitchTwoPokemon (line 123) | public static void SwitchTwoPokemon(PBEBattlePokemon a, PBEBattlePokem...
    method IsSpotOccupied (line 136) | public bool IsSpotOccupied(PBEFieldPosition pos)
    method TryGetPokemon (line 147) | public bool TryGetPokemon(PBEFieldPosition pos, [NotNullWhen(true)] ou...
    method TryGetPokemon (line 160) | public bool TryGetPokemon(byte pkmnId, [NotNullWhen(true)] out PBEBatt...
    method GetPokemon (line 173) | public PBEBattlePokemon GetPokemon(PBEFieldPosition pos)
    method GetPokemon (line 184) | public PBEBattlePokemon GetPokemon(byte pkmnId)

FILE: PokemonBattleEngine/Battle/BattleUtils.cs
  class PBEBattleUtils (line 7) | public static class PBEBattleUtils
    method GetSpreadMoveTargets (line 9) | public static PBETurnTarget GetSpreadMoveTargets(PBEBattlePokemon pkmn...
    method GetPossibleTargets (line 234) | public static PBETurnTarget[] GetPossibleTargets(PBEBattlePokemon pkmn...
    method VerifyPosition (line 504) | internal static void VerifyPosition(PBEBattleFormat format, PBEFieldPo...
    method GetFieldPositionIndex (line 537) | public static int GetFieldPositionIndex(this PBETrainer trainer, PBEFi...
    method OwnsSpot (line 587) | public static bool OwnsSpot(this PBETrainer trainer, PBEFieldPosition ...
    method GetTrainer (line 591) | public static PBETrainer GetTrainer(this PBETeam team, PBEFieldPositio...

FILE: PokemonBattleEngine/Battle/TrainerInfo.cs
  class PBETrainerInfoBase (line 11) | public abstract class PBETrainerInfoBase
    method PBETrainerInfoBase (line 16) | protected PBETrainerInfoBase(IPBEPokemonCollection party)
    method IsOkayForSettings (line 39) | public bool IsOkayForSettings(PBESettings settings)
  class PBETrainerInfo (line 53) | public sealed class PBETrainerInfo : PBETrainerInfoBase
    method PBETrainerInfo (line 59) | public PBETrainerInfo(IPBEPokemonCollection party, string name, bool g...
  class PBEWildInfo (line 78) | public sealed class PBEWildInfo : PBETrainerInfoBase
    method PBEWildInfo (line 80) | public PBEWildInfo(IPBEPokemonCollection party)

FILE: PokemonBattleEngine/Battle/TypeEffectiveness.cs
  class PBETypeEffectiveness (line 7) | public static class PBETypeEffectiveness
    method IsAffectedByAttack (line 448) | public static PBEResult IsAffectedByAttack(PBEBattlePokemon user, PBEB...
    method ThunderWaveTypeCheck (line 494) | public static PBEResult ThunderWaveTypeCheck(PBEBattlePokemon user, PB...
    method GetEffectiveness (line 505) | public static float GetEffectiveness(PBEType attackingType, PBEType de...
    method GetEffectiveness (line 523) | public static float GetEffectiveness(PBEType attackingType, PBEType de...
    method GetEffectiveness (line 529) | public static float GetEffectiveness(PBEType attackingType, IPBEPokemo...
    method GetEffectiveness_Known (line 533) | public static float GetEffectiveness_Known(PBEType attackingType, IPBE...
    method GetEffectiveness (line 537) | public static float GetEffectiveness<T>(PBEType attackingType, T defen...
    method GetStealthRockMultiplier (line 542) | public static float GetStealthRockMultiplier(PBEType type1, PBEType ty...

FILE: PokemonBattleEngine/Data/DataEnums.cs
  type PBELanguage (line 7) | public enum PBELanguage : byte
  type PBEGender (line 20) | public enum PBEGender : byte
  type PBEGenderRatio (line 32) | public enum PBEGenderRatio : byte
  type PBEGrowthRate (line 49) | public enum PBEGrowthRate : byte
  type PBEStat (line 60) | public enum PBEStat : byte
  type PBEMoveCategory (line 80) | public enum PBEMoveCategory : byte
  type PBEType (line 92) | public enum PBEType : byte
  type PBENature (line 115) | public enum PBENature : byte
  type PBEFlavor (line 170) | public enum PBEFlavor : byte
  type PBEItem (line 180) | public enum PBEItem : ushort
  type PBEAbility (line 681) | public enum PBEAbility : byte
  type PBEForm (line 898) | public enum PBEForm : byte
  type PBESpecies (line 1008) | public enum PBESpecies : ushort
  type PBEMoveTarget (line 1661) | public enum PBEMoveTarget : byte
  type PBEMoveFlag (line 1678) | [Flags]
  type PBEMoveEffect (line 1725) | public enum PBEMoveEffect : byte
  type PBEMove (line 1894) | public enum PBEMove : ushort

FILE: PokemonBattleEngine/Data/DataProvider.cs
  class PBEDataProvider (line 10) | public abstract class PBEDataProvider
    method PBEDataProvider (line 17) | protected PBEDataProvider(PBELanguage language, PBERandom rand)
    method IsBerry (line 30) | public abstract bool IsBerry(PBEItem item);
    method GetBerryData (line 31) | public abstract IPBEBerryData GetBerryData(PBEItem item, bool cache = ...
    method TryGetBerryData (line 32) | public abstract bool TryGetBerryData(PBEItem item, [NotNullWhen(true)]...
    method GetItemData (line 33) | public abstract IPBEItemData GetItemData(PBEItem item, bool cache = tr...
    method GetMoveData (line 34) | public abstract IPBEMoveData GetMoveData(PBEMove move, bool cache = tr...
    method HasEvolutions (line 35) | public abstract bool HasEvolutions(PBESpecies species, PBEForm form, b...
    method HasEvolutions (line 36) | public virtual bool HasEvolutions(IPBESpeciesForm pkmn, bool cache = t...
    method GetPokemonData (line 40) | public abstract IPBEPokemonData GetPokemonData(PBESpecies species, PBE...
    method GetSpeciesCaught (line 42) | public abstract int GetSpeciesCaught();
    method GetLegalMoves (line 45) | public abstract IReadOnlyCollection<PBEMove> GetLegalMoves(PBESpecies ...
    method GetPokemonData (line 47) | public virtual IPBEPokemonData GetPokemonData(IPBESpeciesForm pkmn, bo...
    method GetEXPRequired (line 56) | public abstract uint GetEXPRequired(PBEGrowthRate type, byte level);
    method GetEXPLevel (line 57) | public abstract byte GetEXPLevel(PBEGrowthRate type, uint exp);
    method GetEXPModifier (line 59) | public abstract float GetEXPModifier(PBEBattle battle);
    method GetEXPTradeModifier (line 61) | public abstract float GetEXPTradeModifier(PBEBattlePokemon pkmn);
    method IsDarkGrass (line 67) | public abstract bool IsDarkGrass(PBEBattle battle);
    method IsDuskBallSetting (line 68) | public abstract bool IsDuskBallSetting(PBEBattle battle);
    method IsFishing (line 69) | public abstract bool IsFishing(PBEBattle battle);
    method IsGuaranteedCapture (line 70) | public abstract bool IsGuaranteedCapture(PBEBattle battle, PBESpecies ...
    method IsMoonBallFamily (line 71) | public abstract bool IsMoonBallFamily(PBESpecies species, PBEForm form);
    method IsRepeatBallSpecies (line 72) | public abstract bool IsRepeatBallSpecies(PBESpecies species);
    method IsSurfing (line 73) | public abstract bool IsSurfing(PBEBattle battle);
    method IsUnderwater (line 74) | public abstract bool IsUnderwater(PBEBattle battle);
    method GetCatchRateModifier (line 76) | public abstract float GetCatchRateModifier(PBEBattle battle);
    method IsGuaranteedCapture (line 78) | public virtual bool IsGuaranteedCapture(PBEBattle battle, IPBESpeciesF...
    method IsMoonBallFamily (line 82) | public virtual bool IsMoonBallFamily(IPBESpeciesForm pkmn)
    method GetAbilityByName (line 91) | public abstract bool GetAbilityByName(string abilityName, [NotNullWhen...
    method GetAbilityName (line 92) | public abstract IPBEReadOnlyLocalizedString GetAbilityName(PBEAbility ...
    method GetFormByName (line 93) | public abstract bool GetFormByName(PBESpecies species, string formName...
    method GetFormName (line 94) | public abstract IPBEReadOnlyLocalizedString GetFormName(PBESpecies spe...
    method GetGenderByName (line 95) | public abstract bool GetGenderByName(string genderName, [NotNullWhen(t...
    method GetGenderName (line 96) | public abstract IPBEReadOnlyLocalizedString GetGenderName(PBEGender ge...
    method GetItemByName (line 97) | public abstract bool GetItemByName(string itemName, [NotNullWhen(true)...
    method GetItemName (line 98) | public abstract IPBEReadOnlyLocalizedString GetItemName(PBEItem item);
    method GetMoveByName (line 99) | public abstract bool GetMoveByName(string moveName, [NotNullWhen(true)...
    method GetMoveName (line 100) | public abstract IPBEReadOnlyLocalizedString GetMoveName(PBEMove move);
    method GetNatureByName (line 101) | public abstract bool GetNatureByName(string natureName, [NotNullWhen(t...
    method GetNatureName (line 102) | public abstract IPBEReadOnlyLocalizedString GetNatureName(PBENature na...
    method GetSpeciesByName (line 103) | public abstract bool GetSpeciesByName(string speciesName, [NotNullWhen...
    method GetSpeciesName (line 104) | public abstract IPBEReadOnlyLocalizedString GetSpeciesName(PBESpecies ...
    method GetStatByName (line 105) | public abstract bool GetStatByName(string statName, [NotNullWhen(true)...
    method GetStatName (line 106) | public abstract IPBEReadOnlyLocalizedString GetStatName(PBEStat stat);
    method GetTypeByName (line 107) | public abstract bool GetTypeByName(string typeName, [NotNullWhen(true)...
    method GetTypeName (line 108) | public abstract IPBEReadOnlyLocalizedString GetTypeName(PBEType type);
    method GetFormName (line 110) | public virtual IPBEReadOnlyLocalizedString GetFormName(IPBESpeciesForm...

FILE: PokemonBattleEngine/Data/Interfaces/ItemData.cs
  type IPBEItemData (line 3) | public interface IPBEItemData
  type IPBEBerryData (line 8) | public interface IPBEBerryData

FILE: PokemonBattleEngine/Data/Interfaces/LocalizedString.cs
  type IPBEReadOnlyLocalizedString (line 7) | public interface IPBEReadOnlyLocalizedString
  type IPBELocalizedString (line 18) | public interface IPBELocalizedString : IPBEReadOnlyLocalizedString
  class PBELanguageExtensions (line 30) | public static class PBELanguageExtensions
    method ToPBELanguage (line 32) | public static bool ToPBELanguage(this CultureInfo cultureInfo, [NotNul...
    method ToCultureInfo (line 48) | public static CultureInfo ToCultureInfo(this PBELanguage language)
    method FromGlobalLanguage (line 64) | public static string FromGlobalLanguage(this IPBEReadOnlyLocalizedStri...
    method Get (line 68) | public static string Get(this IPBEReadOnlyLocalizedString str, PBELang...

FILE: PokemonBattleEngine/Data/Interfaces/MoveData.cs
  type IPBEMoveData (line 5) | public interface IPBEMoveData
  class PBEMoveDataExtensions (line 22) | public static class PBEMoveDataExtensions
    method HasSecondaryEffects (line 24) | public static bool HasSecondaryEffects(this IPBEMoveData mData, PBESet...
    method IsHPDrainMove (line 28) | public static bool IsHPDrainMove(this IPBEMoveData mData)
    method IsHPRestoreMove (line 32) | public static bool IsHPRestoreMove(this IPBEMoveData mData)
    method IsMultiHitMove (line 36) | public static bool IsMultiHitMove(this IPBEMoveData mData)
    method IsRecoilMove (line 40) | public static bool IsRecoilMove(this IPBEMoveData mData)
    method IsSetDamageMove (line 44) | public static bool IsSetDamageMove(this IPBEMoveData mData)
    method IsSpreadMove (line 48) | public static bool IsSpreadMove(this IPBEMoveData mData)
    method IsWeatherMove (line 52) | public static bool IsWeatherMove(this IPBEMoveData mData)
    method IsMoveUsable (line 58) | public static bool IsMoveUsable(this IPBEMoveData mData)

FILE: PokemonBattleEngine/Data/Interfaces/MovesetInterfaces.cs
  type IPBEMovesetSlot (line 7) | public interface IPBEMovesetSlot
  type IPBEPartyMovesetSlot (line 12) | public interface IPBEPartyMovesetSlot : IPBEMovesetSlot
  type IPBEMoveset (line 16) | public interface IPBEMoveset<T> : IReadOnlyList<T> where T : IPBEMoveset...
  type IPBEMoveset (line 20) | public interface IPBEMoveset : IPBEMoveset<IPBEMovesetSlot>
  type IPBEPartyMoveset (line 24) | public interface IPBEPartyMoveset<T> : IReadOnlyList<T> where T : IPBEPa...
  type IPBEPartyMoveset (line 28) | public interface IPBEPartyMoveset : IPBEPartyMoveset<IPBEPartyMovesetSlot>
  class PBEMovesetInterfaceExtensions (line 33) | public static class PBEMovesetInterfaceExtensions
    method CountMoves (line 35) | public static int CountMoves(this IPBEMoveset moves)
    method ToBytes (line 48) | internal static void ToBytes(this IPBEMoveset moveset, EndianBinaryWri...
    method ToBytes (line 59) | internal static void ToBytes(this IPBEPartyMoveset moveset, EndianBina...
    method ToJson (line 71) | internal static void ToJson(this IPBEMoveset moveset, Utf8JsonWriter w)
    method ToJson (line 84) | internal static void ToJson(this IPBEPartyMoveset moveset, Utf8JsonWri...

FILE: PokemonBattleEngine/Data/Interfaces/PokemonData.cs
  type IPBEPokemonData (line 7) | public interface IPBEPokemonData : IPBEPokemonTypes, IPBESpeciesForm
  class PBEPokemonDataExtensions (line 20) | public static class PBEPokemonDataExtensions
    method HasAbility (line 22) | public static bool HasAbility(this IPBEPokemonData pData, PBEAbility a...

FILE: PokemonBattleEngine/Data/Interfaces/PokemonInterfaces.cs
  type IPBEPokemon (line 14) | public interface IPBEPokemon : IPBESpeciesForm
  type IPBEPartyPokemon (line 34) | public interface IPBEPartyPokemon : IPBEPokemon
  type IPBEPokemonCollection (line 41) | public interface IPBEPokemonCollection<T> : IReadOnlyList<T> where T : I...
  type IPBEPokemonCollection (line 44) | public interface IPBEPokemonCollection : IReadOnlyList<IPBEPokemon>
  type IPBEPartyPokemonCollection (line 47) | public interface IPBEPartyPokemonCollection<T> : IReadOnlyList<T> where ...
  type IPBEPartyPokemonCollection (line 50) | public interface IPBEPartyPokemonCollection : IReadOnlyList<IPBEPartyPok...
  type IPBEPokemonTypes (line 54) | public interface IPBEPokemonTypes
  type IPBEPokemonKnownTypes (line 61) | public interface IPBEPokemonKnownTypes
  type IPBESpeciesForm (line 68) | public interface IPBESpeciesForm
  class PBEPokemonInterfaceExtensions (line 74) | public static class PBEPokemonInterfaceExtensions
    method HasType (line 76) | public static bool HasType(this IPBEPokemonTypes pkmn, PBEType type)
    method HasType_Known (line 84) | public static bool HasType_Known(this IPBEPokemonKnownTypes pkmn, PBET...
    method HasType (line 92) | public static bool HasType<T>(this T pkmn, PBEType type, bool useKnown...
    method ReceivesSTAB (line 96) | public static bool ReceivesSTAB(this IPBEPokemonTypes pkmn, PBEType type)
    method ReceivesSTAB_Known (line 100) | public static bool ReceivesSTAB_Known(this IPBEPokemonKnownTypes pkmn,...
    method ReceivesSTAB (line 104) | public static bool ReceivesSTAB<T>(this T pkmn, PBEType type, bool use...
    method ToBytes (line 109) | internal static void ToBytes(this IPBEPokemon pkmn, EndianBinaryWriter w)
    method ToJson (line 128) | internal static void ToJson(this IPBEPokemon pkmn, Utf8JsonWriter w)
    method ToBytes (line 159) | internal static void ToBytes(this IPBEPokemonCollection party, EndianB...

FILE: PokemonBattleEngine/Data/Interfaces/StatInterfaces.cs
  type IPBEReadOnlyStatCollection (line 8) | public interface IPBEReadOnlyStatCollection
  type IPBEStatCollection (line 17) | public interface IPBEStatCollection : IPBEReadOnlyStatCollection
  class PBEStatInterfaceExtensions (line 27) | public static class PBEStatInterfaceExtensions
    method GetStat (line 29) | public static byte GetStat(this IPBEReadOnlyStatCollection stats, PBES...
    method SetStat (line 42) | public static void SetStat(this IPBEStatCollection stats, PBEStat stat...
    method GetHiddenPowerBasePower (line 56) | public static byte GetHiddenPowerBasePower(this IPBEReadOnlyStatCollec...
    method GetHiddenPowerType (line 60) | public static PBEType GetHiddenPowerType(this IPBEReadOnlyStatCollecti...
    method ToBytes (line 65) | internal static void ToBytes(this IPBEReadOnlyStatCollection stats, En...
    method ToJson (line 74) | internal static void ToJson(this IPBEReadOnlyStatCollection stats, Utf...

FILE: PokemonBattleEngine/Data/Legality/LegalEffortValues.cs
  class PBELegalEffortValues (line 13) | public sealed class PBELegalEffortValues : IPBEStatCollection, IEnumerab...
    class PBELegalEffortValue (line 15) | public sealed class PBELegalEffortValue : INotifyPropertyChanged
      method OnPropertyChanged (line 17) | private void OnPropertyChanged(string property)
      method PBELegalEffortValue (line 52) | internal PBELegalEffortValue(PBELegalEffortValues parent, PBEStat st...
      method Update (line 59) | private void Update(byte newValue)
    method OnPropertyChanged (line 67) | private void OnPropertyChanged(string property)
    method PBELegalEffortValues (line 132) | internal PBELegalEffortValues(PBESettings settings, EndianBinaryReader r)
    method PBELegalEffortValues (line 147) | internal PBELegalEffortValues(PBESettings settings, JsonObject jObj)
    method PBELegalEffortValues (line 162) | internal PBELegalEffortValues(PBELegalEffortValues other)
    method PBELegalEffortValues (line 167) | public PBELegalEffortValues(PBESettings settings, bool randomize)
    method CreateEVs (line 178) | private PBELegalEffortValue[] CreateEVs(byte hp, byte attack, byte def...
    method Clear (line 191) | public void Clear()
    method Equalize (line 198) | public void Equalize()
    method Randomize (line 206) | public void Randomize()
    method GetEnumerator (line 249) | public IEnumerator<PBELegalEffortValue> GetEnumerator()
    method GetEnumerator (line 256) | IEnumerator IEnumerable.GetEnumerator()

FILE: PokemonBattleEngine/Data/Legality/LegalIndividualValues.cs
  class PBELegalIndividualValues (line 13) | public sealed class PBELegalIndividualValues : IPBEStatCollection, IEnum...
    class PBELegalIndividualValue (line 15) | public sealed class PBELegalIndividualValue : INotifyPropertyChanged
      method OnPropertyChanged (line 17) | private void OnPropertyChanged(string property)
      method PBELegalIndividualValue (line 45) | internal PBELegalIndividualValue(PBELegalIndividualValues parent, PB...
    method OnPropertyChanged (line 53) | private void OnPropertyChanged(string property)
    method PBELegalIndividualValues (line 132) | internal PBELegalIndividualValues(PBESettings settings, EndianBinaryRe...
    method PBELegalIndividualValues (line 157) | internal PBELegalIndividualValues(PBESettings settings, JsonObject jObj)
    method PBELegalIndividualValues (line 182) | internal PBELegalIndividualValues(PBELegalIndividualValues other)
    method PBELegalIndividualValues (line 188) | public PBELegalIndividualValues(PBESettings settings, bool randomize)
    method CreateIVs (line 200) | private PBELegalIndividualValue[] CreateIVs(byte hp, byte attack, byte...
    method UpdateHiddenPower (line 212) | private void UpdateHiddenPower()
    method Clear (line 218) | public void Clear()
    method Maximize (line 225) | public void Maximize()
    method Randomize (line 232) | public void Randomize()
    method GetEnumerator (line 240) | public IEnumerator<PBELegalIndividualValue> GetEnumerator()
    method GetEnumerator (line 247) | IEnumerator IEnumerable.GetEnumerator()

FILE: PokemonBattleEngine/Data/Legality/LegalMoveset.cs
  class PBELegalMoveset (line 11) | public sealed class PBELegalMoveset : IPBEMoveset, IPBEMoveset<PBELegalM...
    class PBELegalMovesetSlot (line 13) | public sealed class PBELegalMovesetSlot : IPBEMovesetSlot, INotifyProp...
      method OnPropertyChanged (line 15) | private void OnPropertyChanged(string property)
      method PBELegalMovesetSlot (line 144) | internal PBELegalMovesetSlot(PBELegalMoveset parent, int index)
      method UpdateMove (line 152) | private void UpdateMove(PBEMove move)
      method UpdatePPUps (line 165) | private void UpdatePPUps(byte ppUps)
    method OnPropertyChanged (line 175) | private void OnPropertyChanged(string property)
    method PBELegalMoveset (line 258) | internal PBELegalMoveset(PBELegalMoveset other)
    method PBELegalMoveset (line 279) | internal PBELegalMoveset(PBESpecies species, PBEForm form, byte level,...
    method PBELegalMoveset (line 320) | public PBELegalMoveset(PBESpecies species, PBEForm form, byte level, P...
    method SetAlloweds (line 343) | private void SetAlloweds()
    method SetEditables (line 384) | private void SetEditables()
    method Clear (line 393) | public void Clear()
    method Contains (line 401) | public bool Contains(PBEMove move)
    method Randomize (line 406) | public void Randomize()
    method GetEnumerator (line 435) | public IEnumerator<PBELegalMovesetSlot> GetEnumerator()
    method GetEnumerator (line 442) | IEnumerator<IPBEMovesetSlot> IEnumerable<IPBEMovesetSlot>.GetEnumerator()
    method GetEnumerator (line 446) | IEnumerator IEnumerable.GetEnumerator()

FILE: PokemonBattleEngine/Data/Legality/LegalPokemon.cs
  class PBELegalPokemon (line 12) | public sealed class PBELegalPokemon : IPBEPokemon, INotifyPropertyChanged
    method OnPropertyChanged (line 14) | private void OnPropertyChanged(string property)
    method PBELegalPokemon (line 225) | internal PBELegalPokemon(PBESettings settings, EndianBinaryReader r)
    method PBELegalPokemon (line 265) | internal PBELegalPokemon(PBESettings settings, JsonObject jObj)
    method PBELegalPokemon (line 331) | public PBELegalPokemon(PBESpecies species, PBEForm form, byte level, u...
    method SetSelectable (line 355) | [MemberNotNull(nameof(_pData))]
    method OnFormChanged (line 364) | private void OnFormChanged()
    method GetTruncatedNickname (line 377) | private string GetTruncatedNickname()
    method UpdateAbility (line 386) | private void UpdateAbility()
    method UpdateGender (line 390) | private void UpdateGender()
    method UpdateItem (line 394) | private void UpdateItem()
    method OnSpeciesChanged (line 398) | private void OnSpeciesChanged(PBESpecies oldSpecies)

FILE: PokemonBattleEngine/Data/Legality/LegalPokemonCollection.cs
  class PBELegalPokemonCollection (line 15) | public sealed class PBELegalPokemonCollection : IPBEPokemonCollection, I...
    method OnCollectionChanged (line 17) | private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    method OnPropertyChanged (line 21) | private void OnPropertyChanged(string property)
    method PBELegalPokemonCollection (line 46) | internal PBELegalPokemonCollection(PBESettings settings, EndianBinaryR...
    method PBELegalPokemonCollection (line 60) | public PBELegalPokemonCollection(string path)
    method PBELegalPokemonCollection (line 79) | public PBELegalPokemonCollection(PBESettings settings)
    method PBELegalPokemonCollection (line 85) | public PBELegalPokemonCollection(PBESettings settings, int numPkmnToGe...
    method InsertRandom (line 100) | private void InsertRandom(bool setToMaxLevel, bool fireEvent, int index)
    method Insert (line 106) | private void Insert(PBESpecies species, PBEForm form, byte level, uint...
    method InsertWithEvents (line 110) | private void InsertWithEvents(bool fireEvent, PBELegalPokemon item, in...
    method RemoveWithEvents (line 120) | private void RemoveWithEvents(PBELegalPokemon item, int index)
    method ExceedException (line 138) | private void ExceedException()
    method AddRandom (line 142) | public void AddRandom(bool setToMaxLevel)
    method Add (line 153) | public void Add(PBESpecies species, PBEForm form, byte level, uint exp)
    method Add (line 167) | public void Add(PBELegalPokemon item)
    method InsertRandom (line 182) | public void InsertRandom(bool setToMaxLevel, int index)
    method Insert (line 193) | public void Insert(PBESpecies species, PBEForm form, byte level, uint ...
    method Insert (line 206) | public void Insert(PBELegalPokemon item, int index)
    method Clear (line 221) | public void Clear()
    method Remove (line 233) | public bool Remove(PBELegalPokemon item)
    method RemoveAt (line 243) | public void RemoveAt(int index)
    method ReplaceAt (line 254) | public void ReplaceAt(PBELegalPokemon item, int index)
    method Contains (line 270) | public bool Contains(PBELegalPokemon item)
    method IndexOf (line 274) | public int IndexOf(PBELegalPokemon item)
    method GetEnumerator (line 279) | public IEnumerator<PBELegalPokemon> GetEnumerator()
    method GetEnumerator (line 283) | IEnumerator IEnumerable.GetEnumerator()
    method GetEnumerator (line 287) | IEnumerator<IPBEPokemon> IEnumerable<IPBEPokemon>.GetEnumerator()
    method ToJsonFile (line 292) | public void ToJsonFile(string path)

FILE: PokemonBattleEngine/Data/PBEAlphabeticalList.cs
  class PBEAlphabeticalList (line 12) | public sealed class PBEAlphabeticalList<T> : INotifyCollectionChanged, I...
    class PBEAlphabeticalListEntry (line 14) | private sealed class PBEAlphabeticalListEntry
      method PBEAlphabeticalListEntry (line 19) | public PBEAlphabeticalListEntry(T key, object? parameter)
    method OnCollectionChanged (line 38) | private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    method OnPropertyChanged (line 42) | private void OnPropertyChanged(string property)
    method PBEAlphabeticalList (line 63) | internal PBEAlphabeticalList()
    method PBEAlphabeticalList (line 67) | internal PBEAlphabeticalList(IEnumerable<T> collection, object? parame...
    method Sort (line 72) | private void Sort(PBEAlphabeticalListEntry[]? old)
    method Reset (line 86) | [MemberNotNull(nameof(_list))]
    method Contains (line 105) | public bool Contains(T? item)
    method FindAll (line 109) | public List<T> FindAll(Predicate<T> match)
    method IndexOf (line 122) | public int IndexOf(T? item)
    method GetEnumerator (line 137) | public IEnumerator<T> GetEnumerator()
    method GetEnumerator (line 144) | IEnumerator IEnumerable.GetEnumerator()
    method AsReadOnly (line 149) | public ReadOnlyCollection<T> AsReadOnly()
    method ToArray (line 153) | public T[] ToArray()
    method ToList (line 162) | public List<T> ToList()

FILE: PokemonBattleEngine/Data/PBEList.cs
  class PBEList (line 10) | public sealed class PBEList<T> : INotifyCollectionChanged, INotifyProper...
    method OnCollectionChanged (line 12) | private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    method OnPropertyChanged (line 16) | private void OnPropertyChanged(string property)
    method PBEList (line 37) | internal PBEList()
    method PBEList (line 41) | internal PBEList(int capacity)
    method PBEList (line 45) | internal PBEList(IEnumerable<T> collection)
    method Add (line 50) | internal void Add(T item)
    method Insert (line 58) | internal void Insert(int index, T item)
    method Remove (line 65) | internal bool Remove(T item)
    method RemoveAt (line 78) | internal void RemoveAt(int index)
    method Reset (line 93) | internal void Reset(IEnumerable<T> collection)
    method Swap (line 108) | internal void Swap(T a, T b)
    method Contains (line 127) | public bool Contains(T item)
    method FindAll (line 131) | public List<T> FindAll(Predicate<T> match)
    method IndexOf (line 135) | public int IndexOf(T item)
    method ToArray (line 140) | public T[] ToArray()
    method GetEnumerator (line 145) | public IEnumerator<T> GetEnumerator()
    method GetEnumerator (line 152) | IEnumerator IEnumerable.GetEnumerator()

FILE: PokemonBattleEngine/Data/ReadOnlyLocalizedString.cs
  class PBEReadOnlyLocalizedString (line 3) | public sealed class PBEReadOnlyLocalizedString : IPBEReadOnlyLocalizedSt...
    method PBEReadOnlyLocalizedString (line 14) | public PBEReadOnlyLocalizedString(IPBEReadOnlyLocalizedString other)
    method ToString (line 26) | public override string ToString()

FILE: PokemonBattleEngine/Data/ReadOnlyMoveset.cs
  class PBEReadOnlyMoveset (line 12) | public sealed class PBEReadOnlyMoveset : IPBEMoveset, IPBEMoveset<PBERea...
    class PBEReadOnlyMovesetSlot (line 14) | public sealed class PBEReadOnlyMovesetSlot : IPBEMovesetSlot
      method PBEReadOnlyMovesetSlot (line 19) | internal PBEReadOnlyMovesetSlot(PBEMove move, byte ppUps)
    method PBEReadOnlyMoveset (line 41) | internal PBEReadOnlyMoveset(EndianBinaryReader r)
    method PBEReadOnlyMoveset (line 50) | internal PBEReadOnlyMoveset(JsonArray jArray)
    method PBEReadOnlyMoveset (line 66) | public PBEReadOnlyMoveset(IPBEMoveset other)
    method GetEnumerator (line 77) | public IEnumerator<PBEReadOnlyMovesetSlot> GetEnumerator()
    method GetEnumerator (line 84) | IEnumerator<IPBEMovesetSlot> IEnumerable<IPBEMovesetSlot>.GetEnumerator()
    method GetEnumerator (line 88) | IEnumerator IEnumerable.GetEnumerator()
  class PBEReadOnlyPartyMoveset (line 94) | public sealed class PBEReadOnlyPartyMoveset : IPBEPartyMoveset, IPBEPart...
    class PBEReadOnlyPartyMovesetSlot (line 96) | public sealed class PBEReadOnlyPartyMovesetSlot : IPBEPartyMovesetSlot
      method PBEReadOnlyPartyMovesetSlot (line 102) | internal PBEReadOnlyPartyMovesetSlot(PBESettings settings, PBEMove m...
      method PBEReadOnlyPartyMovesetSlot (line 108) | internal PBEReadOnlyPartyMovesetSlot(PBEMove move, int pp, byte ppUps)
    method PBEReadOnlyPartyMoveset (line 131) | internal PBEReadOnlyPartyMoveset(EndianBinaryReader r)
    method PBEReadOnlyPartyMoveset (line 140) | internal PBEReadOnlyPartyMoveset(JsonArray jArray)
    method PBEReadOnlyPartyMoveset (line 157) | public PBEReadOnlyPartyMoveset(PBESettings settings, IPBEMoveset other)
    method PBEReadOnlyPartyMoveset (line 168) | public PBEReadOnlyPartyMoveset(IPBEPartyMoveset other)
    method GetEnumerator (line 179) | public IEnumerator<PBEReadOnlyPartyMovesetSlot> GetEnumerator()
    method GetEnumerator (line 186) | IEnumerator<IPBEPartyMovesetSlot> IEnumerable<IPBEPartyMovesetSlot>.Ge...
    method GetEnumerator (line 190) | IEnumerator IEnumerable.GetEnumerator()

FILE: PokemonBattleEngine/Data/ReadOnlyPokemon.cs
  class PBEReadOnlyPokemon (line 5) | public sealed class PBEReadOnlyPokemon : IPBEPokemon
    method PBEReadOnlyPokemon (line 25) | internal PBEReadOnlyPokemon(EndianBinaryReader r)

FILE: PokemonBattleEngine/Data/ReadOnlyPokemonCollection.cs
  class PBEReadOnlyPokemonCollection (line 8) | public sealed class PBEReadOnlyPokemonCollection : IPBEPokemonCollection...
    method PBEReadOnlyPokemonCollection (line 25) | internal PBEReadOnlyPokemonCollection(EndianBinaryReader r)
    method GetEnumerator (line 35) | IEnumerator IEnumerable.GetEnumerator()
    method GetEnumerator (line 39) | IEnumerator<IPBEPokemon> IEnumerable<IPBEPokemon>.GetEnumerator()
    method GetEnumerator (line 43) | public IEnumerator<PBEReadOnlyPokemon> GetEnumerator()

FILE: PokemonBattleEngine/Data/Settings.cs
  class PBESettings (line 11) | public sealed class PBESettings : INotifyPropertyChanged
    method OnPropertyChanged (line 13) | private void OnPropertyChanged(string property)
    method PBESettings (line 38) | static PBESettings()
    method PBESettings (line 910) | public PBESettings() { }
    method PBESettings (line 913) | public PBESettings(string code)
    method PBESettings (line 922) | public PBESettings(PBESettings other)
    method PBESettings (line 969) | public PBESettings(EndianBinaryReader r)
    method ShouldNotBeReadOnly (line 974) | private void ShouldNotBeReadOnly()
    method ShouldBeReadOnly (line 981) | public void ShouldBeReadOnly(string nameOf)
    method MakeReadOnly (line 989) | public void MakeReadOnly()
    method GetHashCode (line 999) | public override int GetHashCode()
    method Equals (line 1049) | public override bool Equals(object? obj)
    type PBESettingID (line 1120) | private enum PBESettingID : ushort
    method ToString (line 1167) | public override string ToString()
    method ToBytes (line 1172) | public byte[] ToBytes()
    method FromBytes (line 1439) | private void FromBytes(EndianBinaryReader r)

FILE: PokemonBattleEngine/Data/StatCollection.cs
  class PBEReadOnlyStatCollection (line 5) | public sealed class PBEReadOnlyStatCollection : IPBEReadOnlyStatCollection
    method PBEReadOnlyStatCollection (line 14) | public PBEReadOnlyStatCollection(byte hp, byte attack, byte defense, b...
    method PBEReadOnlyStatCollection (line 23) | internal PBEReadOnlyStatCollection(EndianBinaryReader r)
    method PBEReadOnlyStatCollection (line 25) | public PBEReadOnlyStatCollection(IPBEReadOnlyStatCollection stats)
  class PBEStatCollection (line 30) | public sealed class PBEStatCollection : IPBEStatCollection
    method PBEStatCollection (line 39) | public PBEStatCollection(byte hp, byte attack, byte defense, byte spAt...
    method PBEStatCollection (line 48) | internal PBEStatCollection(EndianBinaryReader r)
    method PBEStatCollection (line 50) | public PBEStatCollection(IPBEReadOnlyStatCollection stats)

FILE: PokemonBattleEngine/Data/Utils/DataUtils_Effects.cs
  class PBEDataUtils (line 3) | public static partial class PBEDataUtils

FILE: PokemonBattleEngine/Data/Utils/DataUtils_Forms.cs
  class PBEDataUtils (line 7) | public static partial class PBEDataUtils
    method CanChangeForm (line 56) | public static bool CanChangeForm(PBESpecies species, bool requireUsabl...
    method HasForms (line 85) | public static bool HasForms(PBESpecies species, bool requireUsableOuts...
    method GetNameOfForm (line 120) | public static string? GetNameOfForm(PBESpecies species, PBEForm form)
    method GetForms (line 142) | public static IReadOnlyList<PBEForm> GetForms(PBESpecies species, bool...
    method GetValidItems (line 177) | public static IReadOnlyList<PBEItem> GetValidItems(PBESpecies species,...
    method IsValidForm (line 231) | public static bool IsValidForm(PBESpecies species, PBEForm form, bool ...

FILE: PokemonBattleEngine/Data/Utils/DataUtils_Items.cs
  class PBEDataUtils (line 9) | public static partial class PBEDataUtils

FILE: PokemonBattleEngine/Data/Utils/DataUtils_Moves.cs
  class PBEDataUtils (line 7) | public static partial class PBEDataUtils
    method GetMovesWithoutFlag (line 17) | private static List<PBEMove> GetMovesWithoutFlag(PBEMoveFlag flag, PBE...
    method HasSecondaryEffects (line 34) | public static bool HasSecondaryEffects(PBEMoveEffect effect, PBESettin...
    method IsHPDrainMove (line 72) | public static bool IsHPDrainMove(PBEMoveEffect effect)
    method IsHPRestoreMove (line 81) | public static bool IsHPRestoreMove(PBEMoveEffect effect)
    method IsMultiHitMove (line 90) | public static bool IsMultiHitMove(PBEMoveEffect effect) // TODO: Tripl...
    method IsRecoilMove (line 100) | public static bool IsRecoilMove(PBEMoveEffect effect) // TODO: JumpKic...
    method IsSetDamageMove (line 110) | public static bool IsSetDamageMove(PBEMoveEffect effect)
    method IsSpreadMove (line 124) | public static bool IsSpreadMove(PBEMoveTarget targets)
    method IsWeatherMove (line 136) | public static bool IsWeatherMove(PBEMoveEffect effect)
    method IsMoveUsable (line 149) | public static bool IsMoveUsable(PBEMove move)
    method IsMoveUsable (line 154) | public static bool IsMoveUsable(PBEMoveEffect effect)

FILE: PokemonBattleEngine/Data/Utils/DataUtils_Stats.cs
  class PBEDataUtils (line 7) | public static partial class PBEDataUtils
    method GetRelationshipToFlavor (line 69) | public static sbyte GetRelationshipToFlavor(this PBENature nature, PBE...
    method GetRelationshipToStat (line 93) | public static sbyte GetRelationshipToStat(this PBENature nature, PBESt...
    method GetLikedFlavor (line 106) | public static PBEFlavor? GetLikedFlavor(this PBENature nature)
    method GetDislikedFlavor (line 118) | public static PBEFlavor? GetDislikedFlavor(this PBENature nature)
    method GetLikedStat (line 130) | public static PBEStat? GetLikedStat(this PBENature nature)
    method GetDislikedStat (line 142) | public static PBEStat? GetDislikedStat(this PBENature nature)
    method IsNeutralNature (line 154) | public static bool IsNeutralNature(this PBENature nature)
    method CalcMaxPP (line 163) | public static int CalcMaxPP(byte ppTier, byte ppUps, PBESettings setti...
    method CalcMaxPP (line 168) | public static int CalcMaxPP(PBEMove move, byte ppUps, PBESettings sett...
    method CalcHP (line 185) | private static ushort CalcHP(PBESpecies species, IPBEReadOnlyStatColle...
    method CalcOtherStat (line 189) | private static ushort CalcOtherStat(IPBEReadOnlyStatCollection baseSta...
    method CalculateStat (line 194) | public static ushort CalculateStat(PBESpecies species, IPBEReadOnlySta...
    method CalculateStat (line 220) | public static ushort CalculateStat(IPBEPokemonData pData, PBEStat stat...
    method CalculateStat (line 224) | public static ushort CalculateStat(IPBESpeciesForm pkmn, PBEStat stat,...
    method CalculateStat (line 228) | public static ushort CalculateStat(PBESpecies species, PBEForm form, P...
    method GetStatRange (line 233) | public static void GetStatRange(PBESpecies species, IPBEReadOnlyStatCo...
    method GetStatRange (line 258) | public static void GetStatRange(IPBEPokemonData pData, PBEStat stat, b...
    method GetStatRange (line 262) | public static void GetStatRange(IPBESpeciesForm pkmn, PBEStat stat, by...
    method GetStatRange (line 266) | public static void GetStatRange(PBESpecies species, PBEForm form, PBES...
    method GetHiddenPowerType (line 272) | public static PBEType GetHiddenPowerType(byte hpIV, byte attackIV, byt...
    method GetHiddenPowerBasePower (line 282) | public static byte GetHiddenPowerBasePower(byte hpIV, byte attackIV, b...
    method GetValidGenders (line 296) | public static IReadOnlyList<PBEGender> GetValidGenders(PBEGenderRatio ...
    method IsOppositeGender (line 306) | public static bool IsOppositeGender(this PBEGender gender, PBEGender o...
    method ToSymbol (line 310) | public static string ToSymbol(this PBEGender gender)

FILE: PokemonBattleEngine/Data/Utils/DataUtils_Validate.cs
  class PBEDataUtils (line 5) | public static partial class PBEDataUtils
    method ValidateSpecies (line 7) | public static void ValidateSpecies(PBESpecies species, PBEForm form, b...
    method ValidateNickname (line 14) | public static void ValidateNickname(string value, PBESettings settings)
    method ValidateLevel (line 25) | public static void ValidateLevel(byte value, PBESettings settings)
    method ValidateEXP (line 32) | public static void ValidateEXP(PBEGrowthRate type, uint value, byte le...
    method ValidateAbility (line 48) | public static void ValidateAbility(PBEAlphabeticalList<PBEAbility> val...
    method ValidateNature (line 55) | public static void ValidateNature(PBENature value)
    method ValidateGender (line 62) | public static void ValidateGender(PBEAlphabeticalList<PBEGender> valid...
    method ValidateItem (line 69) | public static void ValidateItem(PBEAlphabeticalList<PBEItem> valid, PB...
    method ValidateCaughtBall (line 76) | public static void ValidateCaughtBall(PBEItem value)

FILE: PokemonBattleEngine/Network/Client.cs
  class PBEClient (line 32) | public sealed class PBEClient : IDisposable
    method Connect (line 49) | public bool Connect(IPEndPoint ip, int millisecondsTimeout, PBEPacketP...
    method Disconnect (line 78) | public void Disconnect(bool notify)
    method Send (line 103) | public void Send(IPBEPacket packet)
    method BeginReceive (line 117) | private void BeginReceive()
    method OnReceiveLength (line 121) | private void OnReceiveLength(IAsyncResult ar)
    method OnReceiveData (line 152) | private void OnReceiveData(IAsyncResult ar)
    method NotifyError (line 182) | private void NotifyError(Exception ex)
    method Dispose (line 194) | public void Dispose()

FILE: PokemonBattleEngine/Network/Encryption.cs
  class PBEEncryption (line 28) | public sealed class PBEEncryption
    method PBEEncryption (line 32) | public PBEEncryption(SymmetricAlgorithm algorithm)
    method Encrypt (line 37) | public byte[] Encrypt(byte[] data)
    method Decrypt (line 51) | public byte[] Decrypt(byte[] data)

FILE: PokemonBattleEngine/Network/NetworkUtils.cs
  class PBENetworkUtils (line 8) | internal static class PBENetworkUtils
    method Send (line 10) | public static void Send(byte[] data, Socket socket)
    method Send (line 17) | public static void Send(byte[] data, IEnumerable<Socket> sockets)
    method CreateArgs (line 28) | private static SocketAsyncEventArgs CreateArgs(byte[] data)

FILE: PokemonBattleEngine/Network/Server.cs
  class PBEServer (line 32) | public sealed class PBEServer : IDisposable
    method Start (line 52) | public void Start(IPEndPoint ip, int maxConnections, PBEPacketProcesso...
    method Stop (line 84) | public void Stop()
    method SendToAll (line 102) | public void SendToAll(IPBEPacket packet)
    method OnClientConnected (line 113) | private void OnClientConnected(IAsyncResult ar)
    method BeginReceive (line 166) | private void BeginReceive(PBEServerClient client)
    method OnReceiveLength (line 172) | private void OnReceiveLength(IAsyncResult ar)
    method OnReceiveData (line 204) | private void OnReceiveData(IAsyncResult ar)
    method RefuseClient (line 235) | private void RefuseClient(PBEServerClient client, bool isBanned)
    method DisconnectClient (line 241) | public bool DisconnectClient(PBEServerClient client)
    method NotifyError (line 258) | private void NotifyError(Exception ex)
    method Dispose (line 270) | public void Dispose()

FILE: PokemonBattleEngine/Network/ServerClient.cs
  class PBEServerClient (line 9) | public sealed class PBEServerClient
    method PBEServerClient (line 21) | internal PBEServerClient(Socket socket, PBEEncryption? encryption)
    method Send (line 28) | public void Send(IPBEPacket packet)
    method FirePacketReceived (line 38) | internal void FirePacketReceived(IPBEPacket packet)

FILE: PokemonBattleEngine/Packets/ActionsRequestPacket.cs
  class PBEActionsRequestPacket (line 9) | public sealed class PBEActionsRequestPacket : IPBEPacket
    method PBEActionsRequestPacket (line 17) | internal PBEActionsRequestPacket(PBETrainer trainer)
    method PBEActionsRequestPacket (line 34) | internal PBEActionsRequestPacket(byte[] data, EndianBinaryReader r, PB...

FILE: PokemonBattleEngine/Packets/ActionsResponsePacket.cs
  class PBEActionsResponsePacket (line 10) | public sealed class PBEActionsResponsePacket : IPBEPacket
    method PBEActionsResponsePacket (line 17) | public PBEActionsResponsePacket(IList<PBETurnAction> actions)
    method PBEActionsResponsePacket (line 37) | internal PBEActionsResponsePacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/AutoCenterPacket.cs
  type IPBEAutoCenterPacket (line 8) | public interface IPBEAutoCenterPacket : IPBEPacket
  type IPBEAutoCenterPacket_0 (line 15) | public interface IPBEAutoCenterPacket_0 : IPBEAutoCenterPacket
  type IPBEAutoCenterPacket_1 (line 19) | public interface IPBEAutoCenterPacket_1 : IPBEAutoCenterPacket
  class PBEAutoCenterPacket (line 23) | public sealed class PBEAutoCenterPacket : IPBEAutoCenterPacket_0, IPBEAu...
    method PBEAutoCenterPacket (line 35) | internal PBEAutoCenterPacket(PBEBattlePokemon pokemon0, PBEFieldPositi...
    method PBEAutoCenterPacket (line 51) | internal PBEAutoCenterPacket(byte[] data, EndianBinaryReader r, PBEBat...
  class PBEAutoCenterPacket_Hidden0 (line 63) | public sealed class PBEAutoCenterPacket_Hidden0 : IPBEAutoCenterPacket_1
    method PBEAutoCenterPacket_Hidden0 (line 74) | public PBEAutoCenterPacket_Hidden0(PBEAutoCenterPacket other)
    method PBEAutoCenterPacket_Hidden0 (line 89) | internal PBEAutoCenterPacket_Hidden0(byte[] data, EndianBinaryReader r...
  class PBEAutoCenterPacket_Hidden1 (line 100) | public sealed class PBEAutoCenterPacket_Hidden1 : IPBEAutoCenterPacket_0
    method PBEAutoCenterPacket_Hidden1 (line 111) | public PBEAutoCenterPacket_Hidden1(PBEAutoCenterPacket other)
    method PBEAutoCenterPacket_Hidden1 (line 126) | internal PBEAutoCenterPacket_Hidden1(byte[] data, EndianBinaryReader r...
  class PBEAutoCenterPacket_Hidden01 (line 137) | public sealed class PBEAutoCenterPacket_Hidden01 : IPBEAutoCenterPacket
    method PBEAutoCenterPacket_Hidden01 (line 147) | public PBEAutoCenterPacket_Hidden01(PBEAutoCenterPacket other)
    method PBEAutoCenterPacket_Hidden01 (line 161) | internal PBEAutoCenterPacket_Hidden01(byte[] data, EndianBinaryReader ...

FILE: PokemonBattleEngine/Packets/BattlePacket.cs
  class PBEBattlePacket (line 11) | public sealed class PBEBattlePacket : IPBEPacket
    class PBETeamInfo (line 16) | public sealed class PBETeamInfo
      class PBETrainerInfo (line 18) | public sealed class PBETrainerInfo
        class PBEBattlePokemonInfo (line 20) | public sealed class PBEBattlePokemonInfo // SleepTurns would be to...
          method PBEBattlePokemonInfo (line 41) | internal PBEBattlePokemonInfo(PBEBattlePokemon pkmn)
          method PBEBattlePokemonInfo (line 62) | internal PBEBattlePokemonInfo(EndianBinaryReader r)
          method ToBytes (line 84) | internal void ToBytes(EndianBinaryWriter w)
        class PBEInventorySlotInfo (line 106) | public sealed class PBEInventorySlotInfo
          method PBEInventorySlotInfo (line 111) | internal PBEInventorySlotInfo(PBEBattleInventory.PBEBattleInvent...
          method PBEInventorySlotInfo (line 116) | internal PBEInventorySlotInfo(EndianBinaryReader r)
          method ToBytes (line 122) | internal void ToBytes(EndianBinaryWriter w)
        method PBETrainerInfo (line 134) | internal PBETrainerInfo(PBETrainer trainer)
        method PBETrainerInfo (line 151) | internal PBETrainerInfo(EndianBinaryReader r)
        method PBETrainerInfo (line 184) | internal PBETrainerInfo(PBETrainerInfo other, byte? onlyForTrainer)
        method ToBytes (line 200) | internal void ToBytes(EndianBinaryWriter w)
      method PBETeamInfo (line 222) | internal PBETeamInfo(PBETeam team)
      method PBETeamInfo (line 227) | internal PBETeamInfo(EndianBinaryReader r)
      method PBETeamInfo (line 237) | internal PBETeamInfo(PBETeamInfo other, byte? onlyForTrainer)
      method ToBytes (line 243) | internal void ToBytes(EndianBinaryWriter w)
    method PBEBattlePacket (line 262) | internal PBEBattlePacket(PBEBattle battle)
    method PBEBattlePacket (line 282) | internal PBEBattlePacket(byte[] data, EndianBinaryReader r)
    method PBEBattlePacket (line 299) | public PBEBattlePacket(PBEBattlePacket other, byte? onlyForTrainer)

FILE: PokemonBattleEngine/Packets/BattleResultPacket.cs
  class PBEBattleResultPacket (line 8) | public sealed class PBEBattleResultPacket : IPBEPacket
    method PBEBattleResultPacket (line 15) | internal PBEBattleResultPacket(PBEBattleResult battleResult)
    method PBEBattleResultPacket (line 26) | internal PBEBattleResultPacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/FleeResponsePacket.cs
  class PBEFleeResponsePacket (line 7) | public sealed class PBEFleeResponsePacket : IPBEPacket
    method PBEFleeResponsePacket (line 12) | public PBEFleeResponsePacket()
    method PBEFleeResponsePacket (line 21) | internal PBEFleeResponsePacket(byte[] data)

FILE: PokemonBattleEngine/Packets/HazePacket.cs
  class PBEHazePacket (line 7) | public sealed class PBEHazePacket : IPBEPacket
    method PBEHazePacket (line 12) | internal PBEHazePacket()
    method PBEHazePacket (line 21) | internal PBEHazePacket(byte[] data)

FILE: PokemonBattleEngine/Packets/MatchCancelledPacket.cs
  class PBEMatchCancelledPacket (line 7) | public sealed class PBEMatchCancelledPacket : IPBEPacket
    method PBEMatchCancelledPacket (line 12) | public PBEMatchCancelledPacket()
    method PBEMatchCancelledPacket (line 21) | internal PBEMatchCancelledPacket(byte[] data)

FILE: PokemonBattleEngine/Packets/PartyRequestPacket.cs
  class PBEPartyRequestPacket (line 7) | public sealed class PBEPartyRequestPacket : IPBEPacket
    method PBEPartyRequestPacket (line 15) | public PBEPartyRequestPacket(byte battleId, bool requireLegal)
    method PBEPartyRequestPacket (line 27) | internal PBEPartyRequestPacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/PartyResponsePacket.cs
  class PBEPartyResponsePacket (line 9) | public sealed class PBEPartyResponsePacket : IPBEPacket
    method PBEPartyResponsePacket (line 16) | public PBEPartyResponsePacket(IPBEPokemonCollection party)
    method PBEPartyResponsePacket (line 27) | internal PBEPartyResponsePacket(byte[] data, EndianBinaryReader r)
  class PBELegalPartyResponsePacket (line 34) | public sealed class PBELegalPartyResponsePacket : IPBEPacket
    method PBELegalPartyResponsePacket (line 41) | public PBELegalPartyResponsePacket(PBELegalPokemonCollection party)
    method PBELegalPartyResponsePacket (line 53) | internal PBELegalPartyResponsePacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/PlayerJoinedPacket.cs
  class PBEPlayerJoinedPacket (line 8) | public sealed class PBEPlayerJoinedPacket : IPBEPacket
    method PBEPlayerJoinedPacket (line 15) | public PBEPlayerJoinedPacket(string trainerName)
    method PBEPlayerJoinedPacket (line 30) | internal PBEPlayerJoinedPacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/ResponsePacket.cs
  class PBEResponsePacket (line 7) | public sealed class PBEResponsePacket : IPBEPacket
    method PBEResponsePacket (line 12) | public PBEResponsePacket()
    method PBEResponsePacket (line 21) | internal PBEResponsePacket(byte[] data)

FILE: PokemonBattleEngine/Packets/SwitchInRequestPacket.cs
  class PBESwitchInRequestPacket (line 8) | public sealed class PBESwitchInRequestPacket : IPBEPacket
    method PBESwitchInRequestPacket (line 16) | internal PBESwitchInRequestPacket(PBETrainer trainer)
    method PBESwitchInRequestPacket (line 28) | internal PBESwitchInRequestPacket(byte[] data, EndianBinaryReader r, P...

FILE: PokemonBattleEngine/Packets/SwitchInResponsePacket.cs
  class PBESwitchInResponsePacket (line 10) | public sealed class PBESwitchInResponsePacket : IPBEPacket
    method PBESwitchInResponsePacket (line 17) | public PBESwitchInResponsePacket(IList<PBESwitchIn> switches)
    method PBESwitchInResponsePacket (line 37) | internal PBESwitchInResponsePacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/TurnBeganPacket.cs
  class PBETurnBeganPacket (line 7) | public sealed class PBETurnBeganPacket : IPBEPacket
    method PBETurnBeganPacket (line 14) | internal PBETurnBeganPacket(ushort turnNumber)
    method PBETurnBeganPacket (line 25) | internal PBETurnBeganPacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/_AbilityPacket.cs
  class PBEAbilityPacket (line 9) | public sealed class PBEAbilityPacket : IPBEPacket
    method PBEAbilityPacket (line 21) | internal PBEAbilityPacket(PBEBattlePokemon abilityOwner, PBEBattlePoke...
    method PBEAbilityPacket (line 37) | internal PBEAbilityPacket(byte[] data, EndianBinaryReader r, PBEBattle...

FILE: PokemonBattleEngine/Packets/_AbilityReplacedPacket.cs
  class PBEAbilityReplacedPacket (line 9) | public sealed class PBEAbilityReplacedPacket : IPBEPacket
    method PBEAbilityReplacedPacket (line 19) | internal PBEAbilityReplacedPacket(PBEBattlePokemon abilityOwner, PBEAb...
    method PBEAbilityReplacedPacket (line 37) | internal PBEAbilityReplacedPacket(byte[] data, EndianBinaryReader r, P...

FILE: PokemonBattleEngine/Packets/_BattleStatusPacket.cs
  class PBEBattleStatusPacket (line 8) | public sealed class PBEBattleStatusPacket : IPBEPacket
    method PBEBattleStatusPacket (line 16) | internal PBEBattleStatusPacket(PBEBattleStatus battleStatus, PBEBattle...
    method PBEBattleStatusPacket (line 28) | internal PBEBattleStatusPacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/_CapturePacket.cs
  class PBECapturePacket (line 9) | public sealed class PBECapturePacket : IPBEPacket
    method PBECapturePacket (line 21) | internal PBECapturePacket(PBEBattlePokemon pokemon, PBEItem ball, byte...
    method PBECapturePacket (line 37) | internal PBECapturePacket(byte[] data, EndianBinaryReader r, PBEBattle...

FILE: PokemonBattleEngine/Packets/_FleeFailedPacket.cs
  class PBEFleeFailedPacket (line 8) | public sealed class PBEFleeFailedPacket : IPBEPacket
    method PBEFleeFailedPacket (line 16) | internal PBEFleeFailedPacket(PBEBattlePokemon pokemon)
    method PBEFleeFailedPacket (line 28) | internal PBEFleeFailedPacket(byte[] data, EndianBinaryReader r, PBEBat...

FILE: PokemonBattleEngine/Packets/_IllusionPacket.cs
  class PBEIllusionPacket (line 9) | public sealed class PBEIllusionPacket : IPBEPacket
    method PBEIllusionPacket (line 26) | internal PBEIllusionPacket(PBEBattlePokemon pokemon)
    method PBEIllusionPacket (line 47) | internal PBEIllusionPacket(byte[] data, EndianBinaryReader r, PBEBattl...

FILE: PokemonBattleEngine/Packets/_ItemPacket.cs
  class PBEItemPacket (line 9) | public sealed class PBEItemPacket : IPBEPacket
    method PBEItemPacket (line 21) | internal PBEItemPacket(PBEBattlePokemon itemHolder, PBEBattlePokemon p...
    method PBEItemPacket (line 37) | internal PBEItemPacket(byte[] data, EndianBinaryReader r, PBEBattle ba...

FILE: PokemonBattleEngine/Packets/_ItemTurnPacket.cs
  class PBEItemTurnPacket (line 9) | public sealed class PBEItemTurnPacket : IPBEPacket
    method PBEItemTurnPacket (line 19) | internal PBEItemTurnPacket(PBEBattlePokemon itemUserHolder, PBEItem it...
    method PBEItemTurnPacket (line 33) | internal PBEItemTurnPacket(byte[] data, EndianBinaryReader r, PBEBattl...

FILE: PokemonBattleEngine/Packets/_MoveCritPacket.cs
  class PBEMoveCritPacket (line 8) | public sealed class PBEMoveCritPacket : IPBEPacket
    method PBEMoveCritPacket (line 16) | internal PBEMoveCritPacket(PBEBattlePokemon victim)
    method PBEMoveCritPacket (line 28) | internal PBEMoveCritPacket(byte[] data, EndianBinaryReader r, PBEBattl...

FILE: PokemonBattleEngine/Packets/_MoveLockPacket.cs
  class PBEMoveLockPacket (line 9) | public sealed class PBEMoveLockPacket : IPBEPacket
    method PBEMoveLockPacket (line 20) | internal PBEMoveLockPacket(PBEBattlePokemon moveUser, PBEMoveLockType ...
    method PBEMoveLockPacket (line 39) | internal PBEMoveLockPacket(byte[] data, EndianBinaryReader r, PBEBattl...

FILE: PokemonBattleEngine/Packets/_MovePPChangedPacket.cs
  class PBEMovePPChangedPacket (line 9) | public sealed class PBEMovePPChangedPacket : IPBEPacket
    method PBEMovePPChangedPacket (line 19) | internal PBEMovePPChangedPacket(PBEBattlePokemon moveUser, PBEMove mov...
    method PBEMovePPChangedPacket (line 33) | internal PBEMovePPChangedPacket(byte[] data, EndianBinaryReader r, PBE...

FILE: PokemonBattleEngine/Packets/_MoveResultPacket.cs
  class PBEMoveResultPacket (line 8) | public sealed class PBEMoveResultPacket : IPBEPacket
    method PBEMoveResultPacket (line 19) | internal PBEMoveResultPacket(PBEBattlePokemon moveUser, PBEBattlePokem...
    method PBEMoveResultPacket (line 34) | internal PBEMoveResultPacket(byte[] data, EndianBinaryReader r, PBEBat...

FILE: PokemonBattleEngine/Packets/_MoveUsedPacket.cs
  class PBEMoveUsedPacket (line 9) | public sealed class PBEMoveUsedPacket : IPBEPacket
    method PBEMoveUsedPacket (line 19) | internal PBEMoveUsedPacket(PBEBattlePokemon moveUser, PBEMove move, bo...
    method PBEMoveUsedPacket (line 33) | internal PBEMoveUsedPacket(byte[] data, EndianBinaryReader r, PBEBattl...

FILE: PokemonBattleEngine/Packets/_PkmnEXPChangedPacket.cs
  class PBEPkmnEXPChangedPacket (line 8) | public sealed class PBEPkmnEXPChangedPacket : IPBEPacket
    method PBEPkmnEXPChangedPacket (line 18) | internal PBEPkmnEXPChangedPacket(PBEBattlePokemon pokemon, uint oldEXP)
    method PBEPkmnEXPChangedPacket (line 32) | internal PBEPkmnEXPChangedPacket(byte[] data, EndianBinaryReader r, PB...

FILE: PokemonBattleEngine/Packets/_PkmnEXPEarnedPacket.cs
  class PBEPkmnEXPEarnedPacket (line 8) | public sealed class PBEPkmnEXPEarnedPacket : IPBEPacket
    method PBEPkmnEXPEarnedPacket (line 17) | internal PBEPkmnEXPEarnedPacket(PBEBattlePokemon pokemon, uint earned)
    method PBEPkmnEXPEarnedPacket (line 30) | internal PBEPkmnEXPEarnedPacket(byte[] data, EndianBinaryReader r, PBE...

FILE: PokemonBattleEngine/Packets/_PkmnFaintedPacket.cs
  type IPBEPkmnFaintedPacket (line 8) | public interface IPBEPkmnFaintedPacket : IPBEPacket
  class PBEPkmnFaintedPacket (line 13) | public sealed class PBEPkmnFaintedPacket : IPBEPkmnFaintedPacket
    method PBEPkmnFaintedPacket (line 22) | internal PBEPkmnFaintedPacket(PBEBattlePokemon pokemon, PBEFieldPositi...
    method PBEPkmnFaintedPacket (line 35) | internal PBEPkmnFaintedPacket(byte[] data, EndianBinaryReader r, PBEBa...
  class PBEPkmnFaintedPacket_Hidden (line 44) | public sealed class PBEPkmnFaintedPacket_Hidden : IPBEPkmnFaintedPacket
    method PBEPkmnFaintedPacket_Hidden (line 52) | public PBEPkmnFaintedPacket_Hidden(PBEPkmnFaintedPacket other)
    method PBEPkmnFaintedPacket_Hidden (line 64) | internal PBEPkmnFaintedPacket_Hidden(byte[] data, EndianBinaryReader r...

FILE: PokemonBattleEngine/Packets/_PkmnFormChangedPacket.cs
  type IPBEPkmnFormChangedPacket (line 9) | public interface IPBEPkmnFormChangedPacket : IPBEPacket
  class PBEPkmnFormChangedPacket (line 21) | public sealed class PBEPkmnFormChangedPacket : IPBEPkmnFormChangedPacket
    method PBEPkmnFormChangedPacket (line 44) | internal PBEPkmnFormChangedPacket(PBEBattlePokemon pokemon, bool isRev...
    method PBEPkmnFormChangedPacket (line 71) | internal PBEPkmnFormChangedPacket(byte[] data, EndianBinaryReader r, P...
  class PBEPkmnFormChangedPacket_Hidden (line 93) | public sealed class PBEPkmnFormChangedPacket_Hidden : IPBEPkmnFormChange...
    method PBEPkmnFormChangedPacket_Hidden (line 108) | public PBEPkmnFormChangedPacket_Hidden(PBEPkmnFormChangedPacket other)
    method PBEPkmnFormChangedPacket_Hidden (line 127) | internal PBEPkmnFormChangedPacket_Hidden(byte[] data, EndianBinaryRead...

FILE: PokemonBattleEngine/Packets/_PkmnHPChangedPacket.cs
  type IPBEPkmnHPChangedPacket (line 8) | public interface IPBEPkmnHPChangedPacket : IPBEPacket
  class PBEPkmnHPChangedPacket (line 15) | public sealed class PBEPkmnHPChangedPacket : IPBEPkmnHPChangedPacket
    method PBEPkmnHPChangedPacket (line 27) | internal PBEPkmnHPChangedPacket(PBEBattlePokemon pokemon, ushort oldHP...
    method PBEPkmnHPChangedPacket (line 43) | internal PBEPkmnHPChangedPacket(byte[] data, EndianBinaryReader r, PBE...
  class PBEPkmnHPChangedPacket_Hidden (line 55) | public sealed class PBEPkmnHPChangedPacket_Hidden : IPBEPkmnHPChangedPacket
    method PBEPkmnHPChangedPacket_Hidden (line 65) | public PBEPkmnHPChangedPacket_Hidden(PBEPkmnHPChangedPacket other)
    method PBEPkmnHPChangedPacket_Hidden (line 79) | internal PBEPkmnHPChangedPacket_Hidden(byte[] data, EndianBinaryReader...

FILE: PokemonBattleEngine/Packets/_PkmnLevelChangedPacket.cs
  class PBEPkmnLevelChangedPacket (line 8) | public sealed class PBEPkmnLevelChangedPacket : IPBEPacket
    method PBEPkmnLevelChangedPacket (line 17) | internal PBEPkmnLevelChangedPacket(PBEBattlePokemon pokemon)
    method PBEPkmnLevelChangedPacket (line 30) | internal PBEPkmnLevelChangedPacket(byte[] data, EndianBinaryReader r, ...

FILE: PokemonBattleEngine/Packets/_PkmnStatChangedPacket.cs
  class PBEPkmnStatChangedPacket (line 9) | public sealed class PBEPkmnStatChangedPacket : IPBEPacket
    method PBEPkmnStatChangedPacket (line 20) | internal PBEPkmnStatChangedPacket(PBEBattlePokemon pokemon, PBEStat st...
    method PBEPkmnStatChangedPacket (line 35) | internal PBEPkmnStatChangedPacket(byte[] data, EndianBinaryReader r, P...

FILE: PokemonBattleEngine/Packets/_PkmnSwitchInPacket.cs
  type IPBEPkmnSwitchInInfo_Hidden (line 10) | public interface IPBEPkmnSwitchInInfo_Hidden : IPBEPkmnAppearedInfo_Hidden
  type IPBEPkmnSwitchInPacket (line 14) | public interface IPBEPkmnSwitchInPacket : IPBEPacket
  class PBEPkmnSwitchInPacket (line 22) | public sealed class PBEPkmnSwitchInPacket : IPBEPkmnSwitchInPacket
    method PBEPkmnSwitchInPacket (line 34) | internal PBEPkmnSwitchInPacket(PBETrainer trainer, IList<PBEPkmnAppear...
    method PBEPkmnSwitchInPacket (line 57) | internal PBEPkmnSwitchInPacket(byte[] data, EndianBinaryReader r, PBEB...
  class PBEPkmnSwitchInPacket_Hidden (line 76) | public sealed class PBEPkmnSwitchInPacket_Hidden : IPBEPkmnSwitchInPacket
    class PBEPkmnSwitchInInfo (line 81) | public sealed class PBEPkmnSwitchInInfo : IPBEPkmnSwitchInInfo_Hidden
      method PBEPkmnSwitchInInfo (line 94) | internal PBEPkmnSwitchInInfo(PBEPkmnAppearedInfo other)
      method PBEPkmnSwitchInInfo (line 107) | internal PBEPkmnSwitchInInfo(EndianBinaryReader r)
      method ToBytes (line 121) | internal void ToBytes(EndianBinaryWriter w)
    method PBEPkmnSwitchInPacket_Hidden (line 143) | public PBEPkmnSwitchInPacket_Hidden(PBEPkmnSwitchInPacket other)
    method PBEPkmnSwitchInPacket_Hidden (line 171) | internal PBEPkmnSwitchInPacket_Hidden(byte[] data, EndianBinaryReader ...

FILE: PokemonBattleEngine/Packets/_PkmnSwitchOutPacket.cs
  type IPBEPkmnSwitchOutPacket (line 8) | public interface IPBEPkmnSwitchOutPacket : IPBEPacket
  class PBEPkmnSwitchOutPacket (line 16) | public sealed class PBEPkmnSwitchOutPacket : IPBEPkmnSwitchOutPacket
    method PBEPkmnSwitchOutPacket (line 28) | internal PBEPkmnSwitchOutPacket(PBEBattlePokemon pokemon, PBEFieldPosi...
    method PBEPkmnSwitchOutPacket (line 47) | internal PBEPkmnSwitchOutPacket(byte[] data, EndianBinaryReader r, PBE...
  class PBEPkmnSwitchOutPacket_Hidden (line 62) | public sealed class PBEPkmnSwitchOutPacket_Hidden : IPBEPkmnSwitchOutPacket
    method PBEPkmnSwitchOutPacket_Hidden (line 73) | public PBEPkmnSwitchOutPacket_Hidden(PBEPkmnSwitchOutPacket other)
    method PBEPkmnSwitchOutPacket_Hidden (line 91) | internal PBEPkmnSwitchOutPacket_Hidden(byte[] data, EndianBinaryReader...

FILE: PokemonBattleEngine/Packets/_PsychUpPacket.cs
  class PBEPsychUpPacket (line 8) | public sealed class PBEPsychUpPacket : IPBEPacket
    method PBEPsychUpPacket (line 25) | internal PBEPsychUpPacket(PBEBattlePokemon user, PBEBattlePokemon target)
    method PBEPsychUpPacket (line 46) | internal PBEPsychUpPacket(byte[] data, EndianBinaryReader r, PBEBattle...

FILE: PokemonBattleEngine/Packets/_ReflectTypePacket.cs
  class PBEReflectTypePacket (line 9) | public sealed class PBEReflectTypePacket : IPBEPacket
    method PBEReflectTypePacket (line 21) | internal PBEReflectTypePacket(PBEBattlePokemon user, PBEBattlePokemon ...
    method PBEReflectTypePacket (line 37) | internal PBEReflectTypePacket(byte[] data, EndianBinaryReader r, PBEBa...
  class PBEReflectTypePacket_Hidden (line 49) | public sealed class PBEReflectTypePacket_Hidden : IPBEPacket
    method PBEReflectTypePacket_Hidden (line 59) | public PBEReflectTypePacket_Hidden(PBEReflectTypePacket other)
    method PBEReflectTypePacket_Hidden (line 73) | internal PBEReflectTypePacket_Hidden(byte[] data, EndianBinaryReader r...

FILE: PokemonBattleEngine/Packets/_SpecialMessagePacket.cs
  class PBESpecialMessagePacket (line 10) | public sealed class PBESpecialMessagePacket : IPBEPacket
    method PBESpecialMessagePacket (line 18) | internal PBESpecialMessagePacket(PBESpecialMessage message, params obj...
    method PBESpecialMessagePacket (line 69) | internal PBESpecialMessagePacket(byte[] data, EndianBinaryReader r, PB...

FILE: PokemonBattleEngine/Packets/_Status1Packet.cs
  class PBEStatus1Packet (line 8) | public sealed class PBEStatus1Packet : IPBEPacket
    method PBEStatus1Packet (line 20) | internal PBEStatus1Packet(PBEBattlePokemon status1Receiver, PBEBattleP...
    method PBEStatus1Packet (line 36) | internal PBEStatus1Packet(byte[] data, EndianBinaryReader r, PBEBattle...

FILE: PokemonBattleEngine/Packets/_Status2Packet.cs
  class PBEStatus2Packet (line 8) | public sealed class PBEStatus2Packet : IPBEPacket
    method PBEStatus2Packet (line 20) | internal PBEStatus2Packet(PBEBattlePokemon status2Receiver, PBEBattleP...
    method PBEStatus2Packet (line 36) | internal PBEStatus2Packet(byte[] data, EndianBinaryReader r, PBEBattle...

FILE: PokemonBattleEngine/Packets/_TeamStatusDamagePacket.cs
  class PBETeamStatusDamagePacket (line 8) | public sealed class PBETeamStatusDamagePacket : IPBEPacket
    method PBETeamStatusDamagePacket (line 18) | internal PBETeamStatusDamagePacket(PBETeam team, PBETeamStatus teamSta...
    method PBETeamStatusDamagePacket (line 32) | internal PBETeamStatusDamagePacket(byte[] data, EndianBinaryReader r, ...

FILE: PokemonBattleEngine/Packets/_TeamStatusPacket.cs
  class PBETeamStatusPacket (line 8) | public sealed class PBETeamStatusPacket : IPBEPacket
    method PBETeamStatusPacket (line 17) | internal PBETeamStatusPacket(PBETeam team, PBETeamStatus teamStatus, P...
    method PBETeamStatusPacket (line 30) | internal PBETeamStatusPacket(byte[] data, EndianBinaryReader r, PBEBat...

FILE: PokemonBattleEngine/Packets/_TransformPacket.cs
  class PBETransformPacket (line 9) | public sealed class PBETransformPacket : IPBEPacket
    method PBETransformPacket (line 38) | internal PBETransformPacket(PBEBattlePokemon user, PBEBattlePokemon ta...
    method PBETransformPacket (line 75) | internal PBETransformPacket(byte[] data, EndianBinaryReader r, PBEBatt...

FILE: PokemonBattleEngine/Packets/_TypeChangedPacket.cs
  class PBETypeChangedPacket (line 9) | public sealed class PBETypeChangedPacket : IPBEPacket
    method PBETypeChangedPacket (line 19) | internal PBETypeChangedPacket(PBEBattlePokemon pokemon, PBEType type1,...
    method PBETypeChangedPacket (line 33) | internal PBETypeChangedPacket(byte[] data, EndianBinaryReader r, PBEBa...

FILE: PokemonBattleEngine/Packets/_WeatherDamagePacket.cs
  class PBEWeatherDamagePacket (line 8) | public sealed class PBEWeatherDamagePacket : IPBEPacket
    method PBEWeatherDamagePacket (line 17) | internal PBEWeatherDamagePacket(PBEWeather weather, PBEBattlePokemon d...
    method PBEWeatherDamagePacket (line 30) | internal PBEWeatherDamagePacket(byte[] data, EndianBinaryReader r, PBE...

FILE: PokemonBattleEngine/Packets/_WeatherPacket.cs
  class PBEWeatherPacket (line 8) | public sealed class PBEWeatherPacket : IPBEPacket
    method PBEWeatherPacket (line 16) | internal PBEWeatherPacket(PBEWeather weather, PBEWeatherAction weather...
    method PBEWeatherPacket (line 28) | internal PBEWeatherPacket(byte[] data, EndianBinaryReader r)

FILE: PokemonBattleEngine/Packets/_WildPkmnAppearedPacket.cs
  type IPBEPkmnAppearedInfo_Hidden (line 10) | public interface IPBEPkmnAppearedInfo_Hidden : IPBESpeciesForm
  type IPBEWildPkmnAppearedPacket (line 20) | public interface IPBEWildPkmnAppearedPacket : IPBEPacket
  class PBEPkmnAppearedInfo (line 24) | public sealed class PBEPkmnAppearedInfo : IPBEPkmnSwitchInInfo_Hidden
    method PBEPkmnAppearedInfo (line 41) | internal PBEPkmnAppearedInfo(PBEBattlePokemon pkmn)
    method PBEPkmnAppearedInfo (line 58) | internal PBEPkmnAppearedInfo(EndianBinaryReader r)
    method ToBytes (line 76) | internal void ToBytes(EndianBinaryWriter w)
  class PBEWildPkmnAppearedPacket (line 94) | public sealed class PBEWildPkmnAppearedPacket : IPBEWildPkmnAppearedPacket
    method PBEWildPkmnAppearedPacket (line 102) | internal PBEWildPkmnAppearedPacket(IList<PBEPkmnAppearedInfo> pokemon)
    method PBEWildPkmnAppearedPacket (line 118) | internal PBEWildPkmnAppearedPacket(byte[] data, EndianBinaryReader r)
  class PBEWildPkmnAppearedPacket_Hidden (line 130) | public sealed class PBEWildPkmnAppearedPacket_Hidden : IPBEWildPkmnAppea...
    class PBEWildPkmnInfo (line 135) | public sealed class PBEWildPkmnInfo : IPBEPkmnAppearedInfo_Hidden
      method PBEWildPkmnInfo (line 147) | internal PBEWildPkmnInfo(PBEPkmnAppearedInfo other)
      method PBEWildPkmnInfo (line 159) | internal PBEWildPkmnInfo(EndianBinaryReader r)
      method ToBytes (line 172) | internal void ToBytes(EndianBinaryWriter w)
    method PBEWildPkmnAppearedPacket_Hidden (line 189) | public PBEWildPkmnAppearedPacket_Hidden(PBEWildPkmnAppearedPacket other)
    method PBEWildPkmnAppearedPacket_Hidden (line 210) | internal PBEWildPkmnAppearedPacket_Hidden(byte[] data, EndianBinaryRea...

FILE: PokemonBattleEngine/Packets/__Packet.cs
  type IPBEPacket (line 5) | public interface IPBEPacket

FILE: PokemonBattleEngine/Packets/__PacketProcessor.cs
  class PBEPacketProcessor (line 9) | public class PBEPacketProcessor
    method CheckNull (line 11) | protected static void CheckNull([NotNull] PBEBattle? battle)
    method CreatePacket (line 19) | public IPBEPacket CreatePacket(byte[] data, PBEBattle? battle)
    method WritePacketID (line 39) | public static EndianBinaryWriter WritePacketID(MemoryStream ms, ushort...
    method TryCreatePacket (line 46) | protected virtual IPBEPacket? TryCreatePacket(byte[] data, PBEBattle? ...

FILE: PokemonBattleEngine/Utils/EmptyCollections.cs
  class PBEEmptyReadOnlyCollection (line 6) | internal static class PBEEmptyReadOnlyCollection<T>

FILE: PokemonBattleEngine/Utils/Random.cs
  class PBERandom (line 11) | public class PBERandom
    method PBERandom (line 30) | public PBERandom() : this(Environment.TickCount) { }
    method PBERandom (line 31) | public PBERandom(int? seed) : this(seed ?? Environment.TickCount) { }
    method PBERandom (line 32) | public PBERandom(int seed)
    method RandomBattleTerrain (line 38) | public PBEBattleTerrain RandomBattleTerrain()
    method RandomBool (line 42) | public bool RandomBool()
    method RandomBool (line 46) | public bool RandomBool(int chanceNumerator, int chanceDenominator)
    method RandomElement (line 62) | public T RandomElement<T>(IReadOnlyList<T> source)
    method RandomGender (line 77) | public PBEGender RandomGender(PBEGenderRatio genderRatio)
    method RandomInt (line 91) | public int RandomInt()
    method RandomInt (line 96) | public int RandomInt(int minValue, int maxValue)
    method RandomLevel (line 121) | public byte RandomLevel(PBESettings settings)
    method RandomShiny (line 127) | public bool RandomShiny()
    method RandomSpecies (line 132) | public (PBESpecies, PBEForm) RandomSpecies(bool requireUsableOutsideOf...
    method RandomSpecies (line 136) | public (PBESpecies, PBEForm) RandomSpecies(IReadOnlyList<PBESpecies> e...
    method Shuffle (line 144) | public void Shuffle<T>(IList<T> source)

FILE: PokemonBattleEngine/Utils/Utils.cs
  class PBEUtils (line 8) | public static class PBEUtils
    method Andify (line 13) | public static string Andify<T>(this IReadOnlyList<T> source)
    method ExceptOne (line 34) | public static IEnumerable<T> ExceptOne<T>(this IEnumerable<T> source, ...
    method ToSafeFileName (line 45) | internal static string ToSafeFileName(string fileName)
    method GetSafe (line 55) | internal static JsonNode GetSafe(this JsonArray j, int index)
    method GetSafe (line 64) | internal static JsonNode GetSafe(this JsonObject j, string key)

FILE: PokemonBattleEngineClient.Android/MainActivity.cs
  class MainActivity (line 11) | [Activity(Label = "Pokémon Battle Engine", Icon = "@drawable/icon", Main...
    method OnCreate (line 14) | protected override void OnCreate(Bundle savedInstanceState)
    method CopyDatabase (line 27) | private void CopyDatabase()

FILE: PokemonBattleEngineClient.Android/Resources/Resource.Designer.cs
  class Resource (line 18) | [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.T...
    method Resource (line 22) | static Resource()
    method UpdateIdValues (line 27) | public static void UpdateIdValues()
    class Attribute (line 31) | public partial class Attribute
      method Attribute (line 34) | static Attribute()
      method Attribute (line 39) | private Attribute()
    class Drawable (line 44) | public partial class Drawable
      method Drawable (line 50) | static Drawable()
      method Drawable (line 55) | private Drawable()
    class Id (line 60) | public partial class Id
      method Id (line 66) | static Id()
      method Id (line 71) | private Id()
    class Layout (line 76) | public partial class Layout
      method Layout (line 82) | static Layout()
      method Layout (line 87) | private Layout()
    class String (line 92) | public partial class String
      method String (line 101) | static String()
      method String (line 106) | private String()

FILE: PokemonBattleEngineClient.Desktop/Program.cs
  class Program (line 8) | internal static class Program
    method Main (line 10) | [STAThread]
    method BuildAvaloniaApp (line 17) | public static AppBuilder BuildAvaloniaApp()

FILE: PokemonBattleEngineClient.iOS/AppDelegate.cs
  class AppDelegate (line 15) | [Register("AppDelegate")]
    method FinishedLaunching (line 27) | public override bool FinishedLaunching(UIApplication uiapp, NSDictiona...
    method CopyDatabase (line 39) | private void CopyDatabase()

FILE: PokemonBattleEngineClient.iOS/Main.cs
  class Application (line 5) | public sealed class Application
    method Main (line 7) | private static void Main(string[] args)

FILE: PokemonBattleEngineClient/App.xaml.cs
  class App (line 10) | public sealed class App : Application
    method Initialize (line 12) | public override void Initialize()
    method OnFrameworkInitializationCompleted (line 17) | public override void OnFrameworkInitializationCompleted()

FILE: PokemonBattleEngineClient/Clients/ActionsBuilder.cs
  class ActionsBuilder (line 9) | internal sealed class ActionsBuilder
    method ActionsBuilder (line 19) | public ActionsBuilder(BattleView bv, PBETrainer trainer, Action<PBETur...
    method IsStandBy (line 30) | public bool IsStandBy(PBEBattlePokemon p)
    method Pop (line 36) | public void Pop()
    method PushMove (line 41) | public void PushMove(PBEMove move, PBETurnTarget targets)
    method PushSwitch (line 51) | public void PushSwitch(PBEBattlePokemon switcher)
    method ActionsLoop (line 62) | private void ActionsLoop()

FILE: PokemonBattleEngineClient/Clients/BattleClient.cs
  class BattleClient (line 8) | internal abstract class BattleClient : IDisposable
    method BattleClient (line 18) | protected BattleClient(string name)
    method ShouldUseKnownInfo (line 23) | public bool ShouldUseKnownInfo(PBETrainer pkmnTrainer)
    method Dispose (line 28) | public abstract void Dispose();
    method ShowAllPokemon (line 30) | protected void ShowAllPokemon()
    method ProcessPacket (line 40) | protected virtual bool ProcessPacket(IPBEPacket packet)

FILE: PokemonBattleEngineClient/Clients/NetworkClient.cs
  class NetworkClientConnection (line 12) | internal sealed class NetworkClientConnection : IDisposable
    method NetworkClientConnection (line 19) | public NetworkClientConnection(string host, ushort port, PBELegalPokem...
    method OnConnected (line 38) | private void OnConnected()
    method OnDisconnected (line 43) | private void OnDisconnected(object? sender, EventArgs e)
    method OnError (line 48) | private void OnError(object? sender, Exception ex)
    method OnPacketReceived (line 53) | private void OnPacketReceived(object? sender, IPBEPacket packet)
    method Send (line 89) | private void Send(IPBEPacket packet)
    method Dispose (line 97) | public void Dispose()
  class NetworkClient (line 102) | internal sealed class NetworkClient : NonLocalClient
    method NetworkClient (line 110) | public NetworkClient(PBEClient client, PBEBattlePacket bp, byte battle...
    method OnDisconnected (line 128) | private void OnDisconnected(object? sender, EventArgs e)
    method OnError (line 133) | private void OnError(object? sender, Exception ex)
    method OnPacketReceived (line 137) | private void OnPacketReceived(object? sender, IPBEPacket packet)
    method OnActionsReady (line 172) | private void OnActionsReady(PBETurnAction[] acts)
    method OnSwitchesReady (line 177) | private void OnSwitchesReady(PBESwitchIn[] switches)
    method Send (line 183) | private void Send(IPBEPacket packet)
    method Dispose (line 191) | public override void Dispose()
    method ProcessPacket (line 197) | protected override bool ProcessPacket(IPBEPacket packet)

FILE: PokemonBattleEngineClient/Clients/NonLocalClient.cs
  class NonLocalClient (line 9) | internal abstract class NonLocalClient : BattleClient
    method NonLocalClient (line 11) | protected NonLocalClient(string name) : base(name) { }
    method Dispose (line 13) | public override void Dispose()
    method CreateThread__Unsafe (line 25) | private void CreateThread__Unsafe()
    method StartPacketThread (line 30) | protected void StartPacketThread()
    method PacketThread (line 45) | private void PacketThread()
    method DoDisguisedAppearance (line 69) | private static void DoDisguisedAppearance(PBEBattlePokemon pkmn, PBEPk...
    method ProcessPacket (line 85) | protected override bool ProcessPacket(IPBEPacket packet)

FILE: PokemonBattleEngineClient/Clients/ReplayClient.cs
  class ReplayClient (line 7) | internal sealed class ReplayClient : NonLocalClient
    method ReplayClient (line 14) | public ReplayClient(string path, string name)
    method ProcessPacket (line 23) | protected override bool ProcessPacket(IPBEPacket packet)

FILE: PokemonBattleEngineClient/Clients/SinglePlayerClient.cs
  class SinglePlayerClient (line 9) | internal sealed class SinglePlayerClient : BattleClient
    method SinglePlayerClient (line 17) | public SinglePlayerClient(PBEBattle b, string name) : base(name)
    method CreateBattleThread (line 32) | private static void CreateBattleThread(ThreadStart start)
    method SinglePlayerBattle_OnNewEvent (line 37) | private void SinglePlayerBattle_OnNewEvent(PBEBattle battle, IPBEPacke...
    method SinglePlayerBattle_OnStateChanged (line 44) | private void SinglePlayerBattle_OnStateChanged(PBEBattle battle)
    method OnActionsReady (line 54) | private void OnActionsReady(PBETurnAction[] acts)
    method OnSwitchesReady (line 58) | private void OnSwitchesReady(PBESwitchIn[] switches)
    method GetAI (line 63) | private PBEDDAI GetAI(PBETrainer t)
    method Dispose (line 68) | public override void Dispose()
    method ProcessPacket (line 73) | protected override bool ProcessPacket(IPBEPacket packet)

FILE: PokemonBattleEngineClient/Clients/SwitchesBuilder.cs
  class SwitchesBuilder (line 7) | internal sealed class SwitchesBuilder
    method SwitchesBuilder (line 18) | public SwitchesBuilder(BattleView bv, byte amount, Action<PBESwitchIn[...
    method IsStandBy (line 30) | public bool IsStandBy(PBEBattlePokemon p)
    method IsStandBy (line 35) | public bool IsStandBy(PBEFieldPosition p)
    method Pop (line 41) | public void Pop()
    method Push (line 46) | public void Push(PBEBattlePokemon pkmn, PBEFieldPosition pos)
    method SwitchesLoop (line 55) | private void SwitchesLoop()

FILE: PokemonBattleEngineClient/Infrastructure/BetterWrapPanel.cs
  class BetterWrapPanel (line 13) | public sealed class BetterWrapPanel : Panel, INavigableContainer
    method BetterWrapPanel (line 21) | static BetterWrapPanel()
    method GetControl (line 46) | IInputElement INavigableContainer.GetControl(NavigationDirection direc...
    method MeasureOverride (line 89) | protected override Size MeasureOverride(Size constraint)
    method ArrangeOverride (line 139) | protected override Size ArrangeOverride(Size finalSize)
    method ArrangeLine (line 189) | private void ArrangeLine(Size finalSize, double v, UVSize line, int st...
    type UVSize (line 242) | private struct UVSize
      method UVSize (line 244) | internal UVSize(Orientation orientation, double width, double height)
      method UVSize (line 252) | internal UVSize(Orientation orientation)

FILE: PokemonBattleEngineClient/Infrastructure/Converters.cs
  class FormToTextBitmapConverter (line 12) | public sealed class FormToTextBitmapConverter : IMultiValueConverter
    method Convert (line 15) | public object? Convert(IList<object> values, Type? targetType, object?...
  class ObjectToTextBitmapConverter (line 27) | public sealed class ObjectToTextBitmapConverter : IValueConverter
    method Convert (line 30) | public object? Convert(object? value, Type? targetType, object? parame...
    method ConvertBack (line 51) | public object? ConvertBack(object value, Type targetType, object param...
  class SpeciesToMinispriteConverter (line 56) | public sealed class SpeciesToMinispriteConverter : IValueConverter
    method Convert (line 59) | public object? Convert(object? value, Type? targetType, object? parame...
    method ConvertBack (line 93) | public object? ConvertBack(object? value, Type? targetType, object? pa...

FILE: PokemonBattleEngineClient/Infrastructure/StringRenderer.cs
  class StringRenderer (line 11) | internal static class StringRenderer
    type IStringRenderFont (line 13) | private interface IStringRenderFont
    class BattleHPFont (line 21) | private class BattleHPFont : IStringRenderFont
    class BattleLevelFont (line 29) | private class BattleLevelFont : IStringRenderFont
    class BattleNameFont (line 40) | private class BattleNameFont : IStringRenderFont
    class DefaultFont (line 54) | private class DefaultFont : IStringRenderFont
    method Render (line 69) | [return: NotNullIfNotNull("str")]

FILE: PokemonBattleEngineClient/Infrastructure/Utils.cs
  class Utils (line 17) | public static class Utils
    method Utils (line 36) | static Utils()
    method DoesResourceExist (line 61) | public static bool DoesResourceExist(string resource)
    method GetResourceStream (line 73) | public static Stream GetResourceStream(string resource)
    method GetResourceUri (line 82) | public static Uri GetResourceUri(string resource)
    method SetWorkingDirectory (line 88) | public static void SetWorkingDirectory(string workingDirectory)
    method HasFemaleSprite (line 96) | private static bool HasFemaleSprite(PBESpecies species, bool minisprite)
    method GetMinispriteBitmap (line 100) | public static Bitmap GetMinispriteBitmap(PBESpecies species, PBEForm f...
    method GetPokemonSpriteUri (line 106) | public static Uri GetPokemonSpriteUri(PBEBattlePokemon pkmn, bool back...
    method GetPokemonSpriteUri (line 110) | public static Uri GetPokemonSpriteUri(IPBEPokemon pkmn)
    method GetPokemonSpriteUri (line 114) | public static Uri GetPokemonSpriteUri(PBESpecies species, PBEForm form...
    method CustomPokemonToString (line 129) | public static string CustomPokemonToString(PBEBattlePokemon pkmn, bool...

FILE: PokemonBattleEngineClient/Infrastructure/WriteableBitmapSurface.cs
  class WriteableBitmapSurface (line 7) | internal sealed class WriteableBitmapSurface : IFramebufferPlatformSurface
    method WriteableBitmapSurface (line 10) | public WriteableBitmapSurface(WriteableBitmap bmp)
    method Lock (line 14) | public ILockedFramebuffer Lock()

FILE: PokemonBattleEngineClient/MainWindow.xaml.cs
  class MainWindow (line 7) | public sealed class MainWindow : Window
    method MainWindow (line 9) | public MainWindow()
    method HandleClosing (line 19) | protected override bool HandleClosing()

FILE: PokemonBattleEngineClient/Models/MoveInfo.cs
  class MoveInfo (line 13) | public sealed class MoveInfo
    method CreateBrushes (line 16) | internal static void CreateBrushes()
    method MoveInfo (line 47) | internal MoveInfo(PBEBattlePokemon pkmn, PBEMove move, Action<PBEMove>...

FILE: PokemonBattleEngineClient/Models/PokemonInfo.cs
  class PokemonInfo (line 9) | public sealed class PokemonInfo
    method PokemonInfo (line 14) | internal PokemonInfo(PBEBattlePokemon pkmn, bool useKnownInfo)
    method From (line 20) | internal static PokemonInfo? From(BattleClient client, PBETeam team, P...

FILE: PokemonBattleEngineClient/Models/SwitchInfo.cs
  class SwitchInfo (line 9) | public sealed class SwitchInfo
    method SwitchInfo (line 17) | internal SwitchInfo(PBEBattlePokemon pkmn, bool locked, Action<PBEBatt...

FILE: PokemonBattleEngineClient/Models/TargetInfo.cs
  class TargetInfo (line 6) | public sealed class TargetInfo : INotifyPropertyChanged
    method OnPropertyChanged (line 8) | private void OnPropertyChanged(string property)

FILE: PokemonBattleEngineClient/Models/TeamInfo.cs
  class TeamInfo (line 5) | public sealed class TeamInfo
    method TeamInfo (line 10) | internal TeamInfo(string name, PBELegalPokemonCollection party)

FILE: PokemonBattleEngineClient/Views/ActionsView.xaml.cs
  class ActionsView (line 13) | public sealed class ActionsView : UserControl, INotifyPropertyChanged
    method OnPropertyChanged (line 15) | private void OnPropertyChanged(string property)
    method ActionsView (line 183) | public ActionsView()
    method DisplayActions (line 195) | internal void DisplayActions(int index, PBEBattlePokemon pkmn)
    method DisplaySwitches (line 217) | internal void DisplaySwitches(int index)
    method UndoLast (line 232) | public void UndoLast()
    method SelectPokemonForTurn (line 255) | private void SelectPokemonForTurn(PBEBattlePokemon pkmn)
    method SelectMoveForTurn (line 262) | private void SelectMoveForTurn(PBEMove move)
    method SelectSwitch (line 268) | private void SelectSwitch(PBEBattlePokemon pkmn)
    method DisplayTargets (line 274) | private void DisplayTargets(PBEMove move)
    method CanUsePosition (line 728) | private bool CanUsePosition(PBEFieldPosition pos)
    method DisplayPositions (line 733) | private void DisplayPositions()
    method SelectTarget (line 790) | public void SelectTarget(string arg)
    method SelectPosition (line 807) | public void SelectPosition(string arg)

FILE: PokemonBattleEngineClient/Views/BattleView.xaml.cs
  class BattleView (line 7) | public sealed class BattleView : UserControl
    method BattleView (line 15) | public BattleView()
    method BattleView (line 24) | internal BattleView(BattleClient client)
    method AddMessage (line 36) | internal void AddMessage(string message, bool messageBox = true, bool ...

FILE: PokemonBattleEngineClient/Views/FieldView.xaml.cs
  class FieldView (line 17) | public sealed class FieldView : UserControl, INotifyPropertyChanged
    method OnPropertyChanged (line 19) | private void OnPropertyChanged(string property)
    method CreateResources (line 63) | internal static void CreateResources()
    method FieldView (line 96) | public FieldView()
    method SetBattleView (line 108) | internal void SetBattleView(BattleView battleView)
    method SetMessage (line 184) | internal void SetMessage(string message)
    method UpdateWeather (line 190) | internal void UpdateWeather()
    method GetPokemonViewStuff (line 235) | private void GetPokemonViewStuff(PBEBattlePokemon pkmn, PBEFieldPositi...
    method UpdatePokemon (line 242) | private void UpdatePokemon(PBEBattlePokemon pkmn, bool backSprite, HPB...
    method ShowPokemon (line 255) | internal void ShowPokemon(PBEBattlePokemon pkmn)
    method HidePokemon (line 265) | internal void HidePokemon(PBEBattlePokemon pkmn, PBEFieldPosition oldP...
    method UpdatePokemon (line 274) | internal void UpdatePokemon(PBEBattlePokemon pkmn, bool hpBar, bool sp...
    method MovePokemon (line 282) | internal void MovePokemon(PBEBattlePokemon pkmn, PBEFieldPosition oldP...

FILE: PokemonBattleEngineClient/Views/HPBarView.xaml.cs
  class HPBarView (line 16) | public sealed class HPBarView : UserControl, INotifyPropertyChanged
    method OnPropertyChanged (line 18) | private void OnPropertyChanged(string property)
    method CreateResources (line 53) | internal static void CreateResources()
    method HPBarView (line 70) | public HPBarView()
    method Update (line 79) | internal void Update(PBEBattlePokemon pkmn, bool useKnownInfo)

FILE: PokemonBattleEngineClient/Views/MainView.xaml.cs
  class MainView (line 19) | public sealed class MainView : UserControl, INotifyPropertyChanged
    method OnPropertyChanged (line 21) | private void OnPropertyChanged(string property)
    method MainView (line 52) | public MainView()
    method ResetConnectButton (line 67) | private void ResetConnectButton()
    method Connect (line 73) | public void Connect()
    method WatchReplay (line 117) | public void WatchReplay()
    method SinglePlayer (line 124) | public void SinglePlayer(string battleType)
    method Add (line 200) | private void Add(BattleClient client)
    method HandleClosing (line 214) | internal void HandleClosing()

FILE: PokemonBattleEngineClient/Views/MessageView.xaml.cs
  class MessageView (line 12) | public sealed class MessageView : UserControl
    class Message (line 14) | public sealed class Message
      method Message (line 21) | internal Message(string message)
    method MessageView (line 41) | public MessageView()
    method AddMessage (line 49) | public void AddMessage(string message)

FILE: PokemonBattleEngineClient/Views/PokemonView.xaml.cs
  class PokemonView (line 11) | public sealed class PokemonView : UserControl, INotifyPropertyChanged
    method OnPropertyChanged (line 13) | private void OnPropertyChanged(string property)
    method PokemonView (line 38) | public PokemonView()
    method Update (line 47) | public void Update(PBEBattlePokemon pkmn, bool backSprite, bool useKno...

FILE: PokemonBattleEngineClient/Views/TeamBuilderView.xaml.cs
  class TeamBuilderView (line 15) | public sealed class TeamBuilderView : UserControl, INotifyPropertyChanged
    method OnPropertyChanged (line 17) | private void OnPropertyChanged(string property)
    method UpdateEXPRequirements (line 116) | private void UpdateEXPRequirements()
    method UpdateComboBoxes (line 122) | private void UpdateComboBoxes(string? property)
    method OnPkmnPropertyChanged (line 162) | private void OnPkmnPropertyChanged(object? sender, PropertyChangedEven...
    method OnComboBoxSelectionChanged (line 170) | private void OnComboBoxSelectionChanged(object? sender, SelectionChang...
    method TeamBuilderView (line 203) | public TeamBuilderView()
    method AddTeam (line 256) | public void AddTeam()
    method RemoveTeam (line 263) | public void RemoveTeam()
    method SaveTeam (line 273) | public void SaveTeam()
    method AddPartyMember (line 279) | public void AddPartyMember()
    method RemovePartyMember (line 287) | public void RemovePartyMember()
    method OnSelectedMonChanged (line 294) | private void OnSelectedMonChanged(object? sender, SelectionChangedEven...
    method OnSelectedTeamSizeChanged (line 302) | private void OnSelectedTeamSizeChanged(object? sender, NotifyCollectio...
    method OnSelectedTeamChanged (line 307) | private void OnSelectedTeamChanged(object? sender, SelectionChangedEve...
    method OnVisualChanged (line 319) | private void OnVisualChanged(object? sender, SelectionChangedEventArgs e)
    method UpdateSprites (line 323) | public void UpdateSprites()

FILE: PokemonBattleEngineDiscord/BattleContext.cs
  class BattleContext (line 19) | internal sealed partial class BattleContext
    class Battler (line 21) | private sealed class Battler
      method Battler (line 28) | public Battler(PBETeam t, SocketUser? u)
      method GetName (line 39) | public string GetName()
      method Is (line 43) | public bool Is(SocketUser u)
    method BattleContext (line 63) | public BattleContext(PBEBattle battle, SocketUser? battler0, SocketUse...
    method Begin (line 89) | public async Task Begin(ITextChannel channel)
    method Battle_OnStateChanged (line 113) | private void Battle_OnStateChanged(PBEBattle battle)
    method Battle_OnNewEvent (line 117) | private void Battle_OnNewEvent(PBEBattle battle, IPBEPacket packet)
    method OnChannelDeleted (line 122) | public static void OnChannelDeleted(SocketChannel channel)
    method OnLeftGuild (line 135) | public static void OnLeftGuild(SocketGuild guild)
    method OnUserLeft (line 149) | public static Task OnUserLeft(SocketGuildUser user)
    method OnGuildMemberUpdated (line 160) | public static void OnGuildMemberUpdated(SocketGuildUser user)
    method GetBattleContext (line 170) | public static bool GetBattleContext(SocketUser user, [NotNullWhen(true...
    method Forfeit (line 178) | public async Task Forfeit(SocketUser user)
    method Forfeit (line 183) | private async Task Forfeit(Battler battler)
    method CloseNormalWithException (line 187) | private async Task CloseNormalWithException(Exception ex)
    method CloseNormalWithMessage (line 192) | private async Task CloseNormalWithMessage(string message, bool saveRep...
    method CloseNormalAndDelete (line 204) | private async Task CloseNormalAndDelete(bool saveReplay)
    method CloseNormal (line 209) | private async Task CloseNormal(bool saveReplay)
    method CloseSilent (line 214) | private void CloseSilent(bool saveReplay)
    method SetEmbedTitle (line 243) | private void SetEmbedTitle()
    method SendQueuedMessages (line 257) | private async Task SendQueuedMessages()
    method SendActiveBattlerEmbeds (line 270) | private async Task SendActiveBattlerEmbeds()
    method CreateAndSendEmbedAsync (line 278) | private async Task<IUserMessage> CreateAndSendEmbedAsync(string embedD...
    method AddStatChanges (line 315) | private static void AddStatChanges(PBEBattlePokemon pkmn, StringBuilde...
    method CreatePokemonEmbed (line 352) | private static void CreatePokemonEmbed(PBEBattlePokemon pkmn, bool add...
    method CreateKnownPokemonEmbed (line 466) | private string CreateKnownPokemonEmbed(PBEBattlePokemon pkmn)
    method GetBattler (line 541) | private Battler GetBattler(SocketUser battler)
    method GetBattler (line 553) | private Battler GetBattler(PBETrainer trainer)
    method GetTrainerName (line 566) | private string GetTrainerName(PBETrainer trainer)
    method GetTeamName (line 570) | private string GetTeamName(PBETeam team, bool _)
    method Battle_OnStateChanged (line 575) | private async Task Battle_OnStateChanged()
    method Battle_OnNewEvent (line 610) | private async Task Battle_OnNewEvent(IPBEPacket packet)

FILE: PokemonBattleEngineDiscord/BattleContext_Constants.cs
  class BattleContext (line 7) | internal sealed partial class BattleContext

FILE: PokemonBattleEngineDiscord/BotCommands.cs
  class BotCommands (line 17) | public sealed class BotCommands : ModuleBase<SocketCommandContext>
    class AbilityCommands (line 19) | [Group("ability")]
      method Info (line 22) | [Command("info")]
    method AcceptChallenge (line 44) | [Command("accept", true)]
    method ChallengeUser (line 50) | [Command("challenge")]
    method ChallengeAI (line 57) | [Command("challengeai", true)]
    method DontDelete (line 64) | [Command("dontdelete", true)]
    method Forfeit (line 71) | [Command("forfeit", true)]
    method Help (line 78) | [Command("help", true)]
    class ItemCommands (line 105) | [Group("item")]
      method Info (line 109) | [Command("info")]
    class MoveCommands (line 170) | [Group("move")]
      method Info (line 174) | [Command("info")]
    class SpeciesCommands (line 214) | [Group("pokemon")]
      method Info (line 218) | [Command("info")]
    class TypeCommands (line 354) | [Group("type")]
      method Info (line 366) | [Command("info")]

FILE: PokemonBattleEngineDiscord/ChannelHandler.cs
  class ChannelHandler (line 11) | internal sealed class ChannelHandler
    method OnChannelDeleted (line 21) | public static Task OnChannelDeleted(SocketChannel channel)
    method OnLeftGuild (line 50) | public static void OnLeftGuild(SocketGuild guild)
    method OnConnected (line 57) | public static void OnConnected()
    method OnDisconnected (line 62) | public static void OnDisconnected()
    method CreateCategories (line 68) | private static async Task CreateCategories(IGuild guild)
    method CreateCategory (line 104) | private static Task<ICategoryChannel> CreateCategory(IGuild guild, str...
    method CreateChannel (line 108) | public static async Task<ITextChannel> CreateChannel(IGuild guild, str...
    method GetChannelDeletionEmbed (line 114) | private static Embed GetChannelDeletionEmbed(int num)
    method CheckChannelsForDeletion (line 123) | private static void CheckChannelsForDeletion(object? state)
    method CheckChannelsForDeletion (line 130) | private static async Task CheckChannelsForDeletion()
    method DontDelete (line 154) | public static Task DontDelete(SocketCommandContext context)
    method MarkChannelForDeletion (line 174) | public static Task MarkChannelForDeletion(ITextChannel channel)
    method ChangeCategory (line 186) | public static Task ChangeCategory(ITextChannel channel)

FILE: PokemonBattleEngineDiscord/Matchmaking.cs
  class Matchmaking (line 14) | internal static class Matchmaking
    class Challenge (line 16) | public sealed class Challenge
      method Challenge (line 23) | public Challenge(SocketUser challenger, SocketUser challengee, IGuil...
    method OnLeftGuild (line 36) | public static void OnLeftGuild(SocketGuild guild)
    method OnUserLeft (line 43) | public static void OnUserLeft(SocketGuildUser user)
    method PrintParticipating (line 51) | private static async Task PrintParticipating(SocketUser tag, SocketUse...
    method RemoveOldChallenges (line 55) | private static void RemoveOldChallenges()
    method GetChallenge (line 60) | private static Challenge? GetChallenge(SocketUser challengee)
    method StartBattle (line 71) | private static async Task StartBattle(Challenge c)
    method StartBattle (line 80) | private static async Task StartBattle(IGuild guild, SocketUser? battle...
    method AcceptChallenge (line 95) | public static Task AcceptChallenge(SocketCommandContext ctx)
    method ChallengeAI (line 127) | public static Task ChallengeAI(SocketCommandContext ctx)
    method ChallengeUser (line 136) | public static Task ChallengeUser(SocketCommandContext ctx, SocketUser ...
    method Forfeit (line 186) | public static async Task Forfeit(SocketCommandContext ctx)

FILE: PokemonBattleEngineDiscord/Program.cs
  class Program (line 11) | internal sealed class Program
    method Main (line 17) | public static void Main(string[] args)
    method MainAsync (line 21) | private async Task MainAsync(string[] args)
    method OnReactionAdded (line 48) | private Task OnReactionAdded(Cacheable<IUserMessage, ulong> message, I...
    method OnChannelDeleted (line 53) | private async Task OnChannelDeleted(SocketChannel arg)
    method OnLeftGuild (line 59) | private Task OnLeftGuild(SocketGuild arg)
    method OnUserLeft (line 66) | private async Task OnUserLeft(SocketGuildUser arg)
    method OnConnected (line 71) | private Task OnConnected()
    method OnDisconnected (line 76) | private Task OnDisconnected(Exception arg)
    method OnGuildMemberUpdated (line 82) | private Task OnGuildMemberUpdated(SocketGuildUser arg1, SocketGuildUse...
    method CommandMessageReceived (line 88) | private async Task CommandMessageReceived(SocketMessage arg)
    method LogMessage (line 104) | private Task LogMessage(LogMessage arg)

FILE: PokemonBattleEngineDiscord/ReactionHandler.cs
  class ReactionHandler (line 9) | internal static class ReactionHandler
    class Reaction (line 11) | private class Reaction
      method Reaction (line 17) | public Reaction(IUserMessage msg, IEmote emote, Func<Task> clickFunc)
    method OnReactionAdded (line 28) | public static void OnReactionAdded(SocketReaction inEvent)
    method AddListener (line 51) | public static void AddListener(IUser user, IUserMessage msg, IEmote em...
    method RemoveListeners (line 63) | public static void RemoveListeners(IUser? a, IUser? b)

FILE: PokemonBattleEngineDiscord/ReplaySaver.cs
  class ReplaySaver (line 8) | internal static class ReplaySaver
    method GetTodayFolderPath (line 18) | private static string GetTodayFolderPath()
    method SaveReplay (line 30) | public static void SaveReplay(PBEBattle battle, ulong battleId)
    method RemoveOldReplays (line 40) | public static void RemoveOldReplays()

FILE: PokemonBattleEngineDiscord/Utils.cs
  class Utils (line 13) | internal static class Utils
    method Blend (line 80) | public static Color Blend(this Color color, Color backColor, float dep...
    method GetColor (line 87) | public static Color GetColor(PBEType type1, PBEType type2)
    method GetColor (line 96) | public static Color GetColor(PBEBattlePokemon pkmn)
    method RandomColor (line 102) | public static Color RandomColor()
    method RandomElement (line 108) | public static T RandomElement<T>(this IReadOnlyList<T> source)
    method InitFemaleSpriteLookup (line 123) | public static async Task InitFemaleSpriteLookup()
    method HasFemaleSprite (line 140) | private static bool HasFemaleSprite(PBESpecies species)
    method GetPokemonSprite (line 144) | public static string GetPokemonSprite(PBEBattlePokemon pokemon)
    method GetPokemonSprite (line 148) | public static string GetPokemonSprite(PBESpecies species, PBEForm form...

FILE: PokemonBattleEngineExtras/AIBattleDemo.cs
  class AIBattleDemo (line 13) | internal sealed class AIBattleDemo
    method AIBattleDemo (line 22) | public AIBattleDemo()
    method CatchException (line 73) | private void CatchException(Exception e)
    method GetAI (line 86) | private PBEDDAI GetAI(PBETrainer t)
    method Battle_OnNewEvent (line 91) | private void Battle_OnNewEvent(PBEBattle battle, IPBEPacket packet)
    method Battle_OnStateChanged (line 122) | private void Battle_OnStateChanged(PBEBattle battle)

FILE: PokemonBattleEngineExtras/LocalizationDumper.cs
  class LocalizationDumper (line 9) | internal static class LocalizationDumper
    method Run (line 12) | public static void Run(SqliteConnection con)

FILE: PokemonBattleEngineExtras/NARCTextDumper.cs
  class NARCTextDumper (line 8) | internal static class NARCTextDumper
    method Dump (line 13) | public static void Dump()

FILE: PokemonBattleEngineExtras/PokemonDataDumper.cs
  class PokemonDataDumper (line 14) | internal static partial class PokemonDataDumper
    method Run (line 48) | public static void Run(SqliteConnection con)
    method AddSpecies (line 110) | private static Pokemon AddSpecies((PBESpecies, PBEForm) key)
    method AddLevelUpMove (line 119) | private static void AddLevelUpMove((PBESpecies, PBEForm) key, PBEMove ...
    method AddOtherMove (line 133) | private static void AddOtherMove((PBESpecies, PBEForm) key, PBEMove mo...
    method AddEvolution (line 146) | private static void AddEvolution((PBESpecies, PBEForm) baybee, (PBESpe...
    method GetGen3Key (line 151) | private static (PBESpecies, PBEForm) GetGen3Key(EndianBinaryReader rea...
    method B2W2_PokeData (line 173) | private static void B2W2_PokeData()
    method Gen3_LevelUp (line 240) | private static void Gen3_LevelUp()
    method Gen4_LevelUp (line 305) | private static void Gen4_LevelUp()
    method Gen5_LevelUp (line 350) | private static void Gen5_LevelUp()
    method Gen3_TMHM (line 391) | private static void Gen3_TMHM()
    method Gen4_TMHM (line 449) | private static void Gen4_TMHM()
    method Gen5_TMHM (line 492) | private static void Gen5_TMHM()
    method FRLGE_Tutor (line 545) | private static void FRLGE_Tutor()
    method XD_Tutor (line 577) | private static void XD_Tutor()
    method Pt_Tutor (line 598) | private static void Pt_Tutor()
    method HGSS_Tutor (line 621) | private static void HGSS_Tutor()
    method Gen5_Tutor (line 643) | private static void Gen5_Tutor()
    method Gen34_Egg (line 706) | private static void Gen34_Egg()
    method Gen5_Egg (line 761) | private static void Gen5_Egg()
    method Fix_FormPokedata (line 782) | private static void Fix_FormPokedata()
    method Fix_BasculinBlueAbility (line 857) | private static void Fix_BasculinBlueAbility()
    method Fix_ArceusTypes (line 861) | private static void Fix_ArceusTypes()
    method Fix_FormEggMoves (line 906) | private static void Fix_FormEggMoves()
    method Fix_ShedinjaEvoMoves (line 933) | private static void Fix_ShedinjaEvoMoves()
    method Fix_FRLGStarterMoves (line 963) | private static void Fix_FRLGStarterMoves()
    method Fix_XDMew (line 970) | private static void Fix_XDMew()
    method Fix_VoltTackle (line 999) | private static void Fix_VoltTackle()
    method Fix_Gen4FreeMoves (line 1003) | private static void Fix_Gen4FreeMoves()
    method Fix_RotomFormMoves (line 1024) | private static void Fix_RotomFormMoves()
    method Fix_RelicSong_SecretSword (line 1033) | private static void Fix_RelicSong_SecretSword()
    method DreamWorld (line 1040) | private static void DreamWorld()
    method WriteToDatabase (line 1064) | private static void WriteToDatabase(SqliteCommand cmd)

FILE: PokemonBattleEngineExtras/PokemonDataDumper_Data.cs
  class PokemonDataDumper (line 7) | internal static partial class PokemonDataDumper
    class Pokemon (line 9) | private sealed class Pokemon : IPBEPokemonTypes

FILE: PokemonBattleEngineExtras/PokemonDataDumper_DreamWorld.cs
  class PokemonDataDumper (line 5) | internal static partial class PokemonDataDumper

FILE: PokemonBattleEngineExtras/Program.cs
  class Program (line 7) | internal sealed class Program
    type Extra (line 9) | private enum Extra
    method Main (line 17) | public static void Main()

FILE: PokemonBattleEngineExtras/Utils.cs
  class Utils (line 8) | internal static class Utils
    method ReadTextFile (line 31) | public static string[][] ReadTextFile(NARC narc, int fileNum)
    method ReadByte (line 107) | public static byte ReadByte(this EndianBinaryReader r, int ofs)
    method ReadUInt16 (line 112) | public static ushort ReadUInt16(this EndianBinaryReader r, int ofs)

FILE: PokemonBattleEngineServer/BattleServer.cs
  class BattleServer (line 15) | internal sealed class BattleServer
    type ServerState (line 20) | private enum ServerState
    method Main (line 45) | public static void Main(string[] args)
    method BattleServer (line 60) | private BattleServer(IPAddress ip, ushort port, bool requireLegalParties)
    method OnClientConnected (line 81) | private void OnClientConnected(object? sender, PBEServerClient client)
    method OnClientDisconnected (line 106) | private void OnClientDisconnected(object? sender, PBEServerClient client)
    method OnClientRefused (line 137) | private void OnClientRefused(object? sender, IPEndPoint clientIP, bool...
    method OnError (line 141) | private void OnError(object? sender, Exception ex)
    method ConnectBattler (line 146) | private void ConnectBattler(PBEServerClient client, string name)
    method ConnectSpectator (line 174) | private void ConnectSpectator(PBEServerClient client, string name)
    method CancelMatch (line 202) | private void CancelMatch()
    method Reset (line 220) | private void Reset()
    method ActionsSubmitted (line 247) | public void ActionsSubmitted(Player player, IReadOnlyList<PBETurnActio...
    method FleeSubmitted (line 267) | public void FleeSubmitted(Player player)
    method SwitchesSubmitted (line 287) | public void SwitchesSubmitted(Player player, IReadOnlyList<PBESwitchIn...
    method BattleStateHandler (line 308) | private void BattleStateHandler(PBEBattle battle)
    method BattleEventHandler (line 345) | private void BattleEventHandler(PBEBattle battle, IPBEPacket packet)
    method DisconnectClient (line 528) | public void DisconnectClient(Player player)
    method SendToAll (line 533) | private void SendToAll(IPBEPacket packet)

FILE: PokemonBattleEngineServer/Player.cs
  class Player (line 10) | internal sealed class Player : IDisposable
    method Player (line 21) | public Player(BattleServer server, PBEServerClient client, byte battle...
    method WaitForResponse (line 30) | public bool WaitForResponse(Type packetType)
    method SetWaitingForActions (line 40) | public void SetWaitingForActions(Type packetType)
    method Send (line 44) | public void Send(IPBEPacket packet)
    method AskForParty (line 54) | public IPBEPokemonCollection? AskForParty(bool requireLegal)
    method OnPacketReceived (line 63) | private void OnPacketReceived(object? sender, IPBEPacket packet)
    method Dispose (line 112) | public void Dispose()

FILE: PokemonBattleEngineTests/Abilities/AntiStatusAbilityTests.cs
  class AntiStatusAbilityTests (line 8) | [Collection("Utils")]
    method AntiStatusAbilityTests (line 11) | public AntiStatusAbilityTests(TestUtils _, ITestOutputHelper output)
    method Immunity_Works (line 16) | [Fact]

FILE: PokemonBattleEngineTests/Abilities/IllusionTests.cs
  class IllusionTests (line 10) | [Collection("Utils")]
    method IllusionTests (line 13) | public IllusionTests(TestUtils _, ITestOutputHelper output)
    method Illusion_Does_Not_Copy_Same_Species (line 18) | [Fact]
    method Illusion_Does_Not_Copy_Active_Wild_Teammate (line 52) | [Fact]
    method Illusion_Does_Copy_Active_Trainer_Teammate (line 88) | [Fact]
    method Illusion_Does_Not_Copy_Just_Swapped_Mon (line 123) | [Fact]
    method Illusion_Copies_Just_Swapped_Mon (line 168) | [Fact]
    method Illusion_Copies_Shaymin_Reversion (line 219) | [Fact]
    method Illusion_Works_Wild (line 286) | [Fact]

FILE: PokemonBattleEngineTests/Abilities/IntimidateTests.cs
  class IntimidateTests (line 8) | [Collection("Utils")]
    method IntimidateTests (line 11) | public IntimidateTests(TestUtils _, ITestOutputHelper output)
    method Intimidate_Works (line 16) | [Fact]
    method Intimidate_Does_Not_Announce_If_No_Foes (line 59) | [Fact]
    method Intimidate_Does_Not_Hit_Through_Substitute (line 97) | [Fact]

FILE: PokemonBattleEngineTests/Abilities/NaturalCureTests.cs
  class NaturalCureTests (line 8) | [Collection("Utils")]
    method NaturalCureTests (line 11) | public NaturalCureTests(TestUtils _, ITestOutputHelper output)
    method NaturalCure_Works_On_Battle_Ending (line 16) | [Fact]

FILE: PokemonBattleEngineTests/Abilities/PoisonHealTests.cs
  class PoisonHealTests (line 8) | [Collection("Utils")]
    method PoisonHealTests (line 11) | public PoisonHealTests(TestUtils _, ITestOutputHelper output)
    method PoisonHeal_BadlyPoisoned_Counter_Works (line 16) | [Fact]

FILE: PokemonBattleEngineTests/ActionsTests.cs
  class ActionsTests (line 9) | [Collection("Utils")]
    method ActionsTests (line 12) | public ActionsTests(TestUtils _, ITestOutputHelper output)
    method Basic_Actions (line 21) | [Fact]
    method Cannot_Send_Egg (line 76) | [Fact]
    method Cannot_Switch_In_Egg (line 122) | [Fact]

FILE: PokemonBattleEngineTests/AutoCenterTests.cs
  class AutoCenterTests (line 8) | [Collection("Utils")]
    method AutoCenterTests (line 11) | public AutoCenterTests(TestUtils _, ITestOutputHelper output)
    method AutoCenter_Works (line 16) | [Theory]
    method AutoCenter_Works_Despite_Available (line 66) | [Theory]
    method AutoCenter_ActivatesFromHazard (line 147) | [Fact]
    method AutoCenter_Works_MultiBattle (line 243) | [Theory]

FILE: PokemonBattleEngineTests/BattleResultTests.cs
  class BattleResultTests (line 8) | [Collection("Utils")]
    method BattleResultTests (line 11) | public BattleResultTests(TestUtils _, ITestOutputHelper output)
    method Explosion_User_Loses_Single (line 18) | [Fact]
    method Explosion_User_Loses_Multiple (line 57) | [Fact]
    method FinalGambit_User_Loses (line 110) | [Fact]
    method HPDrain_And_LiquidOoze (line 149) | [Fact]
    method IronBarbs_User_Loses (line 192) | [Fact]
    method LeechSeed_And_LiquidOoze (line 236) | [Fact]
    method LifeOrb_User_Wins (line 279) | [Fact]
    method Recoil_User_Wins (line 323) | [Fact]

FILE: PokemonBattleEngineTests/BehaviorTests.cs
  class BehaviorTests (line 9) | [Collection("Utils")]
    method BehaviorTests (line 12) | public BehaviorTests(TestUtils _, ITestOutputHelper output)
    method Wild_Pkmn_Positions_Set_Before_Begin (line 17) | [Fact]
    method Fainted_Pkmn_Not_Sent_Out_Single (line 45) | [Fact]
    method Fainted_Pkmn_Not_Sent_Out_Double (line 77) | [Fact]
    method Fainted_Pkmn_Not_Sent_Out_Triple (line 112) | [Fact]
    method Lose_If_Remaining_Ignored (line 159) | [Fact]

FILE: PokemonBattleEngineTests/Forms/CastformCherrimTests.cs
  class CastformCherrimTests (line 8) | [Collection("Utils")]
    method CastformCherrimTests (line 11) | public CastformCherrimTests(TestUtils _, ITestOutputHelper output)
    method CastformCherrim_Interacts_With_AirLock (line 16) | [Theory]
    method CastformCherrim_Loses_Form (line 78) | [Theory]

FILE: PokemonBattleEngineTests/Forms/ShayminTests.cs
  class ShayminTests (line 8) | [Collection("Utils")]
    method ShayminTests (line 11) | public ShayminTests(TestUtils _, ITestOutputHelper output)
    method Shaymin_Reverts_To_Normal_Form_Forever (line 16) | [Fact]

FILE: PokemonBattleEngineTests/Items/GemTests.cs
  class GemTests (line 8) | [Collection("Utils")]
    method GemTests (line 11) | public GemTests(TestUtils _, ITestOutputHelper output)
    method Gem_Works (line 19) | [Theory]
    method Gem_Activates__FixedDamage__Bug (line 79) | [Theory]
    method Gem_Does_Not_Activate__Effectiveness (line 132) | [Fact]
    method Gem_Does_Not_Activate__Fail (line 191) | [Fact]
    method Gem_Does_Not_Activate__Miss (line 233) | [Fact]
    method Gem_Does_Not_Activate__Protection (line 291) | [Fact]

FILE: PokemonBattleEngineTests/Moves/BellyDrumTests.cs
  class BellyDrumTests (line 8) | [Collection("Utils")]
    method BellyDrumTests (line 11) | public BellyDrumTests(TestUtils _, ITestOutputHelper output)
    method BellyDrum_Contrary__Bug (line 16) | [Theory]

FILE: PokemonBattleEngineTests/Moves/CamouflageTests.cs
  class CamouflageTests (line 8) | [Collection("Utils")]
    method CamouflageTests (line 11) | public CamouflageTests(TestUtils _, ITestOutputHelper output)
    method Camouflage_Works (line 16) | [Theory]
    method Camouflage_Fails (line 69) | [Fact]

FILE: PokemonBattleEngineTests/Moves/HelpingHandTests.cs
  class HelpingHandTests (line 8) | [Collection("Utils")]
    method HelpingHandTests (line 11) | public HelpingHandTests(TestUtils _, ITestOutputHelper output)
    method HelpingHand_HitsSemiInvulnerable (line 17) | [Theory]
    method HelpingHand_Fails_If_Self (line 78) | [Fact]

FILE: PokemonBattleEngineTests/Moves/MultiStrikeTests.cs
  class MultiStrikeTests (line 8) | [Collection("Utils")]
    method MultiStrikeTests (line 11) | public MultiStrikeTests(TestUtils _, ITestOutputHelper output)
    method SkillLink_Works__2To5 (line 16) | [Theory]

FILE: PokemonBattleEngineTests/Moves/ProtectionTests.cs
  class ProtectionTests (line 8) | [Collection("Utils")]
    method ProtectionTests (line 11) | public ProtectionTests(TestUtils _, ITestOutputHelper output)
    method Protection_Counter_Resets (line 17) | [Theory]
    method Feint_And_QuickGuard (line 68) | [Theory]
    method UserProtection_Works (line 113) | [Fact]
    method TeamProtection_Works (line 151) | [Theory]

FILE: PokemonBattleEngineTests/Moves/RoostTests.cs
  class RoostTests (line 8) | [Collection("Utils")]
    method RoostTests (line 11) | public RoostTests(TestUtils _, ITestOutputHelper output)
    method Roost_Works (line 16) | [Theory]

FILE: PokemonBattleEngineTests/Moves/SecretPowerTests.cs
  class SecretPowerTests (line 8) | [Collection("Utils")]
    method SecretPowerTests (line 11) | public SecretPowerTests(TestUtils _, ITestOutputHelper output)
    method SecretPower_SereneGrace__Bug (line 16) | [Theory]

FILE: PokemonBattleEngineTests/Moves/TeleportTests.cs
  class TeleportTests (line 8) | [Collection("Utils")]
    method TeleportTests (line 11) | public TeleportTests(TestUtils _, ITestOutputHelper output)
    method Teleport_Works (line 16) | [Fact]

FILE: PokemonBattleEngineTests/Moves/WhirlwindTests.cs
  class WhirlwindTests (line 8) | [Collection("Utils")]
    method WhirlwindTests (line 11) | public WhirlwindTests(TestUtils _, ITestOutputHelper output)
    method Whirlwind_FailsLevel_WildSingleBattle (line 16) | [Fact]
    method Whirlwind_Fails_WildDoubleBattle (line 58) | [Fact]
    method Whirlwind_Succeeds_WildSingleBattle (line 108) | [Fact]
    method Whirlwind_Succeeds_WildDoubleBattle (line 150) | [Fact]

FILE: PokemonBattleEngineTests/Statuses/ConfusionTests.cs
  class ConfusionTests (line 8) | [Collection("Utils")]
    method ConfusionTests (line 11) | public ConfusionTests(TestUtils _, ITestOutputHelper output)
    method Confusion_Heal__Bug (line 16) | [Theory]
    method Confusion_Does_Not_Ignore_Sturdy (line 71) | [Fact]

FILE: PokemonBattleEngineTests/Statuses/PowerTrickTests.cs
  class PowerTrickTests (line 6) | [Collection("Utils")]
    method PowerTrickTests (line 9) | public PowerTrickTests(TestUtils _, ITestOutputHelper output)

FILE: PokemonBattleEngineTests/Statuses/SubstituteTests.cs
  class SubstituteTests (line 8) | [Collection("Utils")]
    method SubstituteTests (line 11) | public SubstituteTests(TestUtils _, ITestOutputHelper output)
    method ColorChange_Does_Not_Activate (line 16) | [Fact]

FILE: PokemonBattleEngineTests/TestUtils.cs
  class TestUtilsCollection (line 16) | [CollectionDefinition("Utils")]
  class TestUtils (line 22) | public class TestUtils
    method TestUtils (line 24) | public TestUtils()
    method SetOutputHelper (line 30) | public static void SetOutputHelper(ITestOutputHelper output)
    class TestOutputConverter (line 35) | private class TestOutputConverter : TextWriter
      method TestOutputConverter (line 38) | public TestOutputConverter(ITestOutputHelper output)
      method WriteLine (line 43) | public override void WriteLine(string? message)
      method WriteLine (line 47) | public override void WriteLine(string format, params object?[] args)
  class TestMoveset (line 55) | internal sealed class TestMoveset : IPBEMoveset, IPBEMoveset<TestMoveset...
    class TestMovesetSlot (line 57) | public sealed class TestMovesetSlot : IPBEMovesetSlot
      method TestMovesetSlot (line 62) | public TestMovesetSlot(PBEMove move, byte ppUps)
    method TestMoveset (line 84) | public TestMoveset(PBESettings settings, params PBEMove[] moves)
    method GetEnumerator (line 100) | public IEnumerator<TestMovesetSlot> GetEnumerator()
    method GetEnumerator (line 104) | IEnumerator<IPBEMovesetSlot> IEnumerable<IPBEMovesetSlot>.GetEnumerator()
    method GetEnumerator (line 108) | IEnumerator IEnumerable.GetEnumerator()
  class TestPartyMoveset (line 113) | internal sealed class TestPartyMoveset : IPBEMoveset, IPBEPartyMoveset, ...
    class TestPartyMovesetSlot (line 115) | public sealed class TestPartyMovesetSlot : IPBEPartyMovesetSlot
      method TestPartyMovesetSlot (line 121) | public TestPartyMovesetSlot(PBEMove move, byte ppUps, PBESettings se...
    method TestPartyMoveset (line 146) | public TestPartyMoveset(PBESettings settings, params PBEMove[] moves)
    method GetEnumerator (line 162) | public IEnumerator<TestPartyMovesetSlot> GetEnumerator()
    method GetEnumerator (line 166) | IEnumerator<IPBEMovesetSlot> IEnumerable<IPBEMovesetSlot>.GetEnumerator()
    method GetEnumerator (line 170) | IEnumerator<IPBEPartyMovesetSlot> IEnumerable<IPBEPartyMovesetSlot>.Ge...
    method GetEnumerator (line 174) | IEnumerator IEnumerable.GetEnumerator()
  class TestPokemon (line 179) | internal sealed class TestPokemon : IPBEPokemon
    method TestPokemon (line 200) | public TestPokemon(PBESettings settings, PBESpecies species, PBEForm f...
  class TestPartyPokemon (line 214) | internal sealed class TestPartyPokemon : IPBEPartyPokemon
    method TestPartyPokemon (line 239) | public TestPartyPokemon(PBESettings settings, PBESpecies species, PBEF...
  class TestPokemonCollection (line 254) | internal sealed class TestPokemonCollection : IPBEPokemonCollection, IPB...
    method TestPokemonCollection (line 265) | public TestPokemonCollection(int count)
    method GetEnumerator (line 270) | public IEnumerator<TestPokemon> GetEnumerator()
    method GetEnumerator (line 274) | IEnumerator<IPBEPokemon> IEnumerable<IPBEPokemon>.GetEnumerator()
    method GetEnumerator (line 278) | IEnumerator IEnumerable.GetEnumerator()
  class TestPartyPokemonCollection (line 283) | internal sealed class TestPartyPokemonCollection : IPBEPokemonCollection...
    method TestPartyPokemonCollection (line 296) | public TestPartyPokemonCollection(int count)
    method GetEnumerator (line 301) | public IEnumerator<TestPartyPokemon> GetEnumerator()
    method GetEnumerator (line 305) | IEnumerator<IPBEPartyPokemon> IEnumerable<IPBEPartyPokemon>.GetEnumera...
    method GetEnumerator (line 309) | IEnumerator<IPBEPokemon> IEnumerable<IPBEPokemon>.GetEnumerator()
    method GetEnumerator (line 313) | IEnumerator IEnumerable.GetEnumerator()
  class TestExtensions (line 319) | internal static class TestExtensions
    method VerifyAbilityHappened (line 321) | public static bool VerifyAbilityHappened(this PBEBattle battle, PBEBat...
    method VerifyItemHappened (line 336) | public static bool VerifyItemHappened(this PBEBattle battle, PBEBattle...
    method VerifyMoveResultHappened (line 351) | public static bool VerifyMoveResultHappened(this PBEBattle battle, PBE...
    method VerifySpecialMessageHappened (line 365) | public static bool VerifySpecialMessageHappened(this PBEBattle battle,...
    method VerifyStatus1Happened (line 387) | public static bool VerifyStatus1Happened(this PBEBattle battle, PBEBat...
    method VerifyStatus2Happened (line 402) | public static bool VerifyStatus2Happened(this PBEBattle battle, PBEBat...
    method VerifyTeamStatusDamageHappened (line 417) | public static bool VerifyTeamStatusDamageHappened(this PBEBattle battl...

FILE: PokemonBattleEngineTests/ThrowTests.cs
  class ThrowTests (line 9) | [Collection("Utils")]
    method ThrowTests (line 12) | public ThrowTests(TestUtils _, ITestOutputHelper output)
    method Wild_Battle_Throws_For_Illegal_Party_Size (line 17) | [Theory]
Condensed preview — 242 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,007K chars).
[
  {
    "path": ".gitattributes",
    "chars": 2520,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".gitignore",
    "chars": 4343,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\nPokemo"
  },
  {
    "path": "LICENSE.md",
    "chars": 1064,
    "preview": "MIT License\n\nCopyright (c) 2022 Kermalis\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "PokemonBattleEngine/Battle/Battle.cs",
    "chars": 23508,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Packets;\nusing Kermalis.PokemonBattleEngine"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleActions.cs",
    "chars": 16544,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\n"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleDamage.cs",
    "chars": 27621,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\nusing System.Linq;\n\nnamespace Kermalis.PokemonBattleEngine.Battl"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleEffects.cs",
    "chars": 142391,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEng"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleEffects_HitLogic.cs",
    "chars": 11746,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Kermalis.PokemonBat"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleEnums.cs",
    "chars": 15513,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\n\nnamespace Kermalis.PokemonBattleEngine.Battle;\n\n/// <summary>Re"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleEvents.cs",
    "chars": 62579,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEng"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleInventory.cs",
    "chars": 2506,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Packets;\nusing System;\nusing System.Collect"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleMoveset.cs",
    "chars": 7793,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing System;\nusing System.Coll"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattlePokemon.cs",
    "chars": 49920,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEng"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleReplay.cs",
    "chars": 3919,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Packets;\nusi"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleTargets.cs",
    "chars": 42304,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEng"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleTeam.cs",
    "chars": 7695,
    "preview": "using Kermalis.PokemonBattleEngine.Packets;\nusing Kermalis.PokemonBattleEngine.Utils;\nusing System;\nusing System.Collec"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleTrainer.cs",
    "chars": 5258,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Packets;\nusing System;\nusing System.Collect"
  },
  {
    "path": "PokemonBattleEngine/Battle/BattleUtils.cs",
    "chars": 18185,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattleEngine.Battle;"
  },
  {
    "path": "PokemonBattleEngine/Battle/TrainerInfo.cs",
    "chars": 2270,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Legality;\nusing Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Battle/TypeEffectiveness.cs",
    "chars": 15535,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Kermalis.PokemonBat"
  },
  {
    "path": "PokemonBattleEngine/Data/DataEnums.cs",
    "chars": 54922,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing System;\n\nnamespace Kermalis.PokemonBattleEngine.Data;\n\n/// <summary>Re"
  },
  {
    "path": "PokemonBattleEngine/Data/DataProvider.cs",
    "chars": 5156,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data.Legality;\nusing Kermalis.PokemonBatt"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/ItemData.cs",
    "chars": 701,
    "preview": "namespace Kermalis.PokemonBattleEngine.Data;\n\npublic interface IPBEItemData\n{\n\t/// <summary>The power <see cref=\"PBEMov"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/LocalizedString.cs",
    "chars": 2843,
    "preview": "using System;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Globalization;\n\nnamespace Kermalis.PokemonBattleEngin"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/MoveData.cs",
    "chars": 1823,
    "preview": "using Kermalis.PokemonBattleEngine.Data.Utils;\n\nnamespace Kermalis.PokemonBattleEngine.Data;\n\npublic interface IPBEMove"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/MovesetInterfaces.cs",
    "chars": 2328,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.Generic;\nusing System.Text.Json;\n\nnamespace Kermalis.PokemonBat"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/PokemonData.cs",
    "chars": 808,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Kermalis.PokemonBattleEngine.Data;\n\npubli"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/PokemonInterfaces.cs",
    "chars": 5657,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data.Utils"
  },
  {
    "path": "PokemonBattleEngine/Data/Interfaces/StatInterfaces.cs",
    "chars": 2928,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing System;\nusing System.Text.Json;\n\nna"
  },
  {
    "path": "PokemonBattleEngine/Data/Legality/LegalEffortValues.cs",
    "chars": 6437,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Utils;\nusing System;\nusing System.Collections;\nusing "
  },
  {
    "path": "PokemonBattleEngine/Data/Legality/LegalIndividualValues.cs",
    "chars": 6411,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEngine.Utils;"
  },
  {
    "path": "PokemonBattleEngine/Data/Legality/LegalMoveset.cs",
    "chars": 11561,
    "preview": "using Kermalis.PokemonBattleEngine.Data.Utils;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic"
  },
  {
    "path": "PokemonBattleEngine/Data/Legality/LegalPokemon.cs",
    "chars": 11818,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEngine.Utils;"
  },
  {
    "path": "PokemonBattleEngine/Data/Legality/LegalPokemonCollection.cs",
    "chars": 8450,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEngine.Utils;"
  },
  {
    "path": "PokemonBattleEngine/Data/PBEAlphabeticalList.cs",
    "chars": 4358,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Data/PBEList.cs",
    "chars": 3808,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Collections.Specialized;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Data/ReadOnlyLocalizedString.cs",
    "chars": 785,
    "preview": "namespace Kermalis.PokemonBattleEngine.Data;\n\npublic sealed class PBEReadOnlyLocalizedString : IPBEReadOnlyLocalizedStr"
  },
  {
    "path": "PokemonBattleEngine/Data/ReadOnlyMoveset.cs",
    "chars": 5310,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.PokemonBattleEngine.Utils;"
  },
  {
    "path": "PokemonBattleEngine/Data/ReadOnlyPokemon.cs",
    "chars": 1352,
    "preview": "using Kermalis.EndianBinaryIO;\n\nnamespace Kermalis.PokemonBattleEngine.Data;\n\npublic sealed class PBEReadOnlyPokemon : "
  },
  {
    "path": "PokemonBattleEngine/Data/ReadOnlyPokemonCollection.cs",
    "chars": 1181,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace Ker"
  },
  {
    "path": "PokemonBattleEngine/Data/Settings.cs",
    "chars": 50795,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System;\nusing System.ComponentModel;\nus"
  },
  {
    "path": "PokemonBattleEngine/Data/StatCollection.cs",
    "chars": 1851,
    "preview": "using Kermalis.EndianBinaryIO;\n\nnamespace Kermalis.PokemonBattleEngine.Data;\n\npublic sealed class PBEReadOnlyStatCollec"
  },
  {
    "path": "PokemonBattleEngine/Data/Utils/DataUtils_Effects.cs",
    "chars": 512,
    "preview": "namespace Kermalis.PokemonBattleEngine.Data.Utils;\n\npublic static partial class PBEDataUtils\n{\n\t#region Static Collecti"
  },
  {
    "path": "PokemonBattleEngine/Data/Utils/DataUtils_Forms.cs",
    "chars": 12910,
    "preview": "using Kermalis.PokemonBattleEngine.Utils;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Kermalis.PokemonBa"
  },
  {
    "path": "PokemonBattleEngine/Data/Utils/DataUtils_Items.cs",
    "chars": 4840,
    "preview": "using Kermalis.PokemonBattleEngine.Utils;\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.Obje"
  },
  {
    "path": "PokemonBattleEngine/Data/Utils/DataUtils_Moves.cs",
    "chars": 5150,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Kermalis.PokemonBattleEngine.Data.Utils;\n"
  },
  {
    "path": "PokemonBattleEngine/Data/Utils/DataUtils_Stats.cs",
    "chars": 11809,
    "preview": "using Kermalis.PokemonBattleEngine.Utils;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Kermalis.PokemonBa"
  },
  {
    "path": "PokemonBattleEngine/Data/Utils/DataUtils_Validate.cs",
    "chars": 2514,
    "preview": "using System;\n\nnamespace Kermalis.PokemonBattleEngine.Data.Utils;\n\npublic static partial class PBEDataUtils\n{\n\tpublic s"
  },
  {
    "path": "PokemonBattleEngine/Network/Client.cs",
    "chars": 4748,
    "preview": "/* EasyTcp\n * \n * Copyright (c) 2019 henkje\n * Permission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "PokemonBattleEngine/Network/Encryption.cs",
    "chars": 2320,
    "preview": "/* EasyTcp\n * \n * Copyright (c) 2019 henkje\n * Permission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "PokemonBattleEngine/Network/NetworkUtils.cs",
    "chars": 1079,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System;\nusing System.Collections.Generic;\nusing System.Net.Sockets;\n\nnamespace Ker"
  },
  {
    "path": "PokemonBattleEngine/Network/Server.cs",
    "chars": 6660,
    "preview": "/* EasyTcp\n * \n * Copyright (c) 2019 henkje\n * Permission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "PokemonBattleEngine/Network/ServerClient.cs",
    "chars": 918,
    "preview": "using Kermalis.PokemonBattleEngine.Packets;\nusing System;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Sockets"
  },
  {
    "path": "PokemonBattleEngine/Packets/ActionsRequestPacket.cs",
    "chars": 1336,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/ActionsResponsePacket.cs",
    "chars": 1265,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System;\nusing System.Collections.Generi"
  },
  {
    "path": "PokemonBattleEngine/Packets/AutoCenterPacket.cs",
    "chars": 5883,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/BattlePacket.cs",
    "chars": 9411,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/BattleResultPacket.cs",
    "chars": 816,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/FleeResponsePacket.cs",
    "chars": 579,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Packets/HazePacket.cs",
    "chars": 557,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Packets/MatchCancelledPacket.cs",
    "chars": 585,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Packets/PartyRequestPacket.cs",
    "chars": 848,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Packets/PartyResponsePacket.cs",
    "chars": 1584,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Legalit"
  },
  {
    "path": "PokemonBattleEngine/Packets/PlayerJoinedPacket.cs",
    "chars": 895,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis"
  },
  {
    "path": "PokemonBattleEngine/Packets/ResponsePacket.cs",
    "chars": 567,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Packets/SwitchInRequestPacket.cs",
    "chars": 919,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/SwitchInResponsePacket.cs",
    "chars": 1268,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System;\nusing System.Collections.Generi"
  },
  {
    "path": "PokemonBattleEngine/Packets/TurnBeganPacket.cs",
    "chars": 723,
    "preview": "using Kermalis.EndianBinaryIO;\nusing System.Collections.ObjectModel;\nusing System.IO;\n\nnamespace Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngine/Packets/_AbilityPacket.cs",
    "chars": 1669,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_AbilityReplacedPacket.cs",
    "chars": 1484,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_BattleStatusPacket.cs",
    "chars": 1033,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_CapturePacket.cs",
    "chars": 1447,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_FleeFailedPacket.cs",
    "chars": 968,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_IllusionPacket.cs",
    "chars": 2156,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_ItemPacket.cs",
    "chars": 1594,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_ItemTurnPacket.cs",
    "chars": 1300,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_MoveCritPacket.cs",
    "chars": 953,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_MoveLockPacket.cs",
    "chars": 1624,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_MovePPChangedPacket.cs",
    "chars": 1267,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_MoveResultPacket.cs",
    "chars": 1416,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_MoveUsedPacket.cs",
    "chars": 1218,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnEXPChangedPacket.cs",
    "chars": 1139,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnEXPEarnedPacket.cs",
    "chars": 1040,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnFaintedPacket.cs",
    "chars": 2075,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnFormChangedPacket.cs",
    "chars": 4746,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnHPChangedPacket.cs",
    "chars": 2762,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnLevelChangedPacket.cs",
    "chars": 1045,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnStatChangedPacket.cs",
    "chars": 1357,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnSwitchInPacket.cs",
    "chars": 5933,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PkmnSwitchOutPacket.cs",
    "chars": 3277,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_PsychUpPacket.cs",
    "chars": 2111,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_ReflectTypePacket.cs",
    "chars": 2546,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_SpecialMessagePacket.cs",
    "chars": 3049,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System;\nusing System.Collections.Generi"
  },
  {
    "path": "PokemonBattleEngine/Packets/_Status1Packet.cs",
    "chars": 1647,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_Status2Packet.cs",
    "chars": 1647,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_TeamStatusDamagePacket.cs",
    "chars": 1299,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_TeamStatusPacket.cs",
    "chars": 1128,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_TransformPacket.cs",
    "chars": 4029,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_TypeChangedPacket.cs",
    "chars": 1232,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/_WeatherDamagePacket.cs",
    "chars": 1151,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_WeatherPacket.cs",
    "chars": 938,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System.Collections.ObjectModel;\nusing S"
  },
  {
    "path": "PokemonBattleEngine/Packets/_WildPkmnAppearedPacket.cs",
    "chars": 6364,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Packets/__Packet.cs",
    "chars": 161,
    "preview": "using System.Collections.ObjectModel;\n\nnamespace Kermalis.PokemonBattleEngine.Packets;\n\npublic interface IPBEPacket\n{\n\t"
  },
  {
    "path": "PokemonBattleEngine/Packets/__PacketProcessor.cs",
    "chars": 6984,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing System;\nusing System.Diagnostics.CodeAn"
  },
  {
    "path": "PokemonBattleEngine/PokemonBattleEngine.csproj",
    "chars": 616,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net7.0</TargetFramework>\n\t\t<OutputType>Library</"
  },
  {
    "path": "PokemonBattleEngine/Utils/EmptyCollections.cs",
    "chars": 234,
    "preview": "using System;\nusing System.Collections.ObjectModel;\n\nnamespace Kermalis.PokemonBattleEngine.Utils;\n\ninternal static cla"
  },
  {
    "path": "PokemonBattleEngine/Utils/Random.cs",
    "chars": 5436,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusin"
  },
  {
    "path": "PokemonBattleEngine/Utils/Utils.cs",
    "chars": 1934,
    "preview": "using System.Collections.Generic;\nusing System.IO;\nusing System.Text.Json.Nodes;\n\nnamespace Kermalis.PokemonBattleEngin"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/AI/AI.cs",
    "chars": 5526,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing System;\nusing System.Collecti"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/AI/AIDecisions.cs",
    "chars": 21345,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine."
  },
  {
    "path": "PokemonBattleEngine.DefaultData/AI/WildAI.cs",
    "chars": 2505,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing System;\n\nnamespace Kermalis.P"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/BerryData.cs",
    "chars": 778,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\n\nnamespace Kermalis.PokemonBattleEngine.DefaultData.Data;\n\npublic sealed parti"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/BerryData_Data.cs",
    "chars": 6647,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\n\nnames"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/EXPTables.cs",
    "chars": 7999,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\n\nnamespace Kermalis.PokemonBattleEngine.DefaultData.Data;\n\npubli"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/EventPokemon.cs",
    "chars": 2163,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\n\nnames"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/EventPokemon_Data.cs",
    "chars": 75145,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing System.Collections.Generi"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/ItemData.cs",
    "chars": 273,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\n\nnamespace Kermalis.PokemonBattleEngine.DefaultData.Data;\n\npublic sealed parti"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/ItemData_Data.cs",
    "chars": 18601,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\n\nnames"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/LegalityChecker.cs",
    "chars": 2438,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing System.Collections.Generi"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/MoveData.cs",
    "chars": 1542,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System;\nusing System.Text;\n\nnamespace Kermalis.PokemonBattleEngine.Defau"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/MoveData_Data.cs",
    "chars": 152314,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\n\nnamesp"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Data/PokemonData.cs",
    "chars": 6136,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing System;\nusing System.Coll"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/DefaultDataProvider.cs",
    "chars": 9655,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine."
  },
  {
    "path": "PokemonBattleEngine.DefaultData/Enums.cs",
    "chars": 6008,
    "preview": "using System;\n\nnamespace Kermalis.PokemonBattleEngine.DefaultData;\n\n[Flags]\npublic enum PBEDDMoveObtainMethod : ulong\n{"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/IPokemonDataExtended.cs",
    "chars": 695,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing System.Collections.Generic;\n\nnamespace Kermalis.PokemonBattleEngine.Defa"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/LocalizedString.cs",
    "chars": 12808,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing System;\nusing System.Coll"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/PokemonBattleEngine.DefaultData.csproj",
    "chars": 905,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net7.0</TargetFramework>\n\t\t<OutputType>Library</"
  },
  {
    "path": "PokemonBattleEngine.DefaultData/RandomTeamGenerator.cs",
    "chars": 47860,
    "preview": "// This file is adapted from Pokémon Showdown (MIT License): https://github.com/smogon/pokemon-showdown/blob/master/dat"
  },
  {
    "path": "PokemonBattleEngine.sln",
    "chars": 18902,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.2900"
  },
  {
    "path": "PokemonBattleEngineClient/App.xaml",
    "chars": 461,
    "preview": "<Application xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/App.xaml.cs",
    "chars": 881,
    "preview": "using Avalonia;\nusing Avalonia.Controls.ApplicationLifetimes;\nusing Avalonia.Markup.Xaml;\nusing Kermalis.PokemonBattleE"
  },
  {
    "path": "PokemonBattleEngineClient/Clients/ActionsBuilder.cs",
    "chars": 1885,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngineC"
  },
  {
    "path": "PokemonBattleEngineClient/Clients/BattleClient.cs",
    "chars": 6357,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Packets;\nusing Kermalis.PokemonBattleEngi"
  },
  {
    "path": "PokemonBattleEngineClient/Clients/NetworkClient.cs",
    "chars": 8582,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data.Legality;\nusing Kermalis.PokemonBatt"
  },
  {
    "path": "PokemonBattleEngineClient/Clients/NonLocalClient.cs",
    "chars": 15841,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine."
  },
  {
    "path": "PokemonBattleEngineClient/Clients/ReplayClient.cs",
    "chars": 1050,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Packets;\nusing Kermalis.PokemonBattleEngi"
  },
  {
    "path": "PokemonBattleEngineClient/Clients/SinglePlayerClient.cs",
    "chars": 2729,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.DefaultData.AI;\nusing Kermalis.PokemonBat"
  },
  {
    "path": "PokemonBattleEngineClient/Clients/SwitchesBuilder.cs",
    "chars": 1701,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngineClient.Views;\nusing System;\n\nnamespace Ker"
  },
  {
    "path": "PokemonBattleEngineClient/Infrastructure/BetterWrapPanel.cs",
    "chars": 7515,
    "preview": "// This source file is adapted from the Avalonia project. \n// (https://github.com/AvaloniaUI/Avalonia)\n\nusing Avalonia;"
  },
  {
    "path": "PokemonBattleEngineClient/Infrastructure/Converters.cs",
    "chars": 3617,
    "preview": "using Avalonia;\nusing Avalonia.Data.Converters;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattle"
  },
  {
    "path": "PokemonBattleEngineClient/Infrastructure/StringRenderer.cs",
    "chars": 6199,
    "preview": "using Avalonia;\nusing Avalonia.Media.Imaging;\nusing Avalonia.Platform;\nusing System;\nusing System.Collections.Concurren"
  },
  {
    "path": "PokemonBattleEngineClient/Infrastructure/Utils.cs",
    "chars": 13717,
    "preview": "using Avalonia;\nusing Avalonia.Media.Imaging;\nusing Avalonia.Platform;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing"
  },
  {
    "path": "PokemonBattleEngineClient/Infrastructure/WriteableBitmapSurface.cs",
    "chars": 424,
    "preview": "using Avalonia.Controls.Platform.Surfaces;\nusing Avalonia.Media.Imaging;\nusing Avalonia.Platform;\n\nnamespace Kermalis.P"
  },
  {
    "path": "PokemonBattleEngineClient/MainWindow.xaml",
    "chars": 459,
    "preview": "<Window xmlns=\"https://github.com/avaloniaui\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xm"
  },
  {
    "path": "PokemonBattleEngineClient/MainWindow.xaml.cs",
    "chars": 671,
    "preview": "using Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing Kermalis.PokemonBattleEngineClient.Views;\n\nnamespace Kermali"
  },
  {
    "path": "PokemonBattleEngineClient/Models/MoveInfo.cs",
    "chars": 5102,
    "preview": "using Avalonia.Media;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermali"
  },
  {
    "path": "PokemonBattleEngineClient/Models/PokemonInfo.cs",
    "chars": 1000,
    "preview": "using Avalonia.Media.Imaging;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data.Utils;"
  },
  {
    "path": "PokemonBattleEngineClient/Models/SwitchInfo.cs",
    "chars": 778,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngineClient.Infrastructure;\nusing ReactiveUI;\nu"
  },
  {
    "path": "PokemonBattleEngineClient/Models/TargetInfo.cs",
    "chars": 1306,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing System.ComponentModel;\n\nnamespace Kermalis.PokemonBattleEngineClient.M"
  },
  {
    "path": "PokemonBattleEngineClient/Models/TeamInfo.cs",
    "chars": 321,
    "preview": "using Kermalis.PokemonBattleEngine.Data.Legality;\n\nnamespace Kermalis.PokemonBattleEngineClient.Models;\n\npublic sealed "
  },
  {
    "path": "PokemonBattleEngineClient/PokemonBattleEngineClient.csproj",
    "chars": 1384,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net7.0</TargetFramework>\n\t\t<OutputType>Library</"
  },
  {
    "path": "PokemonBattleEngineClient/Views/ActionsView.xaml",
    "chars": 7892,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/ActionsView.xaml.cs",
    "chars": 30349,
    "preview": "using Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonB"
  },
  {
    "path": "PokemonBattleEngineClient/Views/BattleView.xaml",
    "chars": 586,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/BattleView.xaml.cs",
    "chars": 1076,
    "preview": "using Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing Kermalis.PokemonBattleEngineClient.Clients;\n\nnamespace Kerma"
  },
  {
    "path": "PokemonBattleEngineClient/Views/FieldView.xaml",
    "chars": 3832,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/FieldView.xaml.cs",
    "chars": 9980,
    "preview": "using Avalonia;\nusing Avalonia.Controls;\nusing Avalonia.Controls.Shapes;\nusing Avalonia.Markup.Xaml;\nusing Avalonia.Med"
  },
  {
    "path": "PokemonBattleEngineClient/Views/HPBarView.xaml",
    "chars": 600,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/HPBarView.xaml.cs",
    "chars": 5287,
    "preview": "using Avalonia;\nusing Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing Avalonia.Media;\nusing Avalonia.Media.Imaging"
  },
  {
    "path": "PokemonBattleEngineClient/Views/MainView.xaml",
    "chars": 4227,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/MainView.xaml.cs",
    "chars": 6719,
    "preview": "using Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing Avalonia.Threading;\nusing Kermalis.PokemonBattleEngine.Battl"
  },
  {
    "path": "PokemonBattleEngineClient/Views/MessageView.xaml",
    "chars": 753,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/MessageView.xaml.cs",
    "chars": 1323,
    "preview": "using Avalonia.Controls;\nusing Avalonia.Layout;\nusing Avalonia.Markup.Xaml;\nusing Avalonia.Media.Imaging;\nusing Avaloni"
  },
  {
    "path": "PokemonBattleEngineClient/Views/PokemonView.xaml",
    "chars": 833,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/PokemonView.xaml.cs",
    "chars": 1759,
    "preview": "using Avalonia;\nusing Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing AvaloniaGif;\nusing Kermalis.PokemonBattleEng"
  },
  {
    "path": "PokemonBattleEngineClient/Views/TeamBuilderView.xaml",
    "chars": 15697,
    "preview": "<UserControl xmlns=\"https://github.com/avaloniaui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n"
  },
  {
    "path": "PokemonBattleEngineClient/Views/TeamBuilderView.xaml.cs",
    "chars": 8988,
    "preview": "using Avalonia.Controls;\nusing Avalonia.Markup.Xaml;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBat"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Assets/AboutAssets.txt",
    "chars": 602,
    "preview": "Any raw assets you want to be deployed with your application can be placed in\nthis directory (and child directories) and"
  },
  {
    "path": "PokemonBattleEngineClient.Android/MainActivity.cs",
    "chars": 1757,
    "preview": "using Android.App;\nusing Android.Content.PM;\nusing Android.OS;\nusing Avalonia;\nusing Avalonia.Android;\nusing Kermalis.P"
  },
  {
    "path": "PokemonBattleEngineClient.Android/PokemonBattleEngineClient.Android.csproj",
    "chars": 4937,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microso"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Properties/AndroidManifest.xml",
    "chars": 413,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" package=\"co"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Properties/AssemblyInfo.cs",
    "chars": 1111,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing Android.App"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Resources/AboutResources.txt",
    "chars": 1693,
    "preview": "Images, layout descriptions, binary blobs and string dictionaries can be included \nin your application as resource files"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Resources/Resource.Designer.cs",
    "chars": 2192,
    "preview": "#pragma warning disable 1591\n//------------------------------------------------------------------------------\n// <auto-g"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Resources/layout/Main.axml",
    "chars": 414,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "PokemonBattleEngineClient.Android/Resources/values/Strings.xml",
    "chars": 188,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"Hello\">Hello World, Click Me!</string>\n    <string "
  },
  {
    "path": "PokemonBattleEngineClient.Desktop/PokemonBattleEngineClient.Desktop.csproj",
    "chars": 631,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFrameworks>net7.0</TargetFrameworks>\n\t\t<OutputType>Exe</Ou"
  },
  {
    "path": "PokemonBattleEngineClient.Desktop/Program.cs",
    "chars": 584,
    "preview": "using Avalonia;\nusing Avalonia.ReactiveUI;\nusing Kermalis.PokemonBattleEngineClient.Infrastructure;\nusing System;\n\nnames"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/AppDelegate.cs",
    "chars": 2339,
    "preview": "using Avalonia;\nusing Avalonia.iOS;\nusing Avalonia.Media;\nusing Foundation;\nusing Kermalis.PokemonBattleEngineClient.Inf"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/Entitlements.plist",
    "chars": 181,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/Info.plist",
    "chars": 1302,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/Main.cs",
    "chars": 241,
    "preview": "using UIKit;\n\nnamespace Kermalis.PokemonBattleEngineClient.iOS\n{\n    public sealed class Application\n    {\n        priva"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/PokemonBattleEngineClient.iOS.csproj",
    "chars": 5811,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microso"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/Properties/AssemblyInfo.cs",
    "chars": 1438,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Inform"
  },
  {
    "path": "PokemonBattleEngineClient.iOS/Resources/LaunchScreen.xib",
    "chars": 3337,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "PokemonBattleEngineDiscord/BattleContext.cs",
    "chars": 26508,
    "preview": "using Discord;\nusing Discord.WebSocket;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.D"
  },
  {
    "path": "PokemonBattleEngineDiscord/BattleContext_Constants.cs",
    "chars": 5593,
    "preview": "using Discord;\nusing Kermalis.PokemonBattleEngine.Data;\nusing System.Collections.Generic;\n\nnamespace Kermalis.PokemonBa"
  },
  {
    "path": "PokemonBattleEngineDiscord/BotCommands.cs",
    "chars": 16153,
    "preview": "using Discord;\nusing Discord.Commands;\nusing Discord.WebSocket;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermal"
  },
  {
    "path": "PokemonBattleEngineDiscord/ChannelHandler.cs",
    "chars": 5223,
    "preview": "using Discord;\nusing Discord.Commands;\nusing Discord.WebSocket;\nusing System;\nusing System.Collections.Generic;\nusing S"
  },
  {
    "path": "PokemonBattleEngineDiscord/Matchmaking.cs",
    "chars": 5768,
    "preview": "using Discord;\nusing Discord.Commands;\nusing Discord.WebSocket;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermal"
  },
  {
    "path": "PokemonBattleEngineDiscord/PokemonBattleEngineDiscord.csproj",
    "chars": 688,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net7.0</TargetFramework>\n\t\t<OutputType>Exe</Outp"
  },
  {
    "path": "PokemonBattleEngineDiscord/Program.cs",
    "chars": 3087,
    "preview": "using Discord;\nusing Discord.Commands;\nusing Discord.WebSocket;\nusing Kermalis.PokemonBattleEngine.DefaultData;\nusing S"
  },
  {
    "path": "PokemonBattleEngineDiscord/ReactionHandler.cs",
    "chars": 1829,
    "preview": "using Discord;\nusing Discord.WebSocket;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\n"
  },
  {
    "path": "PokemonBattleEngineDiscord/ReplaySaver.cs",
    "chars": 1957,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing System;\nusing System.IO;\nusing System.Text.RegularExpressions;\n\nnamesp"
  },
  {
    "path": "PokemonBattleEngineDiscord/Utils.cs",
    "chars": 6386,
    "preview": "using Discord;\nusing Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.Pokem"
  },
  {
    "path": "PokemonBattleEngineExtras/AIBattleDemo.cs",
    "chars": 4827,
    "preview": "using Kermalis.PokemonBattleEngine.Battle;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine."
  },
  {
    "path": "PokemonBattleEngineExtras/LocalizationDumper.cs",
    "chars": 15951,
    "preview": "using Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\nusing Kermalis.SimpleNARC;\nusin"
  },
  {
    "path": "PokemonBattleEngineExtras/NARCTextDumper.cs",
    "chars": 1195,
    "preview": "using Kermalis.SimpleNARC;\nusing System;\nusing System.IO;\nusing System.Text;\n\nnamespace Kermalis.PokemonBattleEngineExt"
  },
  {
    "path": "PokemonBattleEngineExtras/PokemonBattleEngineExtras.csproj",
    "chars": 820,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net7.0</TargetFramework>\n\t\t<OutputType>Exe</Outp"
  },
  {
    "path": "PokemonBattleEngineExtras/PokemonDataDumper.cs",
    "chars": 41147,
    "preview": "using Kermalis.EndianBinaryIO;\nusing Kermalis.PokemonBattleEngine.Data;\nusing Kermalis.PokemonBattleEngine.Data.Utils;\n"
  }
]

// ... and 42 more files (download for full content)

About this extraction

This page contains the full source code of the Kermalis/PokemonBattleEngine GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 242 files (1.7 MB), approximately 562.6k tokens, and a symbol index with 1787 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!