Style cleanup

This commit is contained in:
2025-03-02 17:19:57 +01:00
parent c0bc905c46
commit 284ab3079c
175 changed files with 588 additions and 650 deletions

View File

@@ -94,7 +94,7 @@ public interface IBattle : IScriptSource, IDeepCloneable
void ValidateBattleState();
bool HasForcedTurn(IPokemon pokemon, [NotNullWhen(true)] out ITurnChoice? choice);
/// <summary>
/// Checks whether a choice is actually possible.
/// </summary>
@@ -111,22 +111,22 @@ public interface IBattle : IScriptSource, IDeepCloneable
void SetWeather(StringKey? weatherName);
public IScriptSet Volatile { get; }
/// <summary>
/// Gets the current weather of the battle. If no weather is present, this returns null.
/// </summary>
StringKey? WeatherName { get; }
void SetTerrain(StringKey? terrainName);
StringKey? TerrainName { get; }
/// <summary>
/// Gets the turn choices of the previous turn. This is a list of lists, where each list represents the choices
/// for a single turn. The outer list is ordered from oldest to newest turn.
/// </summary>
IReadOnlyList<IReadOnlyList<ITurnChoice>> PreviousTurnChoices { get; }
CaptureResult AttempCapture(byte sideIndex, byte position, IItem item);
}
@@ -247,10 +247,10 @@ public class BattleImpl : ScriptSource, IBattle
choice = null;
return false;
}
ITurnChoice? forcedChoice = null;
pokemon.RunScriptHook(
script => script.ForceTurnSelection(battleData.SideIndex, battleData.Position, ref forcedChoice));
pokemon.RunScriptHook(script =>
script.ForceTurnSelection(battleData.SideIndex, battleData.Position, ref forcedChoice));
choice = forcedChoice;
return choice != null;
}
@@ -262,7 +262,7 @@ public class BattleImpl : ScriptSource, IBattle
return false;
if (HasForcedTurn(choice.User, out var forcedChoice) && choice != forcedChoice)
return false;
if (choice is IMoveChoice moveChoice)
{
// TODO: Hook to change number of PP needed.
@@ -365,7 +365,7 @@ public class BattleImpl : ScriptSource, IBattle
/// <inheritdoc />
public StringKey? WeatherName => _weatherScript.Script?.Name;
private readonly ScriptContainer _terrainScript = new();
/// <inheritdoc />
@@ -386,7 +386,6 @@ public class BattleImpl : ScriptSource, IBattle
/// <inheritdoc />
public StringKey? TerrainName => _terrainScript.Script?.Name;
private readonly List<IReadOnlyList<ITurnChoice>> _previousTurnChoices = new();
/// <inheritdoc />
@@ -398,7 +397,7 @@ public class BattleImpl : ScriptSource, IBattle
var target = GetPokemon(sideIndex, position);
if (target is not { IsUsable: true })
return CaptureResult.Failed;
var attemptCapture = Library.CaptureLibrary.TryCapture(target, item, Random);
if (attemptCapture.IsCaught)
{

View File

@@ -23,7 +23,7 @@ public class BattleChoiceQueue : IDeepCloneable
{
_choices = choices;
}
/// <summary>
/// Dequeues the next turn choice to be executed. This gives back the choice and sets it to null in the queue. It
/// also increments the internal index.
@@ -40,18 +40,17 @@ public class BattleChoiceQueue : IDeepCloneable
LastRanChoice = choice;
return choice;
}
/// <summary>
/// This reads what the next choice to execute will be, without modifying state.
/// </summary>
public ITurnChoice? Peek() => _currentIndex >= _choices.Length ? null : _choices[_currentIndex];
/// <summary>
/// Checks if there are any more choices to execute.
/// </summary>
public bool HasNext() => _currentIndex < _choices.Length;
/// <summary>
/// This resorts the yet to be executed choices. This can be useful for dealing with situations
/// such as Pokémon changing forms just after the very start of a turn, when turn order has
@@ -72,7 +71,7 @@ public class BattleChoiceQueue : IDeepCloneable
choice.User.RunScriptHook(script => script.ChangeSpeed(choice, ref speed));
choice.Speed = speed;
}
// We only sort the choices that are left
Array.Sort(_choices, currentIndex, length - currentIndex, TurnChoiceComparer.Instance!);
}
@@ -99,8 +98,9 @@ public class BattleChoiceQueue : IDeepCloneable
_choices[_currentIndex] = choice;
return true;
}
internal IReadOnlyList<ITurnChoice?> GetChoices() => _choices;
public ITurnChoice? FirstOrDefault(Func<ITurnChoice, bool> predicate) => _choices.WhereNotNull().FirstOrDefault(predicate);
public ITurnChoice? FirstOrDefault(Func<ITurnChoice, bool> predicate) =>
_choices.WhereNotNull().FirstOrDefault(predicate);
}

View File

@@ -12,7 +12,7 @@ internal static class MoveTurnExecutor
{
var chosenMove = moveChoice.ChosenMove;
var moveData = chosenMove.MoveData;
var moveDataName = moveData.Name;
moveChoice.RunScriptHook(x => x.ChangeMove(moveChoice, ref moveDataName));
if (moveData.Name != moveDataName)
@@ -31,11 +31,11 @@ internal static class MoveTurnExecutor
moveChoice.Script.Set(script);
}
}
}
var targetType = moveData.Target;
var targets = TargetResolver.ResolveTargets(battle, moveChoice.TargetSide, moveChoice.TargetPosition, targetType);
var targets =
TargetResolver.ResolveTargets(battle, moveChoice.TargetSide, moveChoice.TargetPosition, targetType);
moveChoice.RunScriptHook(x => x.ChangeTargets(moveChoice, ref targets));
byte numberOfHits = 1;
@@ -46,7 +46,7 @@ internal static class MoveTurnExecutor
}
var executingMove = new ExecutingMoveImpl(targets, numberOfHits, chosenMove, moveData, moveChoice);
var prevented = false;
executingMove.RunScriptHook(x => x.PreventMove(executingMove, ref prevented));
if (prevented)
@@ -56,9 +56,9 @@ internal static class MoveTurnExecutor
// TODO: Modify the PP used by the move.
if (!executingMove.ChosenMove.TryUse(ppUsed))
return;
battle.EventHook.Invoke(new MoveUseEvent(executingMove));
var failed = false;
executingMove.RunScriptHook(x => x.FailMove(executingMove, ref failed));
if (failed)
@@ -66,12 +66,12 @@ internal static class MoveTurnExecutor
// TODO: fail handling
return;
}
var stopped = false;
executingMove.RunScriptHook(x => x.StopBeforeMove(executingMove, ref stopped));
if (stopped)
return;
executingMove.RunScriptHook(x => x.OnBeforeMove(executingMove));
foreach (var target in targets.WhereNotNull())
{
@@ -88,7 +88,7 @@ internal static class MoveTurnExecutor
// TODO: fail handling
return;
}
var isInvulnerable = false;
target.RunScriptHook(x => x.IsInvulnerableToMove(executingMove, target, ref isInvulnerable));
if (isInvulnerable)
@@ -96,7 +96,7 @@ internal static class MoveTurnExecutor
// TODO: event?
return;
}
var numberOfHits = executingMove.NumberOfHits;
var targetHitStat = executingMove.GetTargetIndex(target) * numberOfHits;
@@ -120,7 +120,7 @@ internal static class MoveTurnExecutor
var effectiveness = battle.Library.StaticLibrary.Types.GetEffectiveness(hitType, target.Types);
executingMove.RunScriptHook(x => x.ChangeEffectiveness(executingMove, target, hitIndex, ref effectiveness));
hitData.Effectiveness = effectiveness;
var blockCritical = false;
executingMove.RunScriptHook(x => x.BlockCriticalHit(executingMove, target, hitIndex, ref blockCritical));
target.RunScriptHook(x => x.BlockIncomingCriticalHit(executingMove, target, hitIndex, ref blockCritical));
@@ -129,10 +129,10 @@ internal static class MoveTurnExecutor
var critical = battle.Library.DamageCalculator.IsCritical(battle, executingMove, target, hitIndex);
hitData.IsCritical = critical;
}
var basePower = battle.Library.DamageCalculator.GetBasePower(executingMove, target, hitIndex, hitData);
hitData.BasePower = basePower;
hitData.Damage = battle.Library.DamageCalculator.GetDamage(executingMove, target, hitIndex, hitData);
var accuracy = useMove.Accuracy;
@@ -140,17 +140,17 @@ internal static class MoveTurnExecutor
// modifying it.
if (accuracy != 255)
{
accuracy = battle.Library.StatCalculator.CalculateModifiedAccuracy(executingMove, target,
hitIndex, accuracy);
accuracy = battle.Library.StatCalculator.CalculateModifiedAccuracy(executingMove, target, hitIndex,
accuracy);
}
if (accuracy < 100 && battle.Random.GetInt(100) >= accuracy)
{
executingMove.RunScriptHook(x => x.OnMoveMiss(executingMove, target));
battle.EventHook.Invoke(new MoveMissEvent(executingMove));
break;
}
var blockIncomingHit = false;
target.RunScriptHook(x => x.BlockIncomingHit(executingMove, target, hitIndex, ref blockIncomingHit));
executingMove.RunScriptHook(x => x.BlockOutgoingHit(executingMove, target, hitIndex, ref blockIncomingHit));
@@ -187,7 +187,7 @@ internal static class MoveTurnExecutor
BatchId = hitEventBatch,
});
target.Damage(damage, DamageSource.MoveDamage, hitEventBatch);
if (!target.IsFainted)
if (!target.IsFainted)
target.RunScriptHook(x => x.OnIncomingHit(executingMove, target, hitIndex));
else
executingMove.RunScriptHook(x => x.OnOpponentFaints(executingMove, target, hitIndex));
@@ -198,14 +198,16 @@ internal static class MoveTurnExecutor
if (secondaryEffect != null)
{
var preventSecondary = false;
target.RunScriptHook(x => x.PreventSecondaryEffect(executingMove, target, hitIndex, ref preventSecondary));
target.RunScriptHook(x =>
x.PreventSecondaryEffect(executingMove, target, hitIndex, ref preventSecondary));
if (!preventSecondary)
{
var chance = secondaryEffect.Chance;
if (chance < 0 || battle.Random.EffectChance(chance, executingMove, target, hitIndex))
{
executingMove.RunScriptHook(x => x.OnSecondaryEffect(executingMove, target, hitIndex));
executingMove.RunScriptHook(x =>
x.OnSecondaryEffect(executingMove, target, hitIndex));
}
}
}
@@ -213,7 +215,7 @@ internal static class MoveTurnExecutor
}
}
}
if (numberOfHits == 0)
{
target.RunScriptHook(x => x.OnMoveMiss(executingMove, target));
@@ -224,6 +226,5 @@ internal static class MoveTurnExecutor
{
executingMove.RunScriptHook(x => x.OnAfterHits(executingMove, target));
}
}
}

View File

@@ -15,8 +15,8 @@ public static class TargetResolver
return target switch
{
MoveTarget.Adjacent or MoveTarget.AdjacentAlly or MoveTarget.AdjacentAllySelf or MoveTarget.AdjacentOpponent
or MoveTarget.Any or MoveTarget.RandomOpponent
or MoveTarget.SelfUse => [battle.GetPokemon(side, position)],
or MoveTarget.Any or MoveTarget.RandomOpponent or MoveTarget.SelfUse =>
[battle.GetPokemon(side, position)],
MoveTarget.All => GetAllTargets(battle),
MoveTarget.AllAdjacentOpponent => GetAllAdjacentAndOpponent(battle, side, position),
MoveTarget.AllAdjacent => GetAllAdjacent(battle, side, position),
@@ -144,7 +144,8 @@ public static class TargetResolver
return
[
battle.GetPokemon(side, position), battle.GetPokemon(side, (byte)left), battle.GetPokemon(side, (byte)right),
battle.GetPokemon(side, position), battle.GetPokemon(side, (byte)left),
battle.GetPokemon(side, (byte)right),
];
}
}

View File

@@ -16,9 +16,11 @@ public static class TurnRunner
{
var queue = battle.ChoiceQueue;
if (queue == null)
{
throw new ArgumentNullException(nameof(battle.ChoiceQueue),
"The battle's choice queue must be set before running a turn.");
}
// We are now at the very beginning of a turn. We have assigned speeds and priorities to all
// choices, and put them in the correct order.
@@ -30,7 +32,7 @@ public static class TurnRunner
{
choice.RunScriptHook(script => script.OnBeforeTurnStart(choice));
}
// Now we can properly begin executing choices.
// One by one dequeue the turns, and run them. If the battle has ended we do not want to
// continue running.
@@ -41,7 +43,7 @@ public static class TurnRunner
continue;
ExecuteChoice(battle, next);
}
// If the battle is not ended, we have arrived at the normal end of a turn. and thus want
// to run the end turn scripts.
@@ -122,7 +124,6 @@ public static class TurnRunner
userSide.SwapPokemon(battleData.Position, fleeChoice.SwitchTo);
}
private static void ExecuteFleeChoice(IBattle battle, IFleeChoice fleeChoice)
{
var user = fleeChoice.User;
@@ -131,7 +132,7 @@ public static class TurnRunner
return;
if (!battle.CanFlee)
return;
var preventFlee = false;
fleeChoice.RunScriptHook(script => script.PreventSelfRunAway(fleeChoice, ref preventFlee));
if (preventFlee)
@@ -148,10 +149,10 @@ public static class TurnRunner
return;
}
}
if (!battle.Library.MiscLibrary.CanFlee(battle, fleeChoice))
return;
var userSide = battle.Sides[battleData.SideIndex];
userSide.MarkAsFled();
battle.ValidateBattleState();
@@ -171,5 +172,4 @@ public static class TurnRunner
}
itemChoice.Item.RunItemScript(battle.Library.ScriptResolver, target ?? user);
}
}

View File

@@ -10,22 +10,22 @@ public record struct BattleResult
ConclusiveResult = conclusiveResult;
WinningSide = winningSide;
}
/// <summary>
/// An inconclusive battle result. This means no side has won.
/// </summary>
public static BattleResult Inconclusive => new(false, null);
/// <summary>
/// A conclusive battle result. This means one side has won.
/// </summary>
public static BattleResult Conclusive(byte winningSide) => new(true, winningSide);
/// <summary>
/// Whether the battle has a conclusive result. If false, no side has won.
/// </summary>
public bool ConclusiveResult { get; }
/// <summary>
/// The side that won the battle. If null, no side has won.
/// </summary>

View File

@@ -14,48 +14,48 @@ public interface IBattleSide : IScriptSource, IDeepCloneable
/// The index of the side on the battle.
/// </summary>
byte Index { get; }
/// <summary>
/// The number of Pokémon that can be on the side.
/// </summary>
byte NumberOfPositions { get; }
/// <summary>
/// A list of Pokémon currently on the battlefield.
/// </summary>
IReadOnlyList<IPokemon?> Pokemon { get; }
/// <summary>
/// The currently set choices for all Pokémon on the battlefield. Cleared when the turn starts.
/// </summary>
IReadOnlyList<ITurnChoice?> SetChoices { get; }
/// <summary>
/// Whether every Pokémon on this side has its choices
/// </summary>
bool AllChoicesSet { get; }
/// <summary>
/// The slots on the side that can still be filled. Once all slots are set to false, this side
/// has lost the battle.
/// </summary>
IReadOnlyList<bool> FillablePositions { get; }
/// <summary>
/// A reference to the battle this side is in.
/// </summary>
IBattle Battle { get; }
/// <summary>
/// Whether this side has fled.
/// </summary>
bool HasFledBattle { get; }
/// <summary>
/// The volatile scripts that are attached to the side.
/// </summary>
IScriptSet VolatileScripts { get; }
/// <summary>
/// Returns true if there are slots that need to be filled with a new pokemon, that have parties
/// responsible for them. Returns false if all slots are filled with usable pokemon, or slots are
@@ -67,7 +67,7 @@ public interface IBattleSide : IScriptSource, IDeepCloneable
/// Sets a choice for a Pokémon on this side.
/// </summary>
void SetChoice(byte position, ITurnChoice choice);
/// <summary>
/// Resets all choices on this side.
/// </summary>
@@ -110,12 +110,12 @@ public interface IBattleSide : IScriptSource, IDeepCloneable
/// Checks whether the side has been defeated.
/// </summary>
bool IsDefeated();
/// <summary>
/// The number of times this side has attempted to flee.
/// </summary>
uint FleeAttempts { get; }
/// <summary>
/// Registers a flee attempt for this side.
/// </summary>
@@ -150,7 +150,7 @@ public class BattleSideImpl : ScriptSource, IBattleSide
Battle = battle;
VolatileScripts = new ScriptSet();
}
/// <inheritdoc />
public byte Index { get; }
@@ -158,6 +158,7 @@ public class BattleSideImpl : ScriptSource, IBattleSide
public byte NumberOfPositions { get; }
private readonly IPokemon?[] _pokemon;
/// <inheritdoc />
public IReadOnlyList<IPokemon?> Pokemon => _pokemon;
@@ -170,6 +171,7 @@ public class BattleSideImpl : ScriptSource, IBattleSide
public bool AllChoicesSet => _setChoices.All(choice => choice is not null);
private readonly bool[] _fillablePositions;
/// <inheritdoc />
public IReadOnlyList<bool> FillablePositions => _fillablePositions;
@@ -223,7 +225,7 @@ public class BattleSideImpl : ScriptSource, IBattleSide
pokemon.RunScriptHook(script => script.OnRemove());
pokemon.SetOnBattlefield(false);
}
_pokemon[index] = null;
}
@@ -259,7 +261,7 @@ public class BattleSideImpl : ScriptSource, IBattleSide
{
Battle.EventHook.Invoke(new SwitchEvent(Index, position, null));
}
return oldPokemon;
}

View File

@@ -7,7 +7,6 @@ namespace PkmnLib.Dynamic.Models.Choices;
/// </summary>
public interface IFleeChoice : ITurnChoice
{
}
/// <inheritdoc cref="IFleeChoice"/>
@@ -22,7 +21,9 @@ public class FleeTurnChoice : TurnChoice, IFleeChoice
public override int ScriptCount => User.ScriptCount;
/// <inheritdoc />
public override void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts) { }
public override void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts)
{
}
/// <inheritdoc />
public override void CollectScripts(List<IEnumerable<ScriptContainer>> scripts) => User.CollectScripts(scripts);

View File

@@ -12,7 +12,7 @@ public interface IItemChoice : ITurnChoice
/// The item that is used.
/// </summary>
public IItem Item { get; }
/// <summary>
/// The side the move is targeted at.
/// </summary>

View File

@@ -32,9 +32,9 @@ public interface IMoveChoice : ITurnChoice
/// The underlying script of the move.
/// </summary>
ScriptContainer Script { get; set; }
Dictionary<StringKey, object?>? AdditionalData { get; }
IScriptSet Volatile { get; }
}
@@ -47,7 +47,7 @@ public class MoveChoice : TurnChoice, IMoveChoice
ChosenMove = usedMove;
TargetSide = targetSide;
TargetPosition = targetPosition;
var secondaryEffect = usedMove.MoveData.SecondaryEffect;
if (secondaryEffect != null)
{

View File

@@ -7,7 +7,6 @@ namespace PkmnLib.Dynamic.Models.Choices;
/// </summary>
public interface IPassChoice : ITurnChoice
{
}
public class PassChoice : TurnChoice, IPassChoice

View File

@@ -7,7 +7,7 @@ public class TurnChoiceComparer : IComparer<ITurnChoice>
{
/// <inheritdoc cref="TurnChoiceComparer"/>
public static TurnChoiceComparer Instance { get; } = new();
private enum CompareValues
{
XEqualsY = 0,
@@ -25,7 +25,7 @@ public class TurnChoiceComparer : IComparer<ITurnChoice>
// This is to ensure that the order of choices is deterministic.
return (CompareValues)x.RandomValue.CompareTo(y.RandomValue);
}
private static CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y)
{
// Deal with possible null values
@@ -77,10 +77,10 @@ public class TurnChoiceComparer : IComparer<ITurnChoice>
_ => CompareValues.XGreaterThanY,
};
}
return CompareValues.XLessThanY;
}
/// <inheritdoc />
public int Compare(ITurnChoice? x, ITurnChoice? y) => (int) CompareImpl(x, y);
public int Compare(ITurnChoice? x, ITurnChoice? y) => (int)CompareImpl(x, y);
}

View File

@@ -19,13 +19,13 @@ public enum DamageSource
/// The damage is done because of struggling.
/// </summary>
Struggle = 2,
/// <summary>
/// The damage is done because of a form change.
/// This happens when the form of a Pokemon changes, and it has less max HP than it had before.
/// </summary>
FormChange = 3,
/// <summary>
/// The damage is done because of the weather.
/// </summary>

View File

@@ -129,12 +129,12 @@ public interface IExecutingMove : IScriptSource
/// Gets a hit based on its raw index.
/// </summary>
IHitData GetDataFromRawIndex(int index);
/// <summary>
/// Gets the targets of this move.
/// </summary>
IReadOnlyList<IPokemon?> Targets { get; }
/// <summary>
/// The underlying move choice.
/// </summary>

View File

@@ -54,7 +54,7 @@ public interface ILearnedMove : IDeepCloneable
/// The maximal power points for this move.
/// </summary>
byte MaxPp { get; }
/// <summary>
/// The current power points for this move.
/// </summary>
@@ -86,7 +86,7 @@ public interface ILearnedMove : IDeepCloneable
public class LearnedMoveImpl : ILearnedMove
{
private byte _maxPpModification = 0;
/// <inheritdoc cref="LearnedMoveImpl" />
public LearnedMoveImpl(IMoveData moveData, MoveLearnMethod learnMethod)
{
@@ -95,8 +95,7 @@ public class LearnedMoveImpl : ILearnedMove
CurrentPp = MaxPp;
}
public LearnedMoveImpl(IMoveData moveData, MoveLearnMethod learnMethod, byte pp)
: this(moveData, learnMethod)
public LearnedMoveImpl(IMoveData moveData, MoveLearnMethod learnMethod, byte pp) : this(moveData, learnMethod)
{
CurrentPp = pp;
}
@@ -109,12 +108,12 @@ public class LearnedMoveImpl : ILearnedMove
/// <inheritdoc />
public MoveLearnMethod LearnMethod { get; }
/// <summary>
/// The available power points for this move.
/// </summary>
public byte CurrentPp { get; private set; }
/// <summary>
/// Try to use the move. This subtracts the amount of PP from the current PP. If the amount requested is
/// higher than the current PP, this will return false, and the PP will not be reduced.
@@ -123,7 +122,7 @@ public class LearnedMoveImpl : ILearnedMove
{
if (CurrentPp < amount)
return false;
CurrentPp -= amount;
return true;
}

View File

@@ -50,7 +50,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// The amount of experience of the Pokemon.
/// </summary>
uint Experience { get; }
/// <summary>
/// Increases the experience of the Pokemon. Returns whether any experience was gained.
/// </summary>
@@ -71,7 +71,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// currently not used, and can be used for other implementations.
/// </summary>
byte Coloring { get; }
/// <summary>
/// Whether the Pokemon is shiny.
/// </summary>
@@ -98,7 +98,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// <param name="weightInKg">The new weight in kilograms</param>
/// <returns></returns>
public bool ChangeWeightInKgBy(float weightInKg);
/// <summary>
/// The height of the Pokémon in meters.
/// </summary>
@@ -124,7 +124,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// The stats of the Pokemon including the stat boosts
/// </summary>
StatisticSet<uint> BoostedStats { get; }
/// <summary>
/// The maximum health of the Pokemon.
/// </summary>
@@ -171,12 +171,12 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// are null.
/// </summary>
IReadOnlyList<ILearnedMove?> Moves { get; }
/// <summary>
/// Checks whether the Pokemon has a specific move in its current moveset.
/// </summary>
bool HasMove(StringKey moveName);
/// <summary>
/// Swaps two moves of the Pokemon.
/// </summary>
@@ -201,7 +201,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// Whether or not this Pokemon was caught this battle.
/// </summary>
bool IsCaught { get; }
public void MarkAsCaught();
/// <summary>
@@ -240,7 +240,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// </summary>
[MustUseReturnValue]
IItem? RemoveHeldItem();
/// <summary>
/// Removes the held item from the Pokemon for the duration of the battle. Returns the previously held item.
/// </summary>
@@ -249,7 +249,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// restored after the battle.
/// </remarks>
IItem? RemoveHeldItemForBattle();
/// <summary>
/// Restores the held item of a Pokémon if it was temporarily removed.
/// </summary>
@@ -273,7 +273,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// Suppresses the ability of the Pokémon.
/// </summary>
public void SuppressAbility();
/// <summary>
/// Returns the currently active ability.
/// </summary>
@@ -322,7 +322,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// heal if the Pokemon has 0 health. If the amount healed is 0, this will return false.
/// </summary>
bool Heal(uint heal, bool allowRevive = false);
/// <summary>
/// Restores all PP of the Pokemon.
/// </summary>
@@ -337,10 +337,12 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// Checks whether the Pokémon has a specific non-volatile status.
/// </summary>
bool HasStatus(StringKey status);
/// <summary>
/// Adds a non-volatile status to the Pokemon.
/// </summary>
void SetStatus(StringKey status);
/// <summary>
/// Removes the current non-volatile status from the Pokemon.
/// </summary>
@@ -371,23 +373,23 @@ public interface IPokemon : IScriptSource, IDeepCloneable
/// Marks a Pokemon as seen in the battle.
/// </summary>
void MarkOpponentAsSeen(IPokemon pokemon);
/// <summary>
/// Removes a type from the Pokémon. Returns whether the type was removed.
/// </summary>
bool RemoveType(TypeIdentifier type);
/// <summary>
/// Adds a type to the Pokémon. Returns whether the type was added. It will not add the type if
/// the Pokémon already has it.
/// </summary>
bool AddType(TypeIdentifier type);
/// <summary>
/// Replace the types of the Pokémon with the provided types.
/// </summary>
void SetTypes(IReadOnlyList<TypeIdentifier> types);
void ChangeAbility(IAbility ability);
/// <summary>
@@ -431,17 +433,17 @@ public interface IPokemonBattleData : IDeepCloneable
/// Adds an opponent to the list of seen opponents.
/// </summary>
void MarkOpponentAsSeen(IPokemon opponent);
/// <summary>
/// A list of items the Pokémon has consumed this battle.
/// </summary>
IReadOnlyList<IItem> ConsumedItems { get; }
/// <summary>
/// Marks an item as consumed.
/// </summary>
void MarkItemAsConsumed(IItem itemName);
uint SwitchInTurn { get; internal set; }
}
@@ -569,7 +571,7 @@ public class PokemonImpl : ScriptSource, IPokemon
{
BatchId = batchId,
});
var newLevel = Library.StaticLibrary.GrowthRates.CalculateLevel(Species.GrowthRate, Experience);
if (newLevel > Level)
{
@@ -579,7 +581,7 @@ public class PokemonImpl : ScriptSource, IPokemon
{
BatchId = batchId,
});
if (newLevel >= maxLevel)
{
Experience = Library.StaticLibrary.GrowthRates.CalculateExperience(Species.GrowthRate, maxLevel);
@@ -597,7 +599,7 @@ public class PokemonImpl : ScriptSource, IPokemon
/// <inheritdoc />
public byte Coloring { get; }
/// <inheritdoc />
public bool IsShiny => Coloring == 1;
@@ -686,7 +688,11 @@ public class PokemonImpl : ScriptSource, IPokemon
private List<TypeIdentifier> _types = new();
/// <inheritdoc />
public IReadOnlyList<TypeIdentifier> Types { get => _types; private set => _types = value.ToList(); }
public IReadOnlyList<TypeIdentifier> Types
{
get => _types;
private set => _types = value.ToList();
}
/// <inheritdoc />
public bool IsEgg { get; private set; }
@@ -730,7 +736,7 @@ public class PokemonImpl : ScriptSource, IPokemon
HeldItem = null;
return previous;
}
private IItem? _stolenHeldItem;
/// <inheritdoc />
@@ -753,7 +759,7 @@ public class PokemonImpl : ScriptSource, IPokemon
return false;
if (!Library.ScriptResolver.TryResolveBattleItemScript(HeldItem, out _))
return false;
if (BattleData != null)
{
var prevented = false;
@@ -761,7 +767,7 @@ public class PokemonImpl : ScriptSource, IPokemon
if (prevented)
return false;
}
// TODO: actually consume the item
throw new NotImplementedException();
}
@@ -798,12 +804,12 @@ public class PokemonImpl : ScriptSource, IPokemon
RecalculateBoostedStats();
return true;
}
/// <summary>
/// Whether the ability of the Pokémon is suppressed.
/// </summary>
public bool AbilitySuppressed { get; private set; }
/// <inheritdoc />
public void SuppressAbility()
{
@@ -933,7 +939,7 @@ public class PokemonImpl : ScriptSource, IPokemon
this.RunScriptHook(script => script.ChangeIncomingDamage(this, source, ref dmg));
damage = dmg;
}
// If the damage is more than the current health, we cap it at the current health, to prevent
// underflow.
if (damage >= CurrentHealth)
@@ -989,7 +995,7 @@ public class PokemonImpl : ScriptSource, IPokemon
{
if (IsFainted && !allowRevive)
return false;
var maxAmount = this.BoostedStats.Hp - CurrentHealth;
var maxAmount = BoostedStats.Hp - CurrentHealth;
if (heal > maxAmount)
heal = maxAmount;
if (heal == 0)
@@ -1019,7 +1025,8 @@ public class PokemonImpl : ScriptSource, IPokemon
{
for (byte i = 0; i < Moves.Count; i++)
{
if (Moves[i] is not null) continue;
if (Moves[i] is not null)
continue;
index = i;
break;
}

View File

@@ -10,7 +10,7 @@ public interface IPokemonParty : IReadOnlyList<IPokemon?>, IDeepCloneable
{
event EventHandler<(IPokemon?, int index)>? OnSwapInto;
event EventHandler<(int index1, int index2)>? OnSwap;
/// <summary>
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
/// </summary>
@@ -28,7 +28,7 @@ public interface IPokemonParty : IReadOnlyList<IPokemon?>, IDeepCloneable
/// This will return false if all Pokemon are fainted, or eggs, etc.
/// </remarks>
bool HasUsablePokemon();
/// <summary>
/// Packs the party so that all Pokémon are at the front, and the empty slots are at the back.
/// </summary>
@@ -46,7 +46,6 @@ public class PokemonParty : IPokemonParty
_pokemon = new IPokemon[size];
}
/// <inheritdoc />
public event EventHandler<(IPokemon?, int index)>? OnSwapInto;
@@ -73,10 +72,9 @@ public class PokemonParty : IPokemonParty
OnSwap?.Invoke(this, (index1, index2));
}
/// <inheritdoc />
public bool HasUsablePokemon() => _pokemon.Any(p => p is { IsUsable: true });
/// <inheritdoc />
public IEnumerator<IPokemon?> GetEnumerator() => ((IEnumerable<IPokemon?>)_pokemon).GetEnumerator();
@@ -95,11 +93,11 @@ public class PokemonParty : IPokemonParty
// Pack the party so that all Pokémon are at the front.
for (var i = 0; i < _pokemon.Length; i++)
{
if (_pokemon[i] != null)
if (_pokemon[i] != null)
continue;
for (var j = i + 1; j < _pokemon.Length; j++)
{
if (_pokemon[j] == null)
if (_pokemon[j] == null)
continue;
Swap(i, j);
break;

View File

@@ -134,7 +134,7 @@ public record SerializedStats
public SerializedStats()
{
}
public SerializedStats(ImmutableStatisticSet<byte> stats)
{
Hp = stats.Hp;
@@ -144,7 +144,7 @@ public record SerializedStats
SpecialDefense = stats.SpecialDefense;
Speed = stats.Speed;
}
public SerializedStats(long hp, long attack, long defense, long specialAttack, long specialDefense, long speed)
{
Hp = hp;