Imlements baneful bunker, data fixes
This commit is contained in:
parent
6434f9925c
commit
92ab67ddf8
|
@ -325,6 +325,7 @@ public class BattleImpl : ScriptSource, IBattle
|
||||||
{
|
{
|
||||||
_weatherScript.Clear();
|
_weatherScript.Clear();
|
||||||
}
|
}
|
||||||
|
// TODO: Trigger weather change script hooks
|
||||||
}
|
}
|
||||||
|
|
||||||
private IScriptSet Volatile { get; } = new ScriptSet();
|
private IScriptSet Volatile { get; } = new ScriptSet();
|
||||||
|
|
|
@ -44,8 +44,7 @@ internal static class MoveTurnExecutor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var executingMove = new ExecutingMoveImpl(targets, numberOfHits, moveChoice.User, chosenMove, moveData,
|
var executingMove = new ExecutingMoveImpl(targets, numberOfHits, chosenMove, moveData, moveChoice);
|
||||||
moveChoice.Script);
|
|
||||||
|
|
||||||
var prevented = false;
|
var prevented = false;
|
||||||
executingMove.RunScriptHook(x => x.PreventMove(executingMove, ref prevented));
|
executingMove.RunScriptHook(x => x.PreventMove(executingMove, ref prevented));
|
||||||
|
@ -151,6 +150,10 @@ internal static class MoveTurnExecutor
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var blockIncomingHit = false;
|
||||||
|
target.RunScriptHook(x => x.BlockIncomingHit(executingMove, target, hitIndex, ref blockIncomingHit));
|
||||||
|
if (blockIncomingHit)
|
||||||
|
break;
|
||||||
if (useMove.Category == MoveCategory.Status)
|
if (useMove.Category == MoveCategory.Status)
|
||||||
{
|
{
|
||||||
var secondaryEffect = useMove.SecondaryEffect;
|
var secondaryEffect = useMove.SecondaryEffect;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using PkmnLib.Dynamic.Models.Choices;
|
||||||
using PkmnLib.Dynamic.ScriptHandling;
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
using PkmnLib.Static;
|
using PkmnLib.Static;
|
||||||
using PkmnLib.Static.Moves;
|
using PkmnLib.Static.Moves;
|
||||||
|
@ -133,6 +134,11 @@ public interface IExecutingMove : IScriptSource
|
||||||
/// Gets the targets of this move.
|
/// Gets the targets of this move.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IReadOnlyList<IPokemon?> Targets { get; }
|
IReadOnlyList<IPokemon?> Targets { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The underlying move choice.
|
||||||
|
/// </summary>
|
||||||
|
IMoveChoice MoveChoice { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IExecutingMove"/>
|
/// <inheritdoc cref="IExecutingMove"/>
|
||||||
|
@ -142,15 +148,14 @@ public class ExecutingMoveImpl : ScriptSource, IExecutingMove
|
||||||
private readonly IHitData[] _hits;
|
private readonly IHitData[] _hits;
|
||||||
|
|
||||||
/// <inheritdoc cref="ExecutingMoveImpl"/>
|
/// <inheritdoc cref="ExecutingMoveImpl"/>
|
||||||
public ExecutingMoveImpl(IReadOnlyList<IPokemon?> targets, byte numberOfHits, IPokemon user, ILearnedMove chosenMove,
|
public ExecutingMoveImpl(IReadOnlyList<IPokemon?> targets, byte numberOfHits, ILearnedMove chosenMove,
|
||||||
IMoveData useMove, ScriptContainer script)
|
IMoveData useMove, IMoveChoice moveChoice)
|
||||||
{
|
{
|
||||||
_targets = targets;
|
_targets = targets;
|
||||||
NumberOfHits = numberOfHits;
|
NumberOfHits = numberOfHits;
|
||||||
User = user;
|
|
||||||
ChosenMove = chosenMove;
|
ChosenMove = chosenMove;
|
||||||
UseMove = useMove;
|
UseMove = useMove;
|
||||||
Script = script;
|
MoveChoice = moveChoice;
|
||||||
|
|
||||||
var totalHits = targets.Count * numberOfHits;
|
var totalHits = targets.Count * numberOfHits;
|
||||||
_hits = new IHitData[totalHits];
|
_hits = new IHitData[totalHits];
|
||||||
|
@ -167,7 +172,7 @@ public class ExecutingMoveImpl : ScriptSource, IExecutingMove
|
||||||
public byte NumberOfHits { get; }
|
public byte NumberOfHits { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IPokemon User { get; }
|
public IPokemon User => MoveChoice.User;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ILearnedMove ChosenMove { get; }
|
public ILearnedMove ChosenMove { get; }
|
||||||
|
@ -176,7 +181,7 @@ public class ExecutingMoveImpl : ScriptSource, IExecutingMove
|
||||||
public IMoveData UseMove { get; }
|
public IMoveData UseMove { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ScriptContainer Script { get; }
|
public ScriptContainer Script => MoveChoice.Script;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IHitData GetHitData(IPokemon target, byte hit)
|
public IHitData GetHitData(IPokemon target, byte hit)
|
||||||
|
@ -215,6 +220,9 @@ public class ExecutingMoveImpl : ScriptSource, IExecutingMove
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<IPokemon?> Targets => _targets.ToList();
|
public IReadOnlyList<IPokemon?> Targets => _targets.ToList();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IMoveChoice MoveChoice { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override int ScriptCount => 1 + User.ScriptCount;
|
public override int ScriptCount => 1 + User.ScriptCount;
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,10 @@ public interface IPokemon : IScriptSource, IDeepCloneable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void LearnMove(StringKey moveName, MoveLearnMethod method, byte index);
|
void LearnMove(StringKey moveName, MoveLearnMethod method, byte index);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a non-volatile status to the Pokemon.
|
||||||
|
/// </summary>
|
||||||
|
void SetStatus(StringKey status);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the current non-volatile status from the Pokemon.
|
/// Removes the current non-volatile status from the Pokemon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -926,6 +930,14 @@ public class PokemonImpl : ScriptSource, IPokemon
|
||||||
_learnedMoves[index] = new LearnedMoveImpl(move, method);
|
_learnedMoves[index] = new LearnedMoveImpl(move, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void SetStatus(StringKey status)
|
||||||
|
{
|
||||||
|
if (!Library.ScriptResolver.TryResolve(ScriptCategory.Status, status, null, out var statusScript))
|
||||||
|
throw new KeyNotFoundException($"Status script {status} not found");
|
||||||
|
StatusScript.Set(statusScript);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ClearStatus() => StatusScript.Clear();
|
public void ClearStatus() => StatusScript.Clear();
|
||||||
|
|
||||||
|
|
|
@ -497,4 +497,8 @@ public abstract class Script : IDeepCloneable
|
||||||
public virtual void ChangeCatchRateBonus(IPokemon pokemon, IItem pokeball, ref byte modifier)
|
public virtual void ChangeCatchRateBonus(IPokemon pokemon, IItem pokeball, ref byte modifier)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -482,7 +482,7 @@
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": [],
|
"flags": [],
|
||||||
"effect": {
|
"effect": {
|
||||||
"name": "Assist"
|
"name": "assist"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -564,7 +564,7 @@
|
||||||
"type": "fighting",
|
"type": "fighting",
|
||||||
"power": 80,
|
"power": 80,
|
||||||
"pp": 20,
|
"pp": 20,
|
||||||
"accuracy": 0,
|
"accuracy": 255,
|
||||||
"priority": 0,
|
"priority": 0,
|
||||||
"target": "Any",
|
"target": "Any",
|
||||||
"category": "special",
|
"category": "special",
|
||||||
|
@ -608,7 +608,10 @@
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": [
|
"flags": [
|
||||||
"snatch"
|
"snatch"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "aurora_veil"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "autotomize",
|
"name": "autotomize",
|
||||||
|
@ -623,7 +626,7 @@
|
||||||
"snatch"
|
"snatch"
|
||||||
],
|
],
|
||||||
"effect": {
|
"effect": {
|
||||||
"name": "automize"
|
"name": "autotomize"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -670,11 +673,14 @@
|
||||||
"type": "poison",
|
"type": "poison",
|
||||||
"power": 0,
|
"power": 0,
|
||||||
"pp": 10,
|
"pp": 10,
|
||||||
"accuracy": 0,
|
"accuracy": 255,
|
||||||
"priority": 4,
|
"priority": 4,
|
||||||
"target": "Self",
|
"target": "Self",
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": []
|
"flags": [],
|
||||||
|
"effect": {
|
||||||
|
"name": "baneful_bunker"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "barrage",
|
"name": "barrage",
|
||||||
|
@ -689,7 +695,10 @@
|
||||||
"protect",
|
"protect",
|
||||||
"mirror",
|
"mirror",
|
||||||
"ballistics"
|
"ballistics"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "2_5_hit_move"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "barrier",
|
"name": "barrier",
|
||||||
|
@ -702,7 +711,13 @@
|
||||||
"category": "status",
|
"category": "status",
|
||||||
"flags": [
|
"flags": [
|
||||||
"snatch"
|
"snatch"
|
||||||
]
|
],
|
||||||
|
"effect": {
|
||||||
|
"name": "change_target_defense",
|
||||||
|
"parameters": {
|
||||||
|
"amount": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "baton_pass",
|
"name": "baton_pass",
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Move, "baneful_bunker")]
|
||||||
|
public class BanefulBunker : ProtectionScript
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override ProtectionEffectScript GetEffectScript()
|
||||||
|
{
|
||||||
|
return new BanefulBunkerEffect();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
using System;
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||||
|
|
||||||
|
public abstract class ProtectionScript : Script
|
||||||
|
{
|
||||||
|
protected abstract ProtectionEffectScript GetEffectScript();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
// If the user goes last in the turn, the move will fail
|
||||||
|
if (battleData.Battle.ChoiceQueue is not null && !battleData.Battle.ChoiceQueue.HasNext())
|
||||||
|
{
|
||||||
|
move.GetHitData(target, hit).Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var failure = target.Volatile.Get<ProtectionFailureScript>();
|
||||||
|
if (failure == null)
|
||||||
|
{
|
||||||
|
failure = new ProtectionFailureScript();
|
||||||
|
target.Volatile.Add(failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
var successive = failure.ProtectTurns;
|
||||||
|
// Each time, the chance of success is divided by 3.
|
||||||
|
var chance = 1.0 / Math.Pow(3, successive);
|
||||||
|
var random = target.BattleData!.Battle.Random.GetFloat();
|
||||||
|
if (random < chance)
|
||||||
|
{
|
||||||
|
failure.ProtectTurns++;
|
||||||
|
failure.UsedProtect = true;
|
||||||
|
target.Volatile.Add(GetEffectScript());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move.GetHitData(target, hit).Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Static.Moves;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
public class BanefulBunkerEffect : ProtectionEffectScript
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||||
|
{
|
||||||
|
base.BlockIncomingHit(executingMove, target, hitIndex, ref block);
|
||||||
|
if (executingMove.UseMove.Category != MoveCategory.Status && executingMove.UseMove.HasFlag("contact"))
|
||||||
|
{
|
||||||
|
executingMove.User.SetStatus("poisoned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Static.Moves;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
public abstract class ProtectionEffectScript : Script
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||||
|
{
|
||||||
|
if (target.BattleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var originalTarget = executingMove.MoveChoice.TargetPosition;
|
||||||
|
var targetPosition = target.BattleData.Position;
|
||||||
|
|
||||||
|
// We only want to block the hit if it's explicitly targeting the Pokemon.
|
||||||
|
if (targetPosition != originalTarget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (executingMove.UseMove.Target is MoveTarget.All or MoveTarget.SelfUse or MoveTarget.AllAlly
|
||||||
|
or MoveTarget.AllAdjacent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
block = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Dynamic.Models.Choices;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attached script for <see cref="ProtectionEffectScript"/> to keep track of the consecutive turns of using Protect,
|
||||||
|
/// or protect-like moves.
|
||||||
|
/// </summary>
|
||||||
|
[Script(ScriptCategory.Pokemon, "protection_failure")]
|
||||||
|
public class ProtectionFailureScript : Script
|
||||||
|
{
|
||||||
|
public int ProtectTurns { get; set; }
|
||||||
|
public bool UsedProtect { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnBeforeTurnStart(ITurnChoice choice)
|
||||||
|
{
|
||||||
|
UsedProtect = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnEndTurn(IBattle battle)
|
||||||
|
{
|
||||||
|
if (!UsedProtect)
|
||||||
|
{
|
||||||
|
RemoveSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Status;
|
||||||
|
|
||||||
|
[Script(ScriptCategory.Status, "poisoned")]
|
||||||
|
public class Poisoned : Script
|
||||||
|
{
|
||||||
|
// TODO: Implement the Poisoned status effect.
|
||||||
|
}
|
Loading…
Reference in New Issue