Initial work on adding documentation, reorganises modules
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
715f16e2b8
commit
314e9dbe1a
|
@ -1,2 +1,8 @@
|
||||||
|
/// The type we store a level in. As our implementation is aimed at normal Pokemon behaviour, a u8
|
||||||
|
/// is probably enough, as we'd go up to 100. For other users this might however not be enough. This
|
||||||
|
/// allows them to easily change it.
|
||||||
pub type LevelInt = u8;
|
pub type LevelInt = u8;
|
||||||
|
|
||||||
|
/// The amount of moves a Pokemon can have at once. This is set to 4, as that is the default in most
|
||||||
|
/// current Pokemon generations. A developer should be able to modify this however.
|
||||||
pub const MAX_MOVES: usize = 4;
|
pub const MAX_MOVES: usize = 4;
|
||||||
|
|
|
@ -1,30 +1,49 @@
|
||||||
use crate::dynamic_data::models::learned_move::LearnedMove;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::dynamic_data::script_handling::script::ScriptContainer;
|
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
|
use crate::dynamic_data::LearnedMove;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::dynamic_data::ScriptContainer;
|
||||||
|
use crate::dynamic_data::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
|
|
||||||
|
/// The data on a turn choice that should be contained in every turn choice, regardless of type.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CommonChoiceData<'user, 'library> {
|
struct CommonChoiceData<'user, 'library> {
|
||||||
|
/// The user of the turn choice
|
||||||
user: Arc<Pokemon<'user, 'library>>,
|
user: Arc<Pokemon<'user, 'library>>,
|
||||||
|
/// The speed of the user at the beginning of the turn.
|
||||||
speed: u32,
|
speed: u32,
|
||||||
|
/// This random value is set at the beginning of the turn. It is used for tie breaking of the
|
||||||
|
/// turn order in a predictable way, regardless of implementation and hardware.
|
||||||
random_value: u32,
|
random_value: u32,
|
||||||
|
/// Whether or not the choice has failed. A failed choice will stop running, and execute special
|
||||||
|
/// fail handling during turn execution.
|
||||||
has_failed: bool,
|
has_failed: bool,
|
||||||
|
/// The data we can use to retrieve scripts that are affecting this choice. This will be written
|
||||||
|
/// to once: when we need to initialize it. After that, this is only used to read. To prevent a
|
||||||
|
/// read while we're writing to it, this is a RwLock.
|
||||||
script_source_data: RwLock<ScriptSourceData>,
|
script_source_data: RwLock<ScriptSourceData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This enum defines a single choice for a Pokemon for a battle turn.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TurnChoice<'user, 'library> {
|
pub enum TurnChoice<'user, 'library> {
|
||||||
|
/// A move choice tells a Pokemon to use a move on a target for this turn.
|
||||||
Move(MoveChoice<'user, 'library>),
|
Move(MoveChoice<'user, 'library>),
|
||||||
|
/// An item choice tells a Pokemon to use an item.
|
||||||
Item(ItemChoice<'user, 'library>),
|
Item(ItemChoice<'user, 'library>),
|
||||||
|
/// A switch choice tells a Pokemon to switch with another Pokemon from the party.
|
||||||
Switch(SwitchChoice<'user, 'library>),
|
Switch(SwitchChoice<'user, 'library>),
|
||||||
|
/// A flee choice tells a Pokemon to flee from battle.
|
||||||
Flee(FleeChoice<'user, 'library>),
|
Flee(FleeChoice<'user, 'library>),
|
||||||
|
/// A pass choice tells the user to do nothing that turn.
|
||||||
Pass(PassChoice<'user, 'library>),
|
Pass(PassChoice<'user, 'library>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> TurnChoice<'user, 'library> {
|
impl<'user, 'library> TurnChoice<'user, 'library> {
|
||||||
|
/// The shared choice data between each of the different turn choices.
|
||||||
fn choice_data(&self) -> &CommonChoiceData<'user, 'library> {
|
fn choice_data(&self) -> &CommonChoiceData<'user, 'library> {
|
||||||
match self {
|
match self {
|
||||||
TurnChoice::Move(data) => &data.choice_data,
|
TurnChoice::Move(data) => &data.choice_data,
|
||||||
|
@ -34,6 +53,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
|
||||||
TurnChoice::Pass(data) => &data.choice_data,
|
TurnChoice::Pass(data) => &data.choice_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// The shared choice data between each of the different turn choices.
|
||||||
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData<'user, 'library>> {
|
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData<'user, 'library>> {
|
||||||
match self {
|
match self {
|
||||||
TurnChoice::Move(data) => &mut data.choice_data,
|
TurnChoice::Move(data) => &mut data.choice_data,
|
||||||
|
@ -44,34 +64,49 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the user of the given choice.
|
||||||
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
|
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
|
||||||
&self.choice_data().user
|
&self.choice_data().user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the speed of the user for the choice. Note that this speed is the speed of the Pokemon
|
||||||
|
/// at the start of the turn!
|
||||||
pub fn speed(&self) -> u32 {
|
pub fn speed(&self) -> u32 {
|
||||||
self.choice_data().speed
|
self.choice_data().speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the mutable speed of the user for the choice. Note that this speed is the speed of the Pokemon
|
||||||
|
/// at the start of the turn!
|
||||||
pub fn speed_mut(&mut self) -> &mut u32 {
|
pub fn speed_mut(&mut self) -> &mut u32 {
|
||||||
&mut self.choice_data_mut().speed
|
&mut self.choice_data_mut().speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets whether or not the choice has failed. If we notice this when we execute the choice, we
|
||||||
|
/// will not execute it.
|
||||||
pub fn has_failed(&self) -> bool {
|
pub fn has_failed(&self) -> bool {
|
||||||
self.choice_data().has_failed
|
self.choice_data().has_failed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fails the choice. This will prevent it from executing and run a specific fail handling during
|
||||||
|
/// execution. Note that this can not be undone.
|
||||||
pub fn fail(&mut self) {
|
pub fn fail(&mut self) {
|
||||||
self.choice_data_mut().has_failed = true
|
self.choice_data_mut().has_failed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The random value of a turn choice gets set during the start of a choice, and is used for tie
|
||||||
|
/// breaking of turn executions. This means that choices get executed with a predictable order,
|
||||||
|
/// regardless of implementation details.
|
||||||
pub(crate) fn random_value(&self) -> u32 {
|
pub(crate) fn random_value(&self) -> u32 {
|
||||||
self.choice_data().random_value
|
self.choice_data().random_value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This sets the above random value.
|
||||||
pub(crate) fn set_random_value(&mut self, val: u32) {
|
pub(crate) fn set_random_value(&mut self, val: u32) {
|
||||||
self.choice_data_mut().random_value = val;
|
self.choice_data_mut().random_value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function to get the move choice data from a turn. Note that this will panic if not
|
||||||
|
/// used on a move choice.
|
||||||
pub(crate) fn get_move_turn_data<'b>(&'b self) -> &'b MoveChoice<'user, 'library> {
|
pub(crate) fn get_move_turn_data<'b>(&'b self) -> &'b MoveChoice<'user, 'library> {
|
||||||
if let TurnChoice::Move(data) = self {
|
if let TurnChoice::Move(data) = self {
|
||||||
return data;
|
return data;
|
||||||
|
@ -122,17 +157,25 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The data attached to a move choice.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MoveChoice<'user, 'library> {
|
pub struct MoveChoice<'user, 'library> {
|
||||||
|
/// The move that is used for this choice.
|
||||||
used_move: Arc<LearnedMove<'library>>,
|
used_move: Arc<LearnedMove<'library>>,
|
||||||
|
/// The side this move is aimed at.
|
||||||
target_side: u8,
|
target_side: u8,
|
||||||
|
/// The index of the Pokemon on the side we're aiming at.
|
||||||
target_index: u8,
|
target_index: u8,
|
||||||
|
/// The move script.
|
||||||
script: ScriptContainer,
|
script: ScriptContainer,
|
||||||
|
/// The priority of the move choice at the beginning of the turn.
|
||||||
priority: i8,
|
priority: i8,
|
||||||
|
/// The common turn choice data.
|
||||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> MoveChoice<'user, 'library> {
|
impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||||
|
/// Initializes the data for a new move choice.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
user: Arc<Pokemon<'user, 'library>>,
|
user: Arc<Pokemon<'user, 'library>>,
|
||||||
used_move: Arc<LearnedMove<'library>>,
|
used_move: Arc<LearnedMove<'library>>,
|
||||||
|
@ -155,29 +198,35 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The actual learned move on the Pokemon we use for this choice.
|
||||||
pub fn used_move(&self) -> &Arc<LearnedMove<'library>> {
|
pub fn used_move(&self) -> &Arc<LearnedMove<'library>> {
|
||||||
&self.used_move
|
&self.used_move
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The target side the move is aimed at.
|
||||||
pub fn target_side(&self) -> u8 {
|
pub fn target_side(&self) -> u8 {
|
||||||
self.target_side
|
self.target_side
|
||||||
}
|
}
|
||||||
|
/// The Pokemon index on the side we're aiming at.
|
||||||
pub fn target_index(&self) -> u8 {
|
pub fn target_index(&self) -> u8 {
|
||||||
self.target_index
|
self.target_index
|
||||||
}
|
}
|
||||||
|
/// The priority of the move choice at the beginning of the turn.
|
||||||
pub fn priority(&self) -> i8 {
|
pub fn priority(&self) -> i8 {
|
||||||
self.priority
|
self.priority
|
||||||
}
|
}
|
||||||
|
/// The priority of the move choice at the beginning of the turn.
|
||||||
|
pub fn priority_mut(&mut self) -> &mut i8 {
|
||||||
|
&mut self.priority
|
||||||
|
}
|
||||||
|
/// The user of the choice.
|
||||||
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
|
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
|
||||||
&self.choice_data.user
|
&self.choice_data.user
|
||||||
}
|
}
|
||||||
|
/// The move script of the choice.
|
||||||
pub fn script(&self) -> &ScriptContainer {
|
pub fn script(&self) -> &ScriptContainer {
|
||||||
&self.script
|
&self.script
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn priority_mut(&mut self) -> &mut i8 {
|
|
||||||
&mut self.priority
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> {
|
impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> {
|
||||||
|
@ -199,12 +248,15 @@ impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The data given when we select an item choice.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ItemChoice<'user, 'library> {
|
pub struct ItemChoice<'user, 'library> {
|
||||||
|
/// The shared data of all turn choices.
|
||||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> ItemChoice<'user, 'library> {
|
impl<'user, 'library> ItemChoice<'user, 'library> {
|
||||||
|
/// Initialised a new item choice.
|
||||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
choice_data: Box::new(CommonChoiceData {
|
choice_data: Box::new(CommonChoiceData {
|
||||||
|
@ -234,12 +286,15 @@ impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The data given when we select a switch choice.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SwitchChoice<'user, 'library> {
|
pub struct SwitchChoice<'user, 'library> {
|
||||||
|
/// The shared data of all turn choices.
|
||||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> SwitchChoice<'user, 'library> {
|
impl<'user, 'library> SwitchChoice<'user, 'library> {
|
||||||
|
/// Initialise the turn choice data.
|
||||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
choice_data: Box::new(CommonChoiceData {
|
choice_data: Box::new(CommonChoiceData {
|
||||||
|
@ -269,12 +324,15 @@ impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The data given when we select a flee choice.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FleeChoice<'user, 'library> {
|
pub struct FleeChoice<'user, 'library> {
|
||||||
|
/// The common data all turn choices share.
|
||||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> FleeChoice<'user, 'library> {
|
impl<'user, 'library> FleeChoice<'user, 'library> {
|
||||||
|
/// Initialises a new flee choice.
|
||||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
choice_data: Box::new(CommonChoiceData {
|
choice_data: Box::new(CommonChoiceData {
|
||||||
|
@ -304,12 +362,15 @@ impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The data given when we select a pass choice.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PassChoice<'user, 'library> {
|
pub struct PassChoice<'user, 'library> {
|
||||||
|
/// The common data of all turn choices.
|
||||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'user, 'library> PassChoice<'user, 'library> {
|
impl<'user, 'library> PassChoice<'user, 'library> {
|
||||||
|
/// Initialised a new pass choice.
|
||||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
choice_data: Box::new(CommonChoiceData {
|
choice_data: Box::new(CommonChoiceData {
|
|
@ -0,0 +1,111 @@
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
use crate::dynamic_data::DamageSource;
|
||||||
|
use crate::dynamic_data::ExecutingMove;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::static_data::Form;
|
||||||
|
use crate::static_data::Species;
|
||||||
|
|
||||||
|
/// The event hook is used to store external functions that listen to events.
|
||||||
|
///
|
||||||
|
/// Events happen in many
|
||||||
|
/// different places in the battle, and can be used for GUI applications to show that these events
|
||||||
|
/// are happening.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct EventHook {
|
||||||
|
/// All the registered event listeners on the hook.
|
||||||
|
evt_hook_function: Vec<fn(&Box<&Event>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'battle, 'library> EventHook {
|
||||||
|
/// Register a new listener. This will start receiving all events in the battle. Multiple event
|
||||||
|
/// listeners can exist at the same time. Note that for these functions the event will be disposed
|
||||||
|
/// of after the event is finished being sent.
|
||||||
|
pub fn register_listener(&mut self, func: fn(&Box<&Event>)) {
|
||||||
|
self.evt_hook_function.push(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run a new event. This will send the event to all externally defined event listeners. It will
|
||||||
|
/// dispose of the event afterwards.
|
||||||
|
pub fn trigger<'b>(&self, evt: Event<'b, 'battle, 'library>) {
|
||||||
|
let b = Box::new(&evt);
|
||||||
|
for f in &self.evt_hook_function {
|
||||||
|
f(&b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for EventHook {
|
||||||
|
fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The different events that can occur during the battle, for which a GUI should show something.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Event<'own, 'battle, 'library> {
|
||||||
|
/// A switch event happens when a Pokemon gets switched out for something else.
|
||||||
|
Switch {
|
||||||
|
/// The side the Pokemon got switched from/on
|
||||||
|
side_index: u8,
|
||||||
|
/// The index of the Pokemon that got switched in/out on its side
|
||||||
|
index: u8,
|
||||||
|
/// The new Pokemon that will be on the spot. If none, the spot will now be empty.
|
||||||
|
pokemon: Option<&'own Pokemon<'battle, 'library>>,
|
||||||
|
},
|
||||||
|
/// A swap event happens when two Pokemon on a side swap positions. Note that this is rare.
|
||||||
|
Swap {
|
||||||
|
/// The side the Pokemon swapped on.
|
||||||
|
side_index: u8,
|
||||||
|
/// The index on the side of the first Pokemon that was swapped.
|
||||||
|
index_a: u8,
|
||||||
|
/// The index on the side of the second pokemon that was swapped.
|
||||||
|
index_b: u8,
|
||||||
|
},
|
||||||
|
/// This event happens when a Pokemon changes species during battle. While not normally occuring
|
||||||
|
/// this can be useful for things such as mid-battle evolutions, which some fanmade implementations
|
||||||
|
/// enjoy.
|
||||||
|
SpeciesChange {
|
||||||
|
/// The pokemon that changed species.
|
||||||
|
pokemon: &'own Pokemon<'battle, 'library>,
|
||||||
|
/// The new species of the Pokemon.
|
||||||
|
species: &'own Species,
|
||||||
|
/// The form of the species the Pokemon will have.
|
||||||
|
form: &'own Form,
|
||||||
|
},
|
||||||
|
/// This event happens when a Pokemon changes form during battle. This is rather common.
|
||||||
|
FormChange {
|
||||||
|
/// The pokemon that changed forms.
|
||||||
|
pokemon: &'own Pokemon<'battle, 'library>,
|
||||||
|
/// The new form of the Pokemon.
|
||||||
|
form: &'own Form,
|
||||||
|
},
|
||||||
|
/// This event happens when a Pokemon takes damage.
|
||||||
|
Damage {
|
||||||
|
/// The Pokemon that takes damage.
|
||||||
|
pokemon: &'own Pokemon<'battle, 'library>,
|
||||||
|
/// The source of damage.
|
||||||
|
source: DamageSource,
|
||||||
|
/// The health of the Pokemon before the damage.
|
||||||
|
original_health: u32,
|
||||||
|
/// The health of the Pokemon after the damage.
|
||||||
|
new_health: u32,
|
||||||
|
},
|
||||||
|
/// This event happens when a Pokemon faints.
|
||||||
|
Faint {
|
||||||
|
/// The pokemon that has fainted.
|
||||||
|
pokemon: &'own Pokemon<'battle, 'library>,
|
||||||
|
},
|
||||||
|
/// This event happens when a Pokemon uses a move on a target, just before any hits.
|
||||||
|
MoveUse {
|
||||||
|
/// The data of the move used.
|
||||||
|
executing_move: &'own ExecutingMove<'own, 'battle, 'library>,
|
||||||
|
},
|
||||||
|
/// This event happens when a Pokemon missed.
|
||||||
|
Miss {
|
||||||
|
/// The pokemon that missed.
|
||||||
|
user: &'own Pokemon<'battle, 'library>,
|
||||||
|
},
|
||||||
|
/// The turn is finished running, waiting for new input.
|
||||||
|
EndTurn,
|
||||||
|
}
|
|
@ -1,69 +0,0 @@
|
||||||
use crate::dynamic_data::models::damage_source::DamageSource;
|
|
||||||
use crate::dynamic_data::models::executing_move::ExecutingMove;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::static_data::species_data::form::Form;
|
|
||||||
use crate::static_data::species_data::species::Species;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct EventHook {
|
|
||||||
evt_hook_function: Vec<fn(&Box<&Event>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'battle, 'library> EventHook {
|
|
||||||
pub fn register_listener(&mut self, func: fn(&Box<&Event>)) {
|
|
||||||
self.evt_hook_function.push(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trigger<'b>(&self, evt: Event<'b, 'battle, 'library>) {
|
|
||||||
let b = Box::new(&evt);
|
|
||||||
for f in &self.evt_hook_function {
|
|
||||||
f(&b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for EventHook {
|
|
||||||
fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Event<'own, 'battle, 'library> {
|
|
||||||
Switch {
|
|
||||||
side_index: u8,
|
|
||||||
index: u8,
|
|
||||||
pokemon: Option<&'own Pokemon<'battle, 'library>>,
|
|
||||||
},
|
|
||||||
Swap {
|
|
||||||
side_index: u8,
|
|
||||||
index_a: u8,
|
|
||||||
index_b: u8,
|
|
||||||
},
|
|
||||||
SpeciesChange {
|
|
||||||
pokemon: &'own Pokemon<'battle, 'library>,
|
|
||||||
species: &'own Species,
|
|
||||||
form: &'own Form,
|
|
||||||
},
|
|
||||||
FormChange {
|
|
||||||
pokemon: &'own Pokemon<'battle, 'library>,
|
|
||||||
form: &'own Form,
|
|
||||||
},
|
|
||||||
Damage {
|
|
||||||
pokemon: &'own Pokemon<'battle, 'library>,
|
|
||||||
source: DamageSource,
|
|
||||||
original_health: u32,
|
|
||||||
new_health: u32,
|
|
||||||
},
|
|
||||||
Faint {
|
|
||||||
pokemon: &'own Pokemon<'battle, 'library>,
|
|
||||||
},
|
|
||||||
MoveUse {
|
|
||||||
executing_move: &'own ExecutingMove<'own, 'battle, 'library>,
|
|
||||||
},
|
|
||||||
Miss {
|
|
||||||
user: &'own Pokemon<'battle, 'library>,
|
|
||||||
},
|
|
||||||
EndTurn,
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
pub mod event_hook;
|
|
|
@ -1,35 +1,60 @@
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::Pokemon;
|
||||||
|
|
||||||
|
/// The ChoiceQueue is used to run choices one by one.
|
||||||
|
///
|
||||||
|
/// It functions internally by holding a vector of choices, and passing ownership of the turn choice
|
||||||
|
/// to the turn executor one by one, replacing it with empty spots at the start. It holds several
|
||||||
|
/// helper functions to change the turn order while doing the execution. This is needed, as several
|
||||||
|
/// moves in Pokemon actively mess with this order.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ChoiceQueue<'battle, 'library> {
|
pub struct ChoiceQueue<'battle, 'library> {
|
||||||
|
/// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get
|
||||||
|
/// executed.
|
||||||
queue: Vec<Option<TurnChoice<'battle, 'library>>>,
|
queue: Vec<Option<TurnChoice<'battle, 'library>>>,
|
||||||
|
/// The current index of the turn we need to execute next.
|
||||||
current: usize,
|
current: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'battle, 'library> ChoiceQueue<'battle, 'library> {
|
impl<'battle, 'library> ChoiceQueue<'battle, 'library> {
|
||||||
pub fn new(queue: Vec<Option<TurnChoice<'battle, 'library>>>) -> Self {
|
/// Initializes a ChoiceQueue. We expect the given queue to already be sorted here.
|
||||||
|
pub(crate) fn new(queue: Vec<Option<TurnChoice<'battle, 'library>>>) -> Self {
|
||||||
Self { queue, current: 0 }
|
Self { queue, current: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dequeues the next turn choice to be executed. This gives ownership to the callee, and replaces
|
||||||
|
/// our own reference to the turn choice with an empty spot. It also increments the current position
|
||||||
|
/// by one.
|
||||||
pub fn dequeue<'b>(&'b mut self) -> TurnChoice<'battle, 'library> {
|
pub fn dequeue<'b>(&'b mut self) -> TurnChoice<'battle, 'library> {
|
||||||
let c = self.queue[self.current].take();
|
let c = self.queue[self.current].take();
|
||||||
self.current += 1;
|
self.current += 1;
|
||||||
c.unwrap()
|
c.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek(&mut self) -> &'battle TurnChoice {
|
/// This reads what the next choice to execute will be, without modifying state.
|
||||||
|
pub fn peek(&self) -> &'battle TurnChoice {
|
||||||
self.queue[self.current].as_ref().unwrap()
|
self.queue[self.current].as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if we have any choices remaining.
|
||||||
pub fn has_next(&self) -> bool {
|
pub fn has_next(&self) -> bool {
|
||||||
self.current < self.queue.len()
|
self.current < self.queue.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This resorts the yet to be executed choices. This can be useful for dealing with situations
|
||||||
|
/// such as Pokemon changing forms just after the very start of a turn, when turn order has
|
||||||
|
/// technically already been decided.
|
||||||
|
pub fn resort(&mut self) {
|
||||||
|
let len = self.queue.len();
|
||||||
|
self.queue[self.current..len].sort_unstable_by(|a, b| b.cmp(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This moves the choice of a specific Pokemon up to the next choice to be executed.
|
||||||
pub fn move_pokemon_choice_next(&mut self, _pokemon: &Pokemon) {
|
pub fn move_pokemon_choice_next(&mut self, _pokemon: &Pokemon) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal helper function to be easily able to iterate over the yet to be executed choices.
|
||||||
pub(crate) fn get_queue(&self) -> &[Option<TurnChoice<'battle, 'library>>] {
|
pub(crate) fn get_queue(&self) -> &[Option<TurnChoice<'battle, 'library>>] {
|
||||||
&self.queue[self.current..self.queue.len()]
|
&self.queue[self.current..self.queue.len()]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
pub mod choice_queue;
|
#[doc(inline)]
|
||||||
pub mod target_resolver;
|
pub use choice_queue::*;
|
||||||
pub mod turn_runner;
|
#[doc(inline)]
|
||||||
|
pub use target_resolver::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use turn_runner::*;
|
||||||
|
|
||||||
|
mod choice_queue;
|
||||||
|
mod target_resolver;
|
||||||
|
mod turn_runner;
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::static_data::MoveTarget;
|
|
||||||
use num_traits::abs;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use num_traits::abs;
|
||||||
|
|
||||||
|
use crate::dynamic_data::Battle;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::static_data::MoveTarget;
|
||||||
|
|
||||||
|
/// Helper type for the vector of targets we will return.
|
||||||
pub type TargetList<'own, 'library> = Vec<Option<Arc<Pokemon<'own, 'library>>>>;
|
pub type TargetList<'own, 'library> = Vec<Option<Arc<Pokemon<'own, 'library>>>>;
|
||||||
|
|
||||||
|
/// This returns all Pokemon in the battle.
|
||||||
fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
|
fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
|
||||||
let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize);
|
let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize);
|
||||||
for side in battle.sides() {
|
for side in battle.sides() {
|
||||||
|
@ -17,6 +21,7 @@ fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Little helper function to get the other side. 1 --> 0, 0 --> 1
|
||||||
fn get_opposite_side(side: u8) -> u8 {
|
fn get_opposite_side(side: u8) -> u8 {
|
||||||
if side == 0 {
|
if side == 0 {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -24,7 +29,13 @@ fn get_opposite_side(side: u8) -> u8 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
|
/// Gets all Pokemon that are adjacent to of directly opposite of a Pokemon. This means the target,
|
||||||
|
/// the Pokemon left of it, the Pokemon right of it, and the Pokemon opposite of it.
|
||||||
|
fn get_all_adjacent_opponent<'b, 'library>(
|
||||||
|
side: u8,
|
||||||
|
index: u8,
|
||||||
|
battle: &Battle<'b, 'library>,
|
||||||
|
) -> TargetList<'b, 'library> {
|
||||||
let left = index as i32 - 1;
|
let left = index as i32 - 1;
|
||||||
let right = index + 1;
|
let right = index + 1;
|
||||||
if left < 0 && right >= battle.pokemon_per_side() {
|
if left < 0 && right >= battle.pokemon_per_side() {
|
||||||
|
@ -57,11 +68,9 @@ fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'libr
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all_adjacent_opponent<'b, 'library>(
|
/// Gets all Pokemon that are adjacent to a Pokemon. This includes the target, the pokemon to the
|
||||||
side: u8,
|
/// left of it, and the Pokemon to the right of it.
|
||||||
index: u8,
|
fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
|
||||||
battle: &Battle<'b, 'library>,
|
|
||||||
) -> TargetList<'b, 'library> {
|
|
||||||
let left = index as i32 - 1;
|
let left = index as i32 - 1;
|
||||||
let right = index + 1;
|
let right = index + 1;
|
||||||
if left < 0 && right >= battle.pokemon_per_side() {
|
if left < 0 && right >= battle.pokemon_per_side() {
|
||||||
|
@ -86,6 +95,7 @@ fn get_all_adjacent_opponent<'b, 'library>(
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the target for a specific move target type, given the targeted position.
|
||||||
pub fn resolve_targets<'b, 'library>(
|
pub fn resolve_targets<'b, 'library>(
|
||||||
side: u8,
|
side: u8,
|
||||||
index: u8,
|
index: u8,
|
||||||
|
@ -93,6 +103,8 @@ pub fn resolve_targets<'b, 'library>(
|
||||||
battle: &Battle<'b, 'library>,
|
battle: &Battle<'b, 'library>,
|
||||||
) -> TargetList<'b, 'library> {
|
) -> TargetList<'b, 'library> {
|
||||||
match target {
|
match target {
|
||||||
|
// These all resolve to a single position. We let the client deal with where the target is,
|
||||||
|
// and just return the Pokemon at that given target here.
|
||||||
MoveTarget::Adjacent
|
MoveTarget::Adjacent
|
||||||
| MoveTarget::AdjacentAlly
|
| MoveTarget::AdjacentAlly
|
||||||
| MoveTarget::AdjacentAllySelf
|
| MoveTarget::AdjacentAllySelf
|
||||||
|
@ -102,9 +114,14 @@ pub fn resolve_targets<'b, 'library>(
|
||||||
| MoveTarget::SelfUse => {
|
| MoveTarget::SelfUse => {
|
||||||
vec![battle.get_pokemon(side, index).as_ref().cloned()]
|
vec![battle.get_pokemon(side, index).as_ref().cloned()]
|
||||||
}
|
}
|
||||||
|
// If all pokemon are requested, give all Pokemon on the battlefield
|
||||||
MoveTarget::All => get_all_targets(battle),
|
MoveTarget::All => get_all_targets(battle),
|
||||||
|
// If the adjacent Pokemon are requested, pass those.
|
||||||
MoveTarget::AllAdjacent => get_all_adjacent(side, index, battle),
|
MoveTarget::AllAdjacent => get_all_adjacent(side, index, battle),
|
||||||
|
// If the adjacent and opponent Pokemon are requested, give those.
|
||||||
MoveTarget::AllAdjacentOpponent => get_all_adjacent_opponent(side, index, battle),
|
MoveTarget::AllAdjacentOpponent => get_all_adjacent_opponent(side, index, battle),
|
||||||
|
// If all Pokemon on a side are requested, simply give all Pokemon on the side back, and let
|
||||||
|
// the client deal with what side is passed.
|
||||||
MoveTarget::AllAlly | MoveTarget::AllOpponent => {
|
MoveTarget::AllAlly | MoveTarget::AllOpponent => {
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for pokemon in battle.sides()[side as usize].pokemon().deref() {
|
for pokemon in battle.sides()[side as usize].pokemon().deref() {
|
||||||
|
@ -115,6 +132,7 @@ pub fn resolve_targets<'b, 'library>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether a given side and index are valid for a given movetarget and user.
|
||||||
pub fn is_valid_target(side: u8, index: u8, target: MoveTarget, user: &Pokemon) -> bool {
|
pub fn is_valid_target(side: u8, index: u8, target: MoveTarget, user: &Pokemon) -> bool {
|
||||||
let user_side = user.get_battle_side_index();
|
let user_side = user.get_battle_side_index();
|
||||||
let user_index = user.get_battle_index();
|
let user_index = user.get_battle_index();
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
|
||||||
use crate::dynamic_data::event_hooks::event_hook::Event;
|
|
||||||
use crate::dynamic_data::flow::target_resolver::resolve_targets;
|
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
|
||||||
use crate::dynamic_data::models::damage_source::DamageSource;
|
|
||||||
use crate::dynamic_data::models::executing_move::ExecutingMove;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptWrapper};
|
|
||||||
use crate::static_data::{DataLibrary, MoveCategory};
|
|
||||||
use crate::{run_scripts, script_hook, PkmnResult};
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
|
use crate::dynamic_data::event_hooks::Event;
|
||||||
|
use crate::dynamic_data::flow::target_resolver::resolve_targets;
|
||||||
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptWrapper};
|
||||||
|
use crate::dynamic_data::Battle;
|
||||||
|
use crate::dynamic_data::DamageSource;
|
||||||
|
use crate::dynamic_data::ExecutingMove;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::static_data::{DataLibrary, MoveCategory};
|
||||||
|
use crate::{run_scripts, script_hook, PkmnResult};
|
||||||
|
|
||||||
impl<'own, 'library> Battle<'own, 'library> {
|
impl<'own, 'library> Battle<'own, 'library> {
|
||||||
|
/// Execute the entire turn after the choices are all set.
|
||||||
pub(crate) fn run_turn(&self) -> PkmnResult<()> {
|
pub(crate) fn run_turn(&self) -> PkmnResult<()> {
|
||||||
let choice_queue = self.current_turn_queue();
|
let choice_queue = self.current_turn_queue();
|
||||||
|
|
||||||
|
@ -60,20 +62,19 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_choice(&self, choice: &TurnChoice<'own, 'library>) -> PkmnResult<()> {
|
fn execute_choice(&self, choice: &TurnChoice<'own, 'library>) -> PkmnResult<()> {
|
||||||
|
// A pass turn choice means the user does not intend to do anything. As such, return.
|
||||||
if let TurnChoice::Pass(..) = choice {
|
if let TurnChoice::Pass(..) = choice {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if self.has_ended() {
|
if self.has_ended() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
{
|
let user = choice.user();
|
||||||
let user = choice.user();
|
if !user.is_usable() {
|
||||||
if !user.is_usable() {
|
return Ok(());
|
||||||
return Ok(());
|
}
|
||||||
}
|
if !user.is_on_battlefield() {
|
||||||
if !user.is_on_battlefield() {
|
return Ok(());
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !self.can_use(choice) {
|
if !self.can_use(choice) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct HistoryHolder {}
|
|
|
@ -1 +1,3 @@
|
||||||
pub mod history_holder;
|
/// The history holder holds all specific history events that happened in the battle.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct HistoryHolder {}
|
||||||
|
|
|
@ -1,63 +1,28 @@
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use std::fmt::Debug;
|
||||||
use crate::static_data::statistic_set::StatisticSet;
|
|
||||||
use crate::static_data::statistics::Statistic;
|
|
||||||
use std::sync::atomic::AtomicU32;
|
use std::sync::atomic::AtomicU32;
|
||||||
|
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::static_data::Statistic;
|
||||||
|
use crate::static_data::StatisticSet;
|
||||||
|
|
||||||
|
/// A battle stat calculator is used to calculate stats for a pokemon.
|
||||||
|
pub trait BattleStatCalculator: Debug {
|
||||||
|
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
|
||||||
|
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>);
|
||||||
|
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
|
||||||
|
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
||||||
|
/// Calculate all the boosted stats of a pokemon, including stat boosts.
|
||||||
|
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>);
|
||||||
|
/// Calculate a single boosted stat of a Pokemon, including stat boosts.
|
||||||
|
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A basic implementation of the Gen 7 stat calculator.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BattleStatCalculator {}
|
pub struct Gen7BattleStatCalculator {}
|
||||||
|
|
||||||
impl BattleStatCalculator {
|
|
||||||
pub fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>) {
|
|
||||||
stats.set_stat(Statistic::HP, self.calculate_health_stat(pokemon));
|
|
||||||
stats.set_stat(Statistic::Attack, self.calculate_other_stat(pokemon, Statistic::Attack));
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::Defense,
|
|
||||||
self.calculate_other_stat(pokemon, Statistic::Defense),
|
|
||||||
);
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::SpecialAttack,
|
|
||||||
self.calculate_other_stat(pokemon, Statistic::SpecialAttack),
|
|
||||||
);
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::SpecialDefense,
|
|
||||||
self.calculate_other_stat(pokemon, Statistic::SpecialDefense),
|
|
||||||
);
|
|
||||||
stats.set_stat(Statistic::Speed, self.calculate_other_stat(pokemon, Statistic::Speed));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
|
||||||
if stat == Statistic::HP {
|
|
||||||
self.calculate_health_stat(pokemon)
|
|
||||||
} else {
|
|
||||||
self.calculate_other_stat(pokemon, stat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>) {
|
|
||||||
stats.set_stat(Statistic::HP, self.calculate_boosted_stat(pokemon, Statistic::HP));
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::Attack,
|
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::Attack),
|
|
||||||
);
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::Defense,
|
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::Defense),
|
|
||||||
);
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::SpecialAttack,
|
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::SpecialAttack),
|
|
||||||
);
|
|
||||||
stats.set_stat(
|
|
||||||
Statistic::SpecialDefense,
|
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::SpecialDefense),
|
|
||||||
);
|
|
||||||
stats.set_stat(Statistic::Speed, self.calculate_boosted_stat(pokemon, Statistic::Speed));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
|
||||||
(self.calculate_flat_stat(pokemon, stat) as f32 * self.get_stat_boost_modifier(pokemon, stat)) as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
|
impl Gen7BattleStatCalculator {
|
||||||
|
/// The calculation used for health points.
|
||||||
fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 {
|
fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 {
|
||||||
let base = pokemon.form().get_base_stat(Statistic::HP) as u32;
|
let base = pokemon.form().get_base_stat(Statistic::HP) as u32;
|
||||||
let iv = pokemon.individual_values().hp() as u32;
|
let iv = pokemon.individual_values().hp() as u32;
|
||||||
|
@ -66,6 +31,7 @@ impl BattleStatCalculator {
|
||||||
(((2 * base + iv + (ev / 4)) * level) / 100) + level + 10
|
(((2 * base + iv + (ev / 4)) * level) / 100) + level + 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The calculation used for all other stats
|
||||||
fn calculate_other_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
fn calculate_other_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
||||||
let base = pokemon.form().get_base_stat(stat) as u32;
|
let base = pokemon.form().get_base_stat(stat) as u32;
|
||||||
let iv = pokemon.individual_values().get_stat(stat) as u32;
|
let iv = pokemon.individual_values().get_stat(stat) as u32;
|
||||||
|
@ -75,6 +41,7 @@ impl BattleStatCalculator {
|
||||||
return (unmodified as f32 * pokemon.nature().get_stat_modifier(stat)) as u32;
|
return (unmodified as f32 * pokemon.nature().get_stat_modifier(stat)) as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This functions returns the modifier we need to do to a stat for a given stat boost.
|
||||||
fn get_stat_boost_modifier(&self, pokemon: &Pokemon, stat: Statistic) -> f32 {
|
fn get_stat_boost_modifier(&self, pokemon: &Pokemon, stat: Statistic) -> f32 {
|
||||||
let boost = pokemon.stat_boost().get_stat(stat);
|
let boost = pokemon.stat_boost().get_stat(stat);
|
||||||
match boost {
|
match boost {
|
||||||
|
@ -95,3 +62,56 @@ impl BattleStatCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BattleStatCalculator for Gen7BattleStatCalculator {
|
||||||
|
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>) {
|
||||||
|
stats.set_stat(Statistic::HP, self.calculate_health_stat(pokemon));
|
||||||
|
stats.set_stat(Statistic::Attack, self.calculate_other_stat(pokemon, Statistic::Attack));
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::Defense,
|
||||||
|
self.calculate_other_stat(pokemon, Statistic::Defense),
|
||||||
|
);
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::SpecialAttack,
|
||||||
|
self.calculate_other_stat(pokemon, Statistic::SpecialAttack),
|
||||||
|
);
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::SpecialDefense,
|
||||||
|
self.calculate_other_stat(pokemon, Statistic::SpecialDefense),
|
||||||
|
);
|
||||||
|
stats.set_stat(Statistic::Speed, self.calculate_other_stat(pokemon, Statistic::Speed));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
||||||
|
if stat == Statistic::HP {
|
||||||
|
self.calculate_health_stat(pokemon)
|
||||||
|
} else {
|
||||||
|
self.calculate_other_stat(pokemon, stat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>) {
|
||||||
|
stats.set_stat(Statistic::HP, self.calculate_boosted_stat(pokemon, Statistic::HP));
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::Attack,
|
||||||
|
self.calculate_boosted_stat(pokemon, Statistic::Attack),
|
||||||
|
);
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::Defense,
|
||||||
|
self.calculate_boosted_stat(pokemon, Statistic::Defense),
|
||||||
|
);
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::SpecialAttack,
|
||||||
|
self.calculate_boosted_stat(pokemon, Statistic::SpecialAttack),
|
||||||
|
);
|
||||||
|
stats.set_stat(
|
||||||
|
Statistic::SpecialDefense,
|
||||||
|
self.calculate_boosted_stat(pokemon, Statistic::SpecialDefense),
|
||||||
|
);
|
||||||
|
stats.set_stat(Statistic::Speed, self.calculate_boosted_stat(pokemon, Statistic::Speed));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
||||||
|
(self.calculate_flat_stat(pokemon, stat) as f32 * self.get_stat_boost_modifier(pokemon, stat)) as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::dynamic_data::models::executing_move::{ExecutingMove, HitData};
|
use std::sync::Arc;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::dynamic_data::script_handling::ScriptSource;
|
use crate::dynamic_data::script_handling::ScriptSource;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::dynamic_data::{ExecutingMove, HitData};
|
||||||
use crate::script_hook;
|
use crate::script_hook;
|
||||||
use crate::static_data::{MoveCategory, Statistic};
|
use crate::static_data::{MoveCategory, Statistic};
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub trait DamageLibrary: std::fmt::Debug {
|
pub trait DamageLibrary: std::fmt::Debug {
|
||||||
fn has_randomness(&self) -> bool;
|
fn has_randomness(&self) -> bool;
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator;
|
use crate::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator;
|
||||||
use crate::dynamic_data::libraries::damage_library::DamageLibrary;
|
use crate::dynamic_data::libraries::damage_library::DamageLibrary;
|
||||||
use crate::dynamic_data::libraries::misc_library::MiscLibrary;
|
use crate::dynamic_data::libraries::misc_library::MiscLibrary;
|
||||||
use crate::dynamic_data::libraries::script_resolver::ScriptCategory;
|
use crate::dynamic_data::libraries::script_resolver::ScriptCategory;
|
||||||
use crate::dynamic_data::script_handling::item_script::ItemScript;
|
use crate::dynamic_data::ItemScript;
|
||||||
use crate::dynamic_data::script_handling::script::Script;
|
use crate::dynamic_data::Script;
|
||||||
use crate::static_data::items::item::Item;
|
use crate::static_data::Item;
|
||||||
use crate::static_data::libraries::static_data::StaticData;
|
use crate::static_data::StaticData;
|
||||||
use crate::{PkmnResult, StringKey};
|
use crate::{PkmnResult, StringKey};
|
||||||
use std::ops::Deref;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DynamicLibrary {
|
pub struct DynamicLibrary {
|
||||||
static_data: StaticData,
|
static_data: StaticData,
|
||||||
stat_calculator: BattleStatCalculator,
|
stat_calculator: Box<dyn BattleStatCalculator>,
|
||||||
damage_calculator: Box<dyn DamageLibrary>,
|
damage_calculator: Box<dyn DamageLibrary>,
|
||||||
misc_library: Box<dyn MiscLibrary<'static>>,
|
misc_library: Box<dyn MiscLibrary<'static>>,
|
||||||
}
|
}
|
||||||
|
@ -25,7 +26,7 @@ unsafe impl Send for DynamicLibrary {}
|
||||||
impl DynamicLibrary {
|
impl DynamicLibrary {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
static_data: StaticData,
|
static_data: StaticData,
|
||||||
stat_calculator: BattleStatCalculator,
|
stat_calculator: Box<dyn BattleStatCalculator>,
|
||||||
damage_calculator: Box<dyn DamageLibrary>,
|
damage_calculator: Box<dyn DamageLibrary>,
|
||||||
misc_library: Box<dyn MiscLibrary<'static>>,
|
misc_library: Box<dyn MiscLibrary<'static>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -40,8 +41,8 @@ impl DynamicLibrary {
|
||||||
pub fn static_data(&self) -> &StaticData {
|
pub fn static_data(&self) -> &StaticData {
|
||||||
&self.static_data
|
&self.static_data
|
||||||
}
|
}
|
||||||
pub fn stat_calculator(&self) -> &BattleStatCalculator {
|
pub fn stat_calculator(&self) -> &dyn BattleStatCalculator {
|
||||||
&self.stat_calculator
|
self.stat_calculator.deref()
|
||||||
}
|
}
|
||||||
pub fn damage_calculator(&self) -> &dyn DamageLibrary {
|
pub fn damage_calculator(&self) -> &dyn DamageLibrary {
|
||||||
self.damage_calculator.deref()
|
self.damage_calculator.deref()
|
||||||
|
@ -60,16 +61,15 @@ impl DynamicLibrary {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
use crate::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator;
|
use crate::dynamic_data::libraries::battle_stat_calculator::Gen7BattleStatCalculator;
|
||||||
use crate::dynamic_data::libraries::damage_library::Gen7DamageLibrary;
|
use crate::dynamic_data::libraries::damage_library::Gen7DamageLibrary;
|
||||||
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
||||||
use crate::dynamic_data::libraries::misc_library::Gen7MiscLibrary;
|
use crate::dynamic_data::libraries::misc_library::Gen7MiscLibrary;
|
||||||
use crate::static_data::libraries::static_data;
|
|
||||||
|
|
||||||
pub fn build() -> DynamicLibrary {
|
pub fn build() -> DynamicLibrary {
|
||||||
DynamicLibrary {
|
DynamicLibrary {
|
||||||
static_data: static_data::test::build(),
|
static_data: crate::static_data::libraries::static_data::test::build(),
|
||||||
stat_calculator: BattleStatCalculator {},
|
stat_calculator: Box::new(Gen7BattleStatCalculator {}),
|
||||||
damage_calculator: Box::new(Gen7DamageLibrary::new(false)),
|
damage_calculator: Box::new(Gen7DamageLibrary::new(false)),
|
||||||
misc_library: Box::new(Gen7MiscLibrary::new()),
|
misc_library: Box::new(Gen7MiscLibrary::new()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
use crate::dynamic_data::choices::{MoveChoice, SwitchChoice, TurnChoice};
|
use std::fmt::Debug;
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
|
||||||
use crate::dynamic_data::models::executing_move::ExecutingMove;
|
|
||||||
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::dynamic_data::script_handling::ScriptSource;
|
|
||||||
use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
|
|
||||||
use crate::{script_hook, StringKey};
|
|
||||||
use hashbrown::HashSet;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub trait MiscLibrary<'library> {
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
|
use crate::dynamic_data::choices::{MoveChoice, SwitchChoice, TurnChoice};
|
||||||
|
use crate::dynamic_data::script_handling::ScriptSource;
|
||||||
|
use crate::dynamic_data::Battle;
|
||||||
|
use crate::dynamic_data::ExecutingMove;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
|
||||||
|
use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
|
||||||
|
use crate::{script_hook, StringKey};
|
||||||
|
|
||||||
|
pub trait MiscLibrary<'library>: Debug {
|
||||||
fn is_critical(
|
fn is_critical(
|
||||||
&self,
|
&self,
|
||||||
battle: &Battle,
|
battle: &Battle,
|
||||||
|
@ -29,12 +31,6 @@ pub trait MiscLibrary<'library> {
|
||||||
// TODO: get time
|
// TODO: get time
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'library> Debug for dyn MiscLibrary<'library> {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.write_str("MiscLibrary")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Gen7MiscLibrary<'library> {
|
pub struct Gen7MiscLibrary<'library> {
|
||||||
struggle_data: *const MoveData,
|
struggle_data: *const MoveData,
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
pub mod battle_stat_calculator;
|
#[doc(inline)]
|
||||||
pub mod damage_library;
|
pub use battle_stat_calculator::*;
|
||||||
pub mod dynamic_library;
|
#[doc(inline)]
|
||||||
pub mod misc_library;
|
pub use damage_library::*;
|
||||||
pub mod script_resolver;
|
#[doc(inline)]
|
||||||
|
pub use dynamic_library::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use misc_library::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use script_resolver::*;
|
||||||
|
|
||||||
|
mod battle_stat_calculator;
|
||||||
|
mod damage_library;
|
||||||
|
pub(crate) mod dynamic_library;
|
||||||
|
mod misc_library;
|
||||||
|
mod script_resolver;
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
pub mod choices;
|
#[doc(inline)]
|
||||||
pub mod event_hooks;
|
pub use choices::*;
|
||||||
pub mod flow;
|
#[doc(inline)]
|
||||||
pub mod history;
|
pub use event_hooks::*;
|
||||||
pub mod libraries;
|
#[doc(inline)]
|
||||||
pub mod models;
|
pub use flow::*;
|
||||||
pub mod script_handling;
|
#[doc(inline)]
|
||||||
|
pub use history::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use libraries::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use models::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use script_handling::*;
|
||||||
|
|
||||||
|
mod choices;
|
||||||
|
mod event_hooks;
|
||||||
|
mod flow;
|
||||||
|
mod history;
|
||||||
|
pub(crate) mod libraries;
|
||||||
|
mod models;
|
||||||
|
mod script_handling;
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use atomic::Atomic;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
use crate::dynamic_data::event_hooks::event_hook::{Event, EventHook};
|
use crate::dynamic_data::event_hooks::{Event, EventHook};
|
||||||
use crate::dynamic_data::flow::choice_queue::ChoiceQueue;
|
use crate::dynamic_data::history::HistoryHolder;
|
||||||
use crate::dynamic_data::flow::target_resolver::is_valid_target;
|
use crate::dynamic_data::is_valid_target;
|
||||||
use crate::dynamic_data::history::history_holder::HistoryHolder;
|
|
||||||
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
|
||||||
use crate::dynamic_data::models::battle_party::BattleParty;
|
use crate::dynamic_data::models::battle_party::BattleParty;
|
||||||
use crate::dynamic_data::models::battle_random::BattleRandom;
|
use crate::dynamic_data::models::battle_random::BattleRandom;
|
||||||
use crate::dynamic_data::models::battle_result::BattleResult;
|
use crate::dynamic_data::models::battle_result::BattleResult;
|
||||||
use crate::dynamic_data::models::battle_side::BattleSide;
|
use crate::dynamic_data::models::battle_side::BattleSide;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
use crate::dynamic_data::script_handling::script::Script;
|
use crate::dynamic_data::ChoiceQueue;
|
||||||
use crate::dynamic_data::script_handling::script_set::ScriptSet;
|
use crate::dynamic_data::DynamicLibrary;
|
||||||
use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts;
|
use crate::dynamic_data::Script;
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
use crate::dynamic_data::ScriptSet;
|
||||||
use crate::{script_hook, PkmnResult, ScriptCategory, StringKey};
|
use crate::dynamic_data::VolatileScripts;
|
||||||
use atomic::Atomic;
|
use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
use parking_lot::RwLock;
|
use crate::{script_hook, PkmnResult, StringKey};
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Battle<'own, 'library> {
|
pub struct Battle<'own, 'library> {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::dynamic_data::models::executing_move::ExecutingMove;
|
use crate::dynamic_data::models::executing_move::ExecutingMove;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
use crate::dynamic_data::script_handling::ScriptSource;
|
use crate::dynamic_data::script_handling::ScriptSource;
|
||||||
use crate::script_hook;
|
use crate::script_hook;
|
||||||
use crate::utils::random::Random;
|
use crate::utils::Random;
|
||||||
use std::fmt::{Debug, Formatter};
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BattleRandom {
|
pub struct BattleRandom {
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
|
||||||
use crate::dynamic_data::event_hooks::event_hook::Event;
|
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
|
||||||
use crate::dynamic_data::models::battle_party::BattleParty;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::dynamic_data::script_handling::script::Script;
|
|
||||||
use crate::dynamic_data::script_handling::script_set::ScriptSet;
|
|
||||||
use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts;
|
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
|
||||||
use crate::{script_hook, PkmnResult, StringKey};
|
|
||||||
use parking_lot::lock_api::RwLockReadGuard;
|
|
||||||
use parking_lot::{RawRwLock, RwLock};
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use parking_lot::lock_api::RwLockReadGuard;
|
||||||
|
use parking_lot::{RawRwLock, RwLock};
|
||||||
|
|
||||||
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
|
use crate::dynamic_data::event_hooks::Event;
|
||||||
|
use crate::dynamic_data::models::battle::Battle;
|
||||||
|
use crate::dynamic_data::models::battle_party::BattleParty;
|
||||||
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
|
use crate::dynamic_data::Script;
|
||||||
|
use crate::dynamic_data::ScriptSet;
|
||||||
|
use crate::dynamic_data::VolatileScripts;
|
||||||
|
use crate::{script_hook, PkmnResult, StringKey};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BattleSide<'own, 'library> {
|
pub struct BattleSide<'own, 'library> {
|
||||||
index: u8,
|
index: u8,
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
use crate::dynamic_data::flow::target_resolver::TargetList;
|
|
||||||
use crate::dynamic_data::models::learned_move::LearnedMove;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::dynamic_data::script_handling::script::ScriptContainer;
|
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
|
||||||
use crate::static_data::MoveData;
|
|
||||||
use crate::{PkmnResult, PokemonError};
|
|
||||||
use atomic::Atomic;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use atomic::Atomic;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
|
use crate::dynamic_data::models::learned_move::LearnedMove;
|
||||||
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
|
use crate::dynamic_data::ScriptContainer;
|
||||||
|
use crate::dynamic_data::TargetList;
|
||||||
|
use crate::static_data::MoveData;
|
||||||
|
use crate::{PkmnResult, PokemonError};
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct HitData {
|
pub struct HitData {
|
||||||
critical: AtomicBool,
|
critical: AtomicBool,
|
||||||
|
|
|
@ -1,11 +1,34 @@
|
||||||
pub mod battle;
|
#[doc(inline)]
|
||||||
pub mod battle_party;
|
pub use battle::*;
|
||||||
pub mod battle_random;
|
#[doc(inline)]
|
||||||
pub mod battle_result;
|
pub use battle_party::*;
|
||||||
pub mod battle_side;
|
#[doc(inline)]
|
||||||
pub mod damage_source;
|
pub use battle_random::*;
|
||||||
pub mod executing_move;
|
#[doc(inline)]
|
||||||
pub mod learned_move;
|
pub use battle_result::*;
|
||||||
pub mod pokemon;
|
#[doc(inline)]
|
||||||
pub mod pokemon_builder;
|
pub use battle_side::*;
|
||||||
pub mod pokemon_party;
|
#[doc(inline)]
|
||||||
|
pub use damage_source::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use executing_move::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use learned_move::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use pokemon::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use pokemon_builder::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use pokemon_party::*;
|
||||||
|
|
||||||
|
mod battle;
|
||||||
|
mod battle_party;
|
||||||
|
mod battle_random;
|
||||||
|
mod battle_result;
|
||||||
|
mod battle_side;
|
||||||
|
mod damage_source;
|
||||||
|
mod executing_move;
|
||||||
|
mod learned_move;
|
||||||
|
mod pokemon;
|
||||||
|
mod pokemon_builder;
|
||||||
|
mod pokemon_party;
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
use crate::defines::{LevelInt, MAX_MOVES};
|
|
||||||
use crate::dynamic_data::event_hooks::event_hook::Event;
|
|
||||||
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
|
||||||
use crate::dynamic_data::models::damage_source::DamageSource;
|
|
||||||
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
|
|
||||||
use crate::dynamic_data::script_handling::script::{Script, ScriptContainer};
|
|
||||||
use crate::dynamic_data::script_handling::script_set::ScriptSet;
|
|
||||||
use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts;
|
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
|
||||||
use crate::static_data::items::item::Item;
|
|
||||||
use crate::static_data::natures::Nature;
|
|
||||||
use crate::static_data::species_data::ability::Ability;
|
|
||||||
use crate::static_data::species_data::ability_index::AbilityIndex;
|
|
||||||
use crate::static_data::species_data::form::Form;
|
|
||||||
use crate::static_data::species_data::gender::Gender;
|
|
||||||
use crate::static_data::species_data::species::Species;
|
|
||||||
use crate::static_data::statistic_set::{ClampedStatisticSet, StatisticSet};
|
|
||||||
use crate::static_data::DataLibrary;
|
|
||||||
use crate::utils::random::Random;
|
|
||||||
use crate::{script_hook, PkmnResult, ScriptCategory, StringKey};
|
|
||||||
use atomic::Atomic;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, AtomicU8, Ordering};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
use atomic::Atomic;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
|
use crate::defines::{LevelInt, MAX_MOVES};
|
||||||
|
use crate::dynamic_data::event_hooks::Event;
|
||||||
|
use crate::dynamic_data::models::battle::Battle;
|
||||||
|
use crate::dynamic_data::models::damage_source::DamageSource;
|
||||||
|
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
|
||||||
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
|
use crate::dynamic_data::{DynamicLibrary, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScripts};
|
||||||
|
use crate::static_data::Ability;
|
||||||
|
use crate::static_data::AbilityIndex;
|
||||||
|
use crate::static_data::DataLibrary;
|
||||||
|
use crate::static_data::Form;
|
||||||
|
use crate::static_data::Gender;
|
||||||
|
use crate::static_data::Item;
|
||||||
|
use crate::static_data::Nature;
|
||||||
|
use crate::static_data::Species;
|
||||||
|
use crate::static_data::{ClampedStatisticSet, StatisticSet};
|
||||||
|
use crate::utils::Random;
|
||||||
|
use crate::{script_hook, PkmnResult, StringKey};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PokemonBattleData<'pokemon, 'library> {
|
pub struct PokemonBattleData<'pokemon, 'library> {
|
||||||
battle: *mut Battle<'pokemon, 'library>,
|
battle: *mut Battle<'pokemon, 'library>,
|
||||||
|
@ -585,15 +584,15 @@ impl<'own, 'library> VolatileScripts<'own> for Pokemon<'own, 'library> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
use crate::dynamic_data::libraries::dynamic_library;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
use crate::static_data::libraries::data_library::DataLibrary;
|
use crate::dynamic_data::DynamicLibrary;
|
||||||
use crate::static_data::species_data::ability_index::AbilityIndex;
|
use crate::static_data::AbilityIndex;
|
||||||
use crate::static_data::species_data::gender::Gender;
|
use crate::static_data::DataLibrary;
|
||||||
|
use crate::static_data::Gender;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn construct_pokemon() {
|
fn construct_pokemon() {
|
||||||
let lib = dynamic_library::test::build();
|
let lib = crate::dynamic_data::libraries::dynamic_library::test::build();
|
||||||
let species = lib.static_data().species().get(&"foo".into()).unwrap();
|
let species = lib.static_data().species().get(&"foo".into()).unwrap();
|
||||||
let form = species.get_form(&"default".into()).unwrap();
|
let form = species.get_form(&"default".into()).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::defines::LevelInt;
|
use crate::defines::LevelInt;
|
||||||
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
|
||||||
use crate::dynamic_data::models::learned_move::MoveLearnMethod;
|
use crate::dynamic_data::models::learned_move::MoveLearnMethod;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
|
use crate::dynamic_data::DynamicLibrary;
|
||||||
use crate::static_data::{AbilityIndex, DataLibrary, Gender};
|
use crate::static_data::{AbilityIndex, DataLibrary, Gender};
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
use crate::dynamic_data::script_handling::script::{Script, ScriptContainer};
|
|
||||||
use crate::dynamic_data::script_handling::script_set::ScriptSet;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
pub mod item_script;
|
use parking_lot::RwLock;
|
||||||
pub mod script;
|
|
||||||
pub mod script_set;
|
#[doc(inline)]
|
||||||
pub mod volatile_scripts;
|
pub use item_script::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use script::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use script_set::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use volatile_scripts::*;
|
||||||
|
|
||||||
|
mod item_script;
|
||||||
|
mod script;
|
||||||
|
mod script_set;
|
||||||
|
mod volatile_scripts;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! script_hook {
|
macro_rules! script_hook {
|
||||||
|
@ -25,21 +33,6 @@ macro_rules! script_hook {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! script_hook_on_lock {
|
|
||||||
($hook_name: ident, $source: ident, $($parameters: expr),*) => {
|
|
||||||
let mut aggregator = $source.read().get_script_iterator();
|
|
||||||
while let Some(script) = aggregator.get_next() {
|
|
||||||
let lock = &mut script.get().read();
|
|
||||||
let script = lock.as_mut().unwrap();
|
|
||||||
if script.is_suppressed() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
script.$hook_name($($parameters),*);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! run_scripts {
|
macro_rules! run_scripts {
|
||||||
($hook_name: ident, $source: ident, $($parameters: expr),*) => {
|
($hook_name: ident, $source: ident, $($parameters: expr),*) => {
|
||||||
|
@ -198,12 +191,14 @@ impl ScriptAggregator {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use std::any::Any;
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use crate::dynamic_data::script_handling::script::ScriptContainer;
|
use crate::dynamic_data::script_handling::script::ScriptContainer;
|
||||||
use crate::static_data::EffectParameter;
|
use crate::static_data::EffectParameter;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use std::any::Any;
|
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use super::*;
|
||||||
|
|
||||||
pub struct TestScript {
|
pub struct TestScript {
|
||||||
name: StringKey,
|
name: StringKey,
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
|
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
|
||||||
use crate::dynamic_data::models::damage_source::DamageSource;
|
|
||||||
use crate::dynamic_data::models::executing_move::ExecutingMove;
|
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use crate::static_data::moves::secondary_effect::EffectParameter;
|
|
||||||
use crate::static_data::{Item, Statistic};
|
|
||||||
use crate::StringKey;
|
|
||||||
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -14,6 +5,17 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread::JoinHandle;
|
use std::thread::JoinHandle;
|
||||||
|
|
||||||
|
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
|
||||||
|
|
||||||
|
use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
|
||||||
|
use crate::dynamic_data::Battle;
|
||||||
|
use crate::dynamic_data::DamageSource;
|
||||||
|
use crate::dynamic_data::ExecutingMove;
|
||||||
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::static_data::EffectParameter;
|
||||||
|
use crate::static_data::{Item, Statistic};
|
||||||
|
use crate::StringKey;
|
||||||
|
|
||||||
pub trait Script: Send + Sync {
|
pub trait Script: Send + Sync {
|
||||||
fn name(&self) -> &StringKey;
|
fn name(&self) -> &StringKey;
|
||||||
fn get_marked_for_deletion(&self) -> &AtomicBool;
|
fn get_marked_for_deletion(&self) -> &AtomicBool;
|
||||||
|
@ -231,9 +233,10 @@ impl Clone for ScriptContainer {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use std::sync::atomic::{AtomicBool, AtomicPtr};
|
use std::sync::atomic::{AtomicBool, AtomicPtr};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
pub struct TestScript {
|
pub struct TestScript {
|
||||||
name: StringKey,
|
name: StringKey,
|
||||||
container: AtomicPtr<ScriptContainer>,
|
container: AtomicPtr<ScriptContainer>,
|
||||||
|
|
37
src/lib.rs
37
src/lib.rs
|
@ -1,6 +1,8 @@
|
||||||
// The too many arguments is annoying, especially for when we create constructors, disable.
|
// The too many arguments is annoying, especially for when we create constructor, disable.
|
||||||
#![allow(clippy::too_many_arguments, clippy::needless_range_loop)]
|
#![allow(clippy::too_many_arguments, clippy::needless_range_loop)]
|
||||||
#![allow(clippy::not_unsafe_ptr_arg_deref)]
|
#![allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
#![warn(clippy::missing_docs_in_private_items)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(bench_black_box)]
|
#![feature(bench_black_box)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
@ -8,22 +10,45 @@
|
||||||
#![feature(const_option)]
|
#![feature(const_option)]
|
||||||
#![feature(is_some_with)]
|
#![feature(is_some_with)]
|
||||||
|
|
||||||
|
//! PkmnLib
|
||||||
|
//! PkmnLib is a full featured implementation of Pokemon. while currently focused on implementing
|
||||||
|
//! generation 7, this library tries to offload generational differences such as move effects
|
||||||
|
//! to a scripting library.
|
||||||
|
//!
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
use crate::dynamic_data::libraries::script_resolver::ScriptCategory;
|
#[doc(hidden)]
|
||||||
|
pub use utils::*;
|
||||||
|
|
||||||
|
use crate::dynamic_data::ScriptCategory;
|
||||||
|
|
||||||
|
/// The defines module holds the core defines of the library
|
||||||
pub mod defines;
|
pub mod defines;
|
||||||
|
/// The dynamic data module holds data that can change during execution, and things that relate to
|
||||||
|
/// this. This includes things as Pokemon themselves, battles, etc.
|
||||||
pub mod dynamic_data;
|
pub mod dynamic_data;
|
||||||
|
/// The static data module holds data that can be set once, and then never change. This includes
|
||||||
|
/// things such as data about Pokemon species, data about items, etc.
|
||||||
pub mod static_data;
|
pub mod static_data;
|
||||||
|
/// The utils module includes misc utils that are used within PkmnLib
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
/// The PokemonError enum holds all different error states that can be encountered in PkmnLib.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum PokemonError {
|
pub enum PokemonError {
|
||||||
ScriptNotFound { category: ScriptCategory, name: String },
|
/// A script was requested, but we were unable to find it.
|
||||||
MiscError,
|
ScriptNotFound {
|
||||||
|
/// The category of the script we requested,
|
||||||
|
category: ScriptCategory,
|
||||||
|
/// The unique key of the requested script.
|
||||||
|
name: StringKey,
|
||||||
|
},
|
||||||
|
/// We requested data for a specific target, but that target does not exist on the battle field.
|
||||||
InvalidTargetRequested,
|
InvalidTargetRequested,
|
||||||
|
|
||||||
|
/// Misc errors. Use of this should be minimized, but it is useful for early development.
|
||||||
|
MiscError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A simple result type.
|
||||||
pub type PkmnResult<T> = Result<T, PokemonError>;
|
pub type PkmnResult<T> = Result<T, PokemonError>;
|
||||||
|
|
||||||
pub use utils::*;
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
use crate::defines::LevelInt;
|
use crate::defines::LevelInt;
|
||||||
use crate::static_data::growth_rates::growth_rate::GrowthRate;
|
|
||||||
|
pub trait GrowthRate {
|
||||||
|
fn calculate_level(&self, experience: u32) -> LevelInt;
|
||||||
|
fn calculate_experience(&self, level: LevelInt) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LookupGrowthRate {
|
pub struct LookupGrowthRate {
|
||||||
experience: Vec<u32>,
|
experience: Vec<u32>,
|
|
@ -1,6 +0,0 @@
|
||||||
use crate::defines::LevelInt;
|
|
||||||
|
|
||||||
pub trait GrowthRate {
|
|
||||||
fn calculate_level(&self, experience: u32) -> LevelInt;
|
|
||||||
fn calculate_experience(&self, level: LevelInt) -> u32;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
pub mod growth_rate;
|
|
||||||
pub mod lookup_growth_rate;
|
|
||||||
|
|
||||||
pub use growth_rate::*;
|
|
||||||
pub use lookup_growth_rate::*;
|
|
|
@ -1,6 +1,33 @@
|
||||||
use super::item_category::{BattleItemCategory, ItemCategory};
|
|
||||||
use crate::StringKey;
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::StringKey;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum ItemCategory {
|
||||||
|
MiscItem,
|
||||||
|
Pokeball,
|
||||||
|
Medicine,
|
||||||
|
Berry,
|
||||||
|
TMHM,
|
||||||
|
FormChanger,
|
||||||
|
KeyItem,
|
||||||
|
Mail,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum BattleItemCategory {
|
||||||
|
None,
|
||||||
|
Healing,
|
||||||
|
StatusHealing,
|
||||||
|
Pokeball,
|
||||||
|
MiscBattleItem,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Item {
|
pub struct Item {
|
|
@ -1,27 +0,0 @@
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum ItemCategory {
|
|
||||||
MiscItem,
|
|
||||||
Pokeball,
|
|
||||||
Medicine,
|
|
||||||
Berry,
|
|
||||||
TMHM,
|
|
||||||
FormChanger,
|
|
||||||
KeyItem,
|
|
||||||
Mail,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum BattleItemCategory {
|
|
||||||
None,
|
|
||||||
Healing,
|
|
||||||
StatusHealing,
|
|
||||||
Pokeball,
|
|
||||||
MiscBattleItem,
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
pub mod item;
|
|
||||||
pub mod item_category;
|
|
||||||
|
|
||||||
pub use item::*;
|
|
||||||
pub use item_category::*;
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::static_data::Ability;
|
use crate::static_data::Ability;
|
||||||
use crate::static_data::DataLibrary;
|
use crate::static_data::DataLibrary;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AbilityLibrary {
|
pub struct AbilityLibrary {
|
||||||
|
@ -34,9 +35,9 @@ impl DataLibrary<'_, Box<Ability>> for AbilityLibrary {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use crate::static_data::libraries::ability_library::AbilityLibrary;
|
use crate::static_data::Ability;
|
||||||
use crate::static_data::libraries::data_library::DataLibrary;
|
use crate::static_data::AbilityLibrary;
|
||||||
use crate::static_data::species_data::ability::Ability;
|
use crate::static_data::DataLibrary;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
|
|
||||||
pub fn build() -> AbilityLibrary {
|
pub fn build() -> AbilityLibrary {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::defines::LevelInt;
|
use crate::defines::LevelInt;
|
||||||
use crate::static_data::GrowthRate;
|
use crate::static_data::GrowthRate;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashMap;
|
|
||||||
use std::fmt;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
|
||||||
|
|
||||||
pub struct GrowthRateLibrary {
|
pub struct GrowthRateLibrary {
|
||||||
growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>,
|
growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>,
|
||||||
|
@ -35,7 +37,7 @@ impl Debug for GrowthRateLibrary {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use crate::static_data::growth_rates::lookup_growth_rate::LookupGrowthRate;
|
use crate::static_data::growth_rates::LookupGrowthRate;
|
||||||
use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary;
|
use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary;
|
||||||
|
|
||||||
pub fn build() -> GrowthRateLibrary {
|
pub fn build() -> GrowthRateLibrary {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::static_data::DataLibrary;
|
use crate::static_data::DataLibrary;
|
||||||
use crate::static_data::Item;
|
use crate::static_data::Item;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ItemLibrary {
|
pub struct ItemLibrary {
|
||||||
|
@ -34,11 +35,12 @@ impl DataLibrary<'_, Box<Item>> for ItemLibrary {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use crate::static_data::items::item::Item;
|
use hashbrown::HashSet;
|
||||||
use crate::static_data::items::item_category::{BattleItemCategory, ItemCategory};
|
|
||||||
use crate::static_data::libraries::data_library::DataLibrary;
|
use crate::static_data::libraries::data_library::DataLibrary;
|
||||||
use crate::static_data::libraries::item_library::ItemLibrary;
|
use crate::static_data::libraries::item_library::ItemLibrary;
|
||||||
use hashbrown::HashSet;
|
use crate::static_data::Item;
|
||||||
|
use crate::static_data::{BattleItemCategory, ItemCategory};
|
||||||
|
|
||||||
fn build_item() -> Item {
|
fn build_item() -> Item {
|
||||||
Item::new(
|
Item::new(
|
||||||
|
|
|
@ -1,19 +1,28 @@
|
||||||
pub mod ability_library;
|
#[doc(inline)]
|
||||||
pub mod data_library;
|
|
||||||
pub mod growth_rate_library;
|
|
||||||
pub mod item_library;
|
|
||||||
pub mod library_settings;
|
|
||||||
pub mod move_library;
|
|
||||||
pub mod species_library;
|
|
||||||
pub mod static_data;
|
|
||||||
pub mod type_library;
|
|
||||||
|
|
||||||
pub use ability_library::AbilityLibrary;
|
pub use ability_library::AbilityLibrary;
|
||||||
|
#[doc(inline)]
|
||||||
pub use data_library::DataLibrary;
|
pub use data_library::DataLibrary;
|
||||||
|
#[doc(inline)]
|
||||||
pub use growth_rate_library::GrowthRateLibrary;
|
pub use growth_rate_library::GrowthRateLibrary;
|
||||||
|
#[doc(inline)]
|
||||||
pub use item_library::ItemLibrary;
|
pub use item_library::ItemLibrary;
|
||||||
|
#[doc(inline)]
|
||||||
pub use library_settings::LibrarySettings;
|
pub use library_settings::LibrarySettings;
|
||||||
|
#[doc(inline)]
|
||||||
pub use move_library::MoveLibrary;
|
pub use move_library::MoveLibrary;
|
||||||
|
#[doc(inline)]
|
||||||
pub use species_library::SpeciesLibrary;
|
pub use species_library::SpeciesLibrary;
|
||||||
|
#[doc(inline)]
|
||||||
pub use static_data::StaticData;
|
pub use static_data::StaticData;
|
||||||
|
#[doc(inline)]
|
||||||
pub use type_library::TypeLibrary;
|
pub use type_library::TypeLibrary;
|
||||||
|
|
||||||
|
mod ability_library;
|
||||||
|
mod data_library;
|
||||||
|
mod growth_rate_library;
|
||||||
|
mod item_library;
|
||||||
|
mod library_settings;
|
||||||
|
mod move_library;
|
||||||
|
mod species_library;
|
||||||
|
pub(crate) mod static_data;
|
||||||
|
mod type_library;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::static_data::DataLibrary;
|
use crate::static_data::DataLibrary;
|
||||||
use crate::static_data::MoveData;
|
use crate::static_data::MoveData;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MoveLibrary {
|
pub struct MoveLibrary {
|
||||||
|
@ -34,11 +35,12 @@ impl DataLibrary<'_, MoveData> for MoveLibrary {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
use crate::static_data::libraries::data_library::DataLibrary;
|
use crate::static_data::libraries::data_library::DataLibrary;
|
||||||
use crate::static_data::libraries::move_library::MoveLibrary;
|
use crate::static_data::libraries::move_library::MoveLibrary;
|
||||||
use crate::static_data::moves::move_data::{MoveCategory, MoveData, MoveTarget};
|
use crate::static_data::{MoveCategory, MoveData, MoveTarget};
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashSet;
|
|
||||||
|
|
||||||
fn build_move() -> MoveData {
|
fn build_move() -> MoveData {
|
||||||
MoveData::new(
|
MoveData::new(
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::static_data::DataLibrary;
|
use crate::static_data::DataLibrary;
|
||||||
use crate::static_data::Species;
|
use crate::static_data::Species;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpeciesLibrary {
|
pub struct SpeciesLibrary {
|
||||||
|
@ -34,13 +35,14 @@ impl<'a> DataLibrary<'a, Box<Species>> for SpeciesLibrary {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
use crate::static_data::libraries::data_library::DataLibrary;
|
use crate::static_data::libraries::data_library::DataLibrary;
|
||||||
use crate::static_data::libraries::species_library::SpeciesLibrary;
|
use crate::static_data::libraries::species_library::SpeciesLibrary;
|
||||||
use crate::static_data::species_data::form::Form;
|
use crate::static_data::Form;
|
||||||
use crate::static_data::species_data::learnable_moves::LearnableMoves;
|
use crate::static_data::LearnableMoves;
|
||||||
use crate::static_data::species_data::species::Species;
|
use crate::static_data::Species;
|
||||||
use crate::static_data::StaticStatisticSet;
|
use crate::static_data::StaticStatisticSet;
|
||||||
use hashbrown::HashSet;
|
|
||||||
|
|
||||||
fn build_species() -> Species {
|
fn build_species() -> Species {
|
||||||
Species::new(
|
Species::new(
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
pub mod growth_rates;
|
#[doc(inline)]
|
||||||
pub mod items;
|
|
||||||
pub mod libraries;
|
|
||||||
pub mod moves;
|
|
||||||
pub mod natures;
|
|
||||||
pub mod species_data;
|
|
||||||
pub mod statistic_set;
|
|
||||||
pub mod statistics;
|
|
||||||
|
|
||||||
pub use growth_rates::*;
|
pub use growth_rates::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use items::*;
|
pub use items::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use libraries::*;
|
pub use libraries::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use moves::*;
|
pub use moves::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use natures::*;
|
pub use natures::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use species_data::*;
|
pub use species_data::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use statistic_set::*;
|
pub use statistic_set::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use statistics::*;
|
pub use statistics::*;
|
||||||
|
|
||||||
|
mod growth_rates;
|
||||||
|
mod items;
|
||||||
|
pub(crate) mod libraries;
|
||||||
|
mod moves;
|
||||||
|
mod natures;
|
||||||
|
mod species_data;
|
||||||
|
mod statistic_set;
|
||||||
|
mod statistics;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
pub mod move_data;
|
#[doc(inline)]
|
||||||
pub mod secondary_effect;
|
pub use move_data::*;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use secondary_effect::*;
|
||||||
|
|
||||||
pub use move_data::MoveCategory;
|
mod move_data;
|
||||||
pub use move_data::MoveData;
|
mod secondary_effect;
|
||||||
pub use move_data::MoveTarget;
|
|
||||||
|
|
||||||
pub use secondary_effect::EffectParameter;
|
|
||||||
pub use secondary_effect::SecondaryEffect;
|
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
pub mod ability;
|
#[doc(inline)]
|
||||||
pub mod ability_index;
|
|
||||||
pub mod form;
|
|
||||||
pub mod gender;
|
|
||||||
pub mod learnable_moves;
|
|
||||||
pub mod species;
|
|
||||||
|
|
||||||
pub use ability::Ability;
|
pub use ability::Ability;
|
||||||
|
#[doc(inline)]
|
||||||
pub use ability_index::AbilityIndex;
|
pub use ability_index::AbilityIndex;
|
||||||
|
#[doc(inline)]
|
||||||
pub use form::Form;
|
pub use form::Form;
|
||||||
|
#[doc(inline)]
|
||||||
pub use gender::Gender;
|
pub use gender::Gender;
|
||||||
|
#[doc(inline)]
|
||||||
pub use learnable_moves::LearnableMoves;
|
pub use learnable_moves::LearnableMoves;
|
||||||
|
#[doc(inline)]
|
||||||
pub use species::Species;
|
pub use species::Species;
|
||||||
|
|
||||||
|
mod ability;
|
||||||
|
mod ability_index;
|
||||||
|
mod form;
|
||||||
|
mod gender;
|
||||||
|
mod learnable_moves;
|
||||||
|
mod species;
|
||||||
|
|
|
@ -1,18 +1,30 @@
|
||||||
use super::statistics::Statistic;
|
|
||||||
use atomic_prim_traits::AtomicInt;
|
|
||||||
use num_traits::{clamp, NumCast, PrimInt};
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
use atomic_prim_traits::AtomicInt;
|
||||||
|
use num_traits::{clamp, NumCast, PrimInt};
|
||||||
|
|
||||||
|
use super::statistics::Statistic;
|
||||||
|
|
||||||
|
/// A collection of every individual stat. This set can hold any value that is valid for its integer
|
||||||
|
/// type, and can be modified at will.
|
||||||
|
///
|
||||||
|
/// As all data in this type is atomic, threaded access to this struct is completely legal.
|
||||||
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct StatisticSet<T>
|
pub struct StatisticSet<T>
|
||||||
where
|
where
|
||||||
T: AtomicInt,
|
T: AtomicInt,
|
||||||
{
|
{
|
||||||
|
/// The health point stat value.
|
||||||
hp: T,
|
hp: T,
|
||||||
|
/// The physical attack stat value.
|
||||||
attack: T,
|
attack: T,
|
||||||
|
/// The physical defense stat value.
|
||||||
defense: T,
|
defense: T,
|
||||||
|
/// The special attack stat value.
|
||||||
special_attack: T,
|
special_attack: T,
|
||||||
|
/// The special defense stat value.
|
||||||
special_defense: T,
|
special_defense: T,
|
||||||
|
/// The speed stat value.
|
||||||
speed: T,
|
speed: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +32,7 @@ impl<T> StatisticSet<T>
|
||||||
where
|
where
|
||||||
T: AtomicInt,
|
T: AtomicInt,
|
||||||
{
|
{
|
||||||
|
/// Creates a new statistic set with given stats.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
hp: T::Prim,
|
hp: T::Prim,
|
||||||
attack: T::Prim,
|
attack: T::Prim,
|
||||||
|
@ -38,25 +51,32 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The health point stat value.
|
||||||
pub fn hp(&self) -> T::Prim {
|
pub fn hp(&self) -> T::Prim {
|
||||||
self.hp.load(Ordering::Relaxed)
|
self.hp.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
/// The physical attack stat value.
|
||||||
pub fn attack(&self) -> T::Prim {
|
pub fn attack(&self) -> T::Prim {
|
||||||
self.attack.load(Ordering::Relaxed)
|
self.attack.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
/// The physical defense stat value.
|
||||||
pub fn defense(&self) -> T::Prim {
|
pub fn defense(&self) -> T::Prim {
|
||||||
self.defense.load(Ordering::Relaxed)
|
self.defense.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
/// The special attack stat value.
|
||||||
pub fn special_attack(&self) -> T::Prim {
|
pub fn special_attack(&self) -> T::Prim {
|
||||||
self.special_attack.load(Ordering::Relaxed)
|
self.special_attack.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
/// The special defense stat value.
|
||||||
pub fn special_defense(&self) -> T::Prim {
|
pub fn special_defense(&self) -> T::Prim {
|
||||||
self.special_defense.load(Ordering::Relaxed)
|
self.special_defense.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
/// The speed stat value.
|
||||||
pub fn speed(&self) -> T::Prim {
|
pub fn speed(&self) -> T::Prim {
|
||||||
self.speed.load(Ordering::Relaxed)
|
self.speed.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the value of a specific stat
|
||||||
pub fn get_stat(&self, stat: Statistic) -> T::Prim {
|
pub fn get_stat(&self, stat: Statistic) -> T::Prim {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp.load(Ordering::Relaxed),
|
Statistic::HP => self.hp.load(Ordering::Relaxed),
|
||||||
|
@ -68,6 +88,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Modify the value of a specific stat.
|
||||||
pub fn set_stat(&self, stat: Statistic, value: T::Prim) {
|
pub fn set_stat(&self, stat: Statistic, value: T::Prim) {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp.store(value, Ordering::SeqCst),
|
Statistic::HP => self.hp.store(value, Ordering::SeqCst),
|
||||||
|
@ -79,6 +100,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Increase the value of a given stat by a value.
|
||||||
pub fn increase_stat(&self, stat: Statistic, value: T::Prim) {
|
pub fn increase_stat(&self, stat: Statistic, value: T::Prim) {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp.fetch_add(value, Ordering::SeqCst),
|
Statistic::HP => self.hp.fetch_add(value, Ordering::SeqCst),
|
||||||
|
@ -90,6 +112,7 @@ where
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decrease the value of a given stat by a value.
|
||||||
pub fn decrease_stat(&self, stat: Statistic, value: T::Prim) {
|
pub fn decrease_stat(&self, stat: Statistic, value: T::Prim) {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp.fetch_sub(value, Ordering::SeqCst),
|
Statistic::HP => self.hp.fetch_sub(value, Ordering::SeqCst),
|
||||||
|
@ -102,16 +125,25 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A collection of statistics that can not be modified after creation.
|
||||||
|
///
|
||||||
|
/// As no modifications happen, this struct does not use atomics.
|
||||||
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct StaticStatisticSet<T>
|
pub struct StaticStatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
|
/// The health point stat value.
|
||||||
hp: T,
|
hp: T,
|
||||||
|
/// The physical attack stat value.
|
||||||
attack: T,
|
attack: T,
|
||||||
|
/// The physical defense stat value.
|
||||||
defense: T,
|
defense: T,
|
||||||
|
/// The special attack stat value.
|
||||||
special_attack: T,
|
special_attack: T,
|
||||||
|
/// The special defense stat value.
|
||||||
special_defense: T,
|
special_defense: T,
|
||||||
|
/// The speed stat value.
|
||||||
speed: T,
|
speed: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +151,7 @@ impl<T> StaticStatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
|
/// Create a new static statistic set.
|
||||||
pub const fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
pub const fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
hp,
|
hp,
|
||||||
|
@ -130,25 +163,32 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The health point stat value.=
|
||||||
pub const fn hp(&self) -> T {
|
pub const fn hp(&self) -> T {
|
||||||
self.hp
|
self.hp
|
||||||
}
|
}
|
||||||
|
/// The physical attack stat value.
|
||||||
pub const fn attack(&self) -> T {
|
pub const fn attack(&self) -> T {
|
||||||
self.attack
|
self.attack
|
||||||
}
|
}
|
||||||
|
/// The physical defense stat value.
|
||||||
pub const fn defense(&self) -> T {
|
pub const fn defense(&self) -> T {
|
||||||
self.defense
|
self.defense
|
||||||
}
|
}
|
||||||
|
/// The special attack stat value.
|
||||||
pub const fn special_attack(&self) -> T {
|
pub const fn special_attack(&self) -> T {
|
||||||
self.special_attack
|
self.special_attack
|
||||||
}
|
}
|
||||||
|
/// The special defense stat value.
|
||||||
pub const fn special_defense(&self) -> T {
|
pub const fn special_defense(&self) -> T {
|
||||||
self.special_defense
|
self.special_defense
|
||||||
}
|
}
|
||||||
|
/// The speed stat value.
|
||||||
pub const fn speed(&self) -> T {
|
pub const fn speed(&self) -> T {
|
||||||
self.speed
|
self.speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the value of a specific stat
|
||||||
pub const fn get_stat(&self, stat: Statistic) -> T {
|
pub const fn get_stat(&self, stat: Statistic) -> T {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp,
|
Statistic::HP => self.hp,
|
||||||
|
@ -166,14 +206,22 @@ pub struct ClampedStatisticSet<T, const MIN: i64, const MAX: i64>
|
||||||
where
|
where
|
||||||
T: AtomicInt,
|
T: AtomicInt,
|
||||||
{
|
{
|
||||||
|
/// The health point stat value.
|
||||||
hp: T,
|
hp: T,
|
||||||
|
/// The physical attack stat value.
|
||||||
attack: T,
|
attack: T,
|
||||||
|
/// The physical defense stat value.
|
||||||
defense: T,
|
defense: T,
|
||||||
|
/// The special attack stat value.
|
||||||
special_attack: T,
|
special_attack: T,
|
||||||
|
/// The special defense stat value.
|
||||||
special_defense: T,
|
special_defense: T,
|
||||||
|
/// The speed stat value.
|
||||||
speed: T,
|
speed: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A clamped statistic set is a collection of each statistics that can be modified, but that will
|
||||||
|
/// always remain between two compile time constant values (Min, Max).
|
||||||
impl<T, const MIN: i64, const MAX: i64> ClampedStatisticSet<T, MIN, MAX>
|
impl<T, const MIN: i64, const MAX: i64> ClampedStatisticSet<T, MIN, MAX>
|
||||||
where
|
where
|
||||||
T: AtomicInt,
|
T: AtomicInt,
|
||||||
|
@ -302,9 +350,10 @@ where
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use std::sync::atomic::AtomicI32;
|
use std::sync::atomic::AtomicI32;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_get_values() {
|
fn create_get_values() {
|
||||||
let set = StatisticSet::<AtomicI32>::new(1, 2, 3, 4, 5, 6);
|
let set = StatisticSet::<AtomicI32>::new(1, 2, 3, 4, 5, 6);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
pub mod random;
|
#[doc(inline)]
|
||||||
pub mod string_key;
|
|
||||||
|
|
||||||
pub use random::Random;
|
pub use random::Random;
|
||||||
|
#[doc(inline)]
|
||||||
pub use string_key::StringKey;
|
pub use string_key::StringKey;
|
||||||
|
|
||||||
|
mod random;
|
||||||
|
mod string_key;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use pkmn_lib::dynamic_data::models::battle::Battle;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use pkmn_lib::dynamic_data::Battle;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum TestDataGetter {
|
pub enum TestDataGetter {
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use num_traits::PrimInt;
|
use num_traits::PrimInt;
|
||||||
|
use project_root::get_project_root;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use pkmn_lib::defines::LevelInt;
|
use pkmn_lib::defines::LevelInt;
|
||||||
use pkmn_lib::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator;
|
use pkmn_lib::dynamic_data::DynamicLibrary;
|
||||||
use pkmn_lib::dynamic_data::libraries::damage_library::Gen7DamageLibrary;
|
use pkmn_lib::dynamic_data::Gen7BattleStatCalculator;
|
||||||
use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
use pkmn_lib::dynamic_data::Gen7DamageLibrary;
|
||||||
use pkmn_lib::dynamic_data::libraries::misc_library::Gen7MiscLibrary;
|
use pkmn_lib::dynamic_data::Gen7MiscLibrary;
|
||||||
use pkmn_lib::static_data::{
|
use pkmn_lib::static_data::{
|
||||||
Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item,
|
Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item,
|
||||||
ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary,
|
ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary,
|
||||||
SecondaryEffect, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary,
|
SecondaryEffect, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary,
|
||||||
};
|
};
|
||||||
use pkmn_lib::StringKey;
|
use pkmn_lib::StringKey;
|
||||||
use project_root::get_project_root;
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
pub fn load_library() -> DynamicLibrary {
|
pub fn load_library() -> DynamicLibrary {
|
||||||
let mut path = get_project_root().unwrap();
|
let mut path = get_project_root().unwrap();
|
||||||
|
@ -32,7 +34,7 @@ pub fn load_library() -> DynamicLibrary {
|
||||||
load_species(&path, &mut data);
|
load_species(&path, &mut data);
|
||||||
let dynamic = DynamicLibrary::new(
|
let dynamic = DynamicLibrary::new(
|
||||||
data,
|
data,
|
||||||
BattleStatCalculator {},
|
Box::new(Gen7BattleStatCalculator {}),
|
||||||
Box::new(Gen7DamageLibrary::new(false)),
|
Box::new(Gen7DamageLibrary::new(false)),
|
||||||
Box::new(Gen7MiscLibrary::new()),
|
Box::new(Gen7MiscLibrary::new()),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
use super::test_step::TestStep;
|
|
||||||
use pkmn_lib::defines::LevelInt;
|
|
||||||
use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
|
||||||
use pkmn_lib::dynamic_data::models::battle::Battle;
|
|
||||||
use pkmn_lib::dynamic_data::models::battle_party::BattleParty;
|
|
||||||
use pkmn_lib::dynamic_data::models::pokemon::Pokemon;
|
|
||||||
use pkmn_lib::dynamic_data::models::pokemon_builder::PokemonBuilder;
|
|
||||||
use pkmn_lib::dynamic_data::models::pokemon_party::PokemonParty;
|
|
||||||
use pkmn_lib::StringKey;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use pkmn_lib::defines::LevelInt;
|
||||||
|
use pkmn_lib::dynamic_data::Battle;
|
||||||
|
use pkmn_lib::dynamic_data::BattleParty;
|
||||||
|
use pkmn_lib::dynamic_data::DynamicLibrary;
|
||||||
|
use pkmn_lib::dynamic_data::Pokemon;
|
||||||
|
use pkmn_lib::dynamic_data::PokemonBuilder;
|
||||||
|
use pkmn_lib::dynamic_data::PokemonParty;
|
||||||
|
use pkmn_lib::StringKey;
|
||||||
|
|
||||||
|
use super::test_step::TestStep;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct TestCase {
|
pub struct TestCase {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use super::data_getter::TestDataGetter;
|
|
||||||
use pkmn_lib::dynamic_data::choices::{MoveChoice, PassChoice, TurnChoice};
|
|
||||||
use pkmn_lib::dynamic_data::models::battle::Battle;
|
|
||||||
use pkmn_lib::StringKey;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use pkmn_lib::dynamic_data::Battle;
|
||||||
|
use pkmn_lib::dynamic_data::{MoveChoice, PassChoice, TurnChoice};
|
||||||
|
use pkmn_lib::StringKey;
|
||||||
|
|
||||||
|
use super::data_getter::TestDataGetter;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum TestStep {
|
pub enum TestStep {
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
#![test_runner(datatest::runner)]
|
#![test_runner(datatest::runner)]
|
||||||
|
|
||||||
use crate::common::{library_loader, TestCase};
|
|
||||||
use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::lazy::SyncLazy;
|
use std::lazy::SyncLazy;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use pkmn_lib::dynamic_data::DynamicLibrary;
|
||||||
|
|
||||||
|
use crate::common::{library_loader, TestCase};
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
|
|
||||||
static LIBRARY: SyncLazy<DynamicLibrary> = SyncLazy::new(|| {
|
static LIBRARY: SyncLazy<DynamicLibrary> = SyncLazy::new(|| {
|
||||||
|
|
Loading…
Reference in New Issue