Initial work on adding documentation, reorganises modules
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -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::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)]
|
||||
struct CommonChoiceData<'user, 'library> {
|
||||
/// The user of the turn choice
|
||||
user: Arc<Pokemon<'user, 'library>>,
|
||||
/// The speed of the user at the beginning of the turn.
|
||||
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,
|
||||
/// Whether or not the choice has failed. A failed choice will stop running, and execute special
|
||||
/// fail handling during turn execution.
|
||||
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>,
|
||||
}
|
||||
|
||||
/// This enum defines a single choice for a Pokemon for a battle turn.
|
||||
#[derive(Debug)]
|
||||
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>),
|
||||
/// An item choice tells a Pokemon to use an item.
|
||||
Item(ItemChoice<'user, 'library>),
|
||||
/// A switch choice tells a Pokemon to switch with another Pokemon from the party.
|
||||
Switch(SwitchChoice<'user, 'library>),
|
||||
/// A flee choice tells a Pokemon to flee from battle.
|
||||
Flee(FleeChoice<'user, 'library>),
|
||||
/// A pass choice tells the user to do nothing that turn.
|
||||
Pass(PassChoice<'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> {
|
||||
match self {
|
||||
TurnChoice::Move(data) => &data.choice_data,
|
||||
@@ -34,6 +53,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
|
||||
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>> {
|
||||
match self {
|
||||
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>> {
|
||||
&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 {
|
||||
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 {
|
||||
&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 {
|
||||
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) {
|
||||
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 {
|
||||
self.choice_data().random_value
|
||||
}
|
||||
|
||||
/// This sets the above random value.
|
||||
pub(crate) fn set_random_value(&mut self, val: u32) {
|
||||
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> {
|
||||
if let TurnChoice::Move(data) = self {
|
||||
return data;
|
||||
@@ -122,17 +157,25 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The data attached to a move choice.
|
||||
#[derive(Debug)]
|
||||
pub struct MoveChoice<'user, 'library> {
|
||||
/// The move that is used for this choice.
|
||||
used_move: Arc<LearnedMove<'library>>,
|
||||
/// The side this move is aimed at.
|
||||
target_side: u8,
|
||||
/// The index of the Pokemon on the side we're aiming at.
|
||||
target_index: u8,
|
||||
/// The move script.
|
||||
script: ScriptContainer,
|
||||
/// The priority of the move choice at the beginning of the turn.
|
||||
priority: i8,
|
||||
/// The common turn choice data.
|
||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||
}
|
||||
|
||||
impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||
/// Initializes the data for a new move choice.
|
||||
pub fn new(
|
||||
user: Arc<Pokemon<'user, '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>> {
|
||||
&self.used_move
|
||||
}
|
||||
|
||||
/// The target side the move is aimed at.
|
||||
pub fn target_side(&self) -> u8 {
|
||||
self.target_side
|
||||
}
|
||||
/// The Pokemon index on the side we're aiming at.
|
||||
pub fn target_index(&self) -> u8 {
|
||||
self.target_index
|
||||
}
|
||||
/// The priority of the move choice at the beginning of the turn.
|
||||
pub fn priority(&self) -> i8 {
|
||||
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>> {
|
||||
&self.choice_data.user
|
||||
}
|
||||
/// The move script of the choice.
|
||||
pub fn script(&self) -> &ScriptContainer {
|
||||
&self.script
|
||||
}
|
||||
|
||||
pub fn priority_mut(&mut self) -> &mut i8 {
|
||||
&mut self.priority
|
||||
}
|
||||
}
|
||||
|
||||
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)]
|
||||
pub struct ItemChoice<'user, 'library> {
|
||||
/// The shared data of all turn choices.
|
||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||
}
|
||||
|
||||
impl<'user, 'library> ItemChoice<'user, 'library> {
|
||||
/// Initialised a new item choice.
|
||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||
Self {
|
||||
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)]
|
||||
pub struct SwitchChoice<'user, 'library> {
|
||||
/// The shared data of all turn choices.
|
||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||
}
|
||||
|
||||
impl<'user, 'library> SwitchChoice<'user, 'library> {
|
||||
/// Initialise the turn choice data.
|
||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||
Self {
|
||||
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)]
|
||||
pub struct FleeChoice<'user, 'library> {
|
||||
/// The common data all turn choices share.
|
||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||
}
|
||||
|
||||
impl<'user, 'library> FleeChoice<'user, 'library> {
|
||||
/// Initialises a new flee choice.
|
||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||
Self {
|
||||
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)]
|
||||
pub struct PassChoice<'user, 'library> {
|
||||
/// The common data of all turn choices.
|
||||
choice_data: Box<CommonChoiceData<'user, 'library>>,
|
||||
}
|
||||
|
||||
impl<'user, 'library> PassChoice<'user, 'library> {
|
||||
/// Initialised a new pass choice.
|
||||
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
111
src/dynamic_data/event_hooks.rs
Normal file
111
src/dynamic_data/event_hooks.rs
Normal file
@@ -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::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)]
|
||||
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>>>,
|
||||
/// The current index of the turn we need to execute next.
|
||||
current: usize,
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
let c = self.queue[self.current].take();
|
||||
self.current += 1;
|
||||
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()
|
||||
}
|
||||
|
||||
/// Check if we have any choices remaining.
|
||||
pub fn has_next(&self) -> bool {
|
||||
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) {
|
||||
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>>] {
|
||||
&self.queue[self.current..self.queue.len()]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
pub mod choice_queue;
|
||||
pub mod target_resolver;
|
||||
pub mod turn_runner;
|
||||
#[doc(inline)]
|
||||
pub use choice_queue::*;
|
||||
#[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::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>>>>;
|
||||
|
||||
/// This returns all Pokemon in the battle.
|
||||
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);
|
||||
for side in battle.sides() {
|
||||
@@ -17,6 +21,7 @@ fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b
|
||||
v
|
||||
}
|
||||
|
||||
/// Little helper function to get the other side. 1 --> 0, 0 --> 1
|
||||
fn get_opposite_side(side: u8) -> u8 {
|
||||
if side == 0 {
|
||||
return 1;
|
||||
@@ -24,7 +29,13 @@ fn get_opposite_side(side: u8) -> u8 {
|
||||
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 right = index + 1;
|
||||
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>(
|
||||
side: u8,
|
||||
index: u8,
|
||||
battle: &Battle<'b, 'library>,
|
||||
) -> TargetList<'b, 'library> {
|
||||
/// Gets all Pokemon that are adjacent to a Pokemon. This includes the target, the pokemon to the
|
||||
/// left of it, and the Pokemon to the right of it.
|
||||
fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
|
||||
let left = index as i32 - 1;
|
||||
let right = index + 1;
|
||||
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>(
|
||||
side: u8,
|
||||
index: u8,
|
||||
@@ -93,6 +103,8 @@ pub fn resolve_targets<'b, 'library>(
|
||||
battle: &Battle<'b, 'library>,
|
||||
) -> TargetList<'b, 'library> {
|
||||
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::AdjacentAlly
|
||||
| MoveTarget::AdjacentAllySelf
|
||||
@@ -102,9 +114,14 @@ pub fn resolve_targets<'b, 'library>(
|
||||
| MoveTarget::SelfUse => {
|
||||
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),
|
||||
// If the adjacent Pokemon are requested, pass those.
|
||||
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),
|
||||
// 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 => {
|
||||
let mut v = Vec::new();
|
||||
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 {
|
||||
let user_side = user.get_battle_side_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::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> {
|
||||
/// Execute the entire turn after the choices are all set.
|
||||
pub(crate) fn run_turn(&self) -> PkmnResult<()> {
|
||||
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<()> {
|
||||
// A pass turn choice means the user does not intend to do anything. As such, return.
|
||||
if let TurnChoice::Pass(..) = choice {
|
||||
return Ok(());
|
||||
}
|
||||
if self.has_ended() {
|
||||
return Ok(());
|
||||
}
|
||||
{
|
||||
let user = choice.user();
|
||||
if !user.is_usable() {
|
||||
return Ok(());
|
||||
}
|
||||
if !user.is_on_battlefield() {
|
||||
return Ok(());
|
||||
}
|
||||
let user = choice.user();
|
||||
if !user.is_usable() {
|
||||
return Ok(());
|
||||
}
|
||||
if !user.is_on_battlefield() {
|
||||
return Ok(());
|
||||
}
|
||||
if !self.can_use(choice) {
|
||||
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 crate::static_data::statistic_set::StatisticSet;
|
||||
use crate::static_data::statistics::Statistic;
|
||||
use std::fmt::Debug;
|
||||
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)]
|
||||
pub struct BattleStatCalculator {}
|
||||
|
||||
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
|
||||
}
|
||||
pub struct Gen7BattleStatCalculator {}
|
||||
|
||||
impl Gen7BattleStatCalculator {
|
||||
/// The calculation used for health points.
|
||||
fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 {
|
||||
let base = pokemon.form().get_base_stat(Statistic::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
|
||||
}
|
||||
|
||||
/// The calculation used for all other stats
|
||||
fn calculate_other_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
|
||||
let base = pokemon.form().get_base_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;
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let boost = pokemon.stat_boost().get_stat(stat);
|
||||
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 crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dynamic_data::script_handling::ScriptSource;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::dynamic_data::{ExecutingMove, HitData};
|
||||
use crate::script_hook;
|
||||
use crate::static_data::{MoveCategory, Statistic};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait DamageLibrary: std::fmt::Debug {
|
||||
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::damage_library::DamageLibrary;
|
||||
use crate::dynamic_data::libraries::misc_library::MiscLibrary;
|
||||
use crate::dynamic_data::libraries::script_resolver::ScriptCategory;
|
||||
use crate::dynamic_data::script_handling::item_script::ItemScript;
|
||||
use crate::dynamic_data::script_handling::script::Script;
|
||||
use crate::static_data::items::item::Item;
|
||||
use crate::static_data::libraries::static_data::StaticData;
|
||||
use crate::dynamic_data::ItemScript;
|
||||
use crate::dynamic_data::Script;
|
||||
use crate::static_data::Item;
|
||||
use crate::static_data::StaticData;
|
||||
use crate::{PkmnResult, StringKey};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DynamicLibrary {
|
||||
static_data: StaticData,
|
||||
stat_calculator: BattleStatCalculator,
|
||||
stat_calculator: Box<dyn BattleStatCalculator>,
|
||||
damage_calculator: Box<dyn DamageLibrary>,
|
||||
misc_library: Box<dyn MiscLibrary<'static>>,
|
||||
}
|
||||
@@ -25,7 +26,7 @@ unsafe impl Send for DynamicLibrary {}
|
||||
impl DynamicLibrary {
|
||||
pub fn new(
|
||||
static_data: StaticData,
|
||||
stat_calculator: BattleStatCalculator,
|
||||
stat_calculator: Box<dyn BattleStatCalculator>,
|
||||
damage_calculator: Box<dyn DamageLibrary>,
|
||||
misc_library: Box<dyn MiscLibrary<'static>>,
|
||||
) -> Self {
|
||||
@@ -40,8 +41,8 @@ impl DynamicLibrary {
|
||||
pub fn static_data(&self) -> &StaticData {
|
||||
&self.static_data
|
||||
}
|
||||
pub fn stat_calculator(&self) -> &BattleStatCalculator {
|
||||
&self.stat_calculator
|
||||
pub fn stat_calculator(&self) -> &dyn BattleStatCalculator {
|
||||
self.stat_calculator.deref()
|
||||
}
|
||||
pub fn damage_calculator(&self) -> &dyn DamageLibrary {
|
||||
self.damage_calculator.deref()
|
||||
@@ -60,16 +61,15 @@ impl DynamicLibrary {
|
||||
|
||||
#[cfg(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::dynamic_library::DynamicLibrary;
|
||||
use crate::dynamic_data::libraries::misc_library::Gen7MiscLibrary;
|
||||
use crate::static_data::libraries::static_data;
|
||||
|
||||
pub fn build() -> DynamicLibrary {
|
||||
DynamicLibrary {
|
||||
static_data: static_data::test::build(),
|
||||
stat_calculator: BattleStatCalculator {},
|
||||
static_data: crate::static_data::libraries::static_data::test::build(),
|
||||
stat_calculator: Box::new(Gen7BattleStatCalculator {}),
|
||||
damage_calculator: Box::new(Gen7DamageLibrary::new(false)),
|
||||
misc_library: Box::new(Gen7MiscLibrary::new()),
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
use crate::dynamic_data::choices::{MoveChoice, SwitchChoice, TurnChoice};
|
||||
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::fmt::Debug;
|
||||
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(
|
||||
&self,
|
||||
battle: &Battle,
|
||||
@@ -29,12 +31,6 @@ pub trait MiscLibrary<'library> {
|
||||
// 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)]
|
||||
pub struct Gen7MiscLibrary<'library> {
|
||||
struggle_data: *const MoveData,
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
pub mod battle_stat_calculator;
|
||||
pub mod damage_library;
|
||||
pub mod dynamic_library;
|
||||
pub mod misc_library;
|
||||
pub mod script_resolver;
|
||||
#[doc(inline)]
|
||||
pub use battle_stat_calculator::*;
|
||||
#[doc(inline)]
|
||||
pub use damage_library::*;
|
||||
#[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;
|
||||
pub mod event_hooks;
|
||||
pub mod flow;
|
||||
pub mod history;
|
||||
pub mod libraries;
|
||||
pub mod models;
|
||||
pub mod script_handling;
|
||||
#[doc(inline)]
|
||||
pub use choices::*;
|
||||
#[doc(inline)]
|
||||
pub use event_hooks::*;
|
||||
#[doc(inline)]
|
||||
pub use flow::*;
|
||||
#[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::event_hooks::event_hook::{Event, EventHook};
|
||||
use crate::dynamic_data::flow::choice_queue::ChoiceQueue;
|
||||
use crate::dynamic_data::flow::target_resolver::is_valid_target;
|
||||
use crate::dynamic_data::history::history_holder::HistoryHolder;
|
||||
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
||||
use crate::dynamic_data::event_hooks::{Event, EventHook};
|
||||
use crate::dynamic_data::history::HistoryHolder;
|
||||
use crate::dynamic_data::is_valid_target;
|
||||
use crate::dynamic_data::models::battle_party::BattleParty;
|
||||
use crate::dynamic_data::models::battle_random::BattleRandom;
|
||||
use crate::dynamic_data::models::battle_result::BattleResult;
|
||||
use crate::dynamic_data::models::battle_side::BattleSide;
|
||||
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, ScriptCategory, StringKey};
|
||||
use atomic::Atomic;
|
||||
use parking_lot::RwLock;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
use crate::dynamic_data::ChoiceQueue;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::dynamic_data::Script;
|
||||
use crate::dynamic_data::ScriptSet;
|
||||
use crate::dynamic_data::VolatileScripts;
|
||||
use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||
use crate::{script_hook, PkmnResult, StringKey};
|
||||
|
||||
#[derive(Debug)]
|
||||
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::pokemon::Pokemon;
|
||||
use crate::dynamic_data::script_handling::ScriptSource;
|
||||
use crate::script_hook;
|
||||
use crate::utils::random::Random;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::utils::Random;
|
||||
|
||||
#[derive(Default)]
|
||||
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::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
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)]
|
||||
pub struct BattleSide<'own, 'library> {
|
||||
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::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering};
|
||||
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)]
|
||||
pub struct HitData {
|
||||
critical: AtomicBool,
|
||||
|
||||
@@ -1,11 +1,34 @@
|
||||
pub mod battle;
|
||||
pub mod battle_party;
|
||||
pub mod battle_random;
|
||||
pub mod battle_result;
|
||||
pub mod battle_side;
|
||||
pub mod damage_source;
|
||||
pub mod executing_move;
|
||||
pub mod learned_move;
|
||||
pub mod pokemon;
|
||||
pub mod pokemon_builder;
|
||||
pub mod pokemon_party;
|
||||
#[doc(inline)]
|
||||
pub use battle::*;
|
||||
#[doc(inline)]
|
||||
pub use battle_party::*;
|
||||
#[doc(inline)]
|
||||
pub use battle_random::*;
|
||||
#[doc(inline)]
|
||||
pub use battle_result::*;
|
||||
#[doc(inline)]
|
||||
pub use battle_side::*;
|
||||
#[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::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, AtomicU8, Ordering};
|
||||
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)]
|
||||
pub struct PokemonBattleData<'pokemon, 'library> {
|
||||
battle: *mut Battle<'pokemon, 'library>,
|
||||
@@ -585,15 +584,15 @@ impl<'own, 'library> VolatileScripts<'own> for Pokemon<'own, 'library> {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use crate::dynamic_data::libraries::dynamic_library;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::static_data::libraries::data_library::DataLibrary;
|
||||
use crate::static_data::species_data::ability_index::AbilityIndex;
|
||||
use crate::static_data::species_data::gender::Gender;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::static_data::AbilityIndex;
|
||||
use crate::static_data::DataLibrary;
|
||||
use crate::static_data::Gender;
|
||||
|
||||
#[test]
|
||||
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 form = species.get_form(&"default".into()).unwrap();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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::pokemon::Pokemon;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::static_data::{AbilityIndex, DataLibrary, Gender};
|
||||
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};
|
||||
|
||||
pub mod item_script;
|
||||
pub mod script;
|
||||
pub mod script_set;
|
||||
pub mod volatile_scripts;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
#[doc(inline)]
|
||||
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_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_rules! run_scripts {
|
||||
($hook_name: ident, $source: ident, $($parameters: expr),*) => {
|
||||
@@ -198,12 +191,14 @@ impl ScriptAggregator {
|
||||
|
||||
#[cfg(test)]
|
||||
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::static_data::EffectParameter;
|
||||
use crate::StringKey;
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct TestScript {
|
||||
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::fmt::{Debug, Formatter};
|
||||
use std::ops::Deref;
|
||||
@@ -14,6 +5,17 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
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 {
|
||||
fn name(&self) -> &StringKey;
|
||||
fn get_marked_for_deletion(&self) -> &AtomicBool;
|
||||
@@ -231,9 +233,10 @@ impl Clone for ScriptContainer {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::atomic::{AtomicBool, AtomicPtr};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct TestScript {
|
||||
name: StringKey,
|
||||
container: AtomicPtr<ScriptContainer>,
|
||||
|
||||
Reference in New Issue
Block a user