More moves
This commit is contained in:
parent
1b54c78b07
commit
d02c05874b
@ -173,7 +173,9 @@ internal static class MoveTurnExecutor
|
||||
break;
|
||||
if (executingMove.GetHitData(target, hitIndex).HasFailed)
|
||||
break;
|
||||
if (useMove.Category == MoveCategory.Status)
|
||||
var category = useMove.Category;
|
||||
executingMove.RunScriptHook(x => x.ChangeCategory(executingMove, target, hitIndex, ref category));
|
||||
if (category == MoveCategory.Status)
|
||||
{
|
||||
var secondaryEffect = useMove.SecondaryEffect;
|
||||
if (secondaryEffect != null)
|
||||
|
@ -2,6 +2,7 @@ using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.Models.Choices;
|
||||
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Moves;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||
@ -310,14 +311,16 @@ public abstract class Script : IDeepCloneable
|
||||
/// <summary>
|
||||
/// This function allows a script to change the actual offensive stat values used when calculating damage
|
||||
/// </summary>
|
||||
public virtual void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
|
||||
public virtual void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
|
||||
ref uint value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to change the actual defensive stat values used when calculating damage.
|
||||
/// </summary>
|
||||
public virtual void ChangeDefensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
|
||||
public virtual void ChangeDefensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint offensiveStat,
|
||||
ref uint value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -603,4 +606,8 @@ public abstract class Script : IDeepCloneable
|
||||
IList<TypeIdentifier> types)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ChangeCategory(IExecutingMove move, IPokemon target, byte hitIndex, ref MoveCategory category)
|
||||
{
|
||||
}
|
||||
}
|
@ -7684,7 +7684,10 @@
|
||||
"mirror",
|
||||
"sound",
|
||||
"ignore-substitute"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "parting_shot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pay_day",
|
||||
@ -7698,7 +7701,10 @@
|
||||
"flags": [
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "pay_day"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "payback",
|
||||
@ -7713,7 +7719,10 @@
|
||||
"contact",
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "payback"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "peck",
|
||||
@ -7730,6 +7739,7 @@
|
||||
"mirror",
|
||||
"distance"
|
||||
]
|
||||
// No secondary effect
|
||||
},
|
||||
{
|
||||
"name": "perish_song",
|
||||
@ -7744,7 +7754,10 @@
|
||||
"sound",
|
||||
"distance",
|
||||
"ignore-substitute"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "perish_song"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "petal_blizzard",
|
||||
@ -7759,6 +7772,7 @@
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
// No secondary effect
|
||||
},
|
||||
{
|
||||
"name": "petal_dance",
|
||||
@ -7774,7 +7788,10 @@
|
||||
"protect",
|
||||
"mirror",
|
||||
"dance"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "petal_dance"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "phantom_force",
|
||||
@ -7789,7 +7806,10 @@
|
||||
"contact",
|
||||
"charge",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "phantom_force"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pin_missile",
|
||||
@ -7803,7 +7823,10 @@
|
||||
"flags": [
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "2_5_hit_move"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "play_nice",
|
||||
@ -7818,7 +7841,13 @@
|
||||
"reflectable",
|
||||
"mirror",
|
||||
"ignore-substitute"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "change_target_attack",
|
||||
"parameters": {
|
||||
"amount": -1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "play_rough",
|
||||
@ -7833,7 +7862,14 @@
|
||||
"contact",
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "change_target_attack",
|
||||
"chance": 10,
|
||||
"parameters": {
|
||||
"amount": -1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pluck",
|
||||
@ -7849,7 +7885,10 @@
|
||||
"protect",
|
||||
"mirror",
|
||||
"distance"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "bug_bite"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "poison_fang",
|
||||
@ -7865,7 +7904,13 @@
|
||||
"protect",
|
||||
"mirror",
|
||||
"bite"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "set_status",
|
||||
"parameters": {
|
||||
"status": "badly_poisoned"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "poison_gas",
|
||||
@ -7880,7 +7925,13 @@
|
||||
"protect",
|
||||
"reflectable",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "set_status",
|
||||
"parameters": {
|
||||
"status": "poisoned"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "poison_jab",
|
||||
@ -7895,7 +7946,14 @@
|
||||
"contact",
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "set_status",
|
||||
"chance": 30,
|
||||
"parameters": {
|
||||
"status": "poisoned"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "poison_powder",
|
||||
@ -7911,7 +7969,13 @@
|
||||
"reflectable",
|
||||
"mirror",
|
||||
"powder"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "set_status",
|
||||
"parameters": {
|
||||
"status": "poisoned"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "poison_sting",
|
||||
@ -7925,7 +7989,14 @@
|
||||
"flags": [
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "set_status",
|
||||
"chance": 30,
|
||||
"parameters": {
|
||||
"status": "poisoned"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "poison_tail",
|
||||
@ -7940,7 +8011,10 @@
|
||||
"contact",
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "poison_tail"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pollen_puff",
|
||||
@ -7954,7 +8028,10 @@
|
||||
"flags": [
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "pollen_puff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pound",
|
||||
@ -7970,6 +8047,7 @@
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
// No secondary effect
|
||||
},
|
||||
{
|
||||
"name": "powder",
|
||||
@ -7986,7 +8064,10 @@
|
||||
"mirror",
|
||||
"ignore-substitute",
|
||||
"powder"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "powder"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "powder_snow",
|
||||
@ -8000,7 +8081,14 @@
|
||||
"flags": [
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "set_status",
|
||||
"chance": 10,
|
||||
"parameters": {
|
||||
"status": "frozen"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "power_gem",
|
||||
@ -8015,6 +8103,7 @@
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
// No secondary effect
|
||||
},
|
||||
{
|
||||
"name": "power_split",
|
||||
@ -8027,7 +8116,10 @@
|
||||
"category": "status",
|
||||
"flags": [
|
||||
"protect"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "power_split"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "power_swap",
|
||||
@ -8042,7 +8134,10 @@
|
||||
"protect",
|
||||
"mirror",
|
||||
"ignore-substitute"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "power_swap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "power_trick",
|
||||
@ -8055,7 +8150,10 @@
|
||||
"category": "status",
|
||||
"flags": [
|
||||
"snatch"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "power_trick"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "power_trip",
|
||||
@ -8070,7 +8168,10 @@
|
||||
"contact",
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "power_trip"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "power_up_punch",
|
||||
@ -8086,7 +8187,13 @@
|
||||
"protect",
|
||||
"mirror",
|
||||
"punch"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "change_user_attack",
|
||||
"parameters": {
|
||||
"amount": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "power_whip",
|
||||
@ -8102,6 +8209,7 @@
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
// No secondary effect
|
||||
},
|
||||
{
|
||||
"name": "precipice_blades",
|
||||
@ -8117,6 +8225,7 @@
|
||||
"mirror",
|
||||
"nonskybattle"
|
||||
]
|
||||
// No secondary effect
|
||||
},
|
||||
{
|
||||
"name": "present",
|
||||
@ -10909,7 +11018,10 @@
|
||||
"contact",
|
||||
"protect",
|
||||
"mirror"
|
||||
]
|
||||
],
|
||||
"effect": {
|
||||
"name": "thrash"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "throat_chop",
|
@ -8,7 +8,7 @@ public class MoveDataLoaderTests
|
||||
[Test]
|
||||
public async Task TestPrimaryMoveFile()
|
||||
{
|
||||
using var stream = File.OpenRead("Data/Moves.json");
|
||||
await using var stream = File.OpenRead("Data/Moves.jsonc");
|
||||
var typeLibrary = new TypeLibrary();
|
||||
typeLibrary.RegisterType("Normal");
|
||||
typeLibrary.RegisterType("Fire");
|
||||
|
@ -13,7 +13,7 @@ public static class LibraryHelpers
|
||||
var types = TypeDataLoader.LoadTypeLibrary(typesFile);
|
||||
using var naturesFile = File.Open("Data/Natures.csv", FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
var natures = NatureDataLoader.LoadNatureLibrary(naturesFile);
|
||||
using var movesFile = File.Open("Data/Moves.json", FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
using var movesFile = File.Open("Data/Moves.jsonc", FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
var moves = MoveDataLoader.LoadMoves(movesFile, types);
|
||||
using var itemsFile = File.Open("Data/Items.json", FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
var items = ItemDataLoader.LoadItems(itemsFile);
|
||||
@ -24,14 +24,14 @@ public static class LibraryHelpers
|
||||
using var speciesFile = File.Open("Data/Pokemon.json", FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
var species = SpeciesDataLoader.LoadSpecies(speciesFile, types);
|
||||
|
||||
var staticLibrary = new StaticLibraryImpl(new LibrarySettings()
|
||||
var staticLibrary = new StaticLibraryImpl(new LibrarySettings
|
||||
{
|
||||
MaxLevel = 100,
|
||||
ShinyRate = 4096,
|
||||
}, species, moves, abilities, types, natures, growthRates, items);
|
||||
|
||||
var dynamicLibrary = DynamicLibraryImpl.Create(staticLibrary, [
|
||||
new Gen7Plugin(new Gen7PluginConfiguration()
|
||||
new Gen7Plugin(new Gen7PluginConfiguration
|
||||
{
|
||||
DamageCalculatorHasRandomness = false,
|
||||
}),
|
||||
|
@ -133,11 +133,12 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
||||
if (bypassDefense)
|
||||
targetStats = target.FlatStats;
|
||||
var defensiveStat = targetStats.GetStatistic(defensive);
|
||||
var origOffensiveStat = offensiveStat;
|
||||
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeOffensiveStatValue(executingMove, target, hitNumber, ref offensiveStat));
|
||||
script.ChangeOffensiveStatValue(executingMove, target, hitNumber, defensiveStat, ref offensiveStat));
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeDefensiveStatValue(executingMove, target, hitNumber, ref defensiveStat));
|
||||
script.ChangeDefensiveStatValue(executingMove, target, hitNumber, origOffensiveStat, ref defensiveStat));
|
||||
|
||||
var modifier = (float)offensiveStat / defensiveStat;
|
||||
executingMove.RunScriptHook(script =>
|
||||
|
@ -6,7 +6,8 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
public class FoulPlay : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
|
||||
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint _,
|
||||
ref uint value)
|
||||
{
|
||||
value = move.UseMove.Category == MoveCategory.Physical
|
||||
? target.BoostedStats.Attack
|
||||
|
@ -22,6 +22,9 @@ public class GuardSplit : Script
|
||||
|
||||
userStats.SetStatistic(Statistic.Defense, newDefense);
|
||||
userStats.SetStatistic(Statistic.SpecialDefense, newSpecialDefense);
|
||||
targetStats.SetStatistic(Statistic.Defense, newDefense);
|
||||
targetStats.SetStatistic(Statistic.SpecialDefense, newSpecialDefense);
|
||||
user.RecalculateFlatStats();
|
||||
target.RecalculateFlatStats();
|
||||
}
|
||||
}
|
28
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PartingShot.cs
Normal file
28
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PartingShot.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using PkmnLib.Static;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the secondary effect of Parting Shot, which lowers the target's Attack and Special Attack by one stage each,
|
||||
/// then forces the user to switch out if at least one stat change was successful.
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "parting_shot")]
|
||||
public class PartingShot : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
|
||||
var evtBatch = new EventBatchId();
|
||||
var attackChanged = target.ChangeStatBoost(Statistic.Attack, -1, false, evtBatch);
|
||||
var specialAttackChanged = target.ChangeStatBoost(Statistic.SpecialAttack, -1, false, evtBatch);
|
||||
|
||||
if (attackChanged || specialAttackChanged)
|
||||
{
|
||||
battleData.BattleSide.SwapPokemon(battleData.Position, null);
|
||||
}
|
||||
}
|
||||
}
|
7
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PayDay.cs
Normal file
7
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PayDay.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "pay_day")]
|
||||
public class PayDay : Script
|
||||
{
|
||||
// TODO: Implement the Pay Day move effect
|
||||
}
|
23
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Payback.cs
Normal file
23
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Payback.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the secondary effect of Payback, which doubles the move's power if the user moves after the target.
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "payback")]
|
||||
public class Payback : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
|
||||
// Check if the target has already moved this turn
|
||||
if (battleData?.Battle.ChoiceQueue?.FirstOrDefault(x => x.User == target) != null)
|
||||
{
|
||||
basePower = basePower.MultiplyOrMax(2);
|
||||
}
|
||||
}
|
||||
}
|
30
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PerishSong.cs
Normal file
30
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PerishSong.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System.Linq;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the secondary effect of Perish Song, which causes all Pokemon on the field to faint in 3 turns.
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "perish_song")]
|
||||
public class PerishSong : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.User.Volatile.Contains<PerishSongEffect>())
|
||||
return;
|
||||
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
|
||||
// Add Perish Song volatile to all Pokémon on the field
|
||||
foreach (var pokemon in battleData.Battle.Sides.SelectMany(x => x.Pokemon).WhereNotNull())
|
||||
{
|
||||
pokemon.Volatile.Add(new PerishSongEffect(pokemon));
|
||||
}
|
||||
}
|
||||
}
|
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PetalDance.cs
Normal file
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PetalDance.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the secondary effect of Petal Dance, which forces the user to continue using the move for 2-3 turns,
|
||||
/// then confuses the user.
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "petal_dance")]
|
||||
public class PetalDance : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.User.Volatile.Contains<PetalDanceEffect>())
|
||||
return;
|
||||
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
|
||||
var turns = battleData.Battle.Random.GetBool() ? 2 : 3;
|
||||
move.User.Volatile.Add(new PetalDanceEffect(move.User, turns, move.MoveChoice.TargetSide,
|
||||
move.MoveChoice.TargetPosition));
|
||||
}
|
||||
}
|
36
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PhantomForce.cs
Normal file
36
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PhantomForce.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the secondary effect of Phantom Force, which makes the user semi-invulnerable on the first turn
|
||||
/// and attacks on the second turn.
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "phantom_force")]
|
||||
public class PhantomForce : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void PreventMove(IExecutingMove move, ref bool prevent)
|
||||
{
|
||||
if (move.User.Volatile.Contains<PhantomForceCharge>())
|
||||
return;
|
||||
|
||||
move.User.Volatile.Add(new PhantomForceCharge(move.User));
|
||||
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("phantom_force_charge",
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "user", move.User },
|
||||
}));
|
||||
prevent = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.User.Volatile.Contains<PhantomForceCharge>())
|
||||
return;
|
||||
|
||||
move.User.Volatile.Add(new PhantomForceCharge(move.User));
|
||||
}
|
||||
}
|
29
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PoisonTail.cs
Normal file
29
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PoisonTail.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Status;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "poison_tail")]
|
||||
public class PoisonTail : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage)
|
||||
{
|
||||
if (stage == 255)
|
||||
return;
|
||||
stage += 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
|
||||
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
|
||||
{
|
||||
target.SetStatus(ScriptUtils.ResolveName<BadlyPoisoned>());
|
||||
}
|
||||
}
|
||||
}
|
39
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PollenPuff.cs
Normal file
39
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PollenPuff.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using PkmnLib.Static.Moves;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "pollen_puff")]
|
||||
public class PollenPuff : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc />
|
||||
public override void ChangeCategory(IExecutingMove move, IPokemon target, byte hitIndex, ref MoveCategory category)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
var targetBattleData = target.BattleData;
|
||||
|
||||
if (battleData == null || targetBattleData == null)
|
||||
return;
|
||||
|
||||
if (battleData.SideIndex == targetBattleData.SideIndex)
|
||||
{
|
||||
category = MoveCategory.Status;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
var targetBattleData = target.BattleData;
|
||||
|
||||
if (battleData == null || targetBattleData == null)
|
||||
return;
|
||||
|
||||
if (battleData.SideIndex == targetBattleData.SideIndex)
|
||||
{
|
||||
var maxHealth = target.MaxHealth;
|
||||
target.Heal(maxHealth / 2);
|
||||
}
|
||||
}
|
||||
}
|
13
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Powder.cs
Normal file
13
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Powder.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "powder")]
|
||||
public class Powder : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
target.Volatile.Add(new PowderEffect());
|
||||
}
|
||||
}
|
30
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerSplit.cs
Normal file
30
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerSplit.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using PkmnLib.Static;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "power_split")]
|
||||
public class PowerSplit : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var user = move.User;
|
||||
var userStats = user.FlatStats;
|
||||
var targetStats = target.FlatStats;
|
||||
|
||||
var userAttack = userStats.GetStatistic(Statistic.Attack);
|
||||
var targetAttack = targetStats.GetStatistic(Statistic.Attack);
|
||||
var userSpecialAttack = userStats.GetStatistic(Statistic.SpecialAttack);
|
||||
var targetSpecialAttack = targetStats.GetStatistic(Statistic.SpecialAttack);
|
||||
|
||||
var newAttack = (userAttack + targetAttack) / 2;
|
||||
var newSpecialAttack = (userSpecialAttack + targetSpecialAttack) / 2;
|
||||
|
||||
userStats.SetStatistic(Statistic.Attack, newAttack);
|
||||
userStats.SetStatistic(Statistic.SpecialAttack, newSpecialAttack);
|
||||
targetStats.SetStatistic(Statistic.Attack, newAttack);
|
||||
targetStats.SetStatistic(Statistic.SpecialAttack, newSpecialAttack);
|
||||
user.RecalculateFlatStats();
|
||||
target.RecalculateFlatStats();
|
||||
}
|
||||
}
|
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerSwap.cs
Normal file
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerSwap.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using PkmnLib.Static;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "power_swap")]
|
||||
public class PowerSwap : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var user = move.User;
|
||||
|
||||
var eventBatchId = new EventBatchId();
|
||||
var userAttack = user.StatBoost.Attack;
|
||||
var targetAttack = target.StatBoost.Attack;
|
||||
var userSpecialAttack = user.StatBoost.SpecialAttack;
|
||||
var targetSpecialAttack = target.StatBoost.SpecialAttack;
|
||||
|
||||
user.ChangeStatBoost(Statistic.Attack, (sbyte)(targetAttack - userAttack), true, eventBatchId);
|
||||
user.ChangeStatBoost(Statistic.SpecialAttack, (sbyte)(targetSpecialAttack - userSpecialAttack), true,
|
||||
eventBatchId);
|
||||
target.ChangeStatBoost(Statistic.Attack, (sbyte)(userAttack - targetAttack), true, eventBatchId);
|
||||
target.ChangeStatBoost(Statistic.SpecialAttack, (sbyte)(userSpecialAttack - targetSpecialAttack), true,
|
||||
eventBatchId);
|
||||
}
|
||||
}
|
13
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerTrick.cs
Normal file
13
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerTrick.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "power_trick")]
|
||||
public class PowerTrick : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
move.User.Volatile.Add(new PowerTrickEffect());
|
||||
}
|
||||
}
|
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerTrip.cs
Normal file
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/PowerTrip.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "power_trip")]
|
||||
public class PowerTrip : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
|
||||
{
|
||||
var modifier = 1;
|
||||
foreach (Statistic stat in Enum.GetValues(typeof(Statistic)))
|
||||
{
|
||||
if (stat is Statistic.Accuracy or Statistic.Evasion)
|
||||
continue;
|
||||
var statChange = move.User.StatBoost.GetStatistic(stat);
|
||||
if (statChange > 0)
|
||||
modifier += statChange;
|
||||
}
|
||||
|
||||
damage = damage.MultiplyOrMax(modifier);
|
||||
}
|
||||
}
|
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Thrash.cs
Normal file
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Thrash.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the secondary effect of Thrash, which forces the user to continue using the move for 2-3 turns,
|
||||
/// then confuses the user.
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "thrash")]
|
||||
public class Thrash : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.User.Volatile.Contains<ThrashEffect>())
|
||||
return;
|
||||
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
|
||||
var turns = battleData.Battle.Random.GetBool() ? 2 : 3;
|
||||
move.User.Volatile.Add(new ThrashEffect(move.User, turns, move.MoveChoice.TargetSide,
|
||||
move.MoveChoice.TargetPosition));
|
||||
}
|
||||
}
|
@ -1,37 +1,10 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "outrage")]
|
||||
public class OutrageEffect : Script
|
||||
public class OutrageEffect : OutrageLikeEffect
|
||||
{
|
||||
private readonly IPokemon _owner;
|
||||
private int _turns;
|
||||
private readonly byte _targetSide;
|
||||
private readonly byte _targetPosition;
|
||||
|
||||
public OutrageEffect(IPokemon owner, int turns, byte targetSide, byte targetPosition)
|
||||
public OutrageEffect(IPokemon owner, int turns, byte targetSide, byte targetPosition) : base(owner, turns,
|
||||
targetSide, targetPosition, "outrage")
|
||||
{
|
||||
_owner = owner;
|
||||
_turns = turns;
|
||||
_targetSide = targetSide;
|
||||
_targetPosition = targetPosition;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ForceTurnSelection(byte sideIndex, byte position, ref ITurnChoice? choice)
|
||||
{
|
||||
choice = TurnChoiceHelper.CreateMoveChoice(_owner, "outrage", _targetSide, _targetPosition);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnAfterHits(IExecutingMove move, IPokemon target)
|
||||
{
|
||||
_turns--;
|
||||
if (_turns <= 0)
|
||||
{
|
||||
RemoveSelf();
|
||||
_owner.Volatile.Add(new Confusion());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Utils;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
public abstract class OutrageLikeEffect : Script
|
||||
{
|
||||
private readonly IPokemon _owner;
|
||||
private int _turns;
|
||||
private readonly byte _targetSide;
|
||||
private readonly byte _targetPosition;
|
||||
private readonly StringKey _move;
|
||||
|
||||
public OutrageLikeEffect(IPokemon owner, int turns, byte targetSide, byte targetPosition, StringKey move)
|
||||
{
|
||||
_owner = owner;
|
||||
_turns = turns;
|
||||
_targetSide = targetSide;
|
||||
_targetPosition = targetPosition;
|
||||
_move = move;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ForceTurnSelection(byte sideIndex, byte position, ref ITurnChoice? choice)
|
||||
{
|
||||
choice = TurnChoiceHelper.CreateMoveChoice(_owner, "_move", _targetSide, _targetPosition);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnAfterHits(IExecutingMove move, IPokemon target)
|
||||
{
|
||||
_turns--;
|
||||
if (_turns <= 0)
|
||||
{
|
||||
RemoveSelf();
|
||||
_owner.Volatile.Add(new Confusion());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using PkmnLib.Static;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "perish_song")]
|
||||
public class PerishSongEffect : Script
|
||||
{
|
||||
private int _turns;
|
||||
private IPokemon _owner;
|
||||
|
||||
public PerishSongEffect(IPokemon owner, int turns = 3)
|
||||
{
|
||||
_owner = owner;
|
||||
_turns = turns;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnEndTurn(IBattle battle)
|
||||
{
|
||||
_turns--;
|
||||
if (_turns <= 0)
|
||||
{
|
||||
RemoveSelf();
|
||||
_owner.Faint(DamageSource.Misc);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "petal_dance")]
|
||||
public class PetalDanceEffect : OutrageLikeEffect
|
||||
{
|
||||
public PetalDanceEffect(IPokemon owner, int turns, byte targetSide, byte targetPosition) : base(owner, turns,
|
||||
targetSide, targetPosition, "petal_dance")
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "phantom_force")]
|
||||
public class PhantomForceCharge : Script
|
||||
{
|
||||
private readonly IPokemon _owner;
|
||||
|
||||
public PhantomForceCharge(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, "phantom_force", opposingSideIndex, position);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||
{
|
||||
block = true;
|
||||
}
|
||||
}
|
28
Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/PowderEffect.cs
Normal file
28
Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/PowderEffect.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "powder")]
|
||||
public class PowderEffect : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc />
|
||||
public override void BlockOutgoingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||
{
|
||||
var hit = executingMove.GetHitData(target, hitIndex);
|
||||
if (hit.Type.Name == "fire")
|
||||
{
|
||||
executingMove.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("powder_explodes",
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "user", executingMove.User },
|
||||
{ "target", target },
|
||||
}));
|
||||
|
||||
var health = executingMove.User.MaxHealth / 4;
|
||||
executingMove.User.Damage(health, DamageSource.Misc);
|
||||
|
||||
block = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "power_trick")]
|
||||
public class PowerTrickEffect : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
|
||||
ref uint value)
|
||||
{
|
||||
value = defensiveStat;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ChangeDefensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint offensiveStat,
|
||||
ref uint value)
|
||||
{
|
||||
value = offensiveStat;
|
||||
}
|
||||
}
|
10
Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/ThrashEffect.cs
Normal file
10
Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/ThrashEffect.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "thrash")]
|
||||
public class ThrashEffect : OutrageLikeEffect
|
||||
{
|
||||
public ThrashEffect(IPokemon owner, int turns, byte targetSide, byte targetPosition) : base(owner, turns,
|
||||
targetSide, targetPosition, "thrash")
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Status;
|
||||
|
||||
[Script(ScriptCategory.Status, "badly_poisoned")]
|
||||
public class BadlyPoisoned : Script
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user