This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -3,20 +3,20 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
[Script(ScriptCategory.Pokemon, "perish_song")]
|
||||
public class PerishSongEffect : Script, IScriptOnEndTurn
|
||||
{
|
||||
private int _turns;
|
||||
internal int Turns { get; private set; }
|
||||
private IPokemon _owner;
|
||||
|
||||
public PerishSongEffect(IPokemon owner, int turns = 3)
|
||||
{
|
||||
_owner = owner;
|
||||
_turns = turns;
|
||||
Turns = turns;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnEndTurn(IScriptSource owner, IBattle battle)
|
||||
{
|
||||
_turns--;
|
||||
if (_turns <= 0)
|
||||
Turns--;
|
||||
if (Turns <= 0)
|
||||
{
|
||||
RemoveSelf();
|
||||
_owner.Faint(DamageSource.Misc);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
|
||||
|
||||
[Script(ScriptCategory.Side, "spikes")]
|
||||
public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack
|
||||
public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack, IAIInfoScriptExpectedEntryDamage
|
||||
{
|
||||
private int _layers = 1;
|
||||
|
||||
@@ -18,14 +18,7 @@ public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack
|
||||
if (pokemon.IsFloating)
|
||||
return;
|
||||
|
||||
var modifier = _layers switch
|
||||
{
|
||||
1 => 1 / 16f,
|
||||
2 => 3 / 16f,
|
||||
3 => 1 / 4f,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
var damage = (uint)(pokemon.MaxHealth * modifier);
|
||||
var damage = CalculateDamage(pokemon);
|
||||
|
||||
EventBatchId eventBatch = new();
|
||||
pokemon.Damage(damage, DamageSource.Misc, eventBatch);
|
||||
@@ -37,4 +30,26 @@ public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack
|
||||
BatchId = eventBatch,
|
||||
});
|
||||
}
|
||||
|
||||
private uint CalculateDamage(IPokemon pokemon)
|
||||
{
|
||||
var modifier = _layers switch
|
||||
{
|
||||
1 => 1 / 16f,
|
||||
2 => 3 / 16f,
|
||||
3 => 1 / 4f,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
var damage = (uint)(pokemon.MaxHealth * modifier);
|
||||
return damage;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ExpectedEntryDamage(IPokemon pokemon, ref uint damage)
|
||||
{
|
||||
if (pokemon.IsFloating)
|
||||
return;
|
||||
|
||||
damage += CalculateDamage(pokemon);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,12 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
|
||||
|
||||
[Script(ScriptCategory.Side, "stealth_rock")]
|
||||
public class StealthRockEffect : Script, IScriptOnSwitchIn
|
||||
public class StealthRockEffect : Script, IScriptOnSwitchIn, IAIInfoScriptExpectedEntryDamage
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void OnSwitchIn(IPokemon pokemon, byte position)
|
||||
{
|
||||
var typeLibrary = pokemon.Library.StaticLibrary.Types;
|
||||
var effectiveness = 1.0f;
|
||||
if (typeLibrary.TryGetTypeIdentifier("rock", out var rockType))
|
||||
{
|
||||
effectiveness = typeLibrary.GetEffectiveness(rockType, pokemon.Types);
|
||||
}
|
||||
var damage = (uint)(pokemon.MaxHealth / 8f * effectiveness);
|
||||
var damage = CalculateStealthRockDamage(pokemon);
|
||||
EventBatchId batchId = new();
|
||||
pokemon.Damage(damage, DamageSource.Misc, batchId);
|
||||
pokemon.BattleData?.Battle.EventHook.Invoke(new DialogEvent("stealth_rock_damage",
|
||||
@@ -21,4 +15,21 @@ public class StealthRockEffect : Script, IScriptOnSwitchIn
|
||||
{ "pokemon", pokemon },
|
||||
}));
|
||||
}
|
||||
|
||||
private static uint CalculateStealthRockDamage(IPokemon pokemon)
|
||||
{
|
||||
var typeLibrary = pokemon.Library.StaticLibrary.Types;
|
||||
var effectiveness = 1.0f;
|
||||
if (typeLibrary.TryGetTypeIdentifier("rock", out var rockType))
|
||||
{
|
||||
effectiveness = typeLibrary.GetEffectiveness(rockType, pokemon.Types);
|
||||
}
|
||||
return (uint)(pokemon.MaxHealth / 8f * effectiveness);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ExpectedEntryDamage(IPokemon pokemon, ref uint damage)
|
||||
{
|
||||
damage += CalculateStealthRockDamage(pokemon);
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,15 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Status;
|
||||
[Script(ScriptCategory.Status, "badly_poisoned")]
|
||||
public class BadlyPoisoned : Poisoned
|
||||
{
|
||||
private int _turns = 1;
|
||||
internal int Turns { get; private set; } = 1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override float GetPoisonMultiplier() => 1f / (16f * _turns);
|
||||
public override float GetPoisonMultiplier() => 1f / (16f * Turns);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnEndTurn(IScriptSource owner, IBattle battle)
|
||||
{
|
||||
base.OnEndTurn(owner, battle);
|
||||
_turns = Math.Min(_turns + 1, 15);
|
||||
Turns = Math.Min(Turns + 1, 15);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user