PkmnLib_rs/src/dynamic_data/libraries/misc_library.rs

123 lines
3.6 KiB
Rust
Raw Normal View History

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::sync::Arc;
pub trait MiscLibrary<'library> {
fn is_critical(
&self,
battle: &Battle,
executing_move: &ExecutingMove,
target: &Arc<Pokemon>,
hit_number: u8,
) -> bool;
fn can_flee(&self, choice: &SwitchChoice) -> bool;
fn replacement_move<'func>(
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library>;
// TODO: can evolve from level up?
// 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,
struggle_learned_move: Arc<LearnedMove<'library>>,
}
impl<'library> Gen7MiscLibrary<'library> {
pub fn new() -> Self {
let struggle_data = Box::new(MoveData::new(
&StringKey::new("struggle"),
0,
MoveCategory::Physical,
50,
255,
255,
MoveTarget::Any,
0,
SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![]),
HashSet::new(),
));
let struggle_ptr = Box::into_raw(struggle_data);
let struggle_learned_move = Arc::new(LearnedMove::new(unsafe { &*struggle_ptr }, MoveLearnMethod::Unknown));
Self {
struggle_data: struggle_ptr,
struggle_learned_move,
}
}
}
impl<'library> Drop for Gen7MiscLibrary<'library> {
fn drop(&mut self) {
unsafe {
Box::from_raw(self.struggle_data as *mut MoveData);
}
}
}
impl<'library> MiscLibrary<'library> for Gen7MiscLibrary<'library> {
fn is_critical(
&self,
battle: &Battle,
executing_move: &ExecutingMove,
target: &Arc<Pokemon>,
hit_number: u8,
) -> bool {
if executing_move.use_move().category() == MoveCategory::Status {
return false;
}
let mut crit_stage = 0;
script_hook!(
change_critical_stage,
executing_move,
executing_move,
target,
hit_number,
&mut crit_stage
);
// Crit stage is an unsigned byte, so we only care about values of 0 or higher.
// For a critical stage of 3+ we always return true.
match crit_stage {
0 => battle.random().get_max(24) == 0,
1 => battle.random().get_max(8) == 0,
2 => battle.random().get_max(2) == 0,
_ => true,
}
}
fn can_flee(&self, _choice: &SwitchChoice) -> bool {
todo!()
}
fn replacement_move<'func>(
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library> {
TurnChoice::Move(MoveChoice::new(
user.clone(),
self.struggle_learned_move.clone(),
target_side,
target_index,
))
}
}