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.
|
/// Gets the current time of day for the battle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TimeOfDay GetTimeOfDay();
|
TimeOfDay GetTimeOfDay();
|
||||||
|
|
||||||
|
bool CanFlee(IBattle battle, IFleeChoice fleeChoice);
|
||||||
}
|
}
|
|
@ -84,7 +84,75 @@ public static class TurnRunner
|
||||||
case IMoveChoice moveChoice:
|
case IMoveChoice moveChoice:
|
||||||
MoveTurnExecutor.ExecuteMoveChoice(battle, moveChoice);
|
MoveTurnExecutor.ExecuteMoveChoice(battle, moveChoice);
|
||||||
break;
|
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.
|
/// Checks whether the side has been defeated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsDefeated();
|
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>
|
/// <summary>
|
||||||
/// Mark the side as fled.
|
/// Mark the side as fled.
|
||||||
|
@ -267,6 +277,15 @@ public class BattleSideImpl : ScriptSource, IBattleSide
|
||||||
return _fillablePositions.All(fillable => !fillable);
|
return _fillablePositions.All(fillable => !fillable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public uint FleeAttempts { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void RegisterFleeAttempt()
|
||||||
|
{
|
||||||
|
FleeAttempts++;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void MarkAsFled() => HasFledBattle = true;
|
public void MarkAsFled() => HasFledBattle = true;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@ namespace PkmnLib.Dynamic.Models.Choices;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISwitchChoice : ITurnChoice
|
public interface ISwitchChoice : ITurnChoice
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Pokémon to switch to.
|
||||||
|
/// </summary>
|
||||||
|
IPokemon SwitchTo { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ISwitchChoice"/>
|
/// <inheritdoc cref="ISwitchChoice"/>
|
||||||
|
@ -18,6 +21,7 @@ public class SwitchChoice : TurnChoice, ISwitchChoice
|
||||||
SwitchTo = switchTo;
|
SwitchTo = switchTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public IPokemon SwitchTo { get; }
|
public IPokemon SwitchTo { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using PkmnLib.Dynamic;
|
using PkmnLib.Dynamic;
|
||||||
using PkmnLib.Dynamic.Libraries;
|
using PkmnLib.Dynamic.Libraries;
|
||||||
using PkmnLib.Dynamic.Models;
|
using PkmnLib.Dynamic.Models;
|
||||||
|
@ -35,4 +36,31 @@ public class Gen7MiscLibrary : IMiscLibrary
|
||||||
_ => TimeOfDay.Night,
|
_ => 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