Implements switching Pokemon and fleeing from battle
This commit is contained in:
parent
9bdd584b54
commit
1f5a320090
|
@ -19,4 +19,6 @@ public interface IMiscLibrary
|
|||
/// Gets the current time of day for the battle.
|
||||
/// </summary>
|
||||
TimeOfDay GetTimeOfDay();
|
||||
|
||||
bool CanFlee(IBattle battle, IFleeChoice fleeChoice);
|
||||
}
|
|
@ -84,7 +84,75 @@ public static class TurnRunner
|
|||
case IMoveChoice moveChoice:
|
||||
MoveTurnExecutor.ExecuteMoveChoice(battle, moveChoice);
|
||||
break;
|
||||
// TODO: Implement other choice types
|
||||
case ISwitchChoice switchChoice:
|
||||
ExecuteSwitchChoice(battle, switchChoice);
|
||||
break;
|
||||
case IFleeChoice fleeChoice:
|
||||
ExecuteFleeChoice(battle, fleeChoice);
|
||||
break;
|
||||
// TODO: Implement item choice types
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteSwitchChoice(IBattle battle, ISwitchChoice fleeChoice)
|
||||
{
|
||||
var user = fleeChoice.User;
|
||||
var battleData = user.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
var preventSwitch = false;
|
||||
fleeChoice.RunScriptHook(script => script.PreventSelfSwitch(fleeChoice, ref preventSwitch));
|
||||
if (preventSwitch)
|
||||
return;
|
||||
foreach (var side in battle.Sides)
|
||||
{
|
||||
if (side.Index == battleData.SideIndex)
|
||||
continue;
|
||||
foreach (var pokemon in side.Pokemon.WhereNotNull())
|
||||
{
|
||||
pokemon.RunScriptHook(script => script.PreventOpponentSwitch(fleeChoice, ref preventSwitch));
|
||||
if (preventSwitch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
user.Volatile.Clear();
|
||||
var userSide = battle.Sides[battleData.SideIndex];
|
||||
userSide.SwapPokemon(battleData.Position, fleeChoice.SwitchTo);
|
||||
}
|
||||
|
||||
|
||||
private static void ExecuteFleeChoice(IBattle battle, IFleeChoice fleeChoice)
|
||||
{
|
||||
var user = fleeChoice.User;
|
||||
var battleData = user.BattleData;
|
||||
if (battleData == null)
|
||||
return;
|
||||
if (!battle.CanFlee)
|
||||
return;
|
||||
|
||||
var preventFlee = false;
|
||||
fleeChoice.RunScriptHook(script => script.PreventSelfRunAway(fleeChoice, ref preventFlee));
|
||||
if (preventFlee)
|
||||
return;
|
||||
|
||||
foreach (var side in battle.Sides)
|
||||
{
|
||||
if (side.Index == battleData.SideIndex)
|
||||
continue;
|
||||
foreach (var pokemon in side.Pokemon.WhereNotNull())
|
||||
{
|
||||
pokemon.RunScriptHook(script => script.PreventOpponentRunAway(fleeChoice, ref preventFlee));
|
||||
if (preventFlee)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!battle.Library.MiscLibrary.CanFlee(battle, fleeChoice))
|
||||
return;
|
||||
|
||||
var userSide = battle.Sides[battleData.SideIndex];
|
||||
userSide.MarkAsFled();
|
||||
battle.ValidateBattleState();
|
||||
}
|
||||
|
||||
}
|
|
@ -110,6 +110,16 @@ public interface IBattleSide : IScriptSource, IDeepCloneable
|
|||
/// Checks whether the side has been defeated.
|
||||
/// </summary>
|
||||
bool IsDefeated();
|
||||
|
||||
/// <summary>
|
||||
/// The number of times this side has attempted to flee.
|
||||
/// </summary>
|
||||
uint FleeAttempts { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Registers a flee attempt for this side.
|
||||
/// </summary>
|
||||
void RegisterFleeAttempt();
|
||||
|
||||
/// <summary>
|
||||
/// Mark the side as fled.
|
||||
|
@ -267,6 +277,15 @@ public class BattleSideImpl : ScriptSource, IBattleSide
|
|||
return _fillablePositions.All(fillable => !fillable);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public uint FleeAttempts { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterFleeAttempt()
|
||||
{
|
||||
FleeAttempts++;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void MarkAsFled() => HasFledBattle = true;
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ namespace PkmnLib.Dynamic.Models.Choices;
|
|||
/// </summary>
|
||||
public interface ISwitchChoice : ITurnChoice
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The Pokémon to switch to.
|
||||
/// </summary>
|
||||
IPokemon SwitchTo { get; }
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ISwitchChoice"/>
|
||||
|
@ -18,6 +21,7 @@ public class SwitchChoice : TurnChoice, ISwitchChoice
|
|||
SwitchTo = switchTo;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IPokemon SwitchTo { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PkmnLib.Dynamic;
|
||||
using PkmnLib.Dynamic.Libraries;
|
||||
using PkmnLib.Dynamic.Models;
|
||||
|
@ -35,4 +36,31 @@ public class Gen7MiscLibrary : IMiscLibrary
|
|||
_ => TimeOfDay.Night,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanFlee(IBattle battle, IFleeChoice fleeChoice)
|
||||
{
|
||||
var user = fleeChoice.User;
|
||||
var battleData = user.BattleData;
|
||||
if (battleData == null)
|
||||
return false;
|
||||
var opponentSide = battle.Sides[battleData.SideIndex == 0 ? 1 : 0];
|
||||
var opponent = opponentSide.Pokemon.FirstOrDefault(x => x is not null);
|
||||
if (opponent == null)
|
||||
return true;
|
||||
|
||||
var userSpeed = user.FlatStats.Speed;
|
||||
var opponentSpeed = opponent.FlatStats.Speed;
|
||||
// If the player's active Pokémon's Speed is greater than or equal to the wild Pokémon's Speed, fleeing will
|
||||
// always succeed
|
||||
if (userSpeed >= opponentSpeed)
|
||||
return true;
|
||||
|
||||
var userSide = battle.Sides[battleData.SideIndex];
|
||||
|
||||
userSide.RegisterFleeAttempt();
|
||||
var fleeChance = ((userSpeed * 32) / (opponentSpeed / 4) + (30 * userSide.FleeAttempts)) / 256;
|
||||
var random = battle.Random.GetInt(0, 100);
|
||||
return random < fleeChance;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue