Implements more move effects

This commit is contained in:
Deukhoofd 2025-03-07 16:16:22 +01:00
parent 2c987e32ee
commit a6c73a9c04
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
15 changed files with 251 additions and 11 deletions

View File

@ -80,6 +80,12 @@ public interface ILearnedMove : IDeepCloneable
/// Restore the remaining PP by a certain amount. Will prevent it from going above max PP. /// Restore the remaining PP by a certain amount. Will prevent it from going above max PP.
/// </summary> /// </summary>
void RestoreUses(byte amount); void RestoreUses(byte amount);
/// <summary>
/// Forcibly set the remaining PP to a certain amount.
/// </summary>
/// <param name="uses"></param>
void SetCurrentPP(byte uses);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -136,4 +142,10 @@ public class LearnedMoveImpl : ILearnedMove
/// Restore the PP by a certain amount. This will prevent the PP from going above the maximum PP. /// Restore the PP by a certain amount. This will prevent the PP from going above the maximum PP.
/// </summary> /// </summary>
public void RestoreUses(byte amount) => CurrentPp = (byte)Math.Min(CurrentPp + amount, MaxPp); public void RestoreUses(byte amount) => CurrentPp = (byte)Math.Min(CurrentPp + amount, MaxPp);
/// <inheritdoc />
public void SetCurrentPP(byte uses)
{
CurrentPp = Math.Min(uses, MaxPp);
}
} }

View File

@ -1091,6 +1091,7 @@ public class PokemonImpl : ScriptSource, IPokemon
Types = Form.Types; Types = Form.Types;
OverrideAbility = null; OverrideAbility = null;
AbilitySuppressed = false; AbilitySuppressed = false;
RecalculateFlatStats();
} }
} }
} }

View File

@ -21,7 +21,7 @@ public interface IScriptSet : IEnumerable<ScriptContainer>
/// Adds a script with a name to the set. If the script with that name already exists in this /// Adds a script with a name to the set. If the script with that name already exists in this
/// set, this makes that script stack instead. The return value here is that script. /// set, this makes that script stack instead. The return value here is that script.
/// </summary> /// </summary>
ScriptContainer? StackOrAdd(StringKey scriptKey, Func<Script> instantiation); ScriptContainer? StackOrAdd(StringKey scriptKey, Func<Script?> instantiation);
/// <summary> /// <summary>
/// Gets a script from the set using its unique name. /// Gets a script from the set using its unique name.

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PP/@EntryIndexedValue">PP</s:String></wpf:ResourceDictionary>

View File

@ -4572,7 +4572,10 @@
"category": "status", "category": "status",
"flags": [ "flags": [
"nonskybattle" "nonskybattle"
] ],
"effect": {
"name": "gravity"
}
}, },
{ {
"name": "growl", "name": "growl",
@ -4609,7 +4612,14 @@
"category": "status", "category": "status",
"flags": [ "flags": [
"snatch" "snatch"
] ],
"effect": {
"name": "change_multiple_user_stat_boosts",
"parameters": {
"attack": 1,
"specialAttack": 1
}
}
}, },
{ {
"name": "grudge", "name": "grudge",
@ -4622,7 +4632,10 @@
"category": "status", "category": "status",
"flags": [ "flags": [
"ignore-substitute" "ignore-substitute"
] ],
"effect": {
"name": "grudge"
}
}, },
{ {
"name": "guard_split", "name": "guard_split",
@ -4650,7 +4663,10 @@
"protect", "protect",
"mirror", "mirror",
"ignore-substitute" "ignore-substitute"
] ],
"effect": {
"name": "guard_swap"
}
}, },
{ {
"name": "guardian_of_alola", "name": "guardian_of_alola",
@ -4661,7 +4677,10 @@
"priority": 0, "priority": 0,
"target": "Any", "target": "Any",
"category": "special", "category": "special",
"flags": [] "flags": [],
"effect": {
"name": "guardian_of_alola"
}
}, },
{ {
"name": "guillotine", "name": "guillotine",
@ -4676,7 +4695,10 @@
"contact", "contact",
"protect", "protect",
"mirror" "mirror"
] ],
"effect": {
"name": "one_hit_ko"
}
}, },
{ {
"name": "gunk_shot", "name": "gunk_shot",
@ -4690,7 +4712,14 @@
"flags": [ "flags": [
"protect", "protect",
"mirror" "mirror"
] ],
"effect": {
"name": "set_status",
"chance": 30,
"parameters": {
"status": "poisoned"
}
}
}, },
{ {
"name": "gust", "name": "gust",
@ -4723,7 +4752,10 @@
"protect", "protect",
"mirror", "mirror",
"ballistics" "ballistics"
] ],
"effect": {
"name": "gyro_ball"
}
}, },
{ {
"name": "hail", "name": "hail",

View File

@ -0,0 +1,35 @@
using System.Linq;
namespace PkmnLib.Plugin.Gen7.Scripts.Battle;
[Script(ScriptCategory.Battle, "gravity")]
public class Gravity : Script
{
/// <inheritdoc />
public override void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
{
var battleData = target.BattleData;
if (battleData == null)
return;
if (move.UseMove.MoveType.Name == "ground")
{
var targetTypes = target.Types;
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
effectiveness =
// Get the effectiveness of the move against each target type
targetTypes.Select(x => typeLibrary.GetSingleEffectiveness(move.UseMove.MoveType, x))
// Ignore all types that are immune to ground moves
.Where(x => x > 0)
// Multiply all effectiveness values together
.Aggregate(1.0f, (current, x) => current * x);
}
}
/// <inheritdoc />
public override void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail)
{
if (move.UseMove.HasFlag("gravity"))
fail = true;
}
}

View File

@ -22,7 +22,7 @@ public class ChangeMultipleUserStatBoosts : Script
foreach (var par in parameters) foreach (var par in parameters)
{ {
if (!Enum.TryParse<Statistic>(par.Key, true, out var stat)) if (!Enum.TryParse<Statistic>(par.Key, true, out var stat))
continue; throw new ArgumentException($"Invalid stat name: {par.Key}");
if (par.Value is sbyte value) if (par.Value is sbyte value)
{ {
_statBoosts[stat] = value; _statBoosts[stat] = value;

View File

@ -9,6 +9,6 @@ public class Frustration : Script
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower) public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{ {
var friendship = move.User.Happiness; var friendship = move.User.Happiness;
basePower = Math.Min((byte)1, (byte)((255 - friendship) * 2 / 5)); basePower = Math.Max((byte)1, (byte)((255 - friendship) * 2 / 5));
} }
} }

View File

@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Linq;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "gravity")]
public class Gravity : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = target.BattleData;
if (battleData == null)
return;
battleData.Battle.Volatile.StackOrAdd("gravity", () =>
{
battleData.Battle.Library.ScriptResolver.TryResolve(ScriptCategory.Battle, "gravity",
new Dictionary<StringKey, object?>(), out var script);
return script;
});
foreach (var pokemon in battleData.Battle.Sides.SelectMany(x => x.Pokemon).WhereNotNull())
{
var chargeBounceEffect = ScriptUtils.ResolveName<ChargeBounceEffect>();
if (pokemon.Volatile.Contains(chargeBounceEffect))
pokemon.Volatile.Remove(chargeBounceEffect);
var flyEffect = ScriptUtils.ResolveName<ChargeFlyEffect>();
if (pokemon.Volatile.Contains(flyEffect))
pokemon.Volatile.Remove(flyEffect);
// TODO: Sky Drop
}
}
}

View File

@ -0,0 +1,19 @@
using System.Collections.Generic;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "grudge")]
public class Grudge : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
move.User.Volatile.StackOrAdd("grudge", () =>
{
move.User.Library.ScriptResolver.TryResolve(ScriptCategory.Pokemon, "grudge",
new Dictionary<StringKey, object?>(), out var script);
return script;
});
}
}

View File

@ -0,0 +1,27 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "guard_split")]
public class GuardSplit : 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 userDefense = userStats.GetStatistic(Statistic.Defense);
var targetDefense = targetStats.GetStatistic(Statistic.Defense);
var userSpecialDefense = userStats.GetStatistic(Statistic.SpecialDefense);
var targetSpecialDefense = targetStats.GetStatistic(Statistic.SpecialDefense);
var newDefense = (userDefense + targetDefense) / 2;
var newSpecialDefense = (userSpecialDefense + targetSpecialDefense) / 2;
userStats.SetStatistic(Statistic.Defense, newDefense);
userStats.SetStatistic(Statistic.SpecialDefense, newSpecialDefense);
user.RecalculateFlatStats();
}
}

View File

@ -0,0 +1,29 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "guard_swap")]
public class GuardSwap : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
var user = move.User;
var userStats = user.StatBoost;
var targetStats = target.StatBoost;
var userDefense = userStats.GetStatistic(Statistic.Defense);
var targetDefense = targetStats.GetStatistic(Statistic.Defense);
var userSpecialDefense = userStats.GetStatistic(Statistic.SpecialDefense);
var targetSpecialDefense = targetStats.GetStatistic(Statistic.SpecialDefense);
user.ChangeStatBoost(Statistic.Defense, (sbyte)(targetDefense - userDefense), true, eventBatchId);
user.ChangeStatBoost(Statistic.SpecialDefense, (sbyte)(targetSpecialDefense - userSpecialDefense), true,
eventBatchId);
target.ChangeStatBoost(Statistic.Defense, (sbyte)(userDefense - targetDefense), false, eventBatchId);
target.ChangeStatBoost(Statistic.SpecialDefense, (sbyte)(userSpecialDefense - targetSpecialDefense), false,
eventBatchId);
}
}

View File

@ -0,0 +1,12 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "guardian_of_alola")]
public class GuardianOfAlola : Script
{
/// <inheritdoc />
public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
var maxHp = target.BoostedStats.Hp;
damage = (uint)(maxHp * (3f / 4f));
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "gyro_ball")]
public class GyroBall : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
basePower = Math.Min((byte)150, (byte)(25 * target.BoostedStats.Speed / move.User.BoostedStats.Speed + 1));
}
}

View File

@ -0,0 +1,22 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "grudge")]
public class GrudgeEffect : Script
{
private ILearnedMove? _lastMove;
/// <inheritdoc />
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
_lastMove = move.ChosenMove;
}
/// <inheritdoc />
public override void OnFaint(IPokemon pokemon, DamageSource source)
{
if (_lastMove != null && source == DamageSource.MoveDamage)
{
_lastMove.SetCurrentPP(0);
}
}
}