Implement highest damage AI, further work on AI runner, random fixes
All checks were successful
Build / Build (push) Successful in 51s

This commit is contained in:
2025-07-05 14:56:25 +02:00
parent 32aaa5150a
commit c795f20e54
30 changed files with 261 additions and 26 deletions

View File

@@ -0,0 +1,21 @@
using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Dynamic.ScriptHandling.Registry;
using Assembly = System.Reflection.Assembly;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts;
public class GenericScriptTests
{
[Test]
public async Task EveryScriptHasAttribute()
{
var scripts = typeof(Gen7Plugin).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(Script)) && !t.IsAbstract);
foreach (var script in scripts)
{
var attributes = script.GetCustomAttributes(typeof(ScriptAttribute), false);
await Assert.That(attributes).IsNotEmpty().Because(
$"Script {script.Name} does not have the Script attribute defined.");
}
}
}

View File

@@ -2,6 +2,7 @@ using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Battle;
[Script(ScriptCategory.Battle, "wonder_room_effect")]
public class WonderRoomEffect : Script, IScriptChangeDefensiveStatValue, IScriptOnEndTurn
{
public int TurnsLeft { get; private set; } = 5;

View File

@@ -12,6 +12,7 @@ public class Bounce : Script, IScriptPreventMove, IScriptOnBeforeMove, IScriptOn
return;
move.User.Volatile.Add(new ChargeBounceEffect(move.User));
move.MoveChoice.SetAdditionalData("bounce_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("bounce_charge", new Dictionary<string, object>
{
{ "user", move.User },

View File

@@ -12,6 +12,7 @@ public class Dig : Script, IScriptPreventMove, IScriptOnBeforeMove
return;
move.User.Volatile.Add(new DigEffect(move.User));
move.MoveChoice.SetAdditionalData("dig_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("dig_charge", new Dictionary<string, object>
{
{ "user", move.User },

View File

@@ -12,6 +12,7 @@ public class Dive : Script, IScriptPreventMove, IScriptOnSecondaryEffect
return;
move.User.Volatile.Add(new DiveEffect(move.User));
move.MoveChoice.SetAdditionalData("dive_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("dive_charge", new Dictionary<string, object>
{
{ "user", move.User },

View File

@@ -12,6 +12,7 @@ public class Fly : Script, IScriptPreventMove, IScriptOnBeforeMove
return;
move.User.Volatile.Add(new ChargeFlyEffect(move.User));
move.MoveChoice.SetAdditionalData("fly_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("fly_charge", new Dictionary<string, object>
{
{ "user", move.User },

View File

@@ -23,6 +23,11 @@ public class MeFirst : Script, IScriptChangeMove
choice.Fail();
return;
}
if (battleData.Battle.Library.MiscLibrary.IsReplacementChoice(targetMove))
{
choice.Fail();
return;
}
var targetMoveData = targetMove.ChosenMove.MoveData;
moveName = targetMoveData.Name;
choice.Volatile.Add(new MeFirstPowerBoost());

View File

@@ -16,6 +16,7 @@ public class PhantomForce : Script, IScriptPreventMove, IScriptOnSecondaryEffect
return;
move.User.Volatile.Add(new PhantomForceCharge(move.User));
move.MoveChoice.SetAdditionalData("phantom_force_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("phantom_force_charge",
new Dictionary<string, object>
{

View File

@@ -12,6 +12,7 @@ public class ShadowForce : Script, IScriptPreventMove, IScriptOnSecondaryEffect
return;
move.User.Volatile.Add(new ShadowForceCharge(move.User));
move.MoveChoice.SetAdditionalData("shadow_force_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("shadow_force_charge",
new Dictionary<string, object>
{

View File

@@ -12,6 +12,7 @@ public class SkyDrop : Script, IScriptPreventMove, IScriptOnBeforeMove
return;
move.User.Volatile.Add(new ChargeSkyDropEffect(move.User));
move.MoveChoice.SetAdditionalData("sky_drop_charge", true);
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("sky_drop_charge", new Dictionary<string, object>
{
{ "user", move.User },

View File

@@ -33,4 +33,13 @@ public class ChargeBounceEffect : Script, IScriptForceTurnSelection, IScriptChan
if (!move.UseMove.HasFlag("effective_against_fly"))
damage *= 2;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("bounce_charge") != true)
{
RemoveSelf();
}
}
}

View File

@@ -33,4 +33,13 @@ public class ChargeFlyEffect : Script, IScriptForceTurnSelection, IScriptChangeI
if (!move.UseMove.HasFlag("effective_against_fly"))
damage *= 2;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("fly_charge") != true)
{
RemoveSelf();
}
}
}

View File

@@ -33,4 +33,13 @@ public class ChargeSkyDropEffect : Script, IScriptForceTurnSelection, IScriptCha
if (!move.UseMove.HasFlag("effective_against_fly"))
damage *= 2;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("sky_drop_charge") != true)
{
RemoveSelf();
}
}
}

View File

@@ -32,4 +32,13 @@ public class DigEffect : Script, IScriptForceTurnSelection, IScriptChangeIncomin
if (!move.UseMove.HasFlag("effective_against_underground"))
damage *= 2;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("dig_charge") != true)
{
RemoveSelf();
}
}
}

View File

@@ -32,4 +32,13 @@ public class DiveEffect : Script, IScriptForceTurnSelection, IScriptChangeIncomi
if (!move.UseMove.HasFlag("effective_against_underwater"))
damage *= 2;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("dive_charge") != true)
{
RemoveSelf();
}
}
}

View File

@@ -1,5 +1,6 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "helping_hand")]
public class HelpingHandEffect : Script, IScriptChangeBasePower, IScriptOnEndTurn
{
/// <inheritdoc />

View File

@@ -1,5 +1,6 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "lucky_chant")]
public class LuckyChantEffect : Script, IScriptBlockCriticalHit, IScriptOnEndTurn
{
private int _turnsLeft = 5;

View File

@@ -24,4 +24,13 @@ public class PhantomForceCharge : Script, IScriptForceTurnSelection, IScriptBloc
{
block = true;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("phantom_force_charge") != true)
{
moveChoice.User.Volatile.Remove(ScriptUtils.ResolveName<PhantomForceCharge>());
}
}
}

View File

@@ -24,4 +24,13 @@ public class ShadowForceCharge : Script, IScriptForceTurnSelection, IScriptBlock
{
block = true;
}
/// <inheritdoc />
public override void OnAfterMoveChoice(IMoveChoice moveChoice)
{
if (moveChoice.AdditionalData?.ContainsKey("shadow_force_charge") != true)
{
RemoveSelf();
}
}
}

View File

@@ -2,6 +2,7 @@ using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "mat_block")]
public class MatBlockEffect : Script, IScriptOnEndTurn, IScriptBlockIncomingHit
{
/// <inheritdoc />

View File

@@ -1,5 +1,6 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "quick_guard")]
public class QuickGuardEffect : Script, IScriptIsInvulnerableToMove, IScriptOnEndTurn
{
/// <inheritdoc />

View File

@@ -2,6 +2,7 @@ using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "safe_guard")]
public class SafeguardEffect : Script
{
/// <inheritdoc />

View File

@@ -2,6 +2,7 @@ using PkmnLib.Dynamic.BattleFlow;
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "spotlight")]
public class SpotlightEffect : Script, IScriptChangeIncomingTargets, IScriptOnEndTurn
{
private readonly byte _position;

View File

@@ -4,14 +4,10 @@ public static class TurnChoiceHelper
{
public static IMoveChoice CreateMoveChoice(IPokemon owner, StringKey moveName, byte targetSide, byte targetPosition)
{
var move = owner.Moves.FirstOrDefault(x => x?.MoveData.Name == moveName);
if (move == null)
{
if (!owner.Library.StaticLibrary.Moves.TryGet(moveName, out var moveData))
throw new Exception($"Move '{moveName}' not found in move library.");
if (!owner.Library.StaticLibrary.Moves.TryGet(moveName, out var moveData))
throw new Exception($"Move '{moveName}' not found in move library.");
move = new LearnedMoveImpl(moveData, MoveLearnMethod.Unknown);
}
var move = new LearnedMoveImpl(moveData, MoveLearnMethod.Unknown);
return new MoveChoice(owner, move, targetSide, targetPosition);
}
}