Implements AI Switching
All checks were successful
Build / Build (push) Successful in 58s

This commit is contained in:
2025-07-12 13:03:00 +02:00
parent 364d4b9080
commit bf83b25238
34 changed files with 903 additions and 226 deletions

View File

@@ -60,10 +60,10 @@ public class ChangeUserAttack : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Attack);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) => WouldMoveFail(option, Statistic.Attack);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.Attack, ref score);
}
@@ -75,10 +75,10 @@ public class ChangeUserDefense : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Defense);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) => WouldMoveFail(option, Statistic.Defense);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.Defense, ref score);
}
@@ -90,10 +90,11 @@ public class ChangeUserSpecialAttack : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.SpecialAttack);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) =>
WouldMoveFail(option, Statistic.SpecialAttack);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.SpecialAttack, ref score);
}
@@ -105,10 +106,11 @@ public class ChangeUserSpecialDefense : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.SpecialDefense);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) =>
WouldMoveFail(option, Statistic.SpecialDefense);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.SpecialDefense, ref score);
}
@@ -120,10 +122,10 @@ public class ChangeUserSpeed : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Speed);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) => WouldMoveFail(option, Statistic.Speed);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.Speed, ref score);
}
@@ -135,10 +137,10 @@ public class ChangeUserAccuracy : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Accuracy);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) => WouldMoveFail(option, Statistic.Accuracy);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.Accuracy, ref score);
}
@@ -150,9 +152,9 @@ public class ChangeUserEvasion : ChangeUserStats
}
[AIMoveFailureFunction]
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Evasion);
public static bool AIMoveWillFail(IExplicitAI ai, MoveOption option) => WouldMoveFail(option, Statistic.Evasion);
[AIMoveScoreFunction]
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
public static void AIMoveEffectScore(IExplicitAI ai, MoveOption option, ref int score) =>
GetMoveEffectScore(option, Statistic.Evasion, ref score);
}

View File

@@ -8,25 +8,7 @@ public class Conversion2 : Script, IScriptOnSecondaryEffect
{
var previousTurnChoices = target.BattleData?.Battle.PreviousTurnChoices;
var nextExecutingChoice = target.BattleData?.Battle.ChoiceQueue?.Peek();
var lastMoveByTarget = previousTurnChoices?
// The previous turn choices include the choices of the current turn, so we need to have special handling for
// the current turn
.Select((x, index) =>
{
// All choices before the current turn are valid
if (index < previousTurnChoices.Count - 1)
return x;
// If there is no next choice, we're at the end of the list, so we can just return the whole list
if (nextExecutingChoice == null)
return x;
// Otherwise we determine where the next choice is and return everything before that
var indexOfNext = x.IndexOf(nextExecutingChoice);
if (indexOfNext == -1)
return x;
return x.Take(indexOfNext);
}).SelectMany(x => x)
// We only want the last move choice by the target
.OfType<IMoveChoice>().FirstOrDefault(x => x.User == target);
var lastMoveByTarget = target.BattleData?.LastMoveChoice;
if (lastMoveByTarget == null)
{
move.GetHitData(target, hit).Fail();

View File

@@ -8,8 +8,7 @@ public class Copycat : Script, IScriptChangeMove
/// <inheritdoc />
public void ChangeMove(IMoveChoice choice, ref StringKey moveName)
{
var lastMove = choice.User.BattleData?.Battle.PreviousTurnChoices.SelectMany(x => x).OfType<IMoveChoice>()
.LastOrDefault();
var lastMove = choice.User.BattleData?.LastMoveChoice;
if (lastMove == null || !lastMove.ChosenMove.MoveData.CanCopyMove())
{
choice.Fail();

View File

@@ -11,8 +11,7 @@ public class Disable : Script, IScriptOnSecondaryEffect
var battleData = move.User.BattleData;
if (battleData == null)
return;
var choiceQueue = battleData.Battle.PreviousTurnChoices;
var lastMove = choiceQueue.SelectMany(x => x).OfType<IMoveChoice>().LastOrDefault(x => x.User == target);
var lastMove = target.BattleData?.LastMoveChoice;
if (lastMove == null)
{
move.GetHitData(target, hit).Fail();

View File

@@ -12,9 +12,7 @@ public class Encore : Script, IScriptOnSecondaryEffect
if (battle == null)
return;
var currentTurn = battle.ChoiceQueue!.LastRanChoice;
var lastMove = battle.PreviousTurnChoices.SelectMany(x => x).OfType<IMoveChoice>()
.TakeWhile(x => !Equals(x, currentTurn)).LastOrDefault(x => x.User == target);
var lastMove = target.BattleData?.LastMoveChoice;
if (lastMove == null || battle.Library.MiscLibrary.IsReplacementChoice(lastMove))
{
move.GetHitData(target, hit).Fail();

View File

@@ -11,7 +11,7 @@ public class FusionBolt : Script, IScriptChangeDamageModifier
return;
// Grab the choices for the current turn, that have been executed before this move.
var choice = battleData.Battle.PreviousTurnChoices.Last().TakeWhile(x => x != move.MoveChoice)
var choice = battleData.Battle.PreviousTurnChoices.Last().TakeWhile(x => !Equals(x, move.MoveChoice))
// Of these, find the move choice that used Fusion Flare.
.OfType<MoveChoice>().FirstOrDefault(x => x.ChosenMove.MoveData.Name == "fusion_flare");

View File

@@ -11,7 +11,7 @@ public class FusionFlare : Script, IScriptChangeDamageModifier
return;
// Grab the choices for the current turn, that have been executed before this move.
var choice = battleData.Battle.PreviousTurnChoices.Last().TakeWhile(x => x != move.MoveChoice)
var choice = battleData.Battle.PreviousTurnChoices.Last().TakeWhile(x => !Equals(x, move.MoveChoice))
// Of these, find the move choice that used Fusion Bolt.
.OfType<MoveChoice>().FirstOrDefault(x => x.ChosenMove.MoveData.Name == "fusion_bolt");

View File

@@ -14,8 +14,7 @@ public class Instruct : Script, IScriptOnSecondaryEffect
if (battleData == null)
return;
var lastMoveChoiceByTarget = battleData.Battle.PreviousTurnChoices.SelectMany(x => x).Reverse()
.SkipWhile(x => x != move.MoveChoice).OfType<MoveChoice>().FirstOrDefault(x => x.User == target);
var lastMoveChoiceByTarget = target.BattleData?.LastMoveChoice;
if (lastMoveChoiceByTarget == null || !battleData.Battle.CanUse(lastMoveChoiceByTarget))
{

View File

@@ -21,8 +21,7 @@ public class Sketch : Script, IScriptOnSecondaryEffect
return;
}
var choiceQueue = move.Battle.PreviousTurnChoices;
var lastMove = choiceQueue.SelectMany(x => x).OfType<IMoveChoice>().LastOrDefault(x => x.User == target);
var lastMove = target.BattleData?.LastMoveChoice;
if (lastMove == null || lastMove.ChosenMove.MoveData.HasFlag("not_sketchable"))
{
move.GetHitData(target, hit).Fail();

View File

@@ -6,8 +6,7 @@ public class Spite : Script, IScriptOnSecondaryEffect
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var lastMoveChoiceByTarget = move.Battle.PreviousTurnChoices.SelectMany(x => x).Reverse()
.SkipWhile(x => x != move.MoveChoice).OfType<MoveChoice>().FirstOrDefault(x => x.User == target);
var lastMoveChoiceByTarget = target.BattleData?.LastMoveChoice;
if (lastMoveChoiceByTarget == null || lastMoveChoiceByTarget.HasFailed)
{
move.GetHitData(target, hit).Fail();

View File

@@ -6,8 +6,7 @@ public class StompingTantrum : Script, IScriptChangeBasePower
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
var lastMoveChoice = move.Battle.PreviousTurnChoices.Reverse().Skip(1).SelectMany(x => x.Reverse())
.OfType<IMoveChoice>().FirstOrDefault(x => x.User == move.User);
var lastMoveChoice = move.User.BattleData?.LastMoveChoice;
if (lastMoveChoice is { HasFailed: true })
{
basePower = basePower.MultiplyOrMax(2);

View File

@@ -6,8 +6,7 @@ public class Torment : Script, IScriptOnSecondaryEffect
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var lastTargetChoice = move.Battle.PreviousTurnChoices.SelectMany(x => x).Reverse().OfType<IMoveChoice>()
.FirstOrDefault(x => x.User == target);
var lastTargetChoice = target.BattleData?.LastMoveChoice;
target.Volatile.Add(new Pokemon.TormentEffect(lastTargetChoice));
}
}