Complete refactor of the FFI to use handles instead of pointers.
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:
@@ -8,13 +8,10 @@ use crate::dynamic_data::Pokemon;
|
||||
use crate::dynamic_data::ScriptContainer;
|
||||
use crate::dynamic_data::{LearnedMove, ScriptWrapper};
|
||||
use crate::dynamic_data::{ScriptSource, ScriptSourceData};
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// The data on a turn choice that should be contained in every turn choice, regardless of type.
|
||||
#[derive(Debug)]
|
||||
struct CommonChoiceData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The user of the turn choice
|
||||
user: Pokemon,
|
||||
/// The speed of the user at the beginning of the turn.
|
||||
@@ -180,7 +177,6 @@ impl MoveChoice {
|
||||
script: Default::default(),
|
||||
priority: AtomicI8::new(0),
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
@@ -253,7 +249,6 @@ impl ItemChoice {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
@@ -293,7 +288,6 @@ impl SwitchChoice {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
@@ -332,7 +326,6 @@ impl FleeChoice {
|
||||
pub fn new(user: Pokemon) -> Self {
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed: AtomicU32::new(0),
|
||||
random_value: AtomicU32::new(0),
|
||||
@@ -372,7 +365,6 @@ impl PassChoice {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
@@ -485,9 +477,3 @@ impl Ord for TurnChoice {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for TurnChoice {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.choice_data().identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::dynamic_data::choices::TurnChoice;
|
||||
use crate::dynamic_data::script_handling::ScriptSource;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::{script_hook, PkmnError, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
use crate::{script_hook, PkmnError, VecExt};
|
||||
use anyhow::Result;
|
||||
use anyhow_ext::anyhow;
|
||||
use parking_lot::lock_api::MappedRwLockReadGuard;
|
||||
@@ -17,8 +17,6 @@ use std::sync::Arc;
|
||||
/// moves in Pokemon actively mess with this order.
|
||||
#[derive(Debug)]
|
||||
pub struct ChoiceQueue {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get
|
||||
/// executed.
|
||||
queue: RwLock<Vec<Option<Arc<TurnChoice>>>>,
|
||||
@@ -31,7 +29,6 @@ impl ChoiceQueue {
|
||||
pub(crate) fn new(mut queue: Vec<Option<Arc<TurnChoice>>>) -> Self {
|
||||
queue.sort_unstable_by(|a, b| b.cmp(a));
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
queue: RwLock::new(queue),
|
||||
current: AtomicUsize::new(0),
|
||||
}
|
||||
@@ -107,7 +104,7 @@ impl ChoiceQueue {
|
||||
// Find the index for the choice we want to move up.
|
||||
for index in self.current.load(Ordering::Relaxed)..queue_lock.len() {
|
||||
if let Some(Some(choice)) = &queue_lock.get(index) {
|
||||
if pokemon.value_identifier() == choice.user().value_identifier() {
|
||||
if pokemon.eq(choice.user()) {
|
||||
desired_index = Some(index);
|
||||
break;
|
||||
}
|
||||
@@ -158,12 +155,6 @@ impl ChoiceQueue {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for ChoiceQueue {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
@@ -253,10 +244,7 @@ mod tests {
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user2)))),
|
||||
]);
|
||||
let inner_queue = queue.get_queue().unwrap();
|
||||
assert_eq!(
|
||||
inner_queue[0].as_ref().unwrap().user().value_identifier(),
|
||||
user1.value_identifier()
|
||||
);
|
||||
assert_eq!(inner_queue[0].as_ref().unwrap().user().clone(), user1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -283,15 +271,9 @@ mod tests {
|
||||
]);
|
||||
|
||||
user2.change_level_by(60).unwrap();
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user1, queue.peek().unwrap().unwrap().user().clone(),);
|
||||
queue.resort().unwrap();
|
||||
assert_eq!(
|
||||
user2.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user2, queue.peek().unwrap().unwrap().user().clone(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -303,20 +285,11 @@ mod tests {
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user1.clone())))),
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user2.clone())))),
|
||||
]);
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user1, queue.peek().unwrap().unwrap().user().clone(),);
|
||||
assert!(queue.move_pokemon_choice_next(&user2).unwrap());
|
||||
|
||||
assert_eq!(
|
||||
user2.value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user2, queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
assert_eq!(user1, queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -328,16 +301,10 @@ mod tests {
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user1.clone())))),
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user2.clone())))),
|
||||
]);
|
||||
assert_eq!(
|
||||
user2.value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user2, queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
assert!(!queue.move_pokemon_choice_next(&user2).unwrap());
|
||||
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user1, queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
assert!(queue.peek().unwrap().is_none())
|
||||
}
|
||||
|
||||
@@ -350,15 +317,9 @@ mod tests {
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user1.clone())))),
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(user2)))),
|
||||
]);
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user1, queue.peek().unwrap().unwrap().user().clone(),);
|
||||
assert!(queue.move_pokemon_choice_next(&user1).unwrap());
|
||||
assert_eq!(
|
||||
user1.value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(user1, queue.peek().unwrap().unwrap().user().clone(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -382,27 +343,15 @@ mod tests {
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(users[5].clone())))),
|
||||
Some(Arc::new(TurnChoice::Pass(PassChoice::new(users[6].clone())))),
|
||||
]);
|
||||
assert_eq!(
|
||||
users[0].value_identifier(),
|
||||
queue.peek().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(users[0], queue.peek().unwrap().unwrap().user().clone(),);
|
||||
assert!(queue.move_pokemon_choice_next(&users[4]).unwrap());
|
||||
|
||||
assert_eq!(
|
||||
users[4].value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(users[4], queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
for index in 0..4 {
|
||||
assert_eq!(
|
||||
users[index].value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(users[index], queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
}
|
||||
for index in 5..7 {
|
||||
assert_eq!(
|
||||
users[index].value_identifier(),
|
||||
queue.dequeue().unwrap().unwrap().user().value_identifier()
|
||||
);
|
||||
assert_eq!(users[index], queue.dequeue().unwrap().unwrap().user().clone(),);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@ use std::fmt::Debug;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::static_data::Statistic;
|
||||
use crate::static_data::StatisticSet;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// A battle stat calculator is used to calculate stats for a Pokemon.
|
||||
pub trait BattleStatCalculator: Debug + ValueIdentifiable {
|
||||
pub trait BattleStatCalculator: Debug {
|
||||
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
|
||||
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>) -> Result<()>;
|
||||
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
|
||||
@@ -20,10 +19,7 @@ pub trait BattleStatCalculator: Debug + ValueIdentifiable {
|
||||
|
||||
/// A basic implementation of the Gen 7 stat calculator.
|
||||
#[derive(Debug)]
|
||||
pub struct Gen7BattleStatCalculator {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
}
|
||||
pub struct Gen7BattleStatCalculator {}
|
||||
|
||||
impl Default for Gen7BattleStatCalculator {
|
||||
fn default() -> Self {
|
||||
@@ -34,9 +30,7 @@ impl Default for Gen7BattleStatCalculator {
|
||||
impl Gen7BattleStatCalculator {
|
||||
/// Creates a new Gen 7 battle stat calculator
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
}
|
||||
Self {}
|
||||
}
|
||||
|
||||
/// The calculation used for health points.
|
||||
@@ -141,11 +135,6 @@ impl BattleStatCalculator for Gen7BattleStatCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for Gen7BattleStatCalculator {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
pub mod tests {
|
||||
@@ -160,10 +149,5 @@ pub mod tests {
|
||||
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>) -> Result<()>;
|
||||
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> Result<u32>;
|
||||
}
|
||||
impl ValueIdentifiable for BattleStatCalculator {
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ use std::sync::Arc;
|
||||
use crate::dynamic_data::script_handling::ScriptSource;
|
||||
use crate::dynamic_data::{Battle, Pokemon};
|
||||
use crate::dynamic_data::{ExecutingMove, HitData};
|
||||
use crate::script_hook;
|
||||
use crate::static_data::{MoveCategory, Statistic};
|
||||
use crate::{script_hook, ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// A damage library holds the functions related to the calculation of damage. As this can change in
|
||||
/// different generations and implementations, this is handled through a trait.
|
||||
pub trait DamageLibrary: std::fmt::Debug + ValueIdentifiable {
|
||||
pub trait DamageLibrary: std::fmt::Debug {
|
||||
/// Calculate the damage for a given hit on a Pokemon.
|
||||
fn get_damage(
|
||||
&self,
|
||||
@@ -42,8 +42,6 @@ pub trait DamageLibrary: std::fmt::Debug + ValueIdentifiable {
|
||||
/// The implementation of a Damage Library for generation 7.
|
||||
#[derive(Debug)]
|
||||
pub struct Gen7DamageLibrary {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// Defines whether or not a random damage modifier is applied to damage (0.85 - 1.00).
|
||||
has_randomness: bool,
|
||||
}
|
||||
@@ -52,10 +50,7 @@ impl Gen7DamageLibrary {
|
||||
/// Creates a new generation 7 damage library. `has_randomness` defines whether a random damage
|
||||
/// modifier (0.85x - 1.00x) is applied to the calculated damage.
|
||||
pub fn new(has_randomness: bool) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
has_randomness,
|
||||
}
|
||||
Self { has_randomness }
|
||||
}
|
||||
|
||||
/// Calculates the modifier applied to damage from the statistics of the relevant Pokemon.
|
||||
@@ -312,9 +307,3 @@ impl DamageLibrary for Gen7DamageLibrary {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for Gen7DamageLibrary {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ use crate::dynamic_data::{ItemScript, ScriptResolver};
|
||||
use crate::dynamic_data::{Script, ScriptOwnerData};
|
||||
use crate::static_data::Item;
|
||||
use crate::static_data::StaticData;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// The dynamic library stores a static data library, as well as holding different libraries and
|
||||
/// calculators that might be customized between different generations and implementations.
|
||||
pub trait DynamicLibrary: Debug + ValueIdentifiable {
|
||||
pub trait DynamicLibrary: Debug + Send + Sync {
|
||||
/// The static data is the immutable storage data for this library.
|
||||
fn static_data(&self) -> &Arc<dyn StaticData>;
|
||||
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
|
||||
@@ -39,13 +39,10 @@ pub trait DynamicLibrary: Debug + ValueIdentifiable {
|
||||
/// shared between all different usages.
|
||||
fn load_item_script(&self, _key: &Arc<dyn Item>) -> Result<Option<Arc<dyn ItemScript>>>;
|
||||
}
|
||||
|
||||
/// The dynamic library stores a static data library, as well as holding different libraries and
|
||||
/// calculators that might be customized between different generations and implementations.
|
||||
#[derive(Debug)]
|
||||
pub struct DynamicLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The static data is the immutable storage data for this library.
|
||||
static_data: Arc<dyn StaticData>,
|
||||
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
|
||||
@@ -58,9 +55,13 @@ pub struct DynamicLibraryImpl {
|
||||
misc_library: Arc<dyn MiscLibrary>,
|
||||
|
||||
/// The script resolver deals with how to resolve the scripts from specific unique key combinations.
|
||||
script_resolver: Box<dyn ScriptResolver>,
|
||||
script_resolver: Arc<dyn ScriptResolver>,
|
||||
}
|
||||
|
||||
unsafe impl Send for DynamicLibraryImpl {}
|
||||
|
||||
unsafe impl Sync for DynamicLibraryImpl {}
|
||||
|
||||
impl DynamicLibraryImpl {
|
||||
/// Instantiates a new DynamicLibrary with given parameters.
|
||||
pub fn new(
|
||||
@@ -68,10 +69,9 @@ impl DynamicLibraryImpl {
|
||||
stat_calculator: Arc<dyn BattleStatCalculator>,
|
||||
damage_calculator: Arc<dyn DamageLibrary>,
|
||||
misc_library: Arc<dyn MiscLibrary>,
|
||||
script_resolver: Box<dyn ScriptResolver>,
|
||||
script_resolver: Arc<dyn ScriptResolver>,
|
||||
) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
static_data,
|
||||
stat_calculator,
|
||||
damage_calculator,
|
||||
@@ -120,12 +120,6 @@ impl DynamicLibrary for DynamicLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for DynamicLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
pub mod test {
|
||||
@@ -138,6 +132,10 @@ pub mod test {
|
||||
mockall::mock! {
|
||||
#[derive(Debug)]
|
||||
pub DynamicLibrary{}
|
||||
|
||||
unsafe impl Send for DynamicLibrary{}
|
||||
unsafe impl Sync for DynamicLibrary{}
|
||||
|
||||
impl DynamicLibrary for DynamicLibrary {
|
||||
fn static_data(&self) -> &Arc<dyn StaticData>;
|
||||
fn stat_calculator(&self) -> &Arc<dyn BattleStatCalculator>;
|
||||
@@ -151,23 +149,15 @@ pub mod test {
|
||||
) -> Result<Option<Arc<dyn Script>>>;
|
||||
fn load_item_script(&self, _key: &Arc<dyn Item>) -> Result<Option<Arc<dyn ItemScript>>>;
|
||||
}
|
||||
impl ValueIdentifiable for DynamicLibrary{
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build() -> DynamicLibraryImpl {
|
||||
DynamicLibraryImpl {
|
||||
identifier: Default::default(),
|
||||
static_data: Arc::new(crate::static_data::libraries::static_data::test::build()),
|
||||
stat_calculator: Arc::new(Gen7BattleStatCalculator::new()),
|
||||
damage_calculator: Arc::new(Gen7DamageLibrary::new(false)),
|
||||
misc_library: Arc::new(Gen7MiscLibrary::new()),
|
||||
script_resolver: Box::new(EmptyScriptResolver {
|
||||
identifier: Default::default(),
|
||||
}),
|
||||
script_resolver: Arc::new(EmptyScriptResolver {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
|
||||
use crate::static_data::{MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffectImpl};
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// The misc library holds several misc functions required for the battle to run.
|
||||
pub trait MiscLibrary: Debug + ValueIdentifiable {
|
||||
pub trait MiscLibrary: Debug {
|
||||
/// Returns whether or not a Pokemon is allowed to flee or switch out.
|
||||
fn can_flee(&self, choice: &TurnChoice) -> bool;
|
||||
/// Returns the move we need to use if we can't use another move. Typically Struggle.
|
||||
@@ -22,8 +22,6 @@ pub trait MiscLibrary: Debug + ValueIdentifiable {
|
||||
/// A gen 7 implementation for the MiscLibrary.
|
||||
#[derive(Debug)]
|
||||
pub struct Gen7MiscLibrary {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The learned move data for struggle.
|
||||
struggle_learned_move: Arc<LearnedMove>,
|
||||
}
|
||||
@@ -40,7 +38,7 @@ impl Gen7MiscLibrary {
|
||||
255,
|
||||
MoveTarget::Any,
|
||||
0,
|
||||
Some(Box::new(SecondaryEffectImpl::new(
|
||||
Some(Arc::new(SecondaryEffectImpl::new(
|
||||
-1.0,
|
||||
StringKey::new("struggle"),
|
||||
vec![],
|
||||
@@ -48,10 +46,7 @@ impl Gen7MiscLibrary {
|
||||
HashSet::new(),
|
||||
));
|
||||
let struggle_learned_move = Arc::new(LearnedMove::new(struggle_data, MoveLearnMethod::Unknown));
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
struggle_learned_move,
|
||||
}
|
||||
Self { struggle_learned_move }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +71,3 @@ impl MiscLibrary for Gen7MiscLibrary {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for Gen7MiscLibrary {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use anyhow::Result;
|
||||
use std::any::Any;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dynamic_data::{ItemScript, Script, ScriptOwnerData};
|
||||
use crate::static_data::Item;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A script resolver deals with the resolving of scripts. These scripts are non-hardcoded
|
||||
/// implementations of different effects in Pokemon. This allows for things such as generational
|
||||
/// differences, and custom implementations.
|
||||
pub trait ScriptResolver: Debug + ValueIdentifiable {
|
||||
pub trait ScriptResolver: Debug {
|
||||
/// Loads a standard script with a given unique combination of category and key. If no script
|
||||
/// can be created with this combination, returns None.
|
||||
fn load_script(
|
||||
@@ -23,6 +24,8 @@ pub trait ScriptResolver: Debug + ValueIdentifiable {
|
||||
/// combinations, returns None. Note that ItemScripts are immutable, as their script should be
|
||||
/// shared between all different usages.
|
||||
fn load_item_script(&self, _key: &dyn Item) -> Result<Option<Arc<dyn ItemScript>>>;
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any;
|
||||
}
|
||||
|
||||
use std::fmt::Display;
|
||||
@@ -57,16 +60,7 @@ pub enum ScriptCategory {
|
||||
|
||||
/// A basic empty script resolver, that always returns None.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct EmptyScriptResolver {
|
||||
/// A unique identifier so we know what value this is.
|
||||
pub identifier: ValueIdentifier,
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for EmptyScriptResolver {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
pub struct EmptyScriptResolver {}
|
||||
|
||||
impl ScriptResolver for EmptyScriptResolver {
|
||||
fn load_script(
|
||||
@@ -81,4 +75,8 @@ impl ScriptResolver for EmptyScriptResolver {
|
||||
fn load_item_script(&self, _key: &dyn Item) -> Result<Option<Arc<dyn ItemScript>>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,11 @@ use crate::dynamic_data::VolatileScriptsOwner;
|
||||
use crate::dynamic_data::{is_valid_target, ScriptWrapper};
|
||||
use crate::dynamic_data::{ChoiceQueue, ScriptContainer};
|
||||
use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData};
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
use crate::{script_hook, PkmnError, StringKey, VecExt};
|
||||
|
||||
/// The data of a battle.
|
||||
#[derive(Debug)]
|
||||
struct BattleData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The library the battle uses for handling.
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
/// A list of all different parties in the battle.
|
||||
@@ -99,7 +97,6 @@ impl Battle {
|
||||
}
|
||||
|
||||
let battle = BattleData {
|
||||
identifier: Default::default(),
|
||||
library,
|
||||
parties,
|
||||
can_flee,
|
||||
@@ -127,13 +124,6 @@ impl Battle {
|
||||
battle
|
||||
}
|
||||
|
||||
/// Returns a weak reference to the battle.
|
||||
pub fn weak(&self) -> WeakBattleReference {
|
||||
WeakBattleReference {
|
||||
data: Arc::downgrade(&self.data),
|
||||
}
|
||||
}
|
||||
|
||||
/// The library the battle uses for handling.
|
||||
pub fn library(&self) -> &Arc<dyn DynamicLibrary> {
|
||||
&self.data.library
|
||||
@@ -272,7 +262,7 @@ impl Battle {
|
||||
}
|
||||
|
||||
/// Try and set the choice for the battle. If the choice is not valid, this returns false.
|
||||
pub fn try_set_choice(&self, choice: TurnChoice) -> Result<bool> {
|
||||
pub fn try_set_choice(&self, choice: Arc<TurnChoice>) -> Result<bool> {
|
||||
if !self.can_use(&choice) {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -380,6 +370,23 @@ impl Battle {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a weak reference to the battle.
|
||||
pub fn weak(&self) -> WeakBattleReference {
|
||||
WeakBattleReference {
|
||||
data: Arc::downgrade(&self.data),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const c_void {
|
||||
Arc::as_ptr(&self.data) as *const c_void
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Battle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.data, &other.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl WeakBattleReference {
|
||||
@@ -437,12 +444,6 @@ impl ScriptSource for Battle {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for Battle {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.data.identifier
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a battle.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum BattleResult {
|
||||
|
||||
@@ -3,14 +3,11 @@ use std::sync::Arc;
|
||||
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::dynamic_data::models::pokemon_party::PokemonParty;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// A battle party is a wrapper around a party, with the indices for which the party is responsible
|
||||
/// on the field attached.
|
||||
#[derive(Debug)]
|
||||
pub struct BattleParty {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The party the BattleParty is holding.
|
||||
party: Arc<PokemonParty>,
|
||||
/// The indices for which the party is responsible, in the format (side, index)
|
||||
@@ -22,7 +19,6 @@ impl BattleParty {
|
||||
/// for.
|
||||
pub fn new(party: Arc<PokemonParty>, responsible_indices: Vec<(u8, u8)>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
identifier: Default::default(),
|
||||
party,
|
||||
responsible_indices,
|
||||
})
|
||||
@@ -58,9 +54,3 @@ impl BattleParty {
|
||||
&self.party
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for BattleParty {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,11 @@ use crate::dynamic_data::models::executing_move::ExecutingMove;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::dynamic_data::script_handling::ScriptSource;
|
||||
use crate::utils::Random;
|
||||
use crate::{script_hook, PkmnError, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{script_hook, PkmnError};
|
||||
|
||||
/// The RNG for a battle.
|
||||
#[derive(Default)]
|
||||
pub struct BattleRandom {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The actual underlying RNG. This is in a mutex, so it is thread safe, and can be ran
|
||||
/// predictably, with guaranteed the same outputs.
|
||||
random: Mutex<Random>,
|
||||
@@ -22,7 +20,6 @@ impl BattleRandom {
|
||||
/// Initializes a new RNG with a given seed.
|
||||
pub fn new_with_seed(seed: u128) -> Self {
|
||||
BattleRandom {
|
||||
identifier: Default::default(),
|
||||
random: Mutex::new(Random::new(seed)),
|
||||
}
|
||||
}
|
||||
@@ -104,8 +101,6 @@ impl Debug for BattleRandom {
|
||||
impl Clone for BattleRandom {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
|
||||
// As cloning when we can't get a lock on the randomness is completely impossible, we
|
||||
// should unwrap here.
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -113,9 +108,3 @@ impl Clone for BattleRandom {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for BattleRandom {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,11 @@ use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, Scrip
|
||||
use crate::dynamic_data::ScriptSet;
|
||||
use crate::dynamic_data::VolatileScriptsOwner;
|
||||
use crate::dynamic_data::{Script, WeakBattleReference};
|
||||
use crate::{script_hook, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
use crate::{script_hook, StringKey, VecExt};
|
||||
|
||||
/// The data that is stored for a battle side.
|
||||
#[derive(Debug)]
|
||||
struct BattleSideData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The index of the side on the battle.
|
||||
index: u8,
|
||||
/// The number of Pokemon that can be on the side.
|
||||
@@ -47,7 +45,7 @@ struct BattleSideData {
|
||||
}
|
||||
|
||||
/// A side on a battle.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BattleSide {
|
||||
/// The data that is stored for this side.
|
||||
data: Arc<BattleSideData>,
|
||||
@@ -77,7 +75,6 @@ impl BattleSide {
|
||||
|
||||
Self {
|
||||
data: Arc::new(BattleSideData {
|
||||
identifier: Default::default(),
|
||||
index,
|
||||
pokemon_per_side,
|
||||
pokemon,
|
||||
@@ -171,11 +168,11 @@ impl BattleSide {
|
||||
}
|
||||
|
||||
/// Sets a choice for a Pokemon on this side.
|
||||
pub(crate) fn set_choice(&self, choice: TurnChoice) -> Result<()> {
|
||||
pub(crate) fn set_choice(&self, choice: Arc<TurnChoice>) -> Result<()> {
|
||||
for (index, pokemon_slot) in self.data.pokemon.read().iter().enumerate() {
|
||||
if let Some(pokemon) = pokemon_slot {
|
||||
if Pokemon::eq(pokemon, choice.user()) {
|
||||
self.data.choices.write().get_mut_res(index)?.replace(choice.into());
|
||||
self.data.choices.write().get_mut_res(index)?.replace(choice);
|
||||
self.data.choices_set.fetch_add(1, Ordering::SeqCst);
|
||||
return Ok(());
|
||||
}
|
||||
@@ -337,7 +334,7 @@ impl BattleSide {
|
||||
None => return Ok(false),
|
||||
};
|
||||
// Don't allow swapping if different parties are responsible for the indices.
|
||||
if party_a.value_identifier() != party_b.value_identifier() {
|
||||
if !Arc::ptr_eq(party_a, party_b) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@@ -356,6 +353,16 @@ impl BattleSide {
|
||||
data: Arc::downgrade(&self.data),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const c_void {
|
||||
Arc::as_ptr(&self.data) as *const c_void
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for BattleSide {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.data, &other.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl WeakBattleSideReference {
|
||||
@@ -411,9 +418,3 @@ impl ScriptSource for BattleSide {
|
||||
self.battle()?.collect_scripts(scripts)
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for BattleSide {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.data.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,11 @@ use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, Scrip
|
||||
use crate::dynamic_data::ScriptContainer;
|
||||
use crate::dynamic_data::TargetList;
|
||||
use crate::static_data::{MoveData, TypeIdentifier};
|
||||
use crate::{PkmnError, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::PkmnError;
|
||||
|
||||
/// A hit data is the data for a single hit, on a single target.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct HitData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// Whether or not the hit is critical.
|
||||
critical: AtomicBool,
|
||||
/// The base power of the hit.
|
||||
@@ -89,8 +87,6 @@ impl HitData {
|
||||
#[derive(Debug)]
|
||||
|
||||
pub struct ExecutingMove {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The number of hits this move has.
|
||||
number_of_hits: u8,
|
||||
/// A list of hits for this move. For multi target multi hit moves, this stores the hits linearly,
|
||||
@@ -126,7 +122,6 @@ impl ExecutingMove {
|
||||
hits.push(Arc::new(HitData::default()))
|
||||
}
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
number_of_hits,
|
||||
hits,
|
||||
user,
|
||||
@@ -238,15 +233,3 @@ impl ScriptSource for ExecutingMove {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for ExecutingMove {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for HitData {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,11 @@ use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::static_data::MoveData;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// A learned move is the data attached to a Pokemon for a move it has learned. It has information
|
||||
/// such as the remaining amount of users, how it has been learned, etc.
|
||||
#[derive(Debug)]
|
||||
pub struct LearnedMove {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The immutable move information of the move.
|
||||
move_data: Arc<dyn MoveData>,
|
||||
/// The maximal power points for this move.
|
||||
@@ -36,7 +33,6 @@ impl LearnedMove {
|
||||
pub fn new(move_data: Arc<dyn MoveData>, learn_method: MoveLearnMethod) -> Self {
|
||||
let max_pp = move_data.base_usages();
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
move_data,
|
||||
max_pp,
|
||||
remaining_pp: AtomicU8::new(max_pp),
|
||||
@@ -92,12 +88,6 @@ impl LearnedMove {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for LearnedMove {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
mod tests {
|
||||
|
||||
@@ -26,13 +26,11 @@ use crate::static_data::TypeIdentifier;
|
||||
use crate::static_data::{Ability, Statistic};
|
||||
use crate::static_data::{ClampedStatisticSet, StatisticSet};
|
||||
use crate::utils::Random;
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
use crate::{script_hook, PkmnError, StringKey, VecExt};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
|
||||
/// The data of a Pokemon.
|
||||
struct PokemonData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The library data of the Pokemon.
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
/// The species of the Pokemon.
|
||||
@@ -165,7 +163,6 @@ impl Pokemon {
|
||||
.get_nature(nature)
|
||||
.ok_or(PkmnError::InvalidNatureName { nature: nature.clone() })?;
|
||||
let pokemon_data = PokemonData {
|
||||
identifier: Default::default(),
|
||||
library,
|
||||
species: RwLock::new(species),
|
||||
form: RwLock::new(form.clone()),
|
||||
@@ -546,7 +543,7 @@ impl Pokemon {
|
||||
|
||||
/// Change the form of the Pokemon.
|
||||
pub fn change_form(&self, form: &Arc<dyn Form>) -> Result<()> {
|
||||
if self.form().value_identifier() == form.value_identifier() {
|
||||
if Arc::ptr_eq(&self.form(), form) {
|
||||
return Ok(());
|
||||
}
|
||||
*self.data.form.write() = form.clone();
|
||||
@@ -818,6 +815,10 @@ impl Pokemon {
|
||||
data: Arc::downgrade(&self.data),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const c_void {
|
||||
Arc::as_ptr(&self.data) as *const c_void
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Pokemon {
|
||||
@@ -938,12 +939,6 @@ impl VolatileScriptsOwner for Pokemon {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for Pokemon {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.data.identifier
|
||||
}
|
||||
}
|
||||
|
||||
/// A source of damage. This should be as unique as possible.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
|
||||
@@ -3,13 +3,11 @@ use parking_lot::lock_api::RwLockReadGuard;
|
||||
use parking_lot::{RawRwLock, RwLock};
|
||||
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
use crate::VecExt;
|
||||
|
||||
/// A list of Pokemon belonging to a trainer.
|
||||
#[derive(Debug)]
|
||||
pub struct PokemonParty {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying list of Pokemon.
|
||||
pokemon: RwLock<Vec<Option<Pokemon>>>,
|
||||
}
|
||||
@@ -22,7 +20,6 @@ impl PokemonParty {
|
||||
pokemon.push(None);
|
||||
}
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
pokemon: RwLock::new(pokemon),
|
||||
}
|
||||
}
|
||||
@@ -30,7 +27,6 @@ impl PokemonParty {
|
||||
/// Instantiates a party with a list.
|
||||
pub fn new_from_vec(pokemon: Vec<Option<Pokemon>>) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
pokemon: RwLock::new(pokemon),
|
||||
}
|
||||
}
|
||||
@@ -118,9 +114,3 @@ impl PokemonParty {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for PokemonParty {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user