Remove lifetime mess, replace a lot of code with Arc instead of borrows.
Some checks failed
continuous-integration/drone/push Build is failing

This cleans up the codebase massively, and allows me to maintain some semblance of sanity.
This commit is contained in:
2022-08-20 13:17:20 +02:00
parent 2d4253e155
commit 55cc0906c9
34 changed files with 320 additions and 366 deletions

View File

@@ -10,9 +10,9 @@ use crate::dynamic_data::{ScriptSource, ScriptSourceData};
/// The data on a turn choice that should be contained in every turn choice, regardless of type.
#[derive(Debug)]
struct CommonChoiceData<'user, 'library> {
struct CommonChoiceData {
/// The user of the turn choice
user: Arc<Pokemon<'user, 'library>>,
user: Arc<Pokemon>,
/// The speed of the user at the beginning of the turn.
speed: u32,
/// This random value is set at the beginning of the turn. It is used for tie breaking of the
@@ -30,22 +30,22 @@ struct CommonChoiceData<'user, 'library> {
/// This enum defines a single choice for a Pokemon for a battle turn.
#[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub enum TurnChoice<'user, 'library> {
pub enum TurnChoice {
/// A move choice tells a Pokemon to use a move on a target for this turn.
Move(MoveChoice<'user, 'library>),
Move(MoveChoice),
/// An item choice tells a Pokemon to use an item.
Item(ItemChoice<'user, 'library>),
Item(ItemChoice),
/// A switch choice tells a Pokemon to switch with another Pokemon from the party.
Switch(SwitchChoice<'user, 'library>),
Switch(SwitchChoice),
/// A flee choice tells a Pokemon to flee from battle.
Flee(FleeChoice<'user, 'library>),
Flee(FleeChoice),
/// A pass choice tells the user to do nothing that turn.
Pass(PassChoice<'user, 'library>),
Pass(PassChoice),
}
impl<'user, 'library> TurnChoice<'user, 'library> {
impl TurnChoice {
/// The shared choice data between each of the different turn choices.
fn choice_data(&self) -> &CommonChoiceData<'user, 'library> {
fn choice_data(&self) -> &CommonChoiceData {
match self {
TurnChoice::Move(data) => &data.choice_data,
TurnChoice::Item(data) => &data.choice_data,
@@ -55,7 +55,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
}
}
/// The shared choice data between each of the different turn choices.
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData<'user, 'library>> {
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData> {
match self {
TurnChoice::Move(data) => &mut data.choice_data,
TurnChoice::Item(data) => &mut data.choice_data,
@@ -66,7 +66,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
}
/// Get the user of the given choice.
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
pub fn user(&self) -> &Arc<Pokemon> {
&self.choice_data().user
}
@@ -108,7 +108,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
/// Helper function to get the move choice data from a turn. Note that this will panic if not
/// used on a move choice.
pub(crate) fn get_move_turn_data<'b>(&'b self) -> &'b MoveChoice<'user, 'library> {
pub(crate) fn get_move_turn_data(&self) -> &MoveChoice {
if let TurnChoice::Move(data) = self {
return data;
}
@@ -116,7 +116,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
}
}
impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
impl ScriptSource for TurnChoice {
fn get_script_count(&self) -> usize {
match self {
TurnChoice::Move(data) => data.get_script_count(),
@@ -160,9 +160,9 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
/// The data attached to a move choice.
#[derive(Debug)]
pub struct MoveChoice<'user, 'library> {
pub struct MoveChoice {
/// The move that is used for this choice.
used_move: Arc<LearnedMove<'library>>,
used_move: Arc<LearnedMove>,
/// The side this move is aimed at.
target_side: u8,
/// The index of the Pokemon on the side we're aiming at.
@@ -172,17 +172,12 @@ pub struct MoveChoice<'user, 'library> {
/// The priority of the move choice at the beginning of the turn.
priority: i8,
/// The common turn choice data.
choice_data: Box<CommonChoiceData<'user, 'library>>,
choice_data: Box<CommonChoiceData>,
}
impl<'user, 'library> MoveChoice<'user, 'library> {
impl<'user, 'library> MoveChoice {
/// Initializes the data for a new move choice.
pub fn new(
user: Arc<Pokemon<'user, 'library>>,
used_move: Arc<LearnedMove<'library>>,
target_side: u8,
target_index: u8,
) -> Self {
pub fn new(user: Arc<Pokemon>, used_move: Arc<LearnedMove>, target_side: u8, target_index: u8) -> Self {
Self {
used_move,
target_side,
@@ -200,7 +195,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
}
/// The actual learned move on the Pokemon we use for this choice.
pub fn used_move(&self) -> &Arc<LearnedMove<'library>> {
pub fn used_move(&self) -> &Arc<LearnedMove> {
&self.used_move
}
@@ -221,7 +216,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
&mut self.priority
}
/// The user of the choice.
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
pub fn user(&self) -> &Arc<Pokemon> {
&self.choice_data.user
}
/// The move script of the choice.
@@ -230,7 +225,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
}
}
impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> {
impl ScriptSource for MoveChoice {
fn get_script_count(&self) -> usize {
1 + self.choice_data.user.get_script_count()
}
@@ -251,14 +246,14 @@ impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> {
/// The data given when we select an item choice.
#[derive(Debug)]
pub struct ItemChoice<'user, 'library> {
pub struct ItemChoice {
/// The shared data of all turn choices.
choice_data: Box<CommonChoiceData<'user, 'library>>,
choice_data: Box<CommonChoiceData>,
}
impl<'user, 'library> ItemChoice<'user, 'library> {
impl ItemChoice {
/// Initialised a new item choice.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
user,
@@ -271,7 +266,7 @@ impl<'user, 'library> ItemChoice<'user, 'library> {
}
}
impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> {
impl ScriptSource for ItemChoice {
fn get_script_count(&self) -> usize {
0
}
@@ -289,14 +284,14 @@ impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> {
/// The data given when we select a switch choice.
#[derive(Debug)]
pub struct SwitchChoice<'user, 'library> {
pub struct SwitchChoice {
/// The shared data of all turn choices.
choice_data: Box<CommonChoiceData<'user, 'library>>,
choice_data: Box<CommonChoiceData>,
}
impl<'user, 'library> SwitchChoice<'user, 'library> {
impl SwitchChoice {
/// Initialise the turn choice data.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
user,
@@ -309,7 +304,7 @@ impl<'user, 'library> SwitchChoice<'user, 'library> {
}
}
impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> {
impl ScriptSource for SwitchChoice {
fn get_script_count(&self) -> usize {
0
}
@@ -327,14 +322,14 @@ impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> {
/// The data given when we select a flee choice.
#[derive(Debug)]
pub struct FleeChoice<'user, 'library> {
pub struct FleeChoice {
/// The common data all turn choices share.
choice_data: Box<CommonChoiceData<'user, 'library>>,
choice_data: Box<CommonChoiceData>,
}
impl<'user, 'library> FleeChoice<'user, 'library> {
impl FleeChoice {
/// Initialises a new flee choice.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
user,
@@ -347,7 +342,7 @@ impl<'user, 'library> FleeChoice<'user, 'library> {
}
}
impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> {
impl ScriptSource for FleeChoice {
fn get_script_count(&self) -> usize {
0
}
@@ -365,14 +360,14 @@ impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> {
/// The data given when we select a pass choice.
#[derive(Debug)]
pub struct PassChoice<'user, 'library> {
pub struct PassChoice {
/// The common data of all turn choices.
choice_data: Box<CommonChoiceData<'user, 'library>>,
choice_data: Box<CommonChoiceData>,
}
impl<'user, 'library> PassChoice<'user, 'library> {
impl PassChoice {
/// Initialised a new pass choice.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
user,
@@ -385,7 +380,7 @@ impl<'user, 'library> PassChoice<'user, 'library> {
}
}
impl<'user, 'library> ScriptSource<'user> for PassChoice<'user, 'library> {
impl ScriptSource for PassChoice {
fn get_script_count(&self) -> usize {
0
}
@@ -401,21 +396,21 @@ impl<'user, 'library> ScriptSource<'user> for PassChoice<'user, 'library> {
}
}
impl<'user, 'library> PartialEq<Self> for TurnChoice<'user, 'library> {
impl PartialEq<Self> for TurnChoice {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other)
}
}
impl<'user, 'library> Eq for TurnChoice<'user, 'library> {}
impl Eq for TurnChoice {}
impl<'user, 'library> PartialOrd for TurnChoice<'user, 'library> {
impl PartialOrd for TurnChoice {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<'user, 'library> Ord for TurnChoice<'user, 'library> {
impl Ord for TurnChoice {
fn cmp(&self, other: &Self) -> Ordering {
match self {
TurnChoice::Move(data) => {

View File

@@ -1,4 +1,5 @@
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use crate::dynamic_data::DamageSource;
use crate::dynamic_data::ExecutingMove;
@@ -27,7 +28,7 @@ impl<'battle, 'library> EventHook {
/// Run a new event. This will send the event to all externally defined event listeners. It will
/// dispose of the event afterwards.
pub fn trigger<'b>(&self, evt: Event<'b, 'battle, 'library>) {
pub fn trigger(&self, evt: Event) {
let b = Box::new(&evt);
for f in &self.evt_hook_function {
f(&b);
@@ -43,7 +44,7 @@ impl Debug for EventHook {
/// The different events that can occur during the battle, for which a GUI should show something.
#[derive(Debug)]
pub enum Event<'own, 'battle, 'library> {
pub enum Event<'own> {
/// A switch event happens when a Pokemon gets switched out for something else.
Switch {
/// The side the Pokemon got switched from/on
@@ -51,7 +52,7 @@ pub enum Event<'own, 'battle, 'library> {
/// The index of the Pokemon that got switched in/out on its side
index: u8,
/// The new Pokemon that will be on the spot. If none, the spot will now be empty.
pokemon: Option<&'own Pokemon<'battle, 'library>>,
pokemon: Option<&'own Pokemon>,
},
/// A swap event happens when two Pokemon on a side swap positions. Note that this is rare.
Swap {
@@ -67,23 +68,23 @@ pub enum Event<'own, 'battle, 'library> {
/// enjoy.
SpeciesChange {
/// The pokemon that changed species.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The new species of the Pokemon.
species: &'own Species,
species: Arc<Species>,
/// The form of the species the Pokemon will have.
form: &'own Form,
form: Arc<Form>,
},
/// This event happens when a Pokemon changes form during battle. This is rather common.
FormChange {
/// The pokemon that changed forms.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The new form of the Pokemon.
form: &'own Form,
},
/// This event happens when a Pokemon takes damage.
Damage {
/// The Pokemon that takes damage.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The source of damage.
source: DamageSource,
/// The health of the Pokemon before the damage.
@@ -94,7 +95,7 @@ pub enum Event<'own, 'battle, 'library> {
/// This event happens when a Pokemon gets healed
Heal {
/// The Pokemon that gets healed.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The health of the Pokemon before the heal.
original_health: u32,
/// The health of the Pokemon after the heal.
@@ -103,24 +104,24 @@ pub enum Event<'own, 'battle, 'library> {
/// This event happens when a Pokemon faints.
Faint {
/// The pokemon that has fainted.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
},
/// This event happens when a Pokemon uses a move on a target, just before any hits.
MoveUse {
/// The data of the move used.
executing_move: &'own ExecutingMove<'own, 'battle, 'library>,
executing_move: &'own ExecutingMove,
},
/// This event happens when a Pokemon missed.
Miss {
/// The pokemon that missed.
user: &'own Pokemon<'battle, 'library>,
user: &'own Pokemon,
},
/// The turn is finished running, waiting for new input.
EndTurn,
/// A pokemon had its stat boost changed
StatBoostChange {
/// The pokemon that had its stat boosts changed.
user: &'own Pokemon<'battle, 'library>,
user: &'own Pokemon,
/// The statistic that changed.
stat: Statistic,
/// The value of the stat before the change.

View File

@@ -8,31 +8,31 @@ use crate::dynamic_data::Pokemon;
/// helper functions to change the turn order while doing the execution. This is needed, as several
/// moves in Pokemon actively mess with this order.
#[derive(Debug)]
pub struct ChoiceQueue<'battle, 'library> {
pub struct ChoiceQueue {
/// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get
/// executed.
queue: Vec<Option<TurnChoice<'battle, 'library>>>,
queue: Vec<Option<TurnChoice>>,
/// The current index of the turn we need to execute next.
current: usize,
}
impl<'battle, 'library> ChoiceQueue<'battle, 'library> {
impl ChoiceQueue {
/// Initializes a ChoiceQueue. We expect the given queue to already be sorted here.
pub(crate) fn new(queue: Vec<Option<TurnChoice<'battle, 'library>>>) -> Self {
pub(crate) fn new(queue: Vec<Option<TurnChoice>>) -> Self {
Self { queue, current: 0 }
}
/// Dequeues the next turn choice to be executed. This gives ownership to the callee, and replaces
/// our own reference to the turn choice with an empty spot. It also increments the current position
/// by one.
pub fn dequeue<'b>(&'b mut self) -> TurnChoice<'battle, 'library> {
pub fn dequeue<'b>(&'b mut self) -> TurnChoice {
let c = self.queue[self.current].take();
self.current += 1;
c.unwrap()
}
/// This reads what the next choice to execute will be, without modifying state.
pub fn peek(&self) -> &'battle TurnChoice {
pub fn peek(&self) -> &TurnChoice {
self.queue[self.current].as_ref().unwrap()
}
@@ -55,7 +55,7 @@ impl<'battle, 'library> ChoiceQueue<'battle, 'library> {
}
/// Internal helper function to be easily able to iterate over the yet to be executed choices.
pub(crate) fn get_queue(&self) -> &[Option<TurnChoice<'battle, 'library>>] {
pub(crate) fn get_queue(&self) -> &[Option<TurnChoice>] {
&self.queue[self.current..self.queue.len()]
}
}

View File

@@ -8,10 +8,10 @@ use crate::dynamic_data::Pokemon;
use crate::static_data::MoveTarget;
/// Helper type for the vector of targets we will return.
pub type TargetList<'own, 'library> = Vec<Option<Arc<Pokemon<'own, 'library>>>>;
pub type TargetList = Vec<Option<Arc<Pokemon>>>;
/// This returns all Pokemon in the battle.
fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> {
fn get_all_targets<'b, 'library>(battle: &Battle) -> TargetList {
let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize);
for side in battle.sides() {
for pokemon in side.pokemon().deref() {
@@ -31,11 +31,7 @@ fn get_opposite_side(side: u8) -> u8 {
/// Gets all Pokemon that are adjacent to of directly opposite of a Pokemon. This means the target,
/// the Pokemon left of it, the Pokemon right of it, and the Pokemon opposite of it.
fn get_all_adjacent_opponent<'b, 'library>(
side: u8,
index: u8,
battle: &Battle<'b, 'library>,
) -> TargetList<'b, 'library> {
fn get_all_adjacent_opponent<'b, 'library>(side: u8, index: u8, battle: &Battle) -> TargetList {
let left = index as i32 - 1;
let right = index + 1;
if left < 0 && right >= battle.pokemon_per_side() {
@@ -80,7 +76,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
/// 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) -> TargetList {
let left = index as i32 - 1;
let right = index + 1;
if left < 0 && right >= battle.pokemon_per_side() {
@@ -106,12 +102,7 @@ fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'libr
}
/// Gets the target for a specific move target type, given the targeted position.
pub fn resolve_targets<'b, 'library>(
side: u8,
index: u8,
target: MoveTarget,
battle: &Battle<'b, 'library>,
) -> TargetList<'b, 'library> {
pub fn resolve_targets<'b, 'library>(side: u8, index: u8, target: MoveTarget, battle: &Battle) -> TargetList {
match target {
// These all resolve to a single position. We let the client deal with where the target is,
// and just return the Pokemon at that given target here.

View File

@@ -12,7 +12,7 @@ use crate::dynamic_data::Pokemon;
use crate::static_data::{DataLibrary, MoveCategory};
use crate::{run_scripts, script_hook, PkmnResult};
impl<'own, 'library> Battle<'own, 'library> {
impl Battle {
/// Execute the entire turn after the choices are all set.
pub(crate) fn run_turn(&self) -> PkmnResult<()> {
let choice_queue = self.current_turn_queue();
@@ -62,7 +62,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// Executes a single choice.
fn execute_choice(&self, choice: &TurnChoice<'own, 'library>) -> PkmnResult<()> {
fn execute_choice(&self, choice: &TurnChoice) -> PkmnResult<()> {
// A pass turn choice means the user does not intend to do anything. As such, return.
if let TurnChoice::Pass(..) = choice {
return Ok(());
@@ -91,7 +91,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// Executes a move choice.
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice<'own, 'library>) -> PkmnResult<()> {
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice) -> PkmnResult<()> {
let choice = choice.get_move_turn_data();
let used_move = choice.used_move();
let move_data = {
@@ -111,11 +111,11 @@ impl<'own, 'library> Battle<'own, 'library> {
return Ok(());
}
let mut executing_move = ExecutingMove::new(
&targets,
targets.clone(),
number_of_hits,
choice.user().clone(),
used_move.clone(),
move_data,
move_data.clone(),
choice.script().clone(),
);
let mut prevented = false;
@@ -148,11 +148,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// Executes a move turn choice on a single target.
fn handle_move_for_target(
&self,
executing_move: &mut ExecutingMove<'_, 'own, 'library>,
target: &Arc<Pokemon<'own, 'library>>,
) -> PkmnResult<()> {
fn handle_move_for_target(&self, executing_move: &mut ExecutingMove, target: &Arc<Pokemon>) -> PkmnResult<()> {
{
let mut fail = false;
script_hook!(fail_incoming_move, target, executing_move, target, &mut fail);

View File

@@ -25,7 +25,7 @@ pub struct DynamicLibrary {
damage_calculator: Box<dyn DamageLibrary>,
/// The Misc Library holds minor functions that do not fall in any of the other libraries and
/// calculators.
misc_library: Box<dyn MiscLibrary<'static>>,
misc_library: Box<dyn MiscLibrary>,
/// The script resolver deals with how to resolve the scripts from specific unique key combinations.
script_resolver: Box<dyn ScriptResolver>,
@@ -40,7 +40,7 @@ impl DynamicLibrary {
static_data: StaticData,
stat_calculator: Box<dyn BattleStatCalculator>,
damage_calculator: Box<dyn DamageLibrary>,
misc_library: Box<dyn MiscLibrary<'static>>,
misc_library: Box<dyn MiscLibrary>,
script_resolver: Box<dyn ScriptResolver>,
) -> Self {
Self {
@@ -67,7 +67,7 @@ impl DynamicLibrary {
}
/// The Misc Library holds minor functions that do not fall in any of the other libraries and
/// calculators.
pub fn misc_library(&self) -> &dyn MiscLibrary<'static> {
pub fn misc_library(&self) -> &dyn MiscLibrary {
self.misc_library.deref()
}
@@ -84,7 +84,7 @@ impl DynamicLibrary {
/// Loads an item script with the given unique key. If no script can be created with this
/// combinations, returns None. Note that ItemScripts are immutable, as their script should be
/// shared between all different usages.
pub fn load_item_script(&self, _key: &Item) -> PkmnResult<Option<Arc<dyn ItemScript>>> {
pub fn load_item_script(&self, _key: &Arc<Item>) -> PkmnResult<Option<Arc<dyn ItemScript>>> {
todo!()
}
}

View File

@@ -10,35 +10,26 @@ use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
use crate::StringKey;
/// The misc library holds several misc functions required for the battle to run.
pub trait MiscLibrary<'library>: Debug {
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.
fn replacement_move<'func>(
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library>;
fn replacement_move<'func>(&'func self, user: &Arc<Pokemon>, target_side: u8, target_index: u8) -> TurnChoice;
// TODO: can evolve from level up?
// TODO: get time
}
/// A gen 7 implementation for the MiscLibrary.
#[derive(Debug)]
pub struct Gen7MiscLibrary<'library> {
/// The move data for struggle. This is a pointer due to lifetime issues; we know that the
/// learned move based on this has the same lifetime as the move data, but the compiler does not.
/// If possible in a sane manner, we should get rid of this pointer.
struggle_data: *const MoveData,
pub struct Gen7MiscLibrary {
/// The learned move data for struggle.
struggle_learned_move: Arc<LearnedMove<'library>>,
struggle_learned_move: Arc<LearnedMove>,
}
impl<'library> Gen7MiscLibrary<'library> {
impl Gen7MiscLibrary {
/// Instantiates a new MiscLibrary.
pub fn new() -> Self {
let struggle_data = Box::new(MoveData::new(
let struggle_data = Arc::new(MoveData::new(
&StringKey::new("struggle"),
0.into(),
MoveCategory::Physical,
@@ -50,40 +41,23 @@ impl<'library> Gen7MiscLibrary<'library> {
Some(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,
}
let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data.clone(), MoveLearnMethod::Unknown));
Self { struggle_learned_move }
}
}
impl<'library> Default for Gen7MiscLibrary<'library> {
impl Default for Gen7MiscLibrary {
fn default() -> Self {
Self::new()
}
}
impl<'library> Drop for Gen7MiscLibrary<'library> {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.struggle_data as *mut MoveData);
}
}
}
impl<'library> MiscLibrary<'library> for Gen7MiscLibrary<'library> {
impl MiscLibrary for Gen7MiscLibrary {
fn can_flee(&self, _choice: &TurnChoice) -> bool {
todo!()
}
fn replacement_move<'func>(
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library> {
fn replacement_move<'func>(&'func self, user: &Arc<Pokemon>, target_side: u8, target_index: u8) -> TurnChoice {
self.struggle_learned_move.restore_all_uses();
TurnChoice::Move(MoveChoice::new(
user.clone(),

View File

@@ -22,11 +22,11 @@ use crate::{script_hook, PkmnResult, StringKey};
/// A pokemon battle, with any amount of sides and pokemon per side.
#[derive(Debug)]
pub struct Battle<'own, 'library> {
pub struct Battle {
/// The library the battle uses for handling.
library: &'own DynamicLibrary,
library: Arc<DynamicLibrary>,
/// A list of all different parties in the battle.
parties: Vec<BattleParty<'own, 'library>>,
parties: Vec<BattleParty>,
/// Whether or not Pokemon can flee from the battle.
can_flee: bool,
/// The number of sides in the battle. Typically 2.
@@ -34,11 +34,11 @@ pub struct Battle<'own, 'library> {
/// The number of Pokemon that can be on each side.
pokemon_per_side: u8,
/// A list of all sides in the battle.
sides: Vec<BattleSide<'own, 'library>>,
sides: Vec<BattleSide>,
/// The RNG used for the battle.
random: BattleRandom,
/// A queue of the yet to be executed choices in a turn.
current_turn_queue: RwLock<Option<ChoiceQueue<'own, 'library>>>,
current_turn_queue: RwLock<Option<ChoiceQueue>>,
/// Whether or not the battle has ended.
has_ended: AtomicBool,
/// The eventual result of the battle. Inconclusive until the battle is ended.
@@ -55,11 +55,11 @@ pub struct Battle<'own, 'library> {
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'library> Battle<'own, 'library> {
impl<'own, 'library> Battle {
/// Initializes a new battle.
pub fn new(
library: &'own DynamicLibrary,
parties: Vec<BattleParty<'own, 'library>>,
library: Arc<DynamicLibrary>,
parties: Vec<BattleParty>,
can_flee: bool,
number_of_sides: u8,
pokemon_per_side: u8,
@@ -104,11 +104,11 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// The library the battle uses for handling.
pub fn library(&self) -> &'own DynamicLibrary {
self.library
pub fn library(&self) -> &Arc<DynamicLibrary> {
&self.library
}
/// A list of all different parties in the battle.
pub fn parties(&self) -> &Vec<BattleParty<'own, 'library>> {
pub fn parties(&self) -> &Vec<BattleParty> {
&self.parties
}
/// Whether or not Pokemon can flee from the battle.
@@ -124,11 +124,11 @@ impl<'own, 'library> Battle<'own, 'library> {
self.pokemon_per_side
}
/// A list of all sides in the battle.
pub fn sides(&self) -> &Vec<BattleSide<'own, 'library>> {
pub fn sides(&self) -> &Vec<BattleSide> {
&self.sides
}
/// A mutable list of all sides in the battle.
pub fn sides_mut(&mut self) -> &mut Vec<BattleSide<'own, 'library>> {
pub fn sides_mut(&mut self) -> &mut Vec<BattleSide> {
&mut self.sides
}
/// The RNG used for the battle.
@@ -156,12 +156,12 @@ impl<'own, 'library> Battle<'own, 'library> {
self.last_turn_time.load(Ordering::Relaxed)
}
/// A queue of the yet to be executed choices in a turn.
pub fn current_turn_queue(&self) -> &RwLock<Option<ChoiceQueue<'own, 'library>>> {
pub fn current_turn_queue(&self) -> &RwLock<Option<ChoiceQueue>> {
&self.current_turn_queue
}
/// Get a Pokemon on the battlefield, on a specific side and an index on that side.
pub fn get_pokemon(&self, side: u8, index: u8) -> Option<Arc<Pokemon<'own, 'library>>> {
pub fn get_pokemon(&self, side: u8, index: u8) -> Option<Arc<Pokemon>> {
let side = self.sides.get(side as usize);
side?;
let pokemon_read_lock = side.unwrap().pokemon();
@@ -254,7 +254,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// Try and set the choice for the battle. If the choice is not valid, this returns false.
pub fn try_set_choice(&mut self, choice: TurnChoice<'own, 'library>) -> PkmnResult<bool> {
pub fn try_set_choice(&mut self, choice: TurnChoice) -> PkmnResult<bool> {
if !self.can_use(&choice) {
return Ok(false);
}
@@ -332,7 +332,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
}
impl<'own, 'library> VolatileScriptsOwner<'own> for Battle<'own, 'library> {
impl VolatileScriptsOwner for Battle {
fn volatile_scripts(&self) -> &Arc<ScriptSet> {
&self.volatile_scripts
}
@@ -343,7 +343,7 @@ impl<'own, 'library> VolatileScriptsOwner<'own> for Battle<'own, 'library> {
}
}
impl<'own, 'library> ScriptSource<'own> for Battle<'own, 'library> {
impl ScriptSource for Battle {
fn get_script_count(&self) -> usize {
1
}

View File

@@ -6,17 +6,17 @@ use crate::dynamic_data::models::pokemon_party::PokemonParty;
/// 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<'own, 'library> {
pub struct BattleParty {
/// The party the BattleParty is holding.
party: Arc<PokemonParty<'own, 'library>>,
party: Arc<PokemonParty>,
/// The indices for which the party is responsible, in the format (side, index)
responsible_indices: Vec<(u8, u8)>,
}
impl<'own, 'library> BattleParty<'own, 'library> {
impl BattleParty {
/// Initializes a battle party with the underlying party, and the indices the party is responsible
/// for.
pub fn new(party: Arc<PokemonParty<'own, 'library>>, responsible_indices: Vec<(u8, u8)>) -> Self {
pub fn new(party: Arc<PokemonParty>, responsible_indices: Vec<(u8, u8)>) -> Self {
Self {
party,
responsible_indices,
@@ -44,7 +44,7 @@ impl<'own, 'library> BattleParty<'own, 'library> {
}
/// Gets a Pokemon at an index.
pub fn get_pokemon(&self, index: usize) -> &Option<Arc<Pokemon<'own, 'library>>> {
pub fn get_pokemon(&self, index: usize) -> &Option<Arc<Pokemon>> {
self.party.at(index)
}
}

View File

@@ -18,22 +18,22 @@ use crate::{script_hook, PkmnResult, StringKey};
/// A side on a battle.
#[derive(Debug)]
pub struct BattleSide<'own, 'library> {
pub struct BattleSide {
/// The index of the side on the battle.
index: u8,
/// The number of Pokemon that can be on the side.
pokemon_per_side: u8,
/// A list of pokemon currently on the battlefield.
pokemon: RwLock<Vec<Option<Arc<Pokemon<'own, 'library>>>>>,
pokemon: RwLock<Vec<Option<Arc<Pokemon>>>>,
/// The currently set choices for all Pokemon on the battlefield. Cleared when the turn starts.
choices: RwLock<Vec<Option<TurnChoice<'own, 'library>>>>,
choices: RwLock<Vec<Option<TurnChoice>>>,
/// The slots on the side that can still be filled. Once all slots are set to false, this side
/// has lost the battle.
fillable_slots: Vec<AtomicBool>,
/// The number of choices that are set.
choices_set: AtomicU8,
/// A reference to the battle we're part of.
battle: *mut Battle<'own, 'library>,
battle: *mut Battle,
/// Whether or not this side has fled.
has_fled_battle: bool,
/// The volatile scripts that are attached to the side.
@@ -43,7 +43,7 @@ pub struct BattleSide<'own, 'library> {
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'library> BattleSide<'own, 'library> {
impl<'own, 'library> BattleSide {
/// Instantiates a battle side.
pub fn new(index: u8, pokemon_per_side: u8) -> Self {
let mut pokemon = Vec::with_capacity(pokemon_per_side as usize);
@@ -73,7 +73,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
/// Set the battle this side belongs to.
pub(crate) fn set_battle(&mut self, battle: *mut Battle<'own, 'library>) {
pub(crate) fn set_battle(&mut self, battle: *mut Battle) {
self.battle = battle;
}
@@ -86,11 +86,11 @@ impl<'own, 'library> BattleSide<'own, 'library> {
self.pokemon_per_side
}
/// A list of pokemon currently on the battlefield.
pub fn pokemon(&self) -> RwLockReadGuard<'_, RawRwLock, Vec<Option<Arc<Pokemon<'own, 'library>>>>> {
pub fn pokemon(&self) -> RwLockReadGuard<'_, RawRwLock, Vec<Option<Arc<Pokemon>>>> {
self.pokemon.read()
}
/// The currently set choices for all Pokemon on the battlefield. Cleared when the turn starts.
pub fn choices(&self) -> &RwLock<Vec<Option<TurnChoice<'own, 'library>>>> {
pub fn choices(&self) -> &RwLock<Vec<Option<TurnChoice>>> {
&self.choices
}
/// The slots on the side that can still be filled. Once all slots are set to false, this side
@@ -103,7 +103,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
self.choices_set.load(Ordering::SeqCst)
}
/// A reference to the battle we're part of.
pub fn battle(&self) -> &Battle<'own, 'library> {
pub fn battle(&self) -> &Battle {
unsafe { self.battle.as_ref().unwrap() }
}
/// Whether or not this side has fled.
@@ -135,7 +135,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
/// Sets a choice for a Pokemon on this side.
pub(crate) fn set_choice(&self, choice: TurnChoice<'own, 'library>) {
pub(crate) fn set_choice(&self, choice: TurnChoice) {
for (index, pokemon_slot) in self.pokemon.read().iter().enumerate() {
if let Some(pokemon) = pokemon_slot {
if std::ptr::eq(pokemon.deref(), choice.user().deref()) {
@@ -161,7 +161,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
/// Switches out a spot on the field for a different Pokemon.
pub fn set_pokemon(&self, index: u8, pokemon: Option<Arc<Pokemon<'own, 'library>>>) {
pub fn set_pokemon(&self, index: u8, pokemon: Option<Arc<Pokemon>>) {
{
let old = &self.pokemon.read()[index as usize];
if let Some(old_pokemon) = old {
@@ -202,7 +202,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
/// Checks whether a Pokemon is on the field in this side.
pub fn is_pokemon_on_side(&self, pokemon: Arc<Pokemon<'own, 'library>>) -> bool {
pub fn is_pokemon_on_side(&self, pokemon: Arc<Pokemon>) -> bool {
for p in self.pokemon.read().iter().flatten() {
if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
return true;
@@ -218,7 +218,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
/// Checks whether a slot is unfillable or not.
pub fn is_slot_unfillable(&self, pokemon: Arc<Pokemon<'own, 'library>>) -> bool {
pub fn is_slot_unfillable(&self, pokemon: Arc<Pokemon>) -> bool {
for (i, slot) in self.pokemon.read().iter().enumerate() {
if let Some(p) = slot {
if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
@@ -296,7 +296,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
}
impl<'own, 'library> VolatileScriptsOwner<'own> for BattleSide<'own, 'library> {
impl VolatileScriptsOwner for BattleSide {
fn volatile_scripts(&self) -> &Arc<ScriptSet> {
&self.volatile_scripts
}
@@ -308,7 +308,7 @@ impl<'own, 'library> VolatileScriptsOwner<'own> for BattleSide<'own, 'library> {
}
}
impl<'own, 'library> ScriptSource<'own> for BattleSide<'own, 'library> {
impl ScriptSource for BattleSide {
fn get_script_count(&self) -> usize {
self.battle().get_script_count() + 1
}

View File

@@ -84,34 +84,34 @@ impl HitData {
/// An executing move is the data of the move for while it is executing.
#[derive(Debug)]
pub struct ExecutingMove<'own, 'battle, 'library> {
pub struct ExecutingMove {
/// 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,
/// for example: (target1, hit1), (target1, hit2), (target2, hit1), (target2, hit2), etc.
hits: Vec<HitData>,
/// The user of the move.
user: Arc<Pokemon<'battle, 'library>>,
user: Arc<Pokemon>,
/// The move the user has actually chosen to do.
chosen_move: Arc<LearnedMove<'library>>,
chosen_move: Arc<LearnedMove>,
/// The move that the user is actually going to do.
use_move: &'own MoveData,
use_move: Arc<MoveData>,
/// The script of the move.
script: ScriptContainer,
/// The targets for this move.
targets: &'own TargetList<'battle, 'library>,
targets: TargetList,
/// Data required for this to be a script source.
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
impl ExecutingMove {
/// Instantiates an executing move.
pub fn new(
targets: &'own TargetList<'battle, 'library>,
targets: TargetList,
number_of_hits: u8,
user: Arc<Pokemon<'battle, 'library>>,
chosen_move: Arc<LearnedMove<'library>>,
use_move: &'own MoveData,
user: Arc<Pokemon>,
chosen_move: Arc<LearnedMove>,
use_move: Arc<MoveData>,
script: ScriptContainer,
) -> Self {
let total_hits = number_of_hits as usize * targets.len();
@@ -140,16 +140,16 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
self.number_of_hits
}
/// The user of the move.
pub fn user(&self) -> &Arc<Pokemon<'battle, 'library>> {
pub fn user(&self) -> &Arc<Pokemon> {
&self.user
}
/// The move the user has actually chosen to do.
pub fn chosen_move(&self) -> &Arc<LearnedMove<'library>> {
pub fn chosen_move(&self) -> &Arc<LearnedMove> {
&self.chosen_move
}
/// The move that the user is actually going to do.
pub fn use_move(&self) -> &'own MoveData {
self.use_move
pub fn use_move(&self) -> &Arc<MoveData> {
&self.use_move
}
/// The script of the move.
pub fn script(&self) -> &ScriptContainer {
@@ -157,11 +157,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
}
/// Gets a hit data for a target, with a specific index.
pub fn get_hit_data<'func>(
&'func self,
for_target: &'func Arc<Pokemon<'battle, 'library>>,
hit: u8,
) -> PkmnResult<&'func HitData> {
pub fn get_hit_data<'func>(&'func self, for_target: &'func Arc<Pokemon>, hit: u8) -> PkmnResult<&'func HitData> {
for (index, target) in self.targets.iter().enumerate() {
if let Some(target) = target {
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
@@ -174,7 +170,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
}
/// Checks whether a Pokemon is a target for this move.
pub fn is_pokemon_target(&self, pokemon: &Arc<Pokemon<'battle, 'library>>) -> bool {
pub fn is_pokemon_target(&self, pokemon: &Arc<Pokemon>) -> bool {
for target in self.targets.iter().flatten() {
if std::ptr::eq(target.deref().deref(), pokemon.deref().deref()) {
return true;
@@ -184,7 +180,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
}
/// Gets the index of the hits in this move where the hits for a specific target start.
pub(crate) fn get_index_of_target(&self, for_target: &Arc<Pokemon<'battle, 'library>>) -> PkmnResult<usize> {
pub(crate) fn get_index_of_target(&self, for_target: &Arc<Pokemon>) -> PkmnResult<usize> {
for (index, target) in self.targets.iter().enumerate() {
if let Some(target) = target {
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
@@ -202,7 +198,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
}
}
impl<'own, 'battle, 'library> ScriptSource<'own> for ExecutingMove<'own, 'battle, 'library> {
impl ScriptSource for ExecutingMove {
fn get_script_count(&self) -> usize {
1
}

View File

@@ -1,4 +1,5 @@
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
use crate::static_data::MoveData;
@@ -6,9 +7,9 @@ use crate::static_data::MoveData;
/// such as the remaining amount of users, how it has been learned, etc.
#[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct LearnedMove<'library> {
pub struct LearnedMove {
/// The immutable move information of the move.
move_data: &'library MoveData,
move_data: Arc<MoveData>,
/// The maximal power points for this move.
max_pp: u8,
/// The amount of remaining power points. If this is 0, we can not use the move anymore.
@@ -28,11 +29,11 @@ pub enum MoveLearnMethod {
Level = 1,
}
impl<'a> LearnedMove<'a> {
impl LearnedMove {
/// Instantiate a new learned move.
pub fn new(move_data: &'a MoveData, learn_method: MoveLearnMethod) -> Self {
pub fn new(move_data: &Arc<MoveData>, learn_method: MoveLearnMethod) -> Self {
Self {
move_data,
move_data: move_data.clone(),
max_pp: move_data.base_usages(),
remaining_pp: AtomicU8::new(move_data.base_usages()),
learn_method,
@@ -40,8 +41,8 @@ impl<'a> LearnedMove<'a> {
}
/// The immutable move information of the move.
pub fn move_data(&self) -> &MoveData {
self.move_data
pub fn move_data(&self) -> &Arc<MoveData> {
&self.move_data
}
/// The maximal power points for this move.
pub fn max_pp(&self) -> u8 {

View File

@@ -26,23 +26,20 @@ use crate::{script_hook, PkmnResult, StringKey};
/// An individual Pokemon as we know and love them.
#[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct Pokemon<'own, 'library>
where
'own: 'library,
{
pub struct Pokemon {
/// The library data of the Pokemon.
library: &'own DynamicLibrary,
library: Arc<DynamicLibrary>,
/// The species of the Pokemon.
species: &'own Species,
species: Arc<Species>,
/// The form of the Pokemon.
form: &'own Form,
form: Arc<Form>,
/// An optional display species of the Pokemon. If this is set, the client should display this
/// species. An example of usage for this is the Illusion ability.
display_species: Option<&'own Species>,
display_species: Option<Arc<Species>>,
/// An optional display form of the Pokemon. If this is set, the client should display this
// species. An example of usage for this is the Illusion ability.
display_form: Option<&'own Form>,
display_form: Option<Arc<Form>>,
/// The current level of the Pokemon.
level: LevelInt,
@@ -57,7 +54,7 @@ where
/// currently not used, and can be used for other implementations.
coloring: u8,
/// The held item of the Pokemon.
held_item: RwLock<Option<&'own Item>>,
held_item: RwLock<Option<Arc<Item>>>,
/// The remaining health points of the Pokemon.
current_health: AtomicU32,
@@ -78,7 +75,7 @@ where
/// The [effort values](https://bulbapedia.bulbagarden.net/wiki/Effort_values) of the Pokemon.
effort_values: ClampedStatisticSet<u8, 0, 252>,
/// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon.
nature: &'own Nature,
nature: Arc<Nature>,
/// An optional nickname of the Pokemon.
nickname: Option<String>,
@@ -90,11 +87,11 @@ where
override_ability: Option<Ability>,
/// If in battle, we have additional data.
battle_data: RwLock<Option<PokemonBattleData<'own, 'library>>>,
battle_data: RwLock<Option<PokemonBattleData>>,
/// The moves the Pokemon has learned. This is of a set length of [`MAX_MOVES`]. Empty move slots
/// are defined by None.
moves: RwLock<[Option<Arc<LearnedMove<'library>>>; MAX_MOVES]>,
moves: RwLock<[Option<Arc<LearnedMove>>; MAX_MOVES]>,
/// Whether or not the Pokemon is allowed to gain experience.
allowed_experience: bool,
@@ -118,12 +115,12 @@ where
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'library> Pokemon<'own, 'library> {
impl Pokemon {
/// Instantiates a new Pokemon.
pub fn new(
library: &'own DynamicLibrary,
species: &'own Species,
form: &'own Form,
library: Arc<DynamicLibrary>,
species: Arc<Species>,
form: &Arc<Form>,
ability: AbilityIndex,
level: LevelInt,
unique_identifier: u32,
@@ -142,11 +139,12 @@ impl<'own, 'library> Pokemon<'own, 'library> {
.static_data()
.natures()
.get_nature(nature)
.unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature));
.unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature))
.clone();
let mut pokemon = Self {
library,
species,
form,
form: form.clone(),
display_species: None,
display_form: None,
level,
@@ -187,31 +185,31 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// The library data of the Pokemon.
pub fn library(&self) -> &'own DynamicLibrary {
self.library
pub fn library(&self) -> &Arc<DynamicLibrary> {
&self.library
}
/// The species of the Pokemon.
pub fn species(&self) -> &'own Species {
self.species
pub fn species(&self) -> &Arc<Species> {
&self.species
}
/// The form of the Pokemon.
pub fn form(&self) -> &'own Form {
self.form
pub fn form(&self) -> &Arc<Form> {
&self.form
}
/// The species that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_species(&self) -> &'own Species {
if let Some(v) = self.display_species {
pub fn display_species(&self) -> &Arc<Species> {
if let Some(v) = &self.display_species {
v
} else {
self.species
&self.species
}
}
/// The form that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_form(&self) -> &'own Form {
if let Some(v) = self.display_form {
pub fn display_form(&self) -> &Arc<Form> {
if let Some(v) = &self.display_form {
v
} else {
self.form
&self.form
}
}
/// The current level of the Pokemon.
@@ -235,8 +233,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
pub fn coloring(&self) -> u8 {
self.coloring
}
/// Checks whether the Pokemon is holding an item,
pub fn held_item(&self) -> &RwLock<Option<&'own Item>> {
/// Gets the held item of a Pokemon
pub fn held_item(&self) -> &RwLock<Option<Arc<Item>>> {
&self.held_item
}
/// Checks whether the Pokemon is holding a specific item.
@@ -248,11 +246,11 @@ impl<'own, 'library> Pokemon<'own, 'library> {
false
}
/// Changes the held item of the Pokemon/
pub fn set_held_item(&self, item: &'own Item) -> Option<&'own Item> {
self.held_item.write().replace(item)
pub fn set_held_item(&self, item: &Arc<Item>) -> Option<Arc<Item>> {
self.held_item.write().replace(item.clone())
}
/// Removes the held item from the Pokemon.
pub fn remove_held_item(&self) -> Option<&'own Item> {
pub fn remove_held_item(&self) -> Option<Arc<Item>> {
self.held_item.write().take()
}
/// Makes the Pokemon uses its held item.
@@ -260,7 +258,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
if self.held_item.read().is_none() {
return false;
}
let script = self.library.load_item_script(self.held_item.read().unwrap()).unwrap();
let script = self
.library
.load_item_script(&self.held_item.read().as_ref().unwrap())
.unwrap();
if script.is_none() {
return false;
}
@@ -299,7 +300,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// The moves the Pokemon has learned. This is of a set length of [`MAX_MOVES`]. Empty move slots
/// are defined by None.
pub fn learned_moves(&self) -> &RwLock<[Option<Arc<LearnedMove<'library>>>; MAX_MOVES]> {
pub fn learned_moves(&self) -> &RwLock<[Option<Arc<LearnedMove>>; MAX_MOVES]> {
&self.moves
}
@@ -384,7 +385,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Gets the battle the battle is currently in.
pub fn get_battle(&self) -> Option<&Battle<'own, 'library>> {
pub fn get_battle(&self) -> Option<&Battle> {
let r = self.battle_data.read();
if let Some(data) = &r.deref() {
unsafe { data.battle.as_ref() }
@@ -434,8 +435,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon.
pub fn nature(&self) -> &'own Nature {
self.nature
pub fn nature(&self) -> &Arc<Nature> {
&self.nature
}
/// Calculates the flat stats on the Pokemon.
@@ -453,9 +454,9 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Change the species of the Pokemon.
pub fn change_species(&mut self, species: &'own Species, form: &'own Form) {
self.species = species;
self.form = form;
pub fn change_species(&mut self, species: Arc<Species>, form: Arc<Form>) {
self.species = species.clone();
self.form = form.clone();
// If the pokemon is genderless, but it's new species is not, we want to set its gender
if self.gender != Gender::Genderless && species.gender_rate() < 0.0 {
@@ -486,11 +487,11 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Change the form of the Pokemon.
pub fn change_form(&mut self, form: &'own Form) {
if std::ptr::eq(self.form, form) {
pub fn change_form(&mut self, form: &Arc<Form>) {
if Arc::ptr_eq(&self.form, form) {
return;
}
self.form = form;
self.form = form.clone();
self.types.clear();
for t in form.types() {
@@ -512,7 +513,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
.set(ability_script)
.as_ref()
// Ensure the ability script gets initialized with the parameters for the ability.
.on_initialize(self.library, self.active_ability().parameters())
.on_initialize(self.library.as_ref(), self.active_ability().parameters())
} else {
self.ability_script.clear();
}
@@ -547,7 +548,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Sets the current battle the Pokemon is in.
pub fn set_battle_data(&self, battle: *mut Battle<'own, 'library>, battle_side_index: u8) {
pub fn set_battle_data(&self, battle: *mut Battle, battle_side_index: u8) {
let mut w = self.battle_data.write();
if let Some(battle_data) = w.deref_mut() {
battle_data.battle = battle;
@@ -590,7 +591,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Marks an opponent as seen, for use in experience gain.
pub fn mark_opponent_as_seen(&self, pokemon: Weak<Pokemon<'own, 'library>>) {
pub fn mark_opponent_as_seen(&self, pokemon: Weak<Pokemon>) {
let r = self.battle_data.read();
if let Some(battle_data) = &r.deref() {
let mut opponents = battle_data.seen_opponents().write();
@@ -692,9 +693,9 @@ impl<'own, 'library> Pokemon<'own, 'library> {
/// The data of the Pokemon related to being in a battle.
#[derive(Debug)]
pub struct PokemonBattleData<'pokemon, 'library> {
pub struct PokemonBattleData {
/// The battle data of the Pokemon
battle: *mut Battle<'pokemon, 'library>,
battle: *mut Battle,
/// The index of the side of the Pokemon
battle_side_index: AtomicU8,
/// The index of the slot on the side of the Pokemon.
@@ -702,16 +703,16 @@ pub struct PokemonBattleData<'pokemon, 'library> {
/// Whether or not the Pokemon is on the battlefield.
on_battle_field: AtomicBool,
/// A list of opponents the Pokemon has seen this battle.
seen_opponents: RwLock<Vec<Weak<Pokemon<'pokemon, 'library>>>>,
seen_opponents: RwLock<Vec<Weak<Pokemon>>>,
}
impl<'pokemon, 'library> PokemonBattleData<'pokemon, 'library> {
impl PokemonBattleData {
/// The battle data of the Pokemon
pub fn battle_mut(&mut self) -> Option<&mut Battle<'pokemon, 'library>> {
pub fn battle_mut(&mut self) -> Option<&mut Battle> {
unsafe { self.battle.as_mut() }
}
/// The battle data of the Pokemon
pub fn battle(&self) -> Option<&Battle<'pokemon, 'library>> {
pub fn battle(&self) -> Option<&Battle> {
unsafe { self.battle.as_ref() }
}
@@ -728,12 +729,12 @@ impl<'pokemon, 'library> PokemonBattleData<'pokemon, 'library> {
self.on_battle_field.load(Ordering::Relaxed)
}
/// A list of opponents the Pokemon has seen this battle.
pub fn seen_opponents(&self) -> &RwLock<Vec<Weak<Pokemon<'pokemon, 'library>>>> {
pub fn seen_opponents(&self) -> &RwLock<Vec<Weak<Pokemon>>> {
&self.seen_opponents
}
}
impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> {
impl ScriptSource for Pokemon {
fn get_script_count(&self) -> usize {
let mut c = 3;
if let Some(battle_data) = &self.battle_data.read().deref() {
@@ -765,7 +766,7 @@ impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> {
}
}
impl<'own, 'library> VolatileScriptsOwner<'own> for Pokemon<'own, 'library> {
impl VolatileScriptsOwner for Pokemon {
fn volatile_scripts(&self) -> &Arc<ScriptSet> {
&self.volatile
}
@@ -794,7 +795,7 @@ pub mod test {
#[test]
fn construct_pokemon() {
let lib = crate::dynamic_data::libraries::dynamic_library::test::build();
let lib = Arc::new(crate::dynamic_data::libraries::dynamic_library::test::build());
let species = lib.static_data().species().get(&"foo".into()).unwrap();
let form = species.get_form(&"default".into()).unwrap();

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use crate::defines::LevelInt;
use crate::dynamic_data::models::learned_move::MoveLearnMethod;
use crate::dynamic_data::models::pokemon::Pokemon;
@@ -6,9 +8,9 @@ use crate::static_data::{AbilityIndex, DataLibrary, Gender};
use crate::{Random, StringKey};
/// This allows for the easy chain building of a Pokemon.
pub struct PokemonBuilder<'own> {
pub struct PokemonBuilder {
/// The library of the Pokemon.
library: &'own DynamicLibrary,
library: Arc<DynamicLibrary>,
/// The name of the species of the Pokemon.
species: StringKey,
/// The level of the Pokemon.
@@ -19,9 +21,9 @@ pub struct PokemonBuilder<'own> {
random_seed: Option<u128>,
}
impl<'own> PokemonBuilder<'own> {
impl PokemonBuilder {
/// Creates a new PokemonBuilder with a library, species, and level.
pub fn new(library: &'own DynamicLibrary, species: StringKey, level: LevelInt) -> Self {
pub fn new(library: Arc<DynamicLibrary>, species: StringKey, level: LevelInt) -> Self {
Self {
library,
species,
@@ -37,19 +39,19 @@ impl<'own> PokemonBuilder<'own> {
}
/// Finally turn the builder into an actual Pokemon.
pub fn build(self) -> Pokemon<'own, 'own> {
pub fn build(self) -> Pokemon {
let mut random = if let Some(seed) = self.random_seed {
Random::new(seed)
} else {
Random::default()
};
let species = self.library.static_data().species().get(&self.species).unwrap();
let form = species.get_default_form();
let species = self.library.static_data().species().get(&self.species).unwrap().clone();
let form = species.get_default_form().clone();
let p = Pokemon::new(
self.library,
species,
form,
&form,
AbilityIndex {
hidden: false,
index: 0,

View File

@@ -4,12 +4,12 @@ use crate::dynamic_data::models::pokemon::Pokemon;
/// A list of Pokemon belonging to a trainer.
#[derive(Debug)]
pub struct PokemonParty<'pokemon, 'library> {
pub struct PokemonParty {
/// The underlying list of Pokemon.
pokemon: Vec<Option<Arc<Pokemon<'pokemon, 'library>>>>,
pokemon: Vec<Option<Arc<Pokemon>>>,
}
impl<'own, 'library> PokemonParty<'own, 'library> {
impl<'own, 'library> PokemonParty {
/// Instantiates a party with a set size.
pub fn new(size: usize) -> Self {
let mut pokemon = Vec::with_capacity(size);
@@ -20,12 +20,12 @@ impl<'own, 'library> PokemonParty<'own, 'library> {
}
/// Instantiates a party with a list.
pub fn new_from_vec(pokemon: Vec<Option<Arc<Pokemon<'own, 'library>>>>) -> Self {
pub fn new_from_vec(pokemon: Vec<Option<Arc<Pokemon>>>) -> Self {
Self { pokemon }
}
/// Gets a Pokemon at an index in the party.
pub fn at(&self, index: usize) -> &Option<Arc<Pokemon<'own, 'library>>> {
pub fn at(&self, index: usize) -> &Option<Arc<Pokemon>> {
let opt = self.pokemon.get(index);
if let Some(v) = opt {
v
@@ -40,11 +40,7 @@ impl<'own, 'library> PokemonParty<'own, 'library> {
}
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
pub fn swap_into(
&mut self,
index: usize,
pokemon: Option<Arc<Pokemon<'own, 'library>>>,
) -> Option<Arc<Pokemon<'own, 'library>>> {
pub fn swap_into(&mut self, index: usize, pokemon: Option<Arc<Pokemon>>) -> Option<Arc<Pokemon>> {
if index >= self.pokemon.len() {
return pokemon;
}
@@ -69,7 +65,7 @@ impl<'own, 'library> PokemonParty<'own, 'library> {
}
/// Gets the underlying list of Pokemon.
pub fn pokemon(&self) -> &Vec<Option<Arc<Pokemon<'own, 'library>>>> {
pub fn pokemon(&self) -> &Vec<Option<Arc<Pokemon>>> {
&self.pokemon
}

View File

@@ -86,7 +86,7 @@ pub struct ScriptSourceData {
}
/// A script source is a struct on which we can trigger scripts to be run from.
pub trait ScriptSource<'a> {
pub trait ScriptSource {
/// Gets an iterator over all the scripts that are relevant to this script source. If the data
/// has not been initialised, it will do so here.
fn get_script_iterator(&self) -> ScriptIterator {

View File

@@ -5,7 +5,7 @@ use crate::dynamic_data::script_handling::script_set::ScriptSet;
use crate::{PkmnResult, StringKey};
/// This trait adds a bunch of helper functions to deal with volatile scripts on a struct.
pub trait VolatileScriptsOwner<'a> {
pub trait VolatileScriptsOwner {
/// Return the [`ScriptSet`] that are our volatile scripts.
fn volatile_scripts(&self) -> &Arc<ScriptSet>;
/// Loads a volatile script by name.