Style cleanup
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace PkmnLib.Dynamic.Models.Choices;
|
||||
/// </summary>
|
||||
public interface IPassChoice : ITurnChoice
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class PassChoice : TurnChoice, IPassChoice
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user