More removal of RwLocks and replace it with Atomics, to prevent locks.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
59d7344729
commit
c45c7538bf
|
@ -41,6 +41,7 @@ rpath = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Used for PrimInt, so we can check if a generic is an integer
|
# Used for PrimInt, so we can check if a generic is an integer
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
|
atomic_prim_traits = "0.2.0"
|
||||||
# Allow us to assert whether floats are approximately a value
|
# Allow us to assert whether floats are approximately a value
|
||||||
assert_approx_eq = "1.1.0"
|
assert_approx_eq = "1.1.0"
|
||||||
# Used for time based code (i.e. randomness)
|
# Used for time based code (i.e. randomness)
|
||||||
|
|
|
@ -124,7 +124,7 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MoveChoice<'user, 'library> {
|
pub struct MoveChoice<'user, 'library> {
|
||||||
used_move: Arc<RwLock<LearnedMove<'library>>>,
|
used_move: Arc<LearnedMove<'library>>,
|
||||||
target_side: u8,
|
target_side: u8,
|
||||||
target_index: u8,
|
target_index: u8,
|
||||||
script: ScriptContainer,
|
script: ScriptContainer,
|
||||||
|
@ -135,7 +135,7 @@ pub struct MoveChoice<'user, 'library> {
|
||||||
impl<'user, 'library> MoveChoice<'user, 'library> {
|
impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
user: Arc<RwLock<Pokemon<'user, 'library>>>,
|
user: Arc<RwLock<Pokemon<'user, 'library>>>,
|
||||||
used_move: Arc<RwLock<LearnedMove<'library>>>,
|
used_move: Arc<LearnedMove<'library>>,
|
||||||
target_side: u8,
|
target_side: u8,
|
||||||
target_index: u8,
|
target_index: u8,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -155,7 +155,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn used_move(&self) -> &Arc<RwLock<LearnedMove<'library>>> {
|
pub fn used_move(&self) -> &Arc<LearnedMove<'library>> {
|
||||||
&self.used_move
|
&self.used_move
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||||
if self.has_ended() {
|
if self.has_ended() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
{
|
||||||
let user = choice.user().read();
|
let user = choice.user().read();
|
||||||
if !user.is_usable() {
|
if !user.is_usable() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -75,7 +76,7 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||||
if !user.is_on_battlefield() {
|
if !user.is_on_battlefield() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if !self.can_use(&choice) {
|
if !self.can_use(&choice) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -92,12 +93,13 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||||
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice<'own, 'library>) -> PkmnResult<()> {
|
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice<'own, 'library>) -> PkmnResult<()> {
|
||||||
let choice = choice.get_move_turn_data();
|
let choice = choice.get_move_turn_data();
|
||||||
let used_move = choice.used_move();
|
let used_move = choice.used_move();
|
||||||
let move_data_lock = used_move.read();
|
let move_data = {
|
||||||
|
let move_data_lock = used_move;
|
||||||
let move_data = move_data_lock.move_data();
|
let move_data = move_data_lock.move_data();
|
||||||
let mut move_name = move_data.name().clone();
|
let mut move_name = move_data.name().clone();
|
||||||
script_hook!(change_move, choice, choice, &mut move_name);
|
script_hook!(change_move, choice, choice, &mut move_name);
|
||||||
let move_data = self.library().static_data().moves().get(&move_name).unwrap();
|
self.library().static_data().moves().get(&move_name).unwrap()
|
||||||
drop(move_data_lock);
|
};
|
||||||
// FIXME: also change the script on the choice if changed;
|
// FIXME: also change the script on the choice if changed;
|
||||||
let target_type = move_data.target();
|
let target_type = move_data.target();
|
||||||
let targets = resolve_targets(choice.target_side(), choice.target_index(), target_type, self);
|
let targets = resolve_targets(choice.target_side(), choice.target_index(), target_type, self);
|
||||||
|
@ -120,7 +122,7 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||||
if prevented {
|
if prevented {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if !executing_move.chosen_move().write().try_use(1) {
|
if !executing_move.chosen_move().try_use(1) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.event_hook().trigger(Event::MoveUse {
|
self.event_hook().trigger(Event::MoveUse {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
use crate::static_data::statistic_set::StatisticSet;
|
use crate::static_data::statistic_set::StatisticSet;
|
||||||
use crate::static_data::statistics::Statistic;
|
use crate::static_data::statistics::Statistic;
|
||||||
|
use std::sync::atomic::AtomicU32;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BattleStatCalculator {}
|
pub struct BattleStatCalculator {}
|
||||||
|
|
||||||
impl BattleStatCalculator {
|
impl BattleStatCalculator {
|
||||||
pub fn calculate_flat_stats(&self, pokemon: &Pokemon) -> StatisticSet<u32> {
|
pub fn calculate_flat_stats(&self, pokemon: &Pokemon) -> StatisticSet<AtomicU32> {
|
||||||
StatisticSet::<u32>::new(
|
StatisticSet::<AtomicU32>::new(
|
||||||
self.calculate_health_stat(pokemon),
|
self.calculate_health_stat(pokemon),
|
||||||
self.calculate_other_stat(pokemon, Statistic::Attack),
|
self.calculate_other_stat(pokemon, Statistic::Attack),
|
||||||
self.calculate_other_stat(pokemon, Statistic::Defense),
|
self.calculate_other_stat(pokemon, Statistic::Defense),
|
||||||
|
@ -25,8 +26,8 @@ impl BattleStatCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_boosted_stats(&self, pokemon: &Pokemon) -> StatisticSet<u32> {
|
pub fn calculate_boosted_stats(&self, pokemon: &Pokemon) -> StatisticSet<AtomicU32> {
|
||||||
StatisticSet::<u32>::new(
|
StatisticSet::<AtomicU32>::new(
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::HP),
|
self.calculate_boosted_stat(pokemon, Statistic::HP),
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::Attack),
|
self.calculate_boosted_stat(pokemon, Statistic::Attack),
|
||||||
self.calculate_boosted_stat(pokemon, Statistic::Defense),
|
self.calculate_boosted_stat(pokemon, Statistic::Defense),
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl<'library> Debug for dyn MiscLibrary<'library> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Gen7MiscLibrary<'library> {
|
pub struct Gen7MiscLibrary<'library> {
|
||||||
struggle_data: *const MoveData,
|
struggle_data: *const MoveData,
|
||||||
struggle_learned_move: Arc<RwLock<LearnedMove<'library>>>,
|
struggle_learned_move: Arc<LearnedMove<'library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'library> Gen7MiscLibrary<'library> {
|
impl<'library> Gen7MiscLibrary<'library> {
|
||||||
|
@ -50,17 +50,14 @@ impl<'library> Gen7MiscLibrary<'library> {
|
||||||
MoveCategory::Physical,
|
MoveCategory::Physical,
|
||||||
50,
|
50,
|
||||||
255,
|
255,
|
||||||
10,
|
255,
|
||||||
MoveTarget::Any,
|
MoveTarget::Any,
|
||||||
0,
|
0,
|
||||||
SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![]),
|
SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![]),
|
||||||
HashSet::new(),
|
HashSet::new(),
|
||||||
));
|
));
|
||||||
let struggle_ptr = Box::into_raw(struggle_data);
|
let struggle_ptr = Box::into_raw(struggle_data);
|
||||||
let struggle_learned_move = Arc::new(RwLock::new(LearnedMove::new(
|
let struggle_learned_move = Arc::new(LearnedMove::new(unsafe { &*struggle_ptr }, MoveLearnMethod::Unknown));
|
||||||
unsafe { &*struggle_ptr },
|
|
||||||
MoveLearnMethod::Unknown,
|
|
||||||
)));
|
|
||||||
Self {
|
Self {
|
||||||
struggle_data: struggle_ptr,
|
struggle_data: struggle_ptr,
|
||||||
struggle_learned_move,
|
struggle_learned_move,
|
||||||
|
|
|
@ -197,13 +197,13 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||||
}
|
}
|
||||||
if let TurnChoice::Move(data) = choice {
|
if let TurnChoice::Move(data) = choice {
|
||||||
// TODO: Hook to change number of PP needed.
|
// TODO: Hook to change number of PP needed.
|
||||||
if data.used_move().read().remaining_pp() < 1 {
|
if data.used_move().remaining_pp() < 1 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if !is_valid_target(
|
if !is_valid_target(
|
||||||
data.target_side(),
|
data.target_side(),
|
||||||
data.target_index(),
|
data.target_index(),
|
||||||
data.used_move().read().move_data().target(),
|
data.used_move().move_data().target(),
|
||||||
choice.user().read().deref(),
|
choice.user().read().deref(),
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub struct ExecutingMove<'own, 'battle, 'library> {
|
||||||
number_of_hits: u8,
|
number_of_hits: u8,
|
||||||
hits: Vec<HitData>,
|
hits: Vec<HitData>,
|
||||||
user: Arc<RwLock<Pokemon<'battle, 'library>>>,
|
user: Arc<RwLock<Pokemon<'battle, 'library>>>,
|
||||||
chosen_move: Arc<RwLock<LearnedMove<'library>>>,
|
chosen_move: Arc<LearnedMove<'library>>,
|
||||||
use_move: &'own MoveData,
|
use_move: &'own MoveData,
|
||||||
script: ScriptContainer,
|
script: ScriptContainer,
|
||||||
targets: &'own TargetList<'battle, 'library>,
|
targets: &'own TargetList<'battle, 'library>,
|
||||||
|
@ -75,7 +75,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
|
||||||
targets: &'own TargetList<'battle, 'library>,
|
targets: &'own TargetList<'battle, 'library>,
|
||||||
number_of_hits: u8,
|
number_of_hits: u8,
|
||||||
user: Arc<RwLock<Pokemon<'battle, 'library>>>,
|
user: Arc<RwLock<Pokemon<'battle, 'library>>>,
|
||||||
chosen_move: Arc<RwLock<LearnedMove<'library>>>,
|
chosen_move: Arc<LearnedMove<'library>>,
|
||||||
use_move: &'own MoveData,
|
use_move: &'own MoveData,
|
||||||
script: ScriptContainer,
|
script: ScriptContainer,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -104,7 +104,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
|
||||||
pub fn user(&self) -> &Arc<RwLock<Pokemon<'battle, 'library>>> {
|
pub fn user(&self) -> &Arc<RwLock<Pokemon<'battle, 'library>>> {
|
||||||
&self.user
|
&self.user
|
||||||
}
|
}
|
||||||
pub fn chosen_move(&self) -> &Arc<RwLock<LearnedMove<'library>>> {
|
pub fn chosen_move(&self) -> &Arc<LearnedMove<'library>> {
|
||||||
&self.chosen_move
|
&self.chosen_move
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::static_data::MoveData;
|
use crate::static_data::MoveData;
|
||||||
|
use std::sync::atomic::{AtomicU8, Ordering};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LearnedMove<'library> {
|
pub struct LearnedMove<'library> {
|
||||||
move_data: &'library MoveData,
|
move_data: &'library MoveData,
|
||||||
max_pp: u8,
|
max_pp: u8,
|
||||||
remaining_pp: u8,
|
remaining_pp: AtomicU8,
|
||||||
learn_method: MoveLearnMethod,
|
learn_method: MoveLearnMethod,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ impl<'a> LearnedMove<'a> {
|
||||||
Self {
|
Self {
|
||||||
move_data,
|
move_data,
|
||||||
max_pp: move_data.base_usages(),
|
max_pp: move_data.base_usages(),
|
||||||
remaining_pp: move_data.base_usages(),
|
remaining_pp: AtomicU8::new(move_data.base_usages()),
|
||||||
learn_method,
|
learn_method,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,17 +33,17 @@ impl<'a> LearnedMove<'a> {
|
||||||
self.max_pp
|
self.max_pp
|
||||||
}
|
}
|
||||||
pub fn remaining_pp(&self) -> u8 {
|
pub fn remaining_pp(&self) -> u8 {
|
||||||
self.remaining_pp
|
self.remaining_pp.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn learn_method(&self) -> MoveLearnMethod {
|
pub fn learn_method(&self) -> MoveLearnMethod {
|
||||||
self.learn_method
|
self.learn_method
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_use(&mut self, amount: u8) -> bool {
|
pub fn try_use(&self, amount: u8) -> bool {
|
||||||
if amount > self.remaining_pp {
|
if amount > self.remaining_pp() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
self.remaining_pp -= amount;
|
self.remaining_pp.fetch_sub(amount, Ordering::SeqCst);
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use crate::static_data::DataLibrary;
|
||||||
use crate::utils::random::Random;
|
use crate::utils::random::Random;
|
||||||
use crate::{script_hook, PkmnResult, ScriptCategory, StringKey};
|
use crate::{script_hook, PkmnResult, ScriptCategory, StringKey};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use std::sync::atomic::{AtomicI8, AtomicU32, AtomicU8, Ordering};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -63,21 +64,21 @@ where
|
||||||
display_form: Option<&'own Form>,
|
display_form: Option<&'own Form>,
|
||||||
|
|
||||||
level: LevelInt,
|
level: LevelInt,
|
||||||
experience: u32,
|
experience: AtomicU32,
|
||||||
unique_identifier: u32,
|
unique_identifier: u32,
|
||||||
gender: Gender,
|
gender: Gender,
|
||||||
coloring: u8,
|
coloring: u8,
|
||||||
held_item: Option<&'own Item>,
|
held_item: Option<&'own Item>,
|
||||||
current_health: u32,
|
current_health: AtomicU32,
|
||||||
|
|
||||||
weight: f32,
|
weight: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
|
|
||||||
stat_boost: ClampedStatisticSet<i8, -6, 6>,
|
stat_boost: ClampedStatisticSet<AtomicI8, -6, 6>,
|
||||||
flat_stats: StatisticSet<u32>,
|
flat_stats: StatisticSet<AtomicU32>,
|
||||||
boosted_stats: StatisticSet<u32>,
|
boosted_stats: StatisticSet<AtomicU32>,
|
||||||
individual_values: ClampedStatisticSet<u8, 0, 31>,
|
individual_values: ClampedStatisticSet<AtomicU8, 0, 31>,
|
||||||
effort_values: ClampedStatisticSet<u8, 0, 252>,
|
effort_values: ClampedStatisticSet<AtomicU8, 0, 252>,
|
||||||
nature: &'own Nature,
|
nature: &'own Nature,
|
||||||
|
|
||||||
nickname: Option<String>,
|
nickname: Option<String>,
|
||||||
|
@ -88,7 +89,7 @@ where
|
||||||
|
|
||||||
battle_data: Option<PokemonBattleData<'own, 'library>>,
|
battle_data: Option<PokemonBattleData<'own, 'library>>,
|
||||||
|
|
||||||
moves: [Option<Arc<RwLock<LearnedMove<'library>>>>; MAX_MOVES],
|
moves: [Option<Arc<LearnedMove<'library>>>; MAX_MOVES],
|
||||||
allowed_experience: bool,
|
allowed_experience: bool,
|
||||||
|
|
||||||
types: Vec<u8>,
|
types: Vec<u8>,
|
||||||
|
@ -125,7 +126,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
let nature = library
|
let nature = library
|
||||||
.static_data()
|
.static_data()
|
||||||
.natures()
|
.natures()
|
||||||
.get_nature(&nature)
|
.get_nature(nature)
|
||||||
.unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature));
|
.unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature));
|
||||||
let mut pokemon = Self {
|
let mut pokemon = Self {
|
||||||
library,
|
library,
|
||||||
|
@ -134,12 +135,12 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
display_species: None,
|
display_species: None,
|
||||||
display_form: None,
|
display_form: None,
|
||||||
level,
|
level,
|
||||||
experience,
|
experience: AtomicU32::new(experience),
|
||||||
unique_identifier,
|
unique_identifier,
|
||||||
gender,
|
gender,
|
||||||
coloring,
|
coloring,
|
||||||
held_item: None,
|
held_item: None,
|
||||||
current_health: 1,
|
current_health: AtomicU32::new(1),
|
||||||
weight,
|
weight,
|
||||||
height,
|
height,
|
||||||
stat_boost: Default::default(),
|
stat_boost: Default::default(),
|
||||||
|
@ -166,7 +167,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
};
|
};
|
||||||
pokemon.recalculate_flat_stats();
|
pokemon.recalculate_flat_stats();
|
||||||
let health = pokemon.flat_stats().hp();
|
let health = pokemon.flat_stats().hp();
|
||||||
pokemon.current_health = health;
|
pokemon.current_health = AtomicU32::new(health);
|
||||||
|
|
||||||
pokemon
|
pokemon
|
||||||
}
|
}
|
||||||
|
@ -199,7 +200,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
self.level
|
self.level
|
||||||
}
|
}
|
||||||
pub fn experience(&self) -> u32 {
|
pub fn experience(&self) -> u32 {
|
||||||
self.experience
|
self.experience.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn unique_identifier(&self) -> u32 {
|
pub fn unique_identifier(&self) -> u32 {
|
||||||
self.unique_identifier
|
self.unique_identifier
|
||||||
|
@ -240,7 +241,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_health(&self) -> u32 {
|
pub fn current_health(&self) -> u32 {
|
||||||
self.current_health
|
self.current_health.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn max_health(&self) -> u32 {
|
pub fn max_health(&self) -> u32 {
|
||||||
self.boosted_stats.hp()
|
self.boosted_stats.hp()
|
||||||
|
@ -260,31 +261,31 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
pub fn types(&self) -> &Vec<u8> {
|
pub fn types(&self) -> &Vec<u8> {
|
||||||
&self.types
|
&self.types
|
||||||
}
|
}
|
||||||
pub fn learned_moves(&self) -> &[Option<Arc<RwLock<LearnedMove<'library>>>>; MAX_MOVES] {
|
pub fn learned_moves(&self) -> &[Option<Arc<LearnedMove<'library>>>; MAX_MOVES] {
|
||||||
&self.moves
|
&self.moves
|
||||||
}
|
}
|
||||||
pub fn status(&self) -> &ScriptContainer {
|
pub fn status(&self) -> &ScriptContainer {
|
||||||
&self.status_script
|
&self.status_script
|
||||||
}
|
}
|
||||||
pub fn flat_stats(&self) -> &StatisticSet<u32> {
|
pub fn flat_stats(&self) -> &StatisticSet<AtomicU32> {
|
||||||
&self.flat_stats
|
&self.flat_stats
|
||||||
}
|
}
|
||||||
pub fn boosted_stats(&self) -> &StatisticSet<u32> {
|
pub fn boosted_stats(&self) -> &StatisticSet<AtomicU32> {
|
||||||
&self.boosted_stats
|
&self.boosted_stats
|
||||||
}
|
}
|
||||||
pub fn stat_boost(&self) -> &ClampedStatisticSet<i8, -6, 6> {
|
pub fn stat_boost(&self) -> &ClampedStatisticSet<AtomicI8, -6, 6> {
|
||||||
&self.stat_boost
|
&self.stat_boost
|
||||||
}
|
}
|
||||||
pub fn individual_values(&self) -> &ClampedStatisticSet<u8, 0, 31> {
|
pub fn individual_values(&self) -> &ClampedStatisticSet<AtomicU8, 0, 31> {
|
||||||
&self.individual_values
|
&self.individual_values
|
||||||
}
|
}
|
||||||
pub fn effort_values(&self) -> &ClampedStatisticSet<u8, 0, 252> {
|
pub fn effort_values(&self) -> &ClampedStatisticSet<AtomicU8, 0, 252> {
|
||||||
&self.effort_values
|
&self.effort_values
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_battle(&self) -> Option<&Battle<'own, 'library>> {
|
pub fn get_battle(&self) -> Option<&Battle<'own, 'library>> {
|
||||||
if let Some(data) = &self.battle_data {
|
if let Some(data) = &self.battle_data {
|
||||||
Some(&data.battle().unwrap())
|
Some(data.battle().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -401,10 +402,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
let old_health = self.max_health();
|
let old_health = self.max_health();
|
||||||
self.recalculate_flat_stats();
|
self.recalculate_flat_stats();
|
||||||
let diff_health = (self.max_health() - old_health) as i32;
|
let diff_health = (self.max_health() - old_health) as i32;
|
||||||
if self.current_health == 0 && (self.current_health as i32) < -diff_health {
|
if self.current_health() == 0 && (self.current_health() as i32) < -diff_health {
|
||||||
self.current_health = 0;
|
self.current_health.store(0, Ordering::SeqCst);
|
||||||
} else {
|
} else {
|
||||||
self.current_health = self.current_health() + diff_health as u32;
|
self.current_health.fetch_add(diff_health as u32, Ordering::Acquire);
|
||||||
}
|
}
|
||||||
// TODO: consider form specific attacks?
|
// TODO: consider form specific attacks?
|
||||||
|
|
||||||
|
@ -420,7 +421,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_fainted(&self) -> bool {
|
pub fn is_fainted(&self) -> bool {
|
||||||
self.current_health == 0
|
self.current_health() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_battle_data(&mut self, battle: *mut Battle<'own, 'library>, battle_side_index: u8) {
|
pub fn set_battle_data(&mut self, battle: *mut Battle<'own, 'library>, battle_side_index: u8) {
|
||||||
|
@ -475,8 +476,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn damage(&mut self, mut damage: u32, source: DamageSource) {
|
pub fn damage(&mut self, mut damage: u32, source: DamageSource) {
|
||||||
if damage > self.current_health {
|
if damage > self.current_health() {
|
||||||
damage = self.current_health;
|
damage = self.current_health();
|
||||||
}
|
}
|
||||||
if damage == 0 {
|
if damage == 0 {
|
||||||
return;
|
return;
|
||||||
|
@ -491,10 +492,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
new_health,
|
new_health,
|
||||||
});
|
});
|
||||||
// TODO: register history
|
// TODO: register history
|
||||||
script_hook!(on_damage, self, self, source, self.current_health, new_health);
|
script_hook!(on_damage, self, self, source, self.current_health(), new_health);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.current_health = new_health;
|
self.current_health.store(new_health, Ordering::SeqCst);
|
||||||
if self.is_fainted() && damage > 0 {
|
if self.is_fainted() && damage > 0 {
|
||||||
self.on_faint(source);
|
self.on_faint(source);
|
||||||
}
|
}
|
||||||
|
@ -540,7 +541,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||||
panic!("No more moves with an empty space found.");
|
panic!("No more moves with an empty space found.");
|
||||||
}
|
}
|
||||||
let move_data = self.library.static_data().moves().get(move_name).unwrap();
|
let move_data = self.library.static_data().moves().get(move_name).unwrap();
|
||||||
self.moves[move_pos.unwrap()] = Some(Arc::new(RwLock::new(LearnedMove::new(move_data, learn_method))));
|
self.moves[move_pos.unwrap()] = Some(Arc::new(LearnedMove::new(move_data, learn_method)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![feature(bench_black_box)]
|
#![feature(bench_black_box)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(const_option)]
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub mod tests {
|
||||||
use crate::static_data::species_data::form::Form;
|
use crate::static_data::species_data::form::Form;
|
||||||
use crate::static_data::species_data::learnable_moves::LearnableMoves;
|
use crate::static_data::species_data::learnable_moves::LearnableMoves;
|
||||||
use crate::static_data::species_data::species::Species;
|
use crate::static_data::species_data::species::Species;
|
||||||
use crate::static_data::statistic_set::StatisticSet;
|
use crate::static_data::StaticStatisticSet;
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
fn build_species<'a>() -> Species {
|
fn build_species<'a>() -> Species {
|
||||||
|
@ -55,7 +55,7 @@ pub mod tests {
|
||||||
0.0,
|
0.0,
|
||||||
0,
|
0,
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
StatisticSet::default(),
|
StaticStatisticSet::default(),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
LearnableMoves::new(),
|
LearnableMoves::new(),
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use crate::static_data::Ability;
|
|
||||||
use crate::static_data::AbilityIndex;
|
use crate::static_data::AbilityIndex;
|
||||||
use crate::static_data::LearnableMoves;
|
use crate::static_data::LearnableMoves;
|
||||||
use crate::static_data::Statistic;
|
use crate::static_data::Statistic;
|
||||||
use crate::static_data::StatisticSet;
|
use crate::static_data::{Ability, StaticStatisticSet};
|
||||||
use crate::Random;
|
use crate::Random;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
@ -14,7 +13,7 @@ pub struct Form {
|
||||||
weight: f32,
|
weight: f32,
|
||||||
base_experience: u32,
|
base_experience: u32,
|
||||||
types: Vec<u8>,
|
types: Vec<u8>,
|
||||||
base_stats: StatisticSet<u16>,
|
base_stats: StaticStatisticSet<u16>,
|
||||||
abilities: Vec<StringKey>,
|
abilities: Vec<StringKey>,
|
||||||
hidden_abilities: Vec<StringKey>,
|
hidden_abilities: Vec<StringKey>,
|
||||||
moves: LearnableMoves,
|
moves: LearnableMoves,
|
||||||
|
@ -28,7 +27,7 @@ impl Form {
|
||||||
weight: f32,
|
weight: f32,
|
||||||
base_experience: u32,
|
base_experience: u32,
|
||||||
types: Vec<u8>,
|
types: Vec<u8>,
|
||||||
base_stats: StatisticSet<u16>,
|
base_stats: StaticStatisticSet<u16>,
|
||||||
abilities: Vec<StringKey>,
|
abilities: Vec<StringKey>,
|
||||||
hidden_abilities: Vec<StringKey>,
|
hidden_abilities: Vec<StringKey>,
|
||||||
moves: LearnableMoves,
|
moves: LearnableMoves,
|
||||||
|
@ -63,8 +62,8 @@ impl Form {
|
||||||
pub fn types(&self) -> &Vec<u8> {
|
pub fn types(&self) -> &Vec<u8> {
|
||||||
&self.types
|
&self.types
|
||||||
}
|
}
|
||||||
pub fn base_stats(&self) -> StatisticSet<u16> {
|
pub fn base_stats(&self) -> &StaticStatisticSet<u16> {
|
||||||
self.base_stats
|
&self.base_stats
|
||||||
}
|
}
|
||||||
pub fn abilities(&self) -> &Vec<StringKey> {
|
pub fn abilities(&self) -> &Vec<StringKey> {
|
||||||
&self.abilities
|
&self.abilities
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use super::statistics::Statistic;
|
use super::statistics::Statistic;
|
||||||
use num_traits::{cast, clamp, PrimInt};
|
use atomic_prim_traits::AtomicInt;
|
||||||
|
use num_traits::{clamp, NumCast, PrimInt};
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
#[derive(Default, Eq, PartialEq, Copy, Clone, Debug)]
|
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct StatisticSet<T>
|
pub struct StatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: AtomicInt,
|
||||||
{
|
{
|
||||||
hp: T,
|
hp: T,
|
||||||
attack: T,
|
attack: T,
|
||||||
|
@ -16,85 +18,92 @@ where
|
||||||
|
|
||||||
impl<T> StatisticSet<T>
|
impl<T> StatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: AtomicInt,
|
||||||
{
|
{
|
||||||
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
pub fn new(
|
||||||
|
hp: T::Prim,
|
||||||
|
attack: T::Prim,
|
||||||
|
defense: T::Prim,
|
||||||
|
special_attack: T::Prim,
|
||||||
|
special_defense: T::Prim,
|
||||||
|
speed: T::Prim,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
hp,
|
hp: T::new(hp),
|
||||||
attack,
|
attack: T::new(attack),
|
||||||
defense,
|
defense: T::new(defense),
|
||||||
special_attack,
|
special_attack: T::new(special_attack),
|
||||||
special_defense,
|
special_defense: T::new(special_defense),
|
||||||
speed,
|
speed: T::new(speed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hp(&self) -> T {
|
pub fn hp(&self) -> T::Prim {
|
||||||
self.hp
|
self.hp.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn attack(&self) -> T {
|
pub fn attack(&self) -> T::Prim {
|
||||||
self.attack
|
self.attack.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn defense(&self) -> T {
|
pub fn defense(&self) -> T::Prim {
|
||||||
self.defense
|
self.defense.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn special_attack(&self) -> T {
|
pub fn special_attack(&self) -> T::Prim {
|
||||||
self.special_attack
|
self.special_attack.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn special_defense(&self) -> T {
|
pub fn special_defense(&self) -> T::Prim {
|
||||||
self.special_defense
|
self.special_defense.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
pub fn speed(&self) -> T {
|
pub fn speed(&self) -> T::Prim {
|
||||||
self.speed
|
self.speed.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn get_stat(&self, stat: Statistic) -> T {
|
pub fn get_stat(&self, stat: Statistic) -> T::Prim {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp,
|
Statistic::HP => self.hp.load(Ordering::Relaxed),
|
||||||
Statistic::Attack => self.attack,
|
Statistic::Attack => self.attack.load(Ordering::Relaxed),
|
||||||
Statistic::Defense => self.defense,
|
Statistic::Defense => self.defense.load(Ordering::Relaxed),
|
||||||
Statistic::SpecialAttack => self.special_attack,
|
Statistic::SpecialAttack => self.special_attack.load(Ordering::Relaxed),
|
||||||
Statistic::SpecialDefense => self.special_defense,
|
Statistic::SpecialDefense => self.special_defense.load(Ordering::Relaxed),
|
||||||
Statistic::Speed => self.speed,
|
Statistic::Speed => self.speed.load(Ordering::Relaxed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_stat(&mut self, stat: Statistic, value: T) {
|
pub fn set_stat(&self, stat: Statistic, value: T::Prim) {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp = value,
|
Statistic::HP => self.hp.store(value, Ordering::SeqCst),
|
||||||
Statistic::Attack => self.attack = value,
|
Statistic::Attack => self.attack.store(value, Ordering::SeqCst),
|
||||||
Statistic::Defense => self.defense = value,
|
Statistic::Defense => self.defense.store(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialAttack => self.special_attack = value,
|
Statistic::SpecialAttack => self.special_attack.store(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialDefense => self.special_defense = value,
|
Statistic::SpecialDefense => self.special_defense.store(value, Ordering::SeqCst),
|
||||||
Statistic::Speed => self.speed = value,
|
Statistic::Speed => self.speed.store(value, Ordering::SeqCst),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn increase_stat(&mut self, stat: Statistic, value: T) {
|
pub fn increase_stat(&self, stat: Statistic, value: T::Prim) {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp = self.hp + value,
|
Statistic::HP => self.hp.fetch_add(value, Ordering::SeqCst),
|
||||||
Statistic::Attack => self.attack = self.attack + value,
|
Statistic::Attack => self.attack.fetch_add(value, Ordering::SeqCst),
|
||||||
Statistic::Defense => self.defense = self.defense + value,
|
Statistic::Defense => self.defense.fetch_add(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialAttack => self.special_attack = self.special_attack + value,
|
Statistic::SpecialAttack => self.special_attack.fetch_add(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialDefense => self.special_defense = self.special_defense + value,
|
Statistic::SpecialDefense => self.special_defense.fetch_add(value, Ordering::SeqCst),
|
||||||
Statistic::Speed => self.speed = self.speed + value,
|
Statistic::Speed => self.speed.fetch_add(value, Ordering::SeqCst),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrease_stat(&mut self, stat: Statistic, value: T) {
|
pub fn decrease_stat(&self, stat: Statistic, value: T::Prim) {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp = self.hp - value,
|
Statistic::HP => self.hp.fetch_sub(value, Ordering::SeqCst),
|
||||||
Statistic::Attack => self.attack = self.attack - value,
|
Statistic::Attack => self.attack.fetch_sub(value, Ordering::SeqCst),
|
||||||
Statistic::Defense => self.defense = self.defense - value,
|
Statistic::Defense => self.defense.fetch_sub(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialAttack => self.special_attack = self.special_attack - value,
|
Statistic::SpecialAttack => self.special_attack.fetch_sub(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialDefense => self.special_defense = self.special_defense - value,
|
Statistic::SpecialDefense => self.special_defense.fetch_sub(value, Ordering::SeqCst),
|
||||||
Statistic::Speed => self.speed = self.speed - value,
|
Statistic::Speed => self.speed.fetch_sub(value, Ordering::SeqCst),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Eq, PartialEq, Copy, Clone, Debug)]
|
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct ClampedStatisticSet<T, const MIN: i64, const MAX: i64>
|
pub struct StaticStatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
|
@ -106,37 +115,37 @@ where
|
||||||
speed: T,
|
speed: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const MIN: i64, const MAX: i64> ClampedStatisticSet<T, MIN, MAX>
|
impl<T> StaticStatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
pub const fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
hp: cast(clamp(cast::<T, i64>(hp).unwrap(), MIN, MAX)).unwrap(),
|
hp,
|
||||||
attack: cast(clamp(cast::<T, i64>(attack).unwrap(), MIN, MAX)).unwrap(),
|
attack,
|
||||||
defense: cast(clamp(cast::<T, i64>(defense).unwrap(), MIN, MAX)).unwrap(),
|
defense,
|
||||||
special_attack: cast(clamp(cast::<T, i64>(special_attack).unwrap(), MIN, MAX)).unwrap(),
|
special_attack,
|
||||||
special_defense: cast(clamp(cast::<T, i64>(special_defense).unwrap(), MIN, MAX)).unwrap(),
|
special_defense,
|
||||||
speed: cast(clamp(cast::<T, i64>(speed).unwrap(), MIN, MAX)).unwrap(),
|
speed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hp(&self) -> T {
|
pub const fn hp(&self) -> T {
|
||||||
self.hp
|
self.hp
|
||||||
}
|
}
|
||||||
pub fn attack(&self) -> T {
|
pub const fn attack(&self) -> T {
|
||||||
self.attack
|
self.attack
|
||||||
}
|
}
|
||||||
pub fn defense(&self) -> T {
|
pub const fn defense(&self) -> T {
|
||||||
self.defense
|
self.defense
|
||||||
}
|
}
|
||||||
pub fn special_attack(&self) -> T {
|
pub const fn special_attack(&self) -> T {
|
||||||
self.special_attack
|
self.special_attack
|
||||||
}
|
}
|
||||||
pub fn special_defense(&self) -> T {
|
pub const fn special_defense(&self) -> T {
|
||||||
self.special_defense
|
self.special_defense
|
||||||
}
|
}
|
||||||
pub fn speed(&self) -> T {
|
pub const fn speed(&self) -> T {
|
||||||
self.speed
|
self.speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,55 +159,143 @@ where
|
||||||
Statistic::Speed => self.speed,
|
Statistic::Speed => self.speed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_stat(&mut self, stat: Statistic, mut value: T) {
|
#[derive(Default, Eq, PartialEq, Clone, Debug)]
|
||||||
if value < T::from(MIN).unwrap() {
|
pub struct ClampedStatisticSet<T, const MIN: i64, const MAX: i64>
|
||||||
value = T::from(MIN).unwrap();
|
where
|
||||||
} else if value > T::from(MAX).unwrap() {
|
T: AtomicInt,
|
||||||
value = T::from(MAX).unwrap();
|
{
|
||||||
|
hp: T,
|
||||||
|
attack: T,
|
||||||
|
defense: T,
|
||||||
|
special_attack: T,
|
||||||
|
special_defense: T,
|
||||||
|
speed: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const MIN: i64, const MAX: i64> ClampedStatisticSet<T, MIN, MAX>
|
||||||
|
where
|
||||||
|
T: AtomicInt,
|
||||||
|
<T as AtomicInt>::Prim: NumCast,
|
||||||
|
<T as AtomicInt>::Prim: PrimInt,
|
||||||
|
{
|
||||||
|
pub fn min() -> T::Prim {
|
||||||
|
<<T as AtomicInt>::Prim as NumCast>::from(MIN).unwrap()
|
||||||
|
}
|
||||||
|
pub fn max() -> T::Prim {
|
||||||
|
<<T as AtomicInt>::Prim as NumCast>::from(MAX).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clamped_cast(v: T::Prim) -> T {
|
||||||
|
let v = clamp(v, Self::min(), Self::max());
|
||||||
|
T::new(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
hp: T::Prim,
|
||||||
|
attack: T::Prim,
|
||||||
|
defense: T::Prim,
|
||||||
|
special_attack: T::Prim,
|
||||||
|
special_defense: T::Prim,
|
||||||
|
speed: T::Prim,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
hp: Self::clamped_cast(hp),
|
||||||
|
attack: Self::clamped_cast(attack),
|
||||||
|
defense: Self::clamped_cast(defense),
|
||||||
|
special_attack: Self::clamped_cast(special_attack),
|
||||||
|
special_defense: Self::clamped_cast(special_defense),
|
||||||
|
speed: Self::clamped_cast(speed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hp(&self) -> T::Prim {
|
||||||
|
self.hp.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
pub fn attack(&self) -> T::Prim {
|
||||||
|
self.attack.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
pub fn defense(&self) -> T::Prim {
|
||||||
|
self.defense.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
pub fn special_attack(&self) -> T::Prim {
|
||||||
|
self.special_attack.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
pub fn special_defense(&self) -> T::Prim {
|
||||||
|
self.special_defense.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
pub fn speed(&self) -> T::Prim {
|
||||||
|
self.speed.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_stat(&self, stat: Statistic) -> T::Prim {
|
||||||
|
match stat {
|
||||||
|
Statistic::HP => self.hp.load(Ordering::Relaxed),
|
||||||
|
Statistic::Attack => self.attack.load(Ordering::Relaxed),
|
||||||
|
Statistic::Defense => self.defense.load(Ordering::Relaxed),
|
||||||
|
Statistic::SpecialAttack => self.special_attack.load(Ordering::Relaxed),
|
||||||
|
Statistic::SpecialDefense => self.special_defense.load(Ordering::Relaxed),
|
||||||
|
Statistic::Speed => self.speed.load(Ordering::Relaxed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_stat(&self, stat: Statistic, mut value: T::Prim) {
|
||||||
|
if value < Self::min() {
|
||||||
|
value = Self::min();
|
||||||
|
} else if value > Self::max() {
|
||||||
|
value = Self::max();
|
||||||
}
|
}
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => self.hp = value,
|
Statistic::HP => self.hp.store(value, Ordering::SeqCst),
|
||||||
Statistic::Attack => self.attack = value,
|
Statistic::Attack => self.attack.store(value, Ordering::SeqCst),
|
||||||
Statistic::Defense => self.defense = value,
|
Statistic::Defense => self.defense.store(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialAttack => self.special_attack = value,
|
Statistic::SpecialAttack => self.special_attack.store(value, Ordering::SeqCst),
|
||||||
Statistic::SpecialDefense => self.special_defense = value,
|
Statistic::SpecialDefense => self.special_defense.store(value, Ordering::SeqCst),
|
||||||
Statistic::Speed => self.speed = value,
|
Statistic::Speed => self.speed.store(value, Ordering::SeqCst),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_stat(mut new_value: T, original_value: &mut T) -> bool {
|
fn change_stat<F>(v: &T, f: F) -> bool
|
||||||
if new_value < T::from(MIN).unwrap() {
|
where
|
||||||
new_value = T::from(MIN).unwrap();
|
F: FnOnce(T::Prim) -> T::Prim,
|
||||||
} else if new_value > T::from(MAX).unwrap() {
|
{
|
||||||
new_value = T::from(MAX).unwrap();
|
let original_value = v.load(Ordering::Relaxed);
|
||||||
|
let mut new_value = f(original_value);
|
||||||
|
if new_value < Self::min() {
|
||||||
|
new_value = Self::min();
|
||||||
|
} else if new_value > Self::max() {
|
||||||
|
new_value = Self::max();
|
||||||
}
|
}
|
||||||
if *original_value == new_value {
|
if original_value == new_value {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*original_value = new_value;
|
v.store(new_value, Ordering::SeqCst);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn increase_stat(&mut self, stat: Statistic, value: T) -> bool {
|
pub fn increase_stat(&self, stat: Statistic, value: T::Prim) -> bool
|
||||||
|
where
|
||||||
|
<T as AtomicInt>::Prim: PrimInt,
|
||||||
|
{
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => Self::change_stat(self.hp + value, &mut self.hp),
|
Statistic::HP => Self::change_stat(&self.hp, |a| a + value),
|
||||||
Statistic::Attack => Self::change_stat(self.attack + value, &mut self.attack),
|
Statistic::Attack => Self::change_stat(&self.attack, |a| a + value),
|
||||||
Statistic::Defense => Self::change_stat(self.defense + value, &mut self.defense),
|
Statistic::Defense => Self::change_stat(&self.defense, |a| a + value),
|
||||||
Statistic::SpecialAttack => Self::change_stat(self.special_attack + value, &mut self.special_attack),
|
Statistic::SpecialAttack => Self::change_stat(&self.special_attack, |a| a + value),
|
||||||
Statistic::SpecialDefense => Self::change_stat(self.special_defense + value, &mut self.special_defense),
|
Statistic::SpecialDefense => Self::change_stat(&self.special_defense, |a| a + value),
|
||||||
Statistic::Speed => Self::change_stat(self.speed + value, &mut self.speed),
|
Statistic::Speed => Self::change_stat(&self.speed, |a| a + value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrease_stat(&mut self, stat: Statistic, value: T) -> bool {
|
pub fn decrease_stat(&self, stat: Statistic, value: T::Prim) -> bool {
|
||||||
match stat {
|
match stat {
|
||||||
Statistic::HP => Self::change_stat(self.hp - value, &mut self.hp),
|
Statistic::HP => Self::change_stat(&self.hp, |a| a - value),
|
||||||
Statistic::Attack => Self::change_stat(self.attack - value, &mut self.attack),
|
Statistic::Attack => Self::change_stat(&self.attack, |a| a - value),
|
||||||
Statistic::Defense => Self::change_stat(self.defense - value, &mut self.defense),
|
Statistic::Defense => Self::change_stat(&self.defense, |a| a - value),
|
||||||
Statistic::SpecialAttack => Self::change_stat(self.special_attack - value, &mut self.special_attack),
|
Statistic::SpecialAttack => Self::change_stat(&self.special_attack, |a| a - value),
|
||||||
Statistic::SpecialDefense => Self::change_stat(self.special_defense - value, &mut self.special_defense),
|
Statistic::SpecialDefense => Self::change_stat(&self.special_defense, |a| a - value),
|
||||||
Statistic::Speed => Self::change_stat(self.speed - value, &mut self.speed),
|
Statistic::Speed => Self::change_stat(&self.speed, |a| a - value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,10 +303,11 @@ where
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::sync::atomic::AtomicI32;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_get_values() {
|
fn create_get_values() {
|
||||||
let set = StatisticSet::new(1, 2, 3, 4, 5, 6);
|
let set = StatisticSet::<AtomicI32>::new(1, 2, 3, 4, 5, 6);
|
||||||
assert_eq!(set.hp(), 1);
|
assert_eq!(set.hp(), 1);
|
||||||
assert_eq!(set.get_stat(Statistic::HP), 1);
|
assert_eq!(set.get_stat(Statistic::HP), 1);
|
||||||
assert_eq!(set.attack(), 2);
|
assert_eq!(set.attack(), 2);
|
||||||
|
@ -226,7 +324,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_set_value() {
|
fn create_set_value() {
|
||||||
let mut set = StatisticSet::new(1, 2, 3, 4, 5, 6);
|
let set = StatisticSet::<AtomicI32>::new(1, 2, 3, 4, 5, 6);
|
||||||
|
|
||||||
set.set_stat(Statistic::HP, 20);
|
set.set_stat(Statistic::HP, 20);
|
||||||
assert_eq!(set.hp(), 20);
|
assert_eq!(set.hp(), 20);
|
||||||
|
@ -244,21 +342,21 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_increase_value() {
|
fn create_increase_value() {
|
||||||
let mut set = StatisticSet::new(1, 2, 3, 4, 5, 6);
|
let set = StatisticSet::<AtomicI32>::new(1, 2, 3, 4, 5, 6);
|
||||||
set.increase_stat(Statistic::SpecialAttack, 5);
|
set.increase_stat(Statistic::SpecialAttack, 5);
|
||||||
assert_eq!(set.special_attack(), 9);
|
assert_eq!(set.special_attack(), 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_decrease_value() {
|
fn create_decrease_value() {
|
||||||
let mut set = StatisticSet::new(1, 2, 3, 4, 5, 6);
|
let set = StatisticSet::<AtomicI32>::new(1, 2, 3, 4, 5, 6);
|
||||||
set.decrease_stat(Statistic::SpecialAttack, 5);
|
set.decrease_stat(Statistic::SpecialAttack, 5);
|
||||||
assert_eq!(set.special_attack(), -1);
|
assert_eq!(set.special_attack(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_clamped_get_values() {
|
fn create_clamped_get_values() {
|
||||||
let set = ClampedStatisticSet::<i32, { -2 }, 4>::new(-5, 2, 3, 4, 5, 6);
|
let set = ClampedStatisticSet::<AtomicI32, { -2 }, 4>::new(-5, 2, 3, 4, 5, 6);
|
||||||
assert_eq!(set.hp(), -2);
|
assert_eq!(set.hp(), -2);
|
||||||
assert_eq!(set.get_stat(Statistic::HP), -2);
|
assert_eq!(set.get_stat(Statistic::HP), -2);
|
||||||
assert_eq!(set.attack(), 2);
|
assert_eq!(set.attack(), 2);
|
||||||
|
@ -275,7 +373,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_clamped_set_value() {
|
fn create_clamped_set_value() {
|
||||||
let mut set = ClampedStatisticSet::<i32, { -2 }, 4>::new(1, 2, 3, 4, 5, 6);
|
let set = ClampedStatisticSet::<AtomicI32, { -2 }, 4>::new(1, 2, 3, 4, 5, 6);
|
||||||
set.set_stat(Statistic::SpecialAttack, 20);
|
set.set_stat(Statistic::SpecialAttack, 20);
|
||||||
assert_eq!(set.special_attack(), 4);
|
assert_eq!(set.special_attack(), 4);
|
||||||
set.set_stat(Statistic::SpecialAttack, -10);
|
set.set_stat(Statistic::SpecialAttack, -10);
|
||||||
|
@ -284,7 +382,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_clamped_increase_value() {
|
fn create_clamped_increase_value() {
|
||||||
let mut set = ClampedStatisticSet::<i32, { -2 }, 4>::new(1, 2, 3, 2, 2, 6);
|
let set = ClampedStatisticSet::<AtomicI32, { -2 }, 4>::new(1, 2, 3, 2, 2, 6);
|
||||||
let mut has_changed = set.increase_stat(Statistic::SpecialAttack, 20);
|
let mut has_changed = set.increase_stat(Statistic::SpecialAttack, 20);
|
||||||
assert!(has_changed);
|
assert!(has_changed);
|
||||||
assert_eq!(set.special_attack(), 4);
|
assert_eq!(set.special_attack(), 4);
|
||||||
|
@ -295,7 +393,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_clamped_decrease_value() {
|
fn create_clamped_decrease_value() {
|
||||||
let mut set = ClampedStatisticSet::<i32, { -2 }, 4>::new(1, 2, 3, 2, 2, 6);
|
let set = ClampedStatisticSet::<AtomicI32, { -2 }, 4>::new(1, 2, 3, 2, 2, 6);
|
||||||
let mut has_changed = set.decrease_stat(Statistic::SpecialAttack, 20);
|
let mut has_changed = set.decrease_stat(Statistic::SpecialAttack, 20);
|
||||||
assert!(has_changed);
|
assert!(has_changed);
|
||||||
assert_eq!(set.special_attack(), -2);
|
assert_eq!(set.special_attack(), -2);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use pkmn_lib::dynamic_data::libraries::misc_library::Gen7MiscLibrary;
|
||||||
use pkmn_lib::static_data::{
|
use pkmn_lib::static_data::{
|
||||||
Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item,
|
Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item,
|
||||||
ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary,
|
ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary,
|
||||||
SecondaryEffect, Species, StaticData, Statistic, StatisticSet, TypeLibrary,
|
SecondaryEffect, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary,
|
||||||
};
|
};
|
||||||
use pkmn_lib::StringKey;
|
use pkmn_lib::StringKey;
|
||||||
use project_root::get_project_root;
|
use project_root::get_project_root;
|
||||||
|
@ -301,12 +301,12 @@ fn parse_form(name: StringKey, value: &Value, library: &mut StaticData) -> Form
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_statistics<T>(value: &Value) -> StatisticSet<T>
|
fn parse_statistics<T>(value: &Value) -> StaticStatisticSet<T>
|
||||||
where
|
where
|
||||||
T: PrimInt + TryFrom<u64>,
|
T: PrimInt + TryFrom<u64>,
|
||||||
<T as TryFrom<u64>>::Error: Debug,
|
<T as TryFrom<u64>>::Error: Debug,
|
||||||
{
|
{
|
||||||
StatisticSet::new(
|
StaticStatisticSet::new(
|
||||||
<T as TryFrom<u64>>::try_from(value.get("hp").unwrap_or(&Value::Number(0.into())).as_u64().unwrap()).unwrap(),
|
<T as TryFrom<u64>>::try_from(value.get("hp").unwrap_or(&Value::Number(0.into())).as_u64().unwrap()).unwrap(),
|
||||||
<T as TryFrom<u64>>::try_from(
|
<T as TryFrom<u64>>::try_from(
|
||||||
value
|
value
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl TestStep {
|
||||||
let mut used_move = None;
|
let mut used_move = None;
|
||||||
let pokemon_guard = p.read();
|
let pokemon_guard = p.read();
|
||||||
for learned_move in pokemon_guard.learned_moves().iter().flatten() {
|
for learned_move in pokemon_guard.learned_moves().iter().flatten() {
|
||||||
if learned_move.read().move_data().name() == &StringKey::new(use_move) {
|
if learned_move.move_data().name() == &StringKey::new(use_move) {
|
||||||
used_move = Some(learned_move.clone());
|
used_move = Some(learned_move.clone());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue