Style cleanup
This commit is contained in:
@@ -64,13 +64,14 @@ public class LookupGrowthRate : IGrowthRate
|
||||
}
|
||||
}
|
||||
|
||||
return (LevelInt)(_experienceTable.Length);
|
||||
return (LevelInt)_experienceTable.Length;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public uint CalculateExperience(LevelInt level)
|
||||
{
|
||||
if (level < 1) level = 1;
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
return level >= _experienceTable.Length ? _experienceTable[^1] : _experienceTable[level - 1];
|
||||
}
|
||||
}
|
||||
@@ -105,10 +105,10 @@ public interface IItem : INamedValue
|
||||
/// A set of arbitrary flags that can be set on the item.
|
||||
/// </summary>
|
||||
ImmutableHashSet<StringKey> Flags { get; }
|
||||
|
||||
|
||||
ISecondaryEffect? Effect { get; }
|
||||
ISecondaryEffect? BattleEffect { get; }
|
||||
|
||||
|
||||
byte FlingPower { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -160,10 +160,6 @@ public class ItemImpl : IItem
|
||||
/// <inheritdoc />
|
||||
public byte FlingPower { get; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasFlag(string key)
|
||||
{
|
||||
return Flags.Contains(key);
|
||||
}
|
||||
public bool HasFlag(string key) => Flags.Contains(key);
|
||||
}
|
||||
@@ -7,13 +7,13 @@ namespace PkmnLib.Static.Libraries;
|
||||
/// <summary>
|
||||
/// A basic library for data types. Stores data both by name and by index.
|
||||
/// </summary>
|
||||
public abstract class DataLibrary<T> : IEnumerable<T>
|
||||
where T : INamedValue
|
||||
public abstract class DataLibrary<T> : IEnumerable<T> where T : INamedValue
|
||||
{
|
||||
/// <summary>
|
||||
/// The underlying data storage.
|
||||
/// </summary>
|
||||
protected readonly Dictionary<StringKey, T> Data = new();
|
||||
|
||||
private readonly List<T> _values = [];
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -12,24 +12,27 @@ public interface IReadOnlyGrowthRateLibrary : IEnumerable<IGrowthRate>
|
||||
/// Tries to get a growth rate from the library. Returns false if the growth rate is not found.
|
||||
/// </summary>
|
||||
bool TryGet(StringKey key, [MaybeNullWhen(false)] out IGrowthRate value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random growth rate from the library.
|
||||
/// </summary>
|
||||
IGrowthRate GetRandom(IRandom random);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of growth rates in the library.
|
||||
/// </summary>
|
||||
int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the library is empty.
|
||||
/// </summary>
|
||||
bool IsEmpty { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the experience for a given growth key name and a certain level.
|
||||
/// </summary>
|
||||
uint CalculateExperience(StringKey key, LevelInt level);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the level for a given growth key name and a certain experience.
|
||||
/// </summary>
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace PkmnLib.Static.Libraries;
|
||||
/// <summary>
|
||||
/// The library for all items in the game.
|
||||
/// </summary>
|
||||
public interface IReadOnlyItemLibrary : IEnumerable<IItem>
|
||||
public interface IReadOnlyItemLibrary : IEnumerable<IItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to get an item from the library. Returns false if the item is not found.
|
||||
|
||||
@@ -9,7 +9,7 @@ public record LibrarySettings
|
||||
/// The maximum level a Pokémon can reach.
|
||||
/// </summary>
|
||||
public required LevelInt MaxLevel { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The chance of a Pokémon being shiny, as the denominator of a fraction, where the nominator
|
||||
/// is 1. For example, if this is 1000, then the chance of a Pokémon being shiny is 1/1000.
|
||||
|
||||
@@ -13,14 +13,17 @@ public interface IReadOnlyMoveLibrary : IEnumerable<IMoveData>
|
||||
/// Tries to get a move from the library. Returns false if the move is not found.
|
||||
/// </summary>
|
||||
bool TryGet(StringKey key, [MaybeNullWhen(false)] out IMoveData value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random move from the library.
|
||||
/// </summary>
|
||||
IMoveData GetRandom(IRandom random);
|
||||
|
||||
/// <summary>
|
||||
/// The amount of moves in the library.
|
||||
/// </summary>
|
||||
int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the library is empty.
|
||||
/// </summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ public interface IReadOnlySpeciesLibrary : IEnumerable<ISpecies>
|
||||
/// Tries to get a species from the library. Returns false if the species is not found.
|
||||
/// </summary>
|
||||
bool TryGet(StringKey key, [MaybeNullWhen(false)] out ISpecies value);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tried to get a species from the library by its national dex number. Returns false if the species is not found.
|
||||
/// </summary>
|
||||
@@ -45,7 +45,7 @@ public interface IReadOnlySpeciesLibrary : IEnumerable<ISpecies>
|
||||
public class SpeciesLibrary : DataLibrary<ISpecies>, IReadOnlySpeciesLibrary
|
||||
{
|
||||
private Dictionary<ISpecies, ISpecies> _preEvolutionCache = new();
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetById(int id, [MaybeNullWhen(false)] out ISpecies value)
|
||||
{
|
||||
@@ -61,7 +61,7 @@ public class SpeciesLibrary : DataLibrary<ISpecies>, IReadOnlySpeciesLibrary
|
||||
return preEvolution;
|
||||
foreach (var s in this)
|
||||
{
|
||||
if (s.EvolutionData.All(e => e.ToSpecies != species.Name))
|
||||
if (s.EvolutionData.All(e => e.ToSpecies != species.Name))
|
||||
continue;
|
||||
_preEvolutionCache[species] = s;
|
||||
return s;
|
||||
|
||||
@@ -9,32 +9,37 @@ public interface IStaticLibrary
|
||||
/// The miscellaneous settings for the library.
|
||||
/// </summary>
|
||||
LibrarySettings Settings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon species.
|
||||
/// </summary>
|
||||
IReadOnlySpeciesLibrary Species { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon moves.
|
||||
/// </summary>
|
||||
IReadOnlyMoveLibrary Moves { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon abilities.
|
||||
/// </summary>
|
||||
IReadOnlyAbilityLibrary Abilities { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon types and their effectiveness.
|
||||
/// </summary>
|
||||
IReadOnlyTypeLibrary Types { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon natures.
|
||||
/// </summary>
|
||||
IReadOnlyNatureLibrary Natures { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon growth rates.
|
||||
/// </summary>
|
||||
IReadOnlyGrowthRateLibrary GrowthRates { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokémon items.
|
||||
/// </summary>
|
||||
@@ -45,7 +50,9 @@ public interface IStaticLibrary
|
||||
public class StaticLibraryImpl : IStaticLibrary
|
||||
{
|
||||
/// <inheritdoc cref="StaticLibraryImpl" />
|
||||
public StaticLibraryImpl(LibrarySettings settings, IReadOnlySpeciesLibrary species, IReadOnlyMoveLibrary moves, IReadOnlyAbilityLibrary abilities, IReadOnlyTypeLibrary types, IReadOnlyNatureLibrary natures, IReadOnlyGrowthRateLibrary growthRates, IReadOnlyItemLibrary items)
|
||||
public StaticLibraryImpl(LibrarySettings settings, IReadOnlySpeciesLibrary species, IReadOnlyMoveLibrary moves,
|
||||
IReadOnlyAbilityLibrary abilities, IReadOnlyTypeLibrary types, IReadOnlyNatureLibrary natures,
|
||||
IReadOnlyGrowthRateLibrary growthRates, IReadOnlyItemLibrary items)
|
||||
{
|
||||
Settings = settings;
|
||||
Species = species;
|
||||
|
||||
@@ -88,7 +88,7 @@ public class TypeLibrary : IReadOnlyTypeLibrary
|
||||
/// </summary>
|
||||
public TypeIdentifier RegisterType(StringKey name)
|
||||
{
|
||||
var id = new TypeIdentifier((byte)( _types.Count + 1));
|
||||
var id = new TypeIdentifier((byte)(_types.Count + 1));
|
||||
_types.Add(name, id);
|
||||
_effectiveness.Add(Enumerable.Repeat(1.0f, _effectiveness.Count).ToList());
|
||||
foreach (var list in _effectiveness)
|
||||
|
||||
@@ -11,12 +11,12 @@ public interface ISecondaryEffect
|
||||
/// The chance in percentages that the effect triggers. When less than 0, the effect is always active.
|
||||
/// </summary>
|
||||
public float Chance { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of the effect.
|
||||
/// </summary>
|
||||
public StringKey Name { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for the effect.
|
||||
/// </summary>
|
||||
|
||||
@@ -50,8 +50,7 @@ public class Nature(
|
||||
Statistic increaseStat,
|
||||
Statistic decreaseStat,
|
||||
float increaseModifier,
|
||||
float decreaseModifier)
|
||||
: INature
|
||||
float decreaseModifier) : INature
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public StringKey Name { get; } = name;
|
||||
@@ -79,8 +78,6 @@ public class Nature(
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(INature? other)
|
||||
{
|
||||
return other is not null && StringComparer.InvariantCultureIgnoreCase.Equals(Name, other.Name);
|
||||
}
|
||||
public bool Equals(INature? other) =>
|
||||
other is not null && StringComparer.InvariantCultureIgnoreCase.Equals(Name, other.Name);
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public interface IAbility : INamedValue
|
||||
/// The parameters for the script effect of the ability.
|
||||
/// </summary>
|
||||
IReadOnlyDictionary<StringKey, object?> Parameters { get; }
|
||||
|
||||
|
||||
bool HasFlag(StringKey key);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ public interface IAbility : INamedValue
|
||||
public class AbilityImpl : IAbility
|
||||
{
|
||||
/// <inheritdoc cref="AbilityImpl" />
|
||||
public AbilityImpl(StringKey name, StringKey? effect, IReadOnlyDictionary<StringKey, object?> parameters, ImmutableHashSet<StringKey> flags)
|
||||
public AbilityImpl(StringKey name, StringKey? effect, IReadOnlyDictionary<StringKey, object?> parameters,
|
||||
ImmutableHashSet<StringKey> flags)
|
||||
{
|
||||
Name = name;
|
||||
Effect = effect;
|
||||
@@ -46,10 +47,7 @@ public class AbilityImpl : IAbility
|
||||
public ImmutableHashSet<StringKey> Flags;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasFlag(StringKey key)
|
||||
{
|
||||
return Flags.Contains(key);
|
||||
}
|
||||
public bool HasFlag(StringKey key) => Flags.Contains(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -95,8 +95,8 @@ public interface IForm : INamedValue
|
||||
public class FormImpl : IForm
|
||||
{
|
||||
/// <inheritdoc cref="FormImpl" />
|
||||
public FormImpl(StringKey name, float height, float weight, uint baseExperience,
|
||||
IEnumerable<TypeIdentifier> types, ImmutableStatisticSet<ushort> baseStats, IEnumerable<StringKey> abilities,
|
||||
public FormImpl(StringKey name, float height, float weight, uint baseExperience, IEnumerable<TypeIdentifier> types,
|
||||
ImmutableStatisticSet<ushort> baseStats, IEnumerable<StringKey> abilities,
|
||||
IEnumerable<StringKey> hiddenAbilities, ILearnableMoves moves, ImmutableHashSet<StringKey> flags)
|
||||
{
|
||||
Name = name;
|
||||
@@ -109,7 +109,7 @@ public class FormImpl : IForm
|
||||
HiddenAbilities = [..hiddenAbilities];
|
||||
Moves = moves;
|
||||
Flags = flags;
|
||||
|
||||
|
||||
if (Types.Count == 0)
|
||||
throw new ArgumentException("A form must have at least one type.");
|
||||
if (Abilities.Count == 0)
|
||||
@@ -163,20 +163,24 @@ public class FormImpl : IForm
|
||||
for (var i = 0; i < Abilities.Count && i < 255; i++)
|
||||
{
|
||||
if (Abilities[i] == ability.Name)
|
||||
{
|
||||
return new AbilityIndex
|
||||
{
|
||||
IsHidden = false,
|
||||
Index = (byte)i,
|
||||
};
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < HiddenAbilities.Count && i < 255; i++)
|
||||
{
|
||||
if (HiddenAbilities[i] == ability.Name)
|
||||
{
|
||||
return new AbilityIndex
|
||||
{
|
||||
IsHidden = true,
|
||||
Index = (byte)i,
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -191,20 +195,11 @@ public class FormImpl : IForm
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringKey GetRandomAbility(IRandom rand)
|
||||
{
|
||||
return Abilities[rand.GetInt(Abilities.Count)];
|
||||
}
|
||||
public StringKey GetRandomAbility(IRandom rand) => Abilities[rand.GetInt(Abilities.Count)];
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringKey GetRandomHiddenAbility(IRandom rand)
|
||||
{
|
||||
return HiddenAbilities[rand.GetInt(HiddenAbilities.Count)];
|
||||
}
|
||||
public StringKey GetRandomHiddenAbility(IRandom rand) => HiddenAbilities[rand.GetInt(HiddenAbilities.Count)];
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasFlag(string key)
|
||||
{
|
||||
return Flags.Contains(key);
|
||||
}
|
||||
public bool HasFlag(string key) => Flags.Contains(key);
|
||||
}
|
||||
@@ -10,10 +10,12 @@ public enum Gender : byte
|
||||
{
|
||||
/// The Pokémon has no gender.
|
||||
Genderless,
|
||||
|
||||
/// <summary>
|
||||
/// The Pokémon is male.
|
||||
/// </summary>
|
||||
Male,
|
||||
|
||||
/// <summary>
|
||||
/// The Pokémon is female.
|
||||
/// </summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ public interface ILearnableMoves
|
||||
/// <param name="move">The move the Pokémon learns.</param>
|
||||
/// <returns>Whether the move was added successfully.</returns>
|
||||
void AddLevelMove(LevelInt level, StringKey move);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new egg move the Pokémon can learn.
|
||||
/// </summary>
|
||||
@@ -38,7 +38,7 @@ public interface ILearnableMoves
|
||||
/// Gets a list of all moves a Pokémon can learn up to a specific level.
|
||||
/// </summary>
|
||||
IReadOnlyList<StringKey> GetLearnableMovesUpToLevel(LevelInt level);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets all moves a Pokémon can learn by breeding.
|
||||
/// </summary>
|
||||
@@ -50,9 +50,8 @@ public class LearnableMovesImpl : ILearnableMoves
|
||||
{
|
||||
private readonly Dictionary<LevelInt, List<StringKey>> _learnedByLevel = new();
|
||||
private readonly HashSet<StringKey> _distinctLevelMoves = new();
|
||||
|
||||
private readonly List<StringKey> _eggMoves = new();
|
||||
|
||||
private readonly List<StringKey> _eggMoves = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddLevelMove(LevelInt level, StringKey move)
|
||||
@@ -81,10 +80,7 @@ public class LearnableMovesImpl : ILearnableMoves
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<StringKey> GetDistinctLevelMoves()
|
||||
{
|
||||
return _distinctLevelMoves.ToList();
|
||||
}
|
||||
public IReadOnlyList<StringKey> GetDistinctLevelMoves() => _distinctLevelMoves.ToList();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<StringKey> GetLearnableMovesUpToLevel(LevelInt level)
|
||||
|
||||
@@ -50,7 +50,7 @@ public interface ISpecies : INamedValue
|
||||
/// Gets a form by name.
|
||||
/// </summary>
|
||||
bool TryGetForm(StringKey id, [MaybeNullWhen(false)] out IForm form);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the form the Pokémon will have by default, if no other form is specified.
|
||||
/// </summary>
|
||||
@@ -70,7 +70,7 @@ public interface ISpecies : INamedValue
|
||||
/// The data regarding into which Pokémon this species can evolve, and how.
|
||||
/// </summary>
|
||||
IReadOnlyList<IEvolution> EvolutionData { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The egg groups the Pokémon belongs to.
|
||||
/// </summary>
|
||||
@@ -124,14 +124,13 @@ public class SpeciesImpl : ISpecies
|
||||
|
||||
/// <inheritdoc />
|
||||
public ImmutableHashSet<StringKey> Flags { get; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IEvolution> EvolutionData { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICollection<StringKey> EggGroups { get; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetForm(StringKey id, [MaybeNullWhen(false)] out IForm form) => Forms.TryGetValue(id, out form);
|
||||
|
||||
|
||||
@@ -9,33 +9,38 @@ public enum Statistic : byte
|
||||
/// Health Points determine how much damage a Pokémon can receive before fainting.
|
||||
/// </summary>
|
||||
Hp,
|
||||
|
||||
/// <summary>
|
||||
/// Attack determines how much damage a Pokémon deals when using a physical attack.
|
||||
/// </summary>
|
||||
Attack,
|
||||
|
||||
/// <summary>
|
||||
/// Defense determines how much damage a Pokémon receives when it is hit by a physical attack.
|
||||
/// </summary>
|
||||
Defense,
|
||||
|
||||
/// <summary>
|
||||
/// Special Attack determines how much damage a Pokémon deals when using a special attack.
|
||||
/// </summary>
|
||||
SpecialAttack,
|
||||
|
||||
/// <summary>
|
||||
/// Special Defense determines how much damage a Pokémon receives when it is hit by a special attack.
|
||||
/// </summary>
|
||||
SpecialDefense,
|
||||
|
||||
/// <summary>
|
||||
/// Speed determines the order that a Pokémon can act in battle.
|
||||
/// </summary>
|
||||
Speed,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Evasion determines the likelihood that a Pokémon will dodge an attack.
|
||||
/// This is not part of base stats, but is a temporary stat boost.
|
||||
/// </summary>
|
||||
Evasion,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Accuracy determines the likelihood that a Pokémon will hit an attack.
|
||||
/// This is not part of base stats, but is a temporary stat boost.
|
||||
|
||||
@@ -8,8 +8,7 @@ namespace PkmnLib.Static;
|
||||
/// A set of statistics that cannot be changed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The size of the integer to be used</typeparam>
|
||||
public record ImmutableStatisticSet<T>
|
||||
where T : struct
|
||||
public record ImmutableStatisticSet<T> where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The health points stat value.
|
||||
@@ -51,7 +50,7 @@ public record ImmutableStatisticSet<T>
|
||||
SpecialDefense = specialDefense;
|
||||
Speed = speed;
|
||||
}
|
||||
|
||||
|
||||
public ImmutableStatisticSet(ImmutableStatisticSet<T> set)
|
||||
{
|
||||
Hp = set.Hp;
|
||||
@@ -84,8 +83,7 @@ public record ImmutableStatisticSet<T>
|
||||
/// A set of statistics that can be changed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepCloneable
|
||||
where T : struct
|
||||
public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepCloneable where T : struct
|
||||
{
|
||||
/// <inheritdoc cref="StatisticSet{T}"/>
|
||||
public StatisticSet() : base(default, default, default, default, default, default)
|
||||
@@ -97,7 +95,7 @@ public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepC
|
||||
defense, specialAttack, specialDefense, speed)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public StatisticSet(StatisticSet<T> set) : base(set)
|
||||
{
|
||||
}
|
||||
@@ -175,16 +173,12 @@ public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepC
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual T GetUnknownStat(Statistic stat)
|
||||
{
|
||||
throw new ArgumentException($"Invalid statistic {stat}");
|
||||
}
|
||||
|
||||
protected virtual T GetUnknownStat(Statistic stat) => throw new ArgumentException($"Invalid statistic {stat}");
|
||||
|
||||
protected virtual void SetUnknownStat(Statistic stat, T value)
|
||||
{
|
||||
throw new ArgumentException($"Invalid statistic {stat}");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Decreases a statistic in the set by a value.
|
||||
@@ -231,17 +225,13 @@ public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepC
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A set of statistics that can be changed, but are clamped to a minimum and maximum value.
|
||||
/// </summary>
|
||||
public abstract record ClampedStatisticSet<T> : StatisticSet<T>
|
||||
where T : struct, IComparable<T>
|
||||
public abstract record ClampedStatisticSet<T> : StatisticSet<T> where T : struct, IComparable<T>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
|
||||
@@ -257,7 +247,7 @@ public abstract record ClampedStatisticSet<T> : StatisticSet<T>
|
||||
SpecialDefense = Clamp(SpecialDefense, Min, Max);
|
||||
Speed = Clamp(Speed, Min, Max);
|
||||
}
|
||||
|
||||
|
||||
protected ClampedStatisticSet(ClampedStatisticSet<T> set) : base(set)
|
||||
{
|
||||
}
|
||||
@@ -322,13 +312,15 @@ public record StatBoostStatisticSet : ClampedStatisticSet<sbyte>
|
||||
protected override sbyte Max => 6;
|
||||
|
||||
private sbyte _evasion;
|
||||
|
||||
public sbyte Evasion
|
||||
{
|
||||
get => _evasion;
|
||||
set => _evasion = Clamp(value, Min, Max);
|
||||
}
|
||||
|
||||
|
||||
private sbyte _accuracy;
|
||||
|
||||
public sbyte Accuracy
|
||||
{
|
||||
get => _accuracy;
|
||||
@@ -403,13 +395,13 @@ public record IndividualValueStatisticSet : ClampedStatisticSet<byte>
|
||||
public IndividualValueStatisticSet() : base(0, 0, 0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc cref="IndividualValueStatisticSet"/>
|
||||
public IndividualValueStatisticSet(byte hp, byte attack, byte defense, byte specialAttack, byte specialDefense,
|
||||
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public IndividualValueStatisticSet(IndividualValueStatisticSet ivs) : base(ivs)
|
||||
{
|
||||
}
|
||||
@@ -436,7 +428,7 @@ public record EffortValueStatisticSet : ClampedStatisticSet<byte>
|
||||
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public EffortValueStatisticSet(EffortValueStatisticSet evs) : base(evs)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,11 +25,9 @@ public static class DeepCloneHandler
|
||||
/// Recursive references will be handled correctly, and will only be cloned once, to prevent infinite loops and invalid
|
||||
/// references.
|
||||
/// </summary>
|
||||
public static T DeepClone<T>(this T? obj, Dictionary<(Type, int), object>? objects = null) where T : IDeepCloneable
|
||||
{
|
||||
return (T)DeepClone((object?)obj, objects)!;
|
||||
}
|
||||
|
||||
public static T DeepClone<T>(this T? obj, Dictionary<(Type, int), object>? objects = null)
|
||||
where T : IDeepCloneable => (T)DeepClone((object?)obj, objects)!;
|
||||
|
||||
private static object? DeepClone(this object? obj, Dictionary<(Type, int), object>? objects = null)
|
||||
{
|
||||
if (obj == null)
|
||||
@@ -41,7 +39,7 @@ public static class DeepCloneHandler
|
||||
// We use GetUninitializedObject to create an object without calling the constructor. This is necessary to prevent
|
||||
// side effects from the constructor, and to not require a parameterless constructor.
|
||||
var newObj = FormatterServices.GetUninitializedObject(type)!;
|
||||
|
||||
|
||||
// If the objects dictionary is null, we create a new one. We use this dictionary to keep track of objects that have
|
||||
// already been cloned, so we can re-use them instead of cloning them again. This is necessary to prevent infinite
|
||||
// loops and invalid references.
|
||||
@@ -74,7 +72,7 @@ public static class DeepCloneHandler
|
||||
// If the object is a value type or a string, we can just return it.
|
||||
if (type.IsValueType || type == typeof(string))
|
||||
return obj;
|
||||
|
||||
|
||||
// If the object is marked as deep cloneable, we will clone it.
|
||||
if (type.GetInterface(nameof(IDeepCloneable)) != null || ExternalDeepCloneTypes.Contains(type))
|
||||
{
|
||||
@@ -91,8 +89,9 @@ public static class DeepCloneHandler
|
||||
var array = (Array)obj;
|
||||
var newArray = Array.CreateInstance(type.GetElementType()!, array.Length);
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
newArray.SetValue(DeepCloneInternal(array.GetValue(i), type.GetElementType()!, objects),
|
||||
i);
|
||||
{
|
||||
newArray.SetValue(DeepCloneInternal(array.GetValue(i), type.GetElementType()!, objects), i);
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
@@ -115,9 +114,10 @@ public static class DeepCloneHandler
|
||||
var dictionary = (IDictionary)obj;
|
||||
var newDictionary = (IDictionary)Activator.CreateInstance(type);
|
||||
foreach (DictionaryEntry entry in dictionary)
|
||||
newDictionary.Add(
|
||||
DeepCloneInternal(entry.Key, type.GetGenericArguments()[0], objects)!,
|
||||
{
|
||||
newDictionary.Add(DeepCloneInternal(entry.Key, type.GetGenericArguments()[0], objects)!,
|
||||
DeepCloneInternal(entry.Value, type.GetGenericArguments()[1], objects));
|
||||
}
|
||||
return newDictionary;
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,7 @@ public static class DeepCloneHandler
|
||||
/// This method is thread safe, and will only create the expressions once for each type. It returns compiled expressions for
|
||||
/// each field in the type, so that we can get high performance deep cloning.
|
||||
/// </remarks>
|
||||
private static (Func<object, object?> getter, Action<object, object?> setter)[]
|
||||
GetDeepCloneExpressions(Type type)
|
||||
private static (Func<object, object?> getter, Action<object, object?> setter)[] GetDeepCloneExpressions(Type type)
|
||||
{
|
||||
// We use a lock here to prevent multiple threads from trying to create the expressions at the same time.
|
||||
lock (DeepCloneExpressions)
|
||||
|
||||
@@ -2,7 +2,8 @@ namespace PkmnLib.Static.Utils;
|
||||
|
||||
public static class DictionaryHelpers
|
||||
{
|
||||
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
|
||||
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key,
|
||||
TValue defaultValue)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var value))
|
||||
return value;
|
||||
|
||||
@@ -10,7 +10,7 @@ public static class EnumerableHelpers
|
||||
/// </summary>
|
||||
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable) where T : class =>
|
||||
enumerable.Where(x => x is not null)!;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds the index of a value in an enumerable. Returns -1 if the value is not found.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
namespace PkmnLib.Static.Utils.Errors;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ public static class NumericHelpers
|
||||
var result = value * multiplier;
|
||||
return result > byte.MaxValue ? byte.MaxValue : (byte)result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two values. If this overflows, returns <see cref="byte.MaxValue"/>.
|
||||
/// </summary>
|
||||
@@ -22,7 +22,7 @@ public static class NumericHelpers
|
||||
var result = value * multiplier;
|
||||
return result > byte.MaxValue ? byte.MaxValue : (byte)result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two values. If this overflows, returns <see cref="sbyte.MaxValue"/>.
|
||||
/// </summary>
|
||||
@@ -31,7 +31,7 @@ public static class NumericHelpers
|
||||
var result = value * multiplier;
|
||||
return result > sbyte.MaxValue ? sbyte.MaxValue : (sbyte)result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two values. If this overflows, returns <see cref="ushort.MaxValue"/>.
|
||||
/// </summary>
|
||||
@@ -40,7 +40,7 @@ public static class NumericHelpers
|
||||
var result = value * multiplier;
|
||||
return result > ushort.MaxValue ? ushort.MaxValue : (ushort)result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two values. If this overflows, returns <see cref="short.MaxValue"/>.
|
||||
/// </summary>
|
||||
@@ -49,11 +49,10 @@ public static class NumericHelpers
|
||||
var result = value * multiplier;
|
||||
return result > short.MaxValue ? short.MaxValue : (short)result;
|
||||
}
|
||||
|
||||
|
||||
public static uint MultiplyOrMax(this uint value, uint multiplier)
|
||||
{
|
||||
var result = (ulong)value * multiplier;
|
||||
return result > uint.MaxValue ? uint.MaxValue : (uint)result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,19 +21,19 @@ public interface IRandom
|
||||
/// <param name="max">The maximum value (exclusive).</param>
|
||||
/// <returns>A random integer that is greater than or equal to 0 and less than max.</returns>
|
||||
public int GetInt(int max);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a random integer between 0 and <see cref="int.MaxValue"/>.
|
||||
/// </summary>
|
||||
/// <returns>A random integer that is greater than or equal to 0 and less than <see cref="int.MaxValue"/>.</returns>
|
||||
public int GetInt();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a random float that is greater than or equal to 0.0 and less than 1.0.
|
||||
/// </summary>
|
||||
/// <returns>A random float that is greater than or equal to 0.0 and less than 1.0.</returns>
|
||||
public float GetFloat();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a random float that is greater than or equal to min and less than max.
|
||||
/// </summary>
|
||||
@@ -41,7 +41,7 @@ public interface IRandom
|
||||
/// <param name="max">The maximum value (exclusive).</param>
|
||||
/// <returns>A random float that is greater than or equal to min and less than max.</returns>
|
||||
public float GetFloat(float min, float max);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a random boolean. 50% chance of being true.
|
||||
/// </summary>
|
||||
|
||||
@@ -22,14 +22,12 @@ public readonly record struct StringKey
|
||||
/// Converts a <see cref="StringKey"/> to a <see cref="string"/>.
|
||||
/// </summary>
|
||||
public static implicit operator string(StringKey key) => key._key;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="string"/> to a <see cref="StringKey"/>.
|
||||
/// </summary>
|
||||
public static implicit operator StringKey(string key)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(key) ? default : new StringKey(key);
|
||||
}
|
||||
public static implicit operator StringKey(string key) =>
|
||||
string.IsNullOrWhiteSpace(key) ? default : new StringKey(key);
|
||||
|
||||
/// <inheritdoc cref="string.ToString()"/>
|
||||
public override string ToString() => _key.ToLowerInvariant();
|
||||
|
||||
Reference in New Issue
Block a user