More moves, allow for typeless moves
This commit is contained in:
@@ -47,7 +47,7 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
||||
floatDamage = MathF.Floor(floatDamage * randomFactor);
|
||||
}
|
||||
|
||||
if (executingMove.User.Types.Contains(hitData.Type))
|
||||
if (hitData.Type != null && executingMove.User.Types.Contains(hitData.Type.Value))
|
||||
{
|
||||
var stabModifier = 1.5f;
|
||||
executingMove.RunScriptHook(script =>
|
||||
|
||||
@@ -25,7 +25,7 @@ public class FutureSightEffect : Script
|
||||
}
|
||||
var damageCalculator = battle.Library.DamageCalculator;
|
||||
var executingMove = new ExecutingMoveImpl([target], 1, _moveChoice.ChosenMove,
|
||||
_moveChoice.ChosenMove.MoveData, _moveChoice);
|
||||
_moveChoice.ChosenMove.MoveData, _moveChoice, battle);
|
||||
var hitData = executingMove.GetHitData(target, 0);
|
||||
var damage = damageCalculator.GetDamage(executingMove, target, 1, hitData);
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Battle;
|
||||
public class IonDelugeEffect : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
if (moveType.Name == "normal" &&
|
||||
if (moveType?.Name == "normal" &&
|
||||
target.Library.StaticLibrary.Types.TryGetTypeIdentifier("electric", out var electricType))
|
||||
{
|
||||
moveType = electricType;
|
||||
|
||||
@@ -13,4 +13,6 @@ public static class CustomTriggers
|
||||
public static readonly StringKey IgnoreHail = "ignores_hail";
|
||||
|
||||
public static readonly StringKey LightScreenNumberOfTurns = "light_screen_number_of_turns";
|
||||
|
||||
public static readonly StringKey ReflectNumberOfTurns = "reflect_number_of_turns";
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.MoveVolatile;
|
||||
public class ElectrifyEffect : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
var battleData = target.BattleData;
|
||||
if (battleData == null)
|
||||
|
||||
@@ -7,13 +7,14 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
public class HiddenPower : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
var ivs = move.User.IndividualValues;
|
||||
|
||||
var type = GetHiddenPowerValue(ivs, 0x00000001) * 15 / 63;
|
||||
|
||||
move.User.Library.StaticLibrary.Types.TryGetTypeIdentifierFromIndex((byte)(type + 2), out moveType);
|
||||
if (move.User.Library.StaticLibrary.Types.TryGetTypeIdentifierFromIndex((byte)(type + 2), out var t))
|
||||
moveType = t;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
public class Judgement : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
var heldItem = move.User.HeldItem;
|
||||
if (heldItem == null)
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
public class MultiAttack : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
var item = move.User.HeldItem?.Name.ToString();
|
||||
var typeLibrary = move.User.Library.StaticLibrary.Types;
|
||||
@@ -15,6 +15,7 @@ public class MultiAttack : Script
|
||||
return;
|
||||
|
||||
var memoryType = item[..^7];
|
||||
typeLibrary.TryGetTypeIdentifier(memoryType, out moveType);
|
||||
if (typeLibrary.TryGetTypeIdentifier(memoryType, out var t))
|
||||
moveType = t;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class NaturalGift : Script
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
var naturalGiftData = GetNaturalGiftData(move.User.HeldItem);
|
||||
if (naturalGiftData == null)
|
||||
|
||||
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Recycle.cs
Normal file
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Recycle.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "recycle")]
|
||||
public class Recycle : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.User.HeldItem is not null)
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData is null)
|
||||
return;
|
||||
var lastItem = battleData.BattleSide.GetLastConsumedItem(battleData.Position);
|
||||
if (lastItem is null)
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
_ = move.User.SetHeldItem(lastItem);
|
||||
}
|
||||
}
|
||||
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Reflect.cs
Normal file
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Reflect.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "reflect")]
|
||||
public class Reflect : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData is null)
|
||||
return;
|
||||
var numberOfTurns = 5;
|
||||
var dict = new Dictionary<StringKey, object?>
|
||||
{
|
||||
{ "duration", numberOfTurns },
|
||||
};
|
||||
move.User.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ReflectNumberOfTurns, dict));
|
||||
numberOfTurns = (int)dict.GetOrDefault("duration", numberOfTurns)!;
|
||||
|
||||
battleData.BattleSide.VolatileScripts.Add(new Side.ReflectEffect(numberOfTurns));
|
||||
}
|
||||
}
|
||||
12
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/ReflectType.cs
Normal file
12
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/ReflectType.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "reflect_type")]
|
||||
public class ReflectType : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var targetTypes = target.Types;
|
||||
move.User.SetTypes(targetTypes);
|
||||
}
|
||||
}
|
||||
23
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Refresh.cs
Normal file
23
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Refresh.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "refresh")]
|
||||
public class Refresh : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var userStatus = move.User.StatusScript;
|
||||
switch (userStatus.Script?.Name)
|
||||
{
|
||||
case "paralyzed":
|
||||
case "burned":
|
||||
case "poisoned":
|
||||
case "badly_poisoned":
|
||||
move.User.ClearStatus();
|
||||
break;
|
||||
default:
|
||||
move.GetHitData(target, hit).Fail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rest.cs
Normal file
24
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rest.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Status;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "rest")]
|
||||
public class Rest : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.User.HasStatus(ScriptUtils.ResolveName<Sleep>()))
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
if (!move.User.Heal(move.User.MaxHealth, false, forceHeal: false))
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
move.User.SetStatus(ScriptUtils.ResolveName<Sleep>());
|
||||
((Sleep)move.User.StatusScript.Script!).Turns = 2;
|
||||
}
|
||||
}
|
||||
24
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Retaliate.cs
Normal file
24
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Retaliate.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Linq;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "retaliate")]
|
||||
public class Retaliate : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
|
||||
{
|
||||
var battleData = move.User.BattleData;
|
||||
if (battleData is null)
|
||||
return;
|
||||
|
||||
var lastFaint = battleData.BattleSide.GetLastFaintTurn();
|
||||
if (lastFaint == null)
|
||||
return;
|
||||
if (lastFaint >= battleData.Battle.CurrentTurnNumber - 1)
|
||||
{
|
||||
basePower = basePower.MultiplyOrMax(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Return.cs
Normal file
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Return.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "return")]
|
||||
public class Return : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
|
||||
{
|
||||
var friendship = move.User.Happiness;
|
||||
var power = friendship * 2 / 5;
|
||||
// The power is capped at 102, but as friendship is a byte, and thus max 255, this is already heuristically
|
||||
// capped (255 * 2 / 5 = 102).
|
||||
if (power < 1)
|
||||
power = 1;
|
||||
basePower = (byte)power;
|
||||
}
|
||||
}
|
||||
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/RevelationDance.cs
Normal file
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/RevelationDance.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PkmnLib.Static;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "revelation_dance")]
|
||||
public class RevelationDance : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
|
||||
{
|
||||
// The type of the move is the same as the user's first type.
|
||||
var user = move.User;
|
||||
if (user.Types.Count > 0)
|
||||
{
|
||||
moveType = user.Types[0];
|
||||
}
|
||||
// If the user has no types, the move is typeless.
|
||||
else
|
||||
{
|
||||
moveType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Roar.cs
Normal file
7
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Roar.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "roar")]
|
||||
public class Roar : Script
|
||||
{
|
||||
// FIXME: Implement roar
|
||||
}
|
||||
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/RolePlay.cs
Normal file
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/RolePlay.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "role_play")]
|
||||
public class RolePlay : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var ability = target.ActiveAbility;
|
||||
if (ability is null || ability.HasFlag("cant_be_copied"))
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
move.User.ChangeAbility(ability);
|
||||
}
|
||||
}
|
||||
14
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Roost.cs
Normal file
14
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Roost.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "roost")]
|
||||
public class Roost : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
target.Heal(target.MaxHealth / 2);
|
||||
target.Volatile.Add(new RoostEffect());
|
||||
}
|
||||
}
|
||||
22
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rototiller.cs
Normal file
22
Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rototiller.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Linq;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "rototiller")]
|
||||
public class Rototiller : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var pokemon = move.Battle.Sides.SelectMany(x => x.Pokemon).WhereNotNull()
|
||||
.Where(x => x.Types.Any(y => y.Name == "grass"));
|
||||
EventBatchId batchId = new();
|
||||
foreach (var pkmn in pokemon)
|
||||
{
|
||||
pkmn.ChangeStatBoost(Statistic.Attack, 1, pkmn == move.User, batchId);
|
||||
pkmn.ChangeStatBoost(Statistic.SpecialAttack, 1, pkmn == move.User, batchId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ public class PowderEffect : Script
|
||||
public override void BlockOutgoingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||
{
|
||||
var hit = executingMove.GetHitData(target, hitIndex);
|
||||
if (hit.Type.Name == "fire")
|
||||
if (hit.Type?.Name == "fire")
|
||||
{
|
||||
executingMove.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("powder_explodes",
|
||||
new Dictionary<string, object>
|
||||
|
||||
19
Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/RoostEffect.cs
Normal file
19
Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/RoostEffect.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
[Script(ScriptCategory.Pokemon, "roost_effect")]
|
||||
public class RoostEffect : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeTypesForIncomingMove(IExecutingMove executingMove, IPokemon target, byte hitIndex,
|
||||
IList<TypeIdentifier> types)
|
||||
{
|
||||
types.RemoveAll(x => x.Name == "flying");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnEndTurn(IBattle battle) => RemoveSelf();
|
||||
}
|
||||
@@ -1,7 +1,40 @@
|
||||
using PkmnLib.Static.Moves;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
|
||||
|
||||
[Script(ScriptCategory.Side, "reflect")]
|
||||
public class ReflectEffect : Script
|
||||
public class ReflectEffect(int turns) : Script
|
||||
{
|
||||
// TODO: Implement ReflectEffect
|
||||
private int _turns = turns;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
|
||||
{
|
||||
var hitData = move.GetHitData(target, hit);
|
||||
if (move.UseMove.Category != MoveCategory.Physical)
|
||||
return;
|
||||
if (hitData.IsCritical)
|
||||
return;
|
||||
switch (move.Battle.PositionsPerSide)
|
||||
{
|
||||
case 1:
|
||||
damage /= 2;
|
||||
break;
|
||||
default:
|
||||
damage *= 2 / 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnEndTurn(IBattle battle)
|
||||
{
|
||||
if (_turns > 0)
|
||||
{
|
||||
_turns--;
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveSelf();
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,5 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Status;
|
||||
[Script(ScriptCategory.Status, "sleep")]
|
||||
public class Sleep : Script
|
||||
{
|
||||
public int Turns { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user