Documents the ScriptContainer.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
cf4d74d898
commit
25e2a0dda1
|
@ -68,7 +68,7 @@ fn get_all_adjacent_opponent<'b, 'library>(
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets all Pokemon that are adjacent to a Pokemon. This includes the target, the pokemon to the
|
/// 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.
|
/// 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> {
|
fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
|
||||||
let left = index as i32 - 1;
|
let left = index as i32 - 1;
|
||||||
|
@ -132,7 +132,7 @@ pub fn resolve_targets<'b, 'library>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether a given side and index are valid for a given movetarget and user.
|
/// Checks whether a given side and index are valid for a given move target and user.
|
||||||
pub fn is_valid_target(side: u8, index: u8, target: MoveTarget, user: &Pokemon) -> bool {
|
pub fn is_valid_target(side: u8, index: u8, target: MoveTarget, user: &Pokemon) -> bool {
|
||||||
let user_side = user.get_battle_side_index();
|
let user_side = user.get_battle_side_index();
|
||||||
let user_index = user.get_battle_index();
|
let user_index = user.get_battle_index();
|
||||||
|
|
|
@ -5,13 +5,13 @@ use crate::dynamic_data::Pokemon;
|
||||||
use crate::static_data::Statistic;
|
use crate::static_data::Statistic;
|
||||||
use crate::static_data::StatisticSet;
|
use crate::static_data::StatisticSet;
|
||||||
|
|
||||||
/// A battle stat calculator is used to calculate stats for a pokemon.
|
/// A battle stat calculator is used to calculate stats for a Pokemon.
|
||||||
pub trait BattleStatCalculator: Debug {
|
pub trait BattleStatCalculator: Debug {
|
||||||
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
|
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
|
||||||
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>);
|
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>);
|
||||||
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
|
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
|
||||||
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
||||||
/// Calculate all the boosted stats of a pokemon, including stat boosts.
|
/// Calculate all the boosted stats of a Pokemon, including stat boosts.
|
||||||
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>);
|
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<AtomicU32>);
|
||||||
/// Calculate a single boosted stat of a Pokemon, including stat boosts.
|
/// Calculate a single boosted stat of a Pokemon, including stat boosts.
|
||||||
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
||||||
|
|
|
@ -218,7 +218,7 @@ pub trait Script: Send + Sync {
|
||||||
fn on_secondary_effect(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) {}
|
fn on_secondary_effect(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) {}
|
||||||
/// This function triggers on a move or its parents when all hits on a target are finished.
|
/// This function triggers on a move or its parents when all hits on a target are finished.
|
||||||
fn on_after_hits(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) {}
|
fn on_after_hits(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) {}
|
||||||
/// This function prevents the pokemon it is attached to from being able to switch out.
|
/// This function prevents the Pokemon it is attached to from being able to switch out.
|
||||||
fn prevent_self_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
fn prevent_self_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
||||||
/// This function allows the prevention of switching for any opponent.
|
/// This function allows the prevention of switching for any opponent.
|
||||||
fn prevent_opponent_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
fn prevent_opponent_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
||||||
|
@ -253,7 +253,7 @@ pub trait Script: Send + Sync {
|
||||||
/// This function is triggered on a battle and its parents when something attempts to change the
|
/// This function is triggered on a battle and its parents when something attempts to change the
|
||||||
/// weather, and allows for blocking the weather change.
|
/// weather, and allows for blocking the weather change.
|
||||||
fn block_weather(&self, _battle: &Battle, _blocked: &mut bool) {}
|
fn block_weather(&self, _battle: &Battle, _blocked: &mut bool) {}
|
||||||
/// This function is called when a pokeball is thrown at a Pokemon, and allows modifying the catch
|
/// This function is called when a Pokeball is thrown at a Pokemon, and allows modifying the catch
|
||||||
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
||||||
/// example status effects that change capture rates.
|
/// example status effects that change capture rates.
|
||||||
fn change_capture_rate_bonus(&self, _target: &Pokemon, _pokeball: &Item, _modifier: &mut u8) {}
|
fn change_capture_rate_bonus(&self, _target: &Pokemon, _pokeball: &Item, _modifier: &mut u8) {}
|
||||||
|
@ -270,15 +270,32 @@ impl Debug for dyn Script {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A script holder defines the underlying type of how we store individual scripts on a script source.
|
||||||
|
/// The outer [`Arc`] here is so we can take a weak reference to it with dynamic lifetimes, as well as
|
||||||
|
/// copy the value for use during threading.
|
||||||
|
/// The [`RwLock`] is so we cannot modify the internal script while we're reading from it.
|
||||||
|
/// The inner [`Arc`] is the default of Scripts, where there can be multiple owners, and where it can be
|
||||||
|
/// often copied.
|
||||||
type ScriptHolder = Arc<RwLock<Option<Arc<dyn Script>>>>;
|
type ScriptHolder = Arc<RwLock<Option<Arc<dyn Script>>>>;
|
||||||
|
|
||||||
|
/// A script container is used to store a exclusive script. This is for example used for non-volatile
|
||||||
|
/// Pokemon status, weather, ability, etc. It can only hold one script, and that script can be replaced
|
||||||
|
/// if needed.
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct ScriptContainer {
|
pub struct ScriptContainer {
|
||||||
|
/// The actual place where the script is stored.
|
||||||
script: ScriptHolder,
|
script: ScriptHolder,
|
||||||
|
/// The join_handle is a very specific piece of data used in one single specific case; the replacing
|
||||||
|
/// of a script while the script is actively being read from. The RwLock blocks the write, and
|
||||||
|
/// as such, this is delayed to a thread. This join handle is this thread. In some very specific
|
||||||
|
/// cases (mostly test cases), it can be required to make sure that this has been completed before
|
||||||
|
/// continuing.
|
||||||
pub(crate) join_handle: RwLock<Option<JoinHandle<()>>>,
|
pub(crate) join_handle: RwLock<Option<JoinHandle<()>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScriptContainer {
|
impl ScriptContainer {
|
||||||
|
/// Initialize a script container with a specific script. To initialize with an empty script, use
|
||||||
|
/// default() instead.
|
||||||
pub fn new(script: Arc<dyn Script>) -> ScriptContainer {
|
pub fn new(script: Arc<dyn Script>) -> ScriptContainer {
|
||||||
Self {
|
Self {
|
||||||
script: Arc::new(RwLock::new(Some(script))),
|
script: Arc::new(RwLock::new(Some(script))),
|
||||||
|
@ -286,6 +303,7 @@ impl ScriptContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the internal script. Note that this can only be None if the script was marked for deletion.
|
||||||
pub fn get(&self) -> Option<&ScriptHolder> {
|
pub fn get(&self) -> Option<&ScriptHolder> {
|
||||||
if self.script.read().is_some_and(|a| a.is_marked_for_deletion()) {
|
if self.script.read().is_some_and(|a| a.is_marked_for_deletion()) {
|
||||||
if !self.script.is_locked() {
|
if !self.script.is_locked() {
|
||||||
|
@ -297,11 +315,17 @@ impl ScriptContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Changes the internal script. This has several side effects: primarily that it calls the
|
||||||
|
/// [`Script::on_remove`] function on itself. Other special cases are that the script is currently read
|
||||||
|
/// from, and as such can not be replaced yet. In this case, the script will be replaced on a
|
||||||
|
/// separate thread, and be replaced immediately after the script stops being active.
|
||||||
pub fn set(&self, script: Arc<dyn Script>) -> Arc<dyn Script> {
|
pub fn set(&self, script: Arc<dyn Script>) -> Arc<dyn Script> {
|
||||||
if let Some(v) = self.script.read().deref() {
|
if let Some(v) = self.script.read().deref() {
|
||||||
v.on_remove();
|
v.on_remove();
|
||||||
v.mark_for_deletion();
|
v.mark_for_deletion();
|
||||||
}
|
}
|
||||||
|
// If we have a lock on the script, we can't replace it now. Wait until we can get the lock,
|
||||||
|
// and only replace it then. Don't block in the meantime.
|
||||||
if self.script.is_locked() {
|
if self.script.is_locked() {
|
||||||
let holder = self.script.clone();
|
let holder = self.script.clone();
|
||||||
let new = script.clone();
|
let new = script.clone();
|
||||||
|
@ -315,6 +339,9 @@ impl ScriptContainer {
|
||||||
script
|
script
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes the internal script. This calls the [`Script::on_remove`] function on itself. If no
|
||||||
|
/// locks are held to the script, we also immediately set the internal value to None, otherwise
|
||||||
|
/// we just mark it as deleted. If we do this we remove the script later on.
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
if let Some(v) = self.script.read().deref() {
|
if let Some(v) = self.script.read().deref() {
|
||||||
v.on_remove();
|
v.on_remove();
|
||||||
|
@ -325,10 +352,12 @@ impl ScriptContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the underlying reference counter to the script.
|
||||||
pub fn arc(&self) -> &ScriptHolder {
|
pub fn arc(&self) -> &ScriptHolder {
|
||||||
&self.script
|
&self.script
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the underlying script as the downcasted value.
|
||||||
pub fn get_as<T: 'static>(&self) -> MappedRwLockReadGuard<T> {
|
pub fn get_as<T: 'static>(&self) -> MappedRwLockReadGuard<T> {
|
||||||
RwLockReadGuard::map(self.script.read(), |a| unsafe {
|
RwLockReadGuard::map(self.script.read(), |a| unsafe {
|
||||||
let ptr = a.as_ref().as_ref().unwrap().as_ref() as *const dyn Script;
|
let ptr = a.as_ref().as_ref().unwrap().as_ref() as *const dyn Script;
|
||||||
|
|
Loading…
Reference in New Issue