More move effects
This commit is contained in:
parent
9b0ac36597
commit
c0bc905c46
|
@ -4,6 +4,7 @@ using System.Collections.Immutable;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using PkmnLib.Dataloader.Models;
|
using PkmnLib.Dataloader.Models;
|
||||||
using PkmnLib.Static;
|
using PkmnLib.Static;
|
||||||
using PkmnLib.Static.Libraries;
|
using PkmnLib.Static.Libraries;
|
||||||
|
@ -26,12 +27,14 @@ public static class ItemDataLoader
|
||||||
return library;
|
return library;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once MemberCanBePrivate.Global
|
public delegate IItem ItemFactoryDelegate(SerializedItem serialized, StringKey name, ItemCategory type,
|
||||||
public static Func<SerializedItem, StringKey, ItemCategory, BattleItemCategory, int,
|
BattleItemCategory battleType, int price, ImmutableHashSet<StringKey> flags,
|
||||||
IEnumerable<StringKey>, ISecondaryEffect?, ISecondaryEffect?,
|
ISecondaryEffect? effect, ISecondaryEffect? battleTriggerEffect, byte flingPower);
|
||||||
// ReSharper disable once FieldCanBeMadeReadOnly.Global
|
|
||||||
IItem> ItemConstructor = (_, name, type, battleType, price, flags, effect, battleTriggerEffect) =>
|
[PublicAPI]
|
||||||
new ItemImpl(name, type, battleType, price, flags, effect, battleTriggerEffect);
|
public static ItemFactoryDelegate ItemConstructor { get; set; } = (_, name, type, battleType, price, flags, effect,
|
||||||
|
battleTriggerEffect, flingPower) =>
|
||||||
|
new ItemImpl(name, type, battleType, price, flags, effect, battleTriggerEffect, flingPower);
|
||||||
|
|
||||||
private static IItem DeserializeItem(SerializedItem serialized)
|
private static IItem DeserializeItem(SerializedItem serialized)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +45,7 @@ public static class ItemDataLoader
|
||||||
var battleTriggerEffect = serialized.BattleEffect?.ParseEffect();
|
var battleTriggerEffect = serialized.BattleEffect?.ParseEffect();
|
||||||
|
|
||||||
return ItemConstructor(serialized, serialized.Name, itemType, battleType, serialized.Price,
|
return ItemConstructor(serialized, serialized.Name, itemType, battleType, serialized.Price,
|
||||||
serialized.Flags.Select(x => (StringKey)x).ToImmutableHashSet(), effect, battleTriggerEffect);
|
serialized.Flags.Select(x => (StringKey)x).ToImmutableHashSet(), effect, battleTriggerEffect,
|
||||||
|
serialized.FlingPower);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,4 +14,10 @@
|
||||||
<ProjectReference Include="..\PkmnLib.Static\PkmnLib.Static.csproj" />
|
<ProjectReference Include="..\PkmnLib.Static\PkmnLib.Static.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="JetBrains.Annotations">
|
||||||
|
<HintPath>..\..\..\..\.nuget\packages\jetbrains.annotations\2024.2.0\lib\netstandard2.0\JetBrains.Annotations.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -241,6 +241,20 @@ public interface IPokemon : IScriptSource, IDeepCloneable
|
||||||
[MustUseReturnValue]
|
[MustUseReturnValue]
|
||||||
IItem? RemoveHeldItem();
|
IItem? RemoveHeldItem();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the held item from the Pokemon for the duration of the battle. Returns the previously held item.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is used for moves that remove a held item, but do not consume it. In this case, the item needs to be
|
||||||
|
/// restored after the battle.
|
||||||
|
/// </remarks>
|
||||||
|
IItem? RemoveHeldItemForBattle();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restores the held item of a Pokémon if it was temporarily removed.
|
||||||
|
/// </summary>
|
||||||
|
void RestoreStolenHeldItem();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes the Pokemon uses its held item. Returns whether the item was consumed.
|
/// Makes the Pokemon uses its held item. Returns whether the item was consumed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -717,6 +731,21 @@ public class PokemonImpl : ScriptSource, IPokemon
|
||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IItem? _stolenHeldItem;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IItem? RemoveHeldItemForBattle()
|
||||||
|
{
|
||||||
|
return _stolenHeldItem = RemoveHeldItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void RestoreStolenHeldItem()
|
||||||
|
{
|
||||||
|
_ = SetHeldItem(_stolenHeldItem);
|
||||||
|
_stolenHeldItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool ConsumeHeldItem()
|
public bool ConsumeHeldItem()
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper attribute to register scripts through reflection.
|
/// Helper attribute to register scripts through reflection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||||
[MeansImplicitUse]
|
[MeansImplicitUse]
|
||||||
public class ScriptAttribute : Attribute
|
public class ScriptAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
|
@ -554,4 +554,8 @@ public abstract class Script : IDeepCloneable
|
||||||
public virtual void ChangeIncomingDamage(IPokemon pokemon, DamageSource source, ref uint damage)
|
public virtual void ChangeIncomingDamage(IPokemon pokemon, DamageSource source, ref uint damage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref int modifiedAccuracy)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -109,6 +109,8 @@ public interface IItem : INamedValue
|
||||||
ISecondaryEffect? Effect { get; }
|
ISecondaryEffect? Effect { get; }
|
||||||
ISecondaryEffect? BattleEffect { get; }
|
ISecondaryEffect? BattleEffect { get; }
|
||||||
|
|
||||||
|
byte FlingPower { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks whether the item has a specific flag.
|
/// Checks whether the item has a specific flag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -122,7 +124,7 @@ public class ItemImpl : IItem
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="ItemImpl"/>
|
/// <inheritdoc cref="ItemImpl"/>
|
||||||
public ItemImpl(StringKey name, ItemCategory category, BattleItemCategory battleCategory, int price,
|
public ItemImpl(StringKey name, ItemCategory category, BattleItemCategory battleCategory, int price,
|
||||||
IEnumerable<StringKey> flags, ISecondaryEffect? effect, ISecondaryEffect? battleTriggerEffect)
|
IEnumerable<StringKey> flags, ISecondaryEffect? effect, ISecondaryEffect? battleTriggerEffect, byte flingPower)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Category = category;
|
Category = category;
|
||||||
|
@ -130,6 +132,7 @@ public class ItemImpl : IItem
|
||||||
Price = price;
|
Price = price;
|
||||||
Effect = effect;
|
Effect = effect;
|
||||||
BattleEffect = battleTriggerEffect;
|
BattleEffect = battleTriggerEffect;
|
||||||
|
FlingPower = flingPower;
|
||||||
Flags = [..flags];
|
Flags = [..flags];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +157,10 @@ public class ItemImpl : IItem
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ISecondaryEffect? BattleEffect { get; }
|
public ISecondaryEffect? BattleEffect { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public byte FlingPower { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool HasFlag(string key)
|
public bool HasFlag(string key)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ public interface IReadOnlyTypeLibrary
|
||||||
/// Gets the effectiveness for a single attacking type against an amount of defending types.
|
/// Gets the effectiveness for a single attacking type against an amount of defending types.
|
||||||
/// This is equivalent to running get_single_effectiveness on each defending type, and multiplying the results with each other.
|
/// This is equivalent to running get_single_effectiveness on each defending type, and multiplying the results with each other.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
float GetEffectiveness(TypeIdentifier attacking, IReadOnlyList<TypeIdentifier> defending);
|
float GetEffectiveness(TypeIdentifier attacking, IEnumerable<TypeIdentifier> defending);
|
||||||
|
|
||||||
IEnumerable<(TypeIdentifier type, float effectiveness)> GetAllEffectivenessFromAttacking(TypeIdentifier attacking);
|
IEnumerable<(TypeIdentifier type, float effectiveness)> GetAllEffectivenessFromAttacking(TypeIdentifier attacking);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ public class TypeLibrary : IReadOnlyTypeLibrary
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public float GetEffectiveness(TypeIdentifier attacking, IReadOnlyList<TypeIdentifier> defending) =>
|
public float GetEffectiveness(TypeIdentifier attacking, IEnumerable<TypeIdentifier> defending) =>
|
||||||
defending.Aggregate<TypeIdentifier, float>(1,
|
defending.Aggregate<TypeIdentifier, float>(1,
|
||||||
(current, type) => current * GetSingleEffectiveness(attacking, type));
|
(current, type) => current * GetSingleEffectiveness(attacking, type));
|
||||||
|
|
||||||
|
|
|
@ -3614,7 +3614,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Done up to here
|
|
||||||
{
|
{
|
||||||
"name": "fire_spin",
|
"name": "fire_spin",
|
||||||
"type": "fire",
|
"type": "fire",
|
||||||
|
@ -3627,7 +3626,10 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "fire_spin"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "first_impression",
|
"name": "first_impression",
|
||||||
|
@ -3642,7 +3644,10 @@
|
||||||
"contact",
|
"contact",
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "first_impression"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fissure",
|
"name": "fissure",
|
||||||
|
@ -3657,7 +3662,10 @@
|
||||||
"protect",
|
"protect",
|
||||||
"mirror",
|
"mirror",
|
||||||
"nonskybattle"
|
"nonskybattle"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "one_hit_ko"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flail",
|
"name": "flail",
|
||||||
|
@ -3672,7 +3680,10 @@
|
||||||
"contact",
|
"contact",
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "flail"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flame_burst",
|
"name": "flame_burst",
|
||||||
|
@ -3686,7 +3697,10 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "flame_burst"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flame_charge",
|
"name": "flame_charge",
|
||||||
|
@ -3701,7 +3715,13 @@
|
||||||
"contact",
|
"contact",
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "change_user_speed",
|
||||||
|
"parameters": {
|
||||||
|
"amount": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flame_wheel",
|
"name": "flame_wheel",
|
||||||
|
@ -3717,7 +3737,14 @@
|
||||||
"protect",
|
"protect",
|
||||||
"mirror",
|
"mirror",
|
||||||
"defrost"
|
"defrost"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "set_status",
|
||||||
|
"chance": 10,
|
||||||
|
"parameters": {
|
||||||
|
"status": "burned"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flamethrower",
|
"name": "flamethrower",
|
||||||
|
@ -3731,7 +3758,14 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "set_status",
|
||||||
|
"chance": 10,
|
||||||
|
"parameters": {
|
||||||
|
"status": "burned"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flare_blitz",
|
"name": "flare_blitz",
|
||||||
|
@ -3747,7 +3781,10 @@
|
||||||
"protect",
|
"protect",
|
||||||
"mirror",
|
"mirror",
|
||||||
"defrost"
|
"defrost"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "flare_blitz"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flash",
|
"name": "flash",
|
||||||
|
@ -3762,7 +3799,13 @@
|
||||||
"protect",
|
"protect",
|
||||||
"reflectable",
|
"reflectable",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "change_target_accuracy",
|
||||||
|
"parameters": {
|
||||||
|
"amount": -1
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flash_cannon",
|
"name": "flash_cannon",
|
||||||
|
@ -3776,7 +3819,14 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "change_target_special_defense",
|
||||||
|
"chance": 10,
|
||||||
|
"parameters": {
|
||||||
|
"amount": -1
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flatter",
|
"name": "flatter",
|
||||||
|
@ -3791,7 +3841,10 @@
|
||||||
"protect",
|
"protect",
|
||||||
"reflectable",
|
"reflectable",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "flatter"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fleur_cannon",
|
"name": "fleur_cannon",
|
||||||
|
@ -3805,7 +3858,13 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "change_user_special_attack",
|
||||||
|
"parameters": {
|
||||||
|
"amount": -2
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fling",
|
"name": "fling",
|
||||||
|
@ -3819,7 +3878,10 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "fling"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "floral_healing",
|
"name": "floral_healing",
|
||||||
|
@ -3834,7 +3896,10 @@
|
||||||
"protect",
|
"protect",
|
||||||
"reflectable",
|
"reflectable",
|
||||||
"heal"
|
"heal"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "floral_healing"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flower_shield",
|
"name": "flower_shield",
|
||||||
|
@ -3847,7 +3912,10 @@
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": [
|
"flags": [
|
||||||
"distance"
|
"distance"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "flower_shield"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fly",
|
"name": "fly",
|
||||||
|
@ -3865,7 +3933,10 @@
|
||||||
"mirror",
|
"mirror",
|
||||||
"gravity",
|
"gravity",
|
||||||
"distance"
|
"distance"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "fly"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "flying_press",
|
"name": "flying_press",
|
||||||
|
@ -3883,7 +3954,10 @@
|
||||||
"gravity",
|
"gravity",
|
||||||
"distance",
|
"distance",
|
||||||
"nonskybattle"
|
"nonskybattle"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "flying_press"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "focus_blast",
|
"name": "focus_blast",
|
||||||
|
@ -3898,7 +3972,14 @@
|
||||||
"protect",
|
"protect",
|
||||||
"mirror",
|
"mirror",
|
||||||
"ballistics"
|
"ballistics"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "change_target_special_defense",
|
||||||
|
"chance": 10,
|
||||||
|
"parameters": {
|
||||||
|
"amount": -1
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "focus_energy",
|
"name": "focus_energy",
|
||||||
|
@ -3911,7 +3992,10 @@
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": [
|
"flags": [
|
||||||
"snatch"
|
"snatch"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "focus_energy"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "focus_punch",
|
"name": "focus_punch",
|
||||||
|
@ -3926,7 +4010,10 @@
|
||||||
"contact",
|
"contact",
|
||||||
"protect",
|
"protect",
|
||||||
"punch"
|
"punch"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "focus_punch"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "follow_me",
|
"name": "follow_me",
|
||||||
|
@ -3937,7 +4024,10 @@
|
||||||
"priority": 2,
|
"priority": 2,
|
||||||
"target": "Self",
|
"target": "Self",
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": []
|
"flags": [],
|
||||||
|
"effect": {
|
||||||
|
"name": "follow_me"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "force_palm",
|
"name": "force_palm",
|
||||||
|
@ -3952,7 +4042,14 @@
|
||||||
"contact",
|
"contact",
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "set_status",
|
||||||
|
"chance": 30,
|
||||||
|
"parameters": {
|
||||||
|
"status": "paralyzed"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "foresight",
|
"name": "foresight",
|
||||||
|
@ -3968,7 +4065,10 @@
|
||||||
"reflectable",
|
"reflectable",
|
||||||
"mirror",
|
"mirror",
|
||||||
"ignore-substitute"
|
"ignore-substitute"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "foresight"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "forests_curse",
|
"name": "forests_curse",
|
||||||
|
@ -3983,7 +4083,10 @@
|
||||||
"protect",
|
"protect",
|
||||||
"reflectable",
|
"reflectable",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "forests_curse"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "foul_play",
|
"name": "foul_play",
|
||||||
|
@ -3998,7 +4101,10 @@
|
||||||
"contact",
|
"contact",
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "foul_play"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "freeze_dry",
|
"name": "freeze_dry",
|
||||||
|
@ -4012,7 +4118,10 @@
|
||||||
"flags": [
|
"flags": [
|
||||||
"protect",
|
"protect",
|
||||||
"mirror"
|
"mirror"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "freeze_dry"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "freeze_shock",
|
"name": "freeze_shock",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class Gen7BattleStatCalculator : IBattleStatCalculator
|
||||||
var accuracyModifier = 1.0f;
|
var accuracyModifier = 1.0f;
|
||||||
executingMove.RunScriptHook(x => x.ChangeAccuracyModifier(executingMove, target, hitIndex, ref accuracyModifier));
|
executingMove.RunScriptHook(x => x.ChangeAccuracyModifier(executingMove, target, hitIndex, ref accuracyModifier));
|
||||||
var modifiedAccuracy = (int)(moveAccuracy * accuracyModifier);
|
var modifiedAccuracy = (int)(moveAccuracy * accuracyModifier);
|
||||||
|
executingMove.RunScriptHook(x => x.ChangeAccuracy(executingMove, target, hitIndex, ref modifiedAccuracy));
|
||||||
var targetEvasion = target.StatBoost.Evasion;
|
var targetEvasion = target.StatBoost.Evasion;
|
||||||
var ignoreEvasion = false;
|
var ignoreEvasion = false;
|
||||||
executingMove.RunScriptHook(x => x.BypassEvasionStatBoosts(executingMove, target, hitIndex, ref ignoreEvasion));
|
executingMove.RunScriptHook(x => x.BypassEvasionStatBoosts(executingMove, target, hitIndex, ref ignoreEvasion));
|
||||||
|
|
|
@ -7,7 +7,7 @@ public class Bestow : Script
|
||||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
{
|
{
|
||||||
var user = move.User;
|
var user = move.User;
|
||||||
var userHeldItem = user.HeldItem;
|
var userHeldItem = user.RemoveHeldItemForBattle();
|
||||||
var targetHeldItem = target.HeldItem;
|
var targetHeldItem = target.HeldItem;
|
||||||
|
|
||||||
if (userHeldItem == null || targetHeldItem != null)
|
if (userHeldItem == null || targetHeldItem != null)
|
||||||
|
|
|
@ -20,6 +20,12 @@ public class Bounce : Script
|
||||||
prevent = true;
|
prevent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnBeforeMove(IExecutingMove move)
|
||||||
|
{
|
||||||
|
move.User.Volatile.Remove(ScriptUtils.ResolveName<ChargeBounceEffect>());
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +37,5 @@ public class Bounce : Script
|
||||||
{
|
{
|
||||||
target.SetStatus("paralyzed");
|
target.SetStatus("paralyzed");
|
||||||
}
|
}
|
||||||
move.User.Volatile.Remove(ScriptUtils.ResolveName<ChargeBounceEffect>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -77,3 +77,11 @@ public class ChangeTargetSpeed : ChangeTargetStats
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "change_target_accuracy")]
|
||||||
|
public class ChangeTargetAccuracy : ChangeTargetStats
|
||||||
|
{
|
||||||
|
public ChangeTargetAccuracy() : base(Statistic.Accuracy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,6 @@ public class Covet : Script
|
||||||
return;
|
return;
|
||||||
if (move.User.HeldItem != null)
|
if (move.User.HeldItem != null)
|
||||||
return;
|
return;
|
||||||
_ = move.User.SetHeldItem(target.RemoveHeldItem());
|
_ = move.User.SetHeldItem(target.RemoveHeldItemForBattle());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,9 +21,8 @@ public class Dig : Script
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
public override void OnBeforeMove(IExecutingMove move)
|
||||||
{
|
{
|
||||||
move.User.Volatile.Remove(ScriptUtils.ResolveName<DigEffect>());
|
move.User.Volatile.Remove(ScriptUtils.ResolveName<DigEffect>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "fire_spin")]
|
||||||
|
public class FireSpin : MultiHitMove
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
target.Volatile.StackOrAdd("fire_spin", () => new FireSpinEffect(target));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "first_impression")]
|
||||||
|
public class FirstImpression : Script
|
||||||
|
{
|
||||||
|
public override void StopBeforeMove(IExecutingMove move, ref bool stop)
|
||||||
|
{
|
||||||
|
var battleData = move.User.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
if (battleData.SwitchInTurn != battleData.Battle.CurrentTurnNumber)
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "flail")]
|
||||||
|
public class Flail : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
|
||||||
|
{
|
||||||
|
var remainingHealth = move.User.CurrentHealth / move.User.BoostedStats.Hp;
|
||||||
|
var fraction = remainingHealth * 48;
|
||||||
|
basePower = fraction switch
|
||||||
|
{
|
||||||
|
< 2 => 200,
|
||||||
|
< 5 => 150,
|
||||||
|
< 10 => 100,
|
||||||
|
< 17 => 80,
|
||||||
|
< 33 => 40,
|
||||||
|
_ => 20
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "flame_burst")]
|
||||||
|
public class FlameBurst : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var adjacentFoes = GetAdjacentFoes(move.User).WhereNotNull();
|
||||||
|
EventBatchId batchId = new();
|
||||||
|
foreach (var adjacentFoe in adjacentFoes)
|
||||||
|
{
|
||||||
|
adjacentFoe.Damage(adjacentFoe.BoostedStats.Hp / 16, DamageSource.Misc, batchId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<IPokemon?> GetAdjacentFoes(IPokemon pokemon)
|
||||||
|
{
|
||||||
|
var battleData = pokemon.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
yield break;
|
||||||
|
if (battleData.Battle.PositionsPerSide == 1)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var position = battleData.Position;
|
||||||
|
var side = battleData.Battle.Sides[battleData.SideIndex];
|
||||||
|
|
||||||
|
if (position == 0)
|
||||||
|
{
|
||||||
|
yield return side.Pokemon[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yield return side.Pokemon[position - 1];
|
||||||
|
if (position < side.Pokemon.Count - 1)
|
||||||
|
yield return side.Pokemon[position + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "flare_blitz")]
|
||||||
|
public class FlareBlitz : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
|
||||||
|
{
|
||||||
|
target.SetStatus("burned");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var hitData = move.GetHitData(target, hit);
|
||||||
|
var recoilDamage = (uint)(hitData.Damage * (1 / 3));
|
||||||
|
move.User.Damage(recoilDamage, DamageSource.Misc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "flatter")]
|
||||||
|
public class Flatter : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
target.ChangeStatBoost(Statistic.SpecialAttack, 1, false);
|
||||||
|
target.Volatile.StackOrAdd("confusion", () => new Confusion());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "fling")]
|
||||||
|
public class Fling : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
|
||||||
|
{
|
||||||
|
var item = move.User.HeldItem;
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
move.GetHitData(target, hit).Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Category is ItemCategory.FormChanger or ItemCategory.Pokeball or ItemCategory.Mail
|
||||||
|
or ItemCategory.KeyItem or ItemCategory.TmHm)
|
||||||
|
{
|
||||||
|
move.GetHitData(target, hit).Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
basePower = item.FlingPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit) =>
|
||||||
|
move.User.RemoveHeldItemForBattle();
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Terrain;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "floral_healing")]
|
||||||
|
public class FloralHealing : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
if (target.IsFainted)
|
||||||
|
return;
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var modifier = 1f / 2;
|
||||||
|
if (battleData.Battle.TerrainName == ScriptUtils.ResolveName<GrassyTerrain>())
|
||||||
|
modifier = 2f / 3;
|
||||||
|
|
||||||
|
var healing = target.BoostedStats.Hp * modifier;
|
||||||
|
target.Heal((uint)healing);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Linq;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "flower_shield")]
|
||||||
|
public class FlowerShield : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
if (!battleData.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("grass", out var grassType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var batchId = new EventBatchId();
|
||||||
|
var sides = battleData.Battle.Sides;
|
||||||
|
foreach (var side in sides)
|
||||||
|
{
|
||||||
|
foreach (var pokemon in side.Pokemon)
|
||||||
|
{
|
||||||
|
if (pokemon == null || pokemon.IsFainted)
|
||||||
|
continue;
|
||||||
|
if (!pokemon.Types.Contains(grassType))
|
||||||
|
continue;
|
||||||
|
pokemon.ChangeStatBoost(Statistic.Defense, 1, pokemon == move.User, batchId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "fly")]
|
||||||
|
public class Fly : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PreventMove(IExecutingMove move, ref bool prevent)
|
||||||
|
{
|
||||||
|
if (move.User.Volatile.Contains<ChargeFlyEffect>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
move.User.Volatile.Add(new ChargeFlyEffect(move.User));
|
||||||
|
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("fly_charge", new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "user", move.User }
|
||||||
|
}));
|
||||||
|
prevent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnBeforeMove(IExecutingMove move)
|
||||||
|
{
|
||||||
|
move.User.Volatile.Remove(ScriptUtils.ResolveName<ChargeFlyEffect>());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "flying_press")]
|
||||||
|
public class FlyingPress : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
|
||||||
|
{
|
||||||
|
var battleData = move.User.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
|
||||||
|
// If flying type is not found, return
|
||||||
|
if (!typeLibrary.TryGetTypeIdentifier("flying", out var flyingType))
|
||||||
|
return;
|
||||||
|
var flyingEffectiveness = typeLibrary.GetEffectiveness(flyingType, target.Types);
|
||||||
|
effectiveness *= flyingEffectiveness;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "focus_energy")]
|
||||||
|
public class FocusEnergy : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
target.Volatile.Add(new Pokemon.IncreasedCriticalStage());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "focus_punch")]
|
||||||
|
public class FocusPunch : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnBeforeTurnStart(ITurnChoice choice)
|
||||||
|
{
|
||||||
|
choice.User.Volatile.Add(new FocusPunchEffect());
|
||||||
|
choice.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("focus_punch_charge",
|
||||||
|
new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "pokemon", choice.User }
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PreventMove(IExecutingMove move, ref bool prevent)
|
||||||
|
{
|
||||||
|
var focusPunchEffect = move.User.Volatile.Get<FocusPunchEffect>();
|
||||||
|
if (focusPunchEffect == null || focusPunchEffect.WasHit)
|
||||||
|
{
|
||||||
|
prevent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "follow_me")]
|
||||||
|
public class FollowMe : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
|
||||||
|
{
|
||||||
|
if (targets.Count != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var target = targets[0];
|
||||||
|
if (target == null)
|
||||||
|
return;
|
||||||
|
if (target.BattleData?.SideIndex != moveChoice.User.BattleData?.SideIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
targets = [moveChoice.User];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "foresight")]
|
||||||
|
public class Foresight : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
|
||||||
|
target.Volatile.Add(new ForesightEffect(typeLibrary));
|
||||||
|
target.ChangeStatBoost(Statistic.Evasion, (sbyte)-target.StatBoost.Evasion, false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "forests_curse")]
|
||||||
|
public class ForestsCurse : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
|
||||||
|
if (!typeLibrary.TryGetTypeIdentifier("grass", out var grassType))
|
||||||
|
return;
|
||||||
|
target.AddType(grassType);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using PkmnLib.Static.Moves;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "foul_play")]
|
||||||
|
public class FoulPlay : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
|
||||||
|
{
|
||||||
|
value = move.UseMove.Category == MoveCategory.Physical
|
||||||
|
? target.BoostedStats.Attack
|
||||||
|
: target.BoostedStats.SpecialAttack;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "freeze_dry")]
|
||||||
|
public class FreezeDry : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
|
||||||
|
if (!typeLibrary.TryGetTypeIdentifier("water", out var waterType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (target.Types.Contains(waterType))
|
||||||
|
{
|
||||||
|
var effectivenessWithoutWater = target.Types
|
||||||
|
.Where(x => x != waterType)
|
||||||
|
.Select(x => typeLibrary.GetEffectiveness(x, target.Types))
|
||||||
|
.Aggregate(1f, (a, b) => a * b);
|
||||||
|
effectiveness = effectivenessWithoutWater * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
|
||||||
|
{
|
||||||
|
target.SetStatus("frozen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "one_hit_ko")]
|
||||||
|
public class OneHitKo : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref int modifiedAccuracy)
|
||||||
|
{
|
||||||
|
var levelDifference = executingMove.User.Level - target.Level;
|
||||||
|
if (levelDifference < 0)
|
||||||
|
{
|
||||||
|
executingMove.GetHitData(target, hitIndex).Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modifiedAccuracy = 30 + levelDifference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
|
||||||
|
{
|
||||||
|
damage = target.BoostedStats.Hp.MultiplyOrMax(10);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Utils;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Pokemon, "charge_fly")]
|
||||||
|
public class ChargeFlyEffect : Script
|
||||||
|
{
|
||||||
|
private readonly IPokemon _owner;
|
||||||
|
|
||||||
|
public ChargeFlyEffect(IPokemon owner)
|
||||||
|
{
|
||||||
|
_owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ForceTurnSelection(byte sideIndex, byte position, ref ITurnChoice? choice)
|
||||||
|
{
|
||||||
|
var opposingSideIndex = (byte)(_owner.BattleData?.SideIndex == 0 ? 1 : 0);
|
||||||
|
choice = TurnChoiceHelper.CreateMoveChoice(_owner, "fly", opposingSideIndex, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||||
|
{
|
||||||
|
if (!executingMove.UseMove.HasFlag("hit_flying"))
|
||||||
|
block = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
|
||||||
|
{
|
||||||
|
if (!move.UseMove.HasFlag("effective_against_fly"))
|
||||||
|
damage *= 2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Pokemon, "fire_spin")]
|
||||||
|
public class FireSpinEffect : Script
|
||||||
|
{
|
||||||
|
private readonly IPokemon _owner;
|
||||||
|
|
||||||
|
public FireSpinEffect(IPokemon owner)
|
||||||
|
{
|
||||||
|
_owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnEndTurn(IBattle battle)
|
||||||
|
{
|
||||||
|
_owner.Damage(_owner.BoostedStats.Hp / 8, DamageSource.Misc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PreventSelfRunAway(IFleeChoice choice, ref bool prevent) => prevent = true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent) => prevent = true;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Pokemon, "focus_punch")]
|
||||||
|
public class FocusPunchEffect : Script
|
||||||
|
{
|
||||||
|
public bool WasHit { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
WasHit = true;
|
||||||
|
target.BattleData?.Battle.EventHook.Invoke(new DialogEvent("focus_punch_lost_focus",
|
||||||
|
new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "pokemon", target }
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Linq;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
using PkmnLib.Static.Libraries;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Pokemon, "foresight")]
|
||||||
|
public class ForesightEffect : Script
|
||||||
|
{
|
||||||
|
private readonly IReadOnlyTypeLibrary _typeLibrary;
|
||||||
|
private readonly TypeIdentifier _normalType;
|
||||||
|
private readonly TypeIdentifier _fightingType;
|
||||||
|
private readonly TypeIdentifier _ghostType;
|
||||||
|
|
||||||
|
public ForesightEffect(IReadOnlyTypeLibrary typeLibrary)
|
||||||
|
{
|
||||||
|
_typeLibrary = typeLibrary;
|
||||||
|
typeLibrary.TryGetTypeIdentifier("normal", out _normalType);
|
||||||
|
typeLibrary.TryGetTypeIdentifier("fighting", out _fightingType);
|
||||||
|
typeLibrary.TryGetTypeIdentifier("ghost", out _ghostType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted, ref bool prevent)
|
||||||
|
{
|
||||||
|
if (stat == Statistic.Evasion)
|
||||||
|
prevent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
|
||||||
|
{
|
||||||
|
|
||||||
|
var hitData = move.GetHitData(target, hit);
|
||||||
|
if (hitData.Type == _normalType && target.Types.Contains(_fightingType))
|
||||||
|
effectiveness = _typeLibrary.GetEffectiveness(_normalType, target.Types.Where(x => x != _ghostType));
|
||||||
|
else if (hitData.Type == _fightingType && target.Types.Contains(_ghostType))
|
||||||
|
effectiveness = _typeLibrary.GetEffectiveness(_fightingType, target.Types.Where(x => x != _ghostType));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Pokemon, "increased_critical_stage")]
|
||||||
|
public class IncreasedCriticalStage : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage)
|
||||||
|
{
|
||||||
|
// Extreme edge case, should never happen
|
||||||
|
if (stage == byte.MaxValue)
|
||||||
|
{
|
||||||
|
move.GetHitData(target, hit).Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stage += 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Terrain;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Terrain, "grassy_terrain")]
|
||||||
|
public class GrassyTerrain : Script
|
||||||
|
{
|
||||||
|
// TODO: Implement Electric Terrain
|
||||||
|
}
|
Loading…
Reference in New Issue