Tweaks for setting weather
This commit is contained in:
parent
a6c73a9c04
commit
8f262cb4a6
|
@ -106,9 +106,16 @@ public interface IBattle : IScriptSource, IDeepCloneable
|
||||||
bool TrySetChoice(ITurnChoice choice);
|
bool TrySetChoice(ITurnChoice choice);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the current weather for the battle. If null is passed, this clears the weather.
|
/// The script that handles the current weather of the battle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SetWeather(StringKey? weatherName);
|
IReadOnlyScriptContainer WeatherScript { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the current weather for the battle. If null is passed, this clears the weather.
|
||||||
|
/// A duration can be passed to set the duration of the weather in turns. This duration can be modified by
|
||||||
|
/// other scripts before the weather is set through the <see cref="Script.ChangeWeatherDuration"/> script hook.
|
||||||
|
/// </summary>
|
||||||
|
bool SetWeather(StringKey? weatherName, int duration);
|
||||||
|
|
||||||
public IScriptSet Volatile { get; }
|
public IScriptSet Volatile { get; }
|
||||||
|
|
||||||
|
@ -343,28 +350,37 @@ public class BattleImpl : ScriptSource, IBattle
|
||||||
EventHook.Invoke(new EndTurnEvent());
|
EventHook.Invoke(new EndTurnEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ScriptContainer _weatherScript = new();
|
private ScriptContainer _weatherScript = new();
|
||||||
|
public IReadOnlyScriptContainer WeatherScript => _weatherScript;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void SetWeather(StringKey? weatherName)
|
public bool SetWeather(StringKey? weatherName, int duration)
|
||||||
{
|
{
|
||||||
if (weatherName.HasValue)
|
if (weatherName.HasValue)
|
||||||
{
|
{
|
||||||
if (!Library.ScriptResolver.TryResolve(ScriptCategory.Weather, weatherName.Value, null, out var script))
|
if (!Library.ScriptResolver.TryResolve(ScriptCategory.Weather, weatherName.Value, null, out var script))
|
||||||
throw new InvalidOperationException($"Weather script {weatherName} not found.");
|
throw new InvalidOperationException($"Weather script {weatherName} not found.");
|
||||||
|
|
||||||
|
if (script is IWeatherScript weatherScript)
|
||||||
|
{
|
||||||
|
this.RunScriptHook(x => x.ChangeWeatherDuration(weatherName.Value, ref duration));
|
||||||
|
weatherScript.SetTurns(duration);
|
||||||
|
}
|
||||||
|
|
||||||
_weatherScript.Set(script);
|
_weatherScript.Set(script);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_weatherScript.Clear();
|
_weatherScript.Clear();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// TODO: Trigger weather change script hooks
|
// TODO: Trigger weather change script hooks
|
||||||
}
|
}
|
||||||
|
|
||||||
public IScriptSet Volatile { get; } = new ScriptSet();
|
public IScriptSet Volatile { get; } = new ScriptSet();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public StringKey? WeatherName => _weatherScript.Script?.Name;
|
public StringKey? WeatherName => WeatherScript.Script?.Name;
|
||||||
|
|
||||||
private readonly ScriptContainer _terrainScript = new();
|
private readonly ScriptContainer _terrainScript = new();
|
||||||
|
|
||||||
|
@ -415,7 +431,7 @@ public class BattleImpl : ScriptSource, IBattle
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts)
|
public override void GetOwnScripts(List<IEnumerable<ScriptContainer>> scripts)
|
||||||
{
|
{
|
||||||
scripts.Add(_weatherScript);
|
scripts.Add(WeatherScript);
|
||||||
scripts.Add(_terrainScript);
|
scripts.Add(_terrainScript);
|
||||||
scripts.Add(Volatile);
|
scripts.Add(Volatile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -814,6 +814,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
||||||
public void SuppressAbility()
|
public void SuppressAbility()
|
||||||
{
|
{
|
||||||
AbilitySuppressed = true;
|
AbilitySuppressed = true;
|
||||||
|
AbilityScript.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -1130,6 +1131,15 @@ public class PokemonImpl : ScriptSource, IPokemon
|
||||||
public void ChangeAbility(IAbility ability)
|
public void ChangeAbility(IAbility ability)
|
||||||
{
|
{
|
||||||
OverrideAbility = ability;
|
OverrideAbility = ability;
|
||||||
|
if (Library.ScriptResolver.TryResolve(ScriptCategory.Ability, ability.Name, ability.Parameters,
|
||||||
|
out var abilityScript))
|
||||||
|
{
|
||||||
|
AbilityScript.Set(abilityScript);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AbilityScript.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
|
||||||
|
public interface IWeatherScript
|
||||||
|
{
|
||||||
|
public void SetTurns(int turns);
|
||||||
|
}
|
|
@ -559,4 +559,8 @@ public abstract class Script : IDeepCloneable
|
||||||
ref int modifiedAccuracy)
|
ref int modifiedAccuracy)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void ChangeWeatherDuration(StringKey weatherName, ref int duration)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,11 +4,24 @@ using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
namespace PkmnLib.Dynamic.ScriptHandling;
|
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
|
||||||
|
public interface IReadOnlyScriptContainer : IEnumerable<ScriptContainer>, IDeepCloneable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this container is empty.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEmpty { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The script in this container.
|
||||||
|
/// </summary>
|
||||||
|
public Script? Script { get; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A holder class for a script. This is used so we can cache a list of these, and iterate over them, even when
|
/// A holder class for a script. This is used so we can cache a list of these, and iterate over them, even when
|
||||||
/// the underlying script changes.
|
/// the underlying script changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ScriptContainer : IEnumerable<ScriptContainer>, IDeepCloneable
|
public class ScriptContainer : IReadOnlyScriptContainer
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="ScriptContainer"/>
|
/// <inheritdoc cref="ScriptContainer"/>
|
||||||
public ScriptContainer()
|
public ScriptContainer()
|
||||||
|
@ -21,15 +34,11 @@ public class ScriptContainer : IEnumerable<ScriptContainer>, IDeepCloneable
|
||||||
Script = script;
|
Script = script;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Whether this container is empty.
|
|
||||||
/// </summary>
|
|
||||||
[MemberNotNullWhen(false, nameof(ScriptHandling.Script))]
|
[MemberNotNullWhen(false, nameof(ScriptHandling.Script))]
|
||||||
public bool IsEmpty => Script is null;
|
public bool IsEmpty => Script is null;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// The script in this container.
|
|
||||||
/// </summary>
|
|
||||||
public Script? Script { get; private set; }
|
public Script? Script { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -4766,7 +4766,13 @@
|
||||||
"priority": 0,
|
"priority": 0,
|
||||||
"target": "All",
|
"target": "All",
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": []
|
"flags": [],
|
||||||
|
"effect": {
|
||||||
|
"name": "set_weather",
|
||||||
|
"parameters": {
|
||||||
|
"weather": "hail"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hammer_arm",
|
"name": "hammer_arm",
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "set_weather")]
|
||||||
|
public class SetWeather : Script
|
||||||
|
{
|
||||||
|
private string _weather = null!;
|
||||||
|
private int _defaultTurns = 5;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||||
|
{
|
||||||
|
if (!parameters!.TryGetValue("weather", out var weather) || weather is null)
|
||||||
|
{
|
||||||
|
throw new Exception("Weather not provided.");
|
||||||
|
}
|
||||||
|
_weather = weather!.ToString();
|
||||||
|
if (parameters.TryGetValue("turns", out var turns) && turns is int turn)
|
||||||
|
{
|
||||||
|
_defaultTurns = turn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
target.BattleData?.Battle.SetWeather(_weather, _defaultTurns);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,20 +6,15 @@ using PkmnLib.Static.Utils;
|
||||||
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
|
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
|
||||||
|
|
||||||
[Script(ScriptCategory.Weather, "hail")]
|
[Script(ScriptCategory.Weather, "hail")]
|
||||||
public class Hail : Script
|
public class Hail : Script, IWeatherScript
|
||||||
{
|
{
|
||||||
public static void RegisterHailIgnoreAbility(StringKey abilityName)
|
private int? _duration;
|
||||||
{
|
|
||||||
_hailIgnoreAbilities.Add(abilityName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly HashSet<StringKey> _hailIgnoreAbilities =
|
/// <inheritdoc />
|
||||||
[
|
public void SetTurns(int turns)
|
||||||
"ice_body",
|
{
|
||||||
"magic_guard",
|
_duration = turns;
|
||||||
"overcoat",
|
}
|
||||||
"snow_cloak",
|
|
||||||
];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnEndTurn(IBattle battle)
|
public override void OnEndTurn(IBattle battle)
|
||||||
|
@ -36,14 +31,22 @@ public class Hail : Script
|
||||||
continue;
|
continue;
|
||||||
if (pokemon.Types.Contains(iceType))
|
if (pokemon.Types.Contains(iceType))
|
||||||
continue;
|
continue;
|
||||||
if (pokemon.ActiveAbility != null && _hailIgnoreAbilities.Contains(pokemon.ActiveAbility.Name))
|
var ignoresHail = false;
|
||||||
|
pokemon.RunScriptHook(x => x.CustomTrigger("ignores_hail", new Dictionary<StringKey, object?>()
|
||||||
|
{
|
||||||
|
{ "ignoresHail", ignoresHail },
|
||||||
|
}));
|
||||||
|
if (ignoresHail)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var maxHealth = pokemon.BoostedStats.Hp;
|
var maxHealth = pokemon.BoostedStats.Hp;
|
||||||
var damage = maxHealth / 16;
|
var damage = maxHealth / 16;
|
||||||
// TODO: Consider Safety Goggles. Handle it inside the Damage method?
|
|
||||||
pokemon.Damage(damage, DamageSource.Weather, new EventBatchId());
|
pokemon.Damage(damage, DamageSource.Weather, new EventBatchId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_duration--;
|
||||||
|
if (_duration <= 0)
|
||||||
|
RemoveSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue